본문 바로가기
클라우드/opentelemetry

🧭 OpenTelemetry SDK의 심장을 파헤치다: 4가지 핵심 컴포넌트 완벽 가이드

by gasbugs 2025. 10. 14.

안녕하세요! Observability(관측 가능성)의 세계를 탐험하는 개발자 여러분. OpenTelemetry(OTel)가 사실상의 표준으로 자리 잡으면서, 많은 분들이 OTel을 도입하고 계실 텐데요. 하지만 OTel SDK를 사용하면서 "대체 내부에서 어떤 부품들이 어떻게 돌아가는 거지?" 하는 궁금증을 가져본 적 없으신가요? 🤔

 

오늘은 마치 자동차의 엔진을 분해하듯, OpenTelemetry SDK를 구성하는 가장 중요한 4가지 핵심 컴포넌트에 대해 깊이 있게 알아보겠습니다.

 

자, 그럼 OTel SDK의 엔진룸으로 함께 떠나볼까요?

 


🕵️‍♀️ 환경 탐정: Resource Detector

Resource Detector는 이름 그대로 '자원 탐지기' 입니다. 애플리케이션이 시작될 때, 마치 탐정처럼 주변 환경을 샅샅이 조사해서 의미 있는 정보를 자동으로 수집하는 아주 똑똑한 친구죠.

  • 핵심 역할: 내가 실행된 환경이 어디인지(AWS, GCP, Azure?), 컨테이너에서 돌고 있는지(Docker, Kubernetes?), 호스트 이름은 무엇인지 등의 환경 정보를 자동으로 감지하여 모든 텔레메트리 데이터(traces, metrics, logs)에 공통 '꼬리표'로 붙여줍니다.
  • 왜 중요한가?: 이 '꼬리표' 정보 덕분에 우리는 "AWS us-east-1 리전에서 실행 중인 payment-service의 v1.2 버전에서 발생한 에러"와 같이 데이터를 훨씬 풍부한 맥락(Context) 속에서 분석할 수 있습니다. 컨테이너 ID나 Pod 이름을 알면 문제가 생긴 특정 인스턴스를 즉시 찾아낼 수 있죠.

Resource Detector가 수집하는 정보의 예시는 다음과 같습니다.

  • 클라우드 정보: cloud.provider, cloud.region, cloud.account.id
  • 컨테이너 정보: container.name, container.id, container.image.name
  • 호스트 정보: host.name, host.arch
  • OS 정보: os.type, os.version

이 모든 정보가 자동으로 추가되니, 우리가 수동으로 설정해야 하는 번거로움이 크게 줄어듭니다.


📬 컨텍스트 배달부: Propagator

Propagator는 분산 시스템(MSA)에서 '컨텍스트(Context) 전파' 라는 매우 중요한 임무를 수행합니다.

  • 핵심 역할: MSA 환경에서는 하나의 요청이 여러 서비스(Service A -> Service B -> Service C)를 거쳐 처리됩니다. 이때 이 요청들이 모두 하나의 작업(Trace)에 속한다는 것을 알려주는 정보(Trace ID, Span ID 등)를 서비스 경계를 넘어 전달해주는 역할을 합니다. 마치 여러 나라를 여행하는 여행객의 '여권' 과도 같죠.
  • 동작 방식:
    1. Inject(주입): 서비스 A가 서비스 B를 호출할 때, HTTP 헤더 같은 곳에 traceparent 와 같은 형태로 컨텍스트 정보를 주입합니다.
    2. Extract(추출): 서비스 B는 요청을 받으면 헤더에서 컨텍스트 정보를 추출하여 자신의 작업이 서비스 A의 작업에 이어서 계속된다는 것을 인지합니다.
  • 주요 표준: W3C Trace Context(표준), B3(과거에 많이 사용) 등의 약속된 포맷을 사용합니다.

Propagator 덕분에 우리는 여러 서비스에 흩어져 있는 조각난 Span들을 하나의 아름다운 분산 트랜잭션 그래프로 볼 수 있습니다.


