LabHub
배우기 러닝패스 코스

OTCA — OpenTelemetry Certified Associate

OTLP Is a Protocol, Not a Store

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

한 줄 요약

OpenTelemetry 는 텔레메트리를 만들고 보내는 방법을 표준화한 프로젝트입니다. 저장하거나 보여 주는 일은 하지 않습니다. OTLP 는 그 전송 규약이고, 백엔드는 Tempo 든 Jaeger 든 ClickHouse 든 여러분이 고릅니다. 이 경계를 먼저 잡아야 "OpenTelemetry 를 깔면 대시보드가 생기나요"라는 오해가 사라집니다.

Concept map: 만들고 보내는 방법 · 네 가지 시그널 · 어디서 · 언제부터, 얼마나

왜 이게 필요했나

계측 라이브러리가 벤더마다 달랐던 시절에는 백엔드를 바꾸는 일이 곧 전 서비스 재계측이었습니다. 코드 안에 특정 벤더의 SDK 호출이 박혀 있으니까요. OpenTelemetry 는 그 지점을 잘라 냈습니다. 애플리케이션은 OTel API 로만 이야기하고, 어디로 보낼지는 SDK 설정이나 컬렉터 설정에서 정합니다. 그래서 백엔드 교체가 코드 리뷰가 아니라 설정 변경이 됩니다.

어떻게 동작하나

네 가지 시그널이 각각 다른 질문에 답합니다.

시그널 답하는 질문 대표적인 한계
Traces 이 요청이 어디서 시간을 썼는가 언제부터·몇 퍼센트인지는 못 본다
Metrics 언제부터, 얼마나 나빠졌는가 개별 요청 복원 불가
Logs 그 안에서 그렇게 됐는가 서비스 간 상관은 직접 이어야 한다
Profiles 그 시간을 어떤 코드가 썼는가 가장 늦게 표준화된 신호

트레이스는 "어디"에, 메트릭은 "언제와 얼마나"에, 로그는 "왜"에 답합니다. 셋 다 있어야 조사가 끝까지 갑니다. 트레이스에서 trace ID 를 복사해 로그 검색에 넣었을 때 그 요청의 로그가 나오는지 — 이것이 계측이 이어져 있는지 확인하는 가장 값싼 테스트입니다.

구성 요소는 세 층으로 봅니다.

OTLP 는 이 사이를 흐르는 프로토콜입니다. 두 가지 전송 방식이 있고, 초보자가 가장 많이 걸리는 함정이 여기 있습니다.

방식 기본 포트 OTEL_EXPORTER_OTLP_PROTOCOL
gRPC 4317 grpc
HTTP/protobuf 4318 http/protobuf

포트와 프로토콜이 어긋나면 연결 자체가 실패하고, 오류는 애플리케이션 로그에만 남습니다. 컬렉터 쪽 지표는 0 에서 꿈쩍도 하지 않으므로 "컬렉터가 안 받는다"고 오진하기 쉽습니다. 데이터가 아예 안 들어올 때 가장 먼저 확인할 것이 이 조합입니다.

엔드포인트 지정에도 규칙이 있습니다. OTEL_EXPORTER_OTLP_ENDPOINT 는 시그널 공통 베이스 주소이고, HTTP 를 쓸 때는 SDK 가 /v1/traces 같은 경로를 붙입니다. 시그널별로 다른 목적지를 쓰려면 OTEL_EXPORTER_OTLP_TRACES_ENDPOINT 처럼 시그널별 변수를 쓰는데, 이 경우 경로까지 전체를 적어야 합니다.

현장에서 만나는 모습

컬렉터 배포판이 두 가지라는 사실도 실무에서 자주 발목을 잡습니다. Core 는 핵심 컴포넌트만 담아 작고, Contrib 는 커뮤니티 컴포넌트를 대거 포함해 훨씬 큽니다. 문서나 블로그에서 본 컴포넌트 이름을 그대로 붙여 넣었는데 컬렉터가 "알 수 없는 타입"이라며 죽는 일이 흔한데, 이때 대부분 설정 오타를 먼저 의심합니다. 실제 원인은 배포판이 다른 경우가 훨씬 많습니다. otelcol components 로 지금 바이너리에 무엇이 들어 있는지, 각 컴포넌트의 안정성 등급이 무엇인지 먼저 확인하는 습관이 필요합니다.

그리고 Jaeger v2 는 내부적으로 OpenTelemetry Collector 기반으로 재설계되어 OTLP 를 네이티브로 받습니다. Zipkin 익스포터는 폐기 예정 상태이므로 신규 프로젝트에서 새로 도입할 이유가 없습니다.

계측을 실제로 붙일 때 정해야 하는 것들

OpenTelemetry 는 개념이 넓어서, 배운 뒤에 실제로 붙이려 하면 어디부터 손댈지에서 막힌다. 순서가 있다.

자동 계측을 먼저 켠다. 대부분의 언어에 에이전트나 라이브러리가 있어서, 코드를 안 고치고도 HTTP 서버·클라이언트·DB 드라이버의 구간이 생긴다. 여기까지만 해도 "어느 요청이 느린가" 에 답할 수 있고, 이것이 관측성의 8할이다.

그다음에 손으로 구간을 더한다. 자동 계측이 모르는 것은 우리 업무 논리다. 의미 있는 단위(주문 검증, 재고 확인, 정산 계산)에만 구간을 두고, 함수마다 넣지 않는다. 구간이 많아지면 읽기 어려워지고 비용도 늘어난다.

속성 이름은 규약을 따른다. http.request.method, db.system, service.name 처럼 정해진 이름을 쓰면 도구가 알아서 화면을 만들어 준다. 직접 지은 이름은 우리 대시보드에서만 뜻이 통한다. 사내 속성은 접두사를 붙여 구분한다.

전파(propagation)를 확인한다. 서비스를 넘어가면서 추적이 끊기는 것이 가장 흔한 문제다. traceparent 헤더가 프록시·큐·배치를 지나가는지 봐야 한다. 메시지 큐에서는 헤더를 직접 넣고 빼는 코드를 써야 하는 경우가 많다.

표본 추출을 처음부터 정한다. 전부 보내면 비용이 감당이 안 되고, 무작위로 줄이면 정작 느린 요청이 안 남는다. 꼬리 표본 추출(요청이 끝난 뒤 느리거나 오류인 것을 골라 남기는 방식)이 답이지만 수집기 쪽 메모리를 쓴다. 시작은 "오류와 느린 것은 전부, 나머지는 1%" 정도로 잡는다.

수집기를 사이에 둔다. 애플리케이션이 백엔드로 직접 보내면 백엔드를 바꿀 때 전부 재배포해야 한다. 수집기를 두면 대상 변경·필터링·재시도가 그 한 곳에서 끝난다.

다음 확인에서 볼 것

이 모듈은 개념 모듈이라 실습이 없습니다. 퀴즈로 시그널 경계와 OTLP 규약을 확인한 뒤, 다음 모듈에서 SDK 환경변수와 리소스 속성을 직접 쓰고 쿠버네티스 Downward API 로 인스턴스 식별자를 주입해 봅니다.