🎟️ 데이터 게이트키퍼: Sampler

모든 요청을 추적하면 좋겠지만, 트래픽이 많은 서비스에서는 엄청난 양의 데이터가 발생하고 이는 곧 비용 증가로 이어집니다. Sampler는 바로 이 문제를 해결하기 위해 존재합니다.

  • 핵심 역할: "어떤 요청을 기록하고 어떤 요청을 버릴 것인가?" 를 결정하는 샘플링 전략을 담당합니다. 즉, 데이터 수집의 '게이트키퍼' 역할을 하는 셈이죠.
  • 주요 전략:
    • AlwaysOnSampler: 모든 데이터를 기록합니다. (개발 환경에 유용)
    • AlwaysOffSampler: 모든 데이터를 버립니다.
    • TraceIdRatioBasedSampler: 설정된 비율(예: 10%)에 따라 무작위로 데이터를 샘플링합니다. (가장 일반적인 방식)
    • ParentBasedSampler: 부모 Span이 샘플링되었다면, 자식 Span도 따라서 샘플링하는 등 부모의 결정을 따릅니다.

효과적인 샘플링 전략은 비용은 줄이면서도 시스템의 상태를 파악할 수 있는 의미 있는 데이터를 확보하는 데 매우 중요합니다.


🚚 데이터 최종 배송기사: Exporter

Exporter는 SDK 파이프라인의 가장 마지막 단계를 책임지는 '데이터 배송기사' 입니다.

  • 핵심 역할: 애플리케이션 내부에서 수집되고 처리된 텔레메트리 데이터를 최종 분석 시스템(Backend)으로 내보내는(Export) 역할을 합니다.
  • 다양한 목적지: 어떤 분석 시스템을 사용하느냐에 따라 다양한 Exporter를 선택할 수 있습니다.
    • OTLP Exporter: OpenTelemetry의 표준 프로토콜(OTLP)을 사용하여 OTel Collector나 Jaeger, Grafana Tempo 등으로 보냅니다. (가장 권장되는 방식)
    • Jaeger Exporter: Jaeger 포맷으로 직접 보냅니다.
    • Prometheus Exporter: Prometheus가 수집할 수 있는 포맷으로 메트릭을 노출합니다.
    • Console Exporter: 데이터를 화면(콘솔)에 출력해 줍니다. (디버깅용으로 최고!)

어떤 Exporter를 사용하느냐에 따라 우리 데이터의 최종 목적지가 결정됩니다.


✨ 총정리: 데이터의 여정

자, 그럼 이 컴포넌트들이 어떻게 함께 작동하는지 데이터의 여정을 따라가며 정리해볼까요?

  1. (시작) 애플리케이션이 실행되면 Resource Detector가 환경 정보를 수집해 기본 '꼬리표'를 준비합니다. 🕵️‍♀️
  2. (요청 수신) 외부에서 요청이 들어오면 Propagator가 HTTP 헤더 등에서 Trace 컨텍스트를 추출합니다. 📬
  3. (샘플링 결정) 새로운 Trace를 시작할 때, Sampler가 이 Trace를 기록할지 말지 결정합니다. 🎟️
  4. (데이터 처리) 애플리케이션 코드 내에서 Span들이 생성되고, 이 Span들에는 1번에서 수집한 리소스 정보가 모두 포함됩니다.
  5. (데이터 전송) 처리가 완료된 데이터(Span)는 Exporter를 통해 최종 목적지(예: Jaeger)로 배송됩니다. 🚚

이제 맨 처음의 질문으로 돌아가면 답은 명확해졌습니다. 실행 환경의 속성을 '탐지'하는 것은 Resource Detector의 고유한 임무입니다. 이 네 가지 컴포넌트의 역할을 명확히 이해한다면, 여러분의 OpenTelemetry SDK 설정과 활용 능력이 한 단계 더 성장할 것이라 확신합니다!