본문으로 건너뛰기
Kreath Archive
TechProjectsBooksAbout
TechProjectsBooksAbout

내비게이션

  • Tech
  • Projects
  • Books
  • About
  • Tags

카테고리

  • AI / ML
  • 웹 개발
  • 프로그래밍
  • 개발 도구

연결

  • GitHub
  • Email
  • RSS
© 2026 Kreath Archive. All rights reserved.Built with Next.js + MDX
홈TechProjectsBooksAbout
//
  1. 홈
  2. 테크
  3. 2장: OpenTelemetry 아키텍처 심층 분석
2026년 2월 10일·인프라·

2장: OpenTelemetry 아키텍처 심층 분석

OpenTelemetry의 API/SDK/Collector 3계층 구조, W3C TraceContext 기반 컨텍스트 전파, 리소스와 시맨틱 컨벤션, 배포 패턴을 심층적으로 분석합니다.

16분664자8개 섹션
monitoringobservability
공유
opentelemetry2 / 11
1234567891011
이전1장: 관측 가능성의 진화와 OpenTelemetry다음3장: 분산 추적(Distributed Tracing)

학습 목표

  • API와 SDK의 분리 원칙과 그 설계 의도를 이해합니다
  • W3C TraceContext를 통한 컨텍스트 전파 메커니즘을 학습합니다
  • 리소스(Resource)와 인스트루멘테이션 스코프(Instrumentation Scope)의 역할을 파악합니다
  • 시맨틱 컨벤션(Semantic Conventions)의 필요성과 주요 규칙을 이해합니다
  • Agent 모드와 Gateway 모드의 배포 패턴 차이를 비교합니다

API와 SDK의 분리

OpenTelemetry 아키텍처의 가장 핵심적인 설계 결정은 API와 SDK의 분리입니다. 이 분리는 라이브러리 개발자와 애플리케이션 개발자의 역할을 명확히 구분합니다.

API 계층 — 계측의 인터페이스

API 계층은 텔레메트리 데이터를 생성하기 위한 인터페이스만을 정의합니다. 구현 로직은 포함하지 않으며, 의존성이 최소화되어 있습니다. 라이브러리 작성자는 이 API만 사용하여 계측 코드를 작성합니다.

api_example.py
python
from opentelemetry import trace
 
# API만 사용 -- SDK가 없으면 no-op(아무 동작 안 함)
tracer = trace.get_tracer("my-library", "1.0.0")
 
with tracer.start_as_current_span("process-request") as span:
    span.set_attribute("http.method", "GET")
    span.set_attribute("http.url", "https://api.example.com/users")
    # 비즈니스 로직 수행
Info

SDK가 등록되지 않으면 API 호출은 **no-op(무동작)**으로 처리됩니다. 이 덕분에 라이브러리는 OTel API에 의존해도 성능 오버헤드가 없고, 최종 애플리케이션에서 SDK 설치 여부를 자유롭게 결정할 수 있습니다.

SDK 계층 — 처리와 내보내기의 구현

SDK는 API의 실제 구현체로, 텔레메트리 데이터의 처리, 샘플링, 배치, 내보내기를 담당합니다. 애플리케이션의 진입점(entry point)에서 SDK를 초기화하고, 필요한 설정을 주입합니다.

sdk_setup.py
python
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
 
# 리소스 정의 -- 이 텔레메트리가 어디서 오는지 식별
resource = Resource.create({
    "service.name": "user-service",
    "service.version": "2.1.0",
    "deployment.environment": "production",
})
 
# SDK 초기화
provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://collector:4317"))
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)

3계층 아키텍처 전체 흐름


컨텍스트 전파 — 분산 시스템의 접착제

분산 추적의 핵심은 **컨텍스트 전파(Context Propagation)**입니다. 서비스 A에서 시작된 요청이 서비스 B, C를 거칠 때, 동일한 Trace ID를 유지하여 하나의 트레이스로 연결해야 합니다.

W3C TraceContext 표준

OpenTelemetry는 W3C TraceContext 표준을 기본 전파 형식으로 사용합니다. HTTP 요청 시 두 개의 헤더를 통해 컨텍스트를 전달합니다.

HTTP 헤더 예시
text
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
tracestate: congo=t61rcWkgMzE

traceparent 헤더는 네 부분으로 구성됩니다.

필드값설명
version00프로토콜 버전
trace-id4bf92f...4736128비트 트레이스 식별자
parent-id00f067...02b764비트 부모 스팬 식별자
trace-flags01샘플링 플래그 (01 = 샘플링됨)

tracestate 헤더는 벤더별 추가 정보를 키-값 쌍으로 전달합니다. 여러 벤더의 도구가 공존하는 환경에서 각자의 메타데이터를 유지할 수 있게 합니다.

Baggage — 사용자 정의 컨텍스트

Baggage는 트레이스 컨텍스트와 함께 전파되는 사용자 정의 키-값 쌍입니다. 예를 들어, 요청을 보낸 사용자의 테넌트 ID나 기능 플래그 값을 서비스 간에 전달할 수 있습니다.

baggage_example.py
python
from opentelemetry import baggage, context
 
# Baggage 설정
ctx = baggage.set_baggage("tenant.id", "acme-corp")
ctx = baggage.set_baggage("feature.flag", "new-checkout", context=ctx)
 
# 다운스트림 서비스에서 Baggage 읽기
tenant = baggage.get_baggage("tenant.id")
Warning

Baggage는 모든 다운스트림 서비스로 전파되므로, 민감한 정보(사용자 개인정보, 인증 토큰 등)를 Baggage에 담지 마세요. 또한 Baggage 크기가 커지면 모든 HTTP 요청의 헤더 크기가 증가하므로, 필수적인 데이터만 전달해야 합니다.

전파자(Propagator) 구성

OpenTelemetry는 여러 전파 형식을 지원하며, 필요에 따라 조합할 수 있습니다.

propagator_config.py
python
from opentelemetry.propagators.composite import CompositePropagator
from opentelemetry.propagators.b3 import B3MultiFormat
from opentelemetry.propagate import set_global_textmap
from opentelemetry.propagators.textmap import DefaultTextMapPropagator
 
# W3C TraceContext + B3 동시 지원 (Zipkin 호환)
propagator = CompositePropagator([
    DefaultTextMapPropagator(),  # W3C TraceContext
    B3MultiFormat(),              # B3 (Zipkin 호환)
])
set_global_textmap(propagator)

리소스(Resource) — 텔레메트리의 출처 식별

**리소스(Resource)**는 텔레메트리 데이터를 생성하는 엔티티에 대한 불변 속성 집합입니다. 쉽게 말해 "이 데이터가 어디서 왔는지"를 식별하는 메타데이터입니다.

resource_definition.py
python
from opentelemetry.sdk.resources import Resource
from opentelemetry.semconv.resource import ResourceAttributes
 
resource = Resource.create({
    ResourceAttributes.SERVICE_NAME: "payment-service",
    ResourceAttributes.SERVICE_VERSION: "3.2.1",
    ResourceAttributes.SERVICE_NAMESPACE: "checkout",
    ResourceAttributes.DEPLOYMENT_ENVIRONMENT: "production",
    ResourceAttributes.HOST_NAME: "payment-pod-7f8b9",
    ResourceAttributes.CLOUD_PROVIDER: "aws",
    ResourceAttributes.CLOUD_REGION: "ap-northeast-2",
})

리소스는 SDK 초기화 시 한 번 설정되며, 해당 SDK가 생성하는 모든 텔레메트리 데이터에 자동으로 첨부됩니다. 이를 통해 수천 개의 스팬 중에서 특정 서비스, 특정 환경, 특정 호스트의 데이터만 필터링할 수 있습니다.

인스트루멘테이션 스코프(Instrumentation Scope)

**인스트루멘테이션 스코프(Instrumentation Scope)**는 텔레메트리를 생성하는 계측 라이브러리를 식별합니다. Tracer나 Meter를 생성할 때 지정하는 이름과 버전이 바로 이 스코프입니다.

scope_example.py
python
# 각 라이브러리/모듈이 고유한 스코프를 가짐
http_tracer = trace.get_tracer("http-instrumentation", "0.42.0")
db_tracer = trace.get_tracer("sqlalchemy-instrumentation", "0.42.0")
custom_tracer = trace.get_tracer("my-app.checkout", "1.0.0")

이를 통해 "어떤 계측 라이브러리가 이 스팬을 생성했는가"를 추적하고, 특정 라이브러리의 계측을 선택적으로 비활성화할 수 있습니다.


시맨틱 컨벤션(Semantic Conventions)

시맨틱 컨벤션은 텔레메트리 데이터의 속성 이름과 값을 표준화하는 규칙입니다. 이 규칙이 없으면 같은 HTTP 상태 코드를 누구는 http.status, 누구는 status_code, 누구는 response.code로 기록하여 상관관계 분석이 불가능해집니다.

주요 시맨틱 컨벤션

네임스페이스속성 예시설명
httphttp.request.method, http.response.status_codeHTTP 요청/응답
dbdb.system, db.statement데이터베이스
rpcrpc.system, rpc.methodRPC 호출
messagingmessaging.system, messaging.operation메시지 큐
serverserver.address, server.port서버 정보
urlurl.full, url.pathURL 정보
Tip

시맨틱 컨벤션은 지속적으로 진화하고 있으며, 2026년 기준으로 HTTP, 데이터베이스, 메시징 관련 컨벤션이 Stable 상태입니다. 최신 명세는 opentelemetry.io/docs/specs/semconv에서 확인할 수 있습니다.

시맨틱 컨벤션 적용 예시

semconv_usage.py
python
from opentelemetry.semconv.trace import SpanAttributes
 
with tracer.start_as_current_span("http-request") as span:
    # 시맨틱 컨벤션에 따른 표준 속성 설정
    span.set_attribute(SpanAttributes.HTTP_REQUEST_METHOD, "POST")
    span.set_attribute(SpanAttributes.URL_FULL, "https://api.example.com/orders")
    span.set_attribute(SpanAttributes.HTTP_RESPONSE_STATUS_CODE, 201)
    span.set_attribute(SpanAttributes.SERVER_ADDRESS, "api.example.com")
    span.set_attribute(SpanAttributes.SERVER_PORT, 443)

배포 패턴 — Agent vs Gateway

OTel Collector를 배포하는 두 가지 기본 패턴이 있습니다. 실무에서는 이 두 패턴을 조합하여 사용하는 경우가 많습니다.

Agent 모드 (사이드카)

Agent 모드에서는 각 애플리케이션 인스턴스 옆에 Collector가 함께 실행됩니다. Kubernetes에서는 DaemonSet으로 각 노드에 배포하거나, Pod의 사이드카 컨테이너로 실행합니다.

장점

  • 네트워크 지연 최소화 (localhost 통신)
  • 애플리케이션과 같은 노드에서 호스트 메트릭 수집 가능
  • 장애 격리 — 한 노드의 Collector 장애가 다른 노드에 영향 없음

단점

  • 노드 수만큼 Collector 인스턴스 필요 — 리소스 오버헤드
  • 중앙 집중식 설정 변경이 어려움

Gateway 모드 (중앙 집중)

Gateway 모드에서는 독립적인 Collector 클러스터가 모든 텔레메트리 데이터를 중앙에서 수신합니다.

장점

  • 중앙에서 라우팅, 필터링, 변환 정책을 일괄 관리
  • 리소스 효율적 — 필요한 만큼만 스케일 아웃
  • 복잡한 파이프라인(Tail Sampling 등) 구현에 적합

단점

  • 네트워크 장애 시 데이터 손실 위험
  • 단일 장애 지점(SPOF)이 될 수 있음

실무 권장: Agent + Gateway 조합

실무에서는 Agent 모드로 각 노드에서 1차 수집/배치 처리를 하고, Gateway로 전송하여 중앙에서 Tail Sampling, 라우팅, 변환을 수행하는 2계층 구조를 권장합니다. 이 조합은 두 패턴의 장점을 모두 취할 수 있습니다.


OTLP — OpenTelemetry의 표준 프로토콜

**OTLP(OpenTelemetry Protocol)**는 텔레메트리 데이터 전송을 위한 표준 프로토콜입니다. gRPC와 HTTP/JSON 두 가지 전송 방식을 지원합니다.

전송 방식포트특징
gRPC4317고성능, 스트리밍 지원, 프로덕션 권장
HTTP/protobuf4318방화벽 친화적, 브라우저 지원
collector-otlp-config.yaml
yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: "0.0.0.0:4317"
      http:
        endpoint: "0.0.0.0:4318"

OTLP의 핵심 설계 원칙은 다음과 같습니다.

  • 단일 프로토콜 — 트레이스, 메트릭, 로그를 모두 하나의 프로토콜로 전송
  • 효율적 직렬화 — Protocol Buffers 기반으로 네트워크 대역폭 최적화
  • 요청-응답 모델 — 수신 확인을 통한 데이터 유실 방지
  • 부분 성공 — 일부 데이터만 처리 실패해도 나머지는 정상 처리

정리

이번 장에서는 OpenTelemetry의 핵심 아키텍처를 살펴보았습니다. API와 SDK의 분리는 라이브러리 생태계의 호환성을 보장하고, W3C TraceContext 기반 컨텍스트 전파는 서비스 간 추적을 가능하게 합니다. 리소스와 시맨틱 컨벤션은 데이터의 일관성과 검색 가능성을 높이며, Agent와 Gateway 배포 패턴은 다양한 운영 환경에 대응합니다.

다음 장에서는 3대 신호 중 첫 번째인 분산 추적(Distributed Tracing)을 깊이 있게 다룹니다. 스팬의 내부 구조, 스팬 종류, 샘플링 전략을 학습하고 Python으로 직접 계측하는 실습을 진행합니다.

이 글이 도움이 되셨나요?

관련 주제 더 보기

#monitoring#observability

관련 글

인프라

3장: 분산 추적(Distributed Tracing)

스팬의 내부 구조와 종류, 부모-자식 관계, 샘플링 전략(Head/Tail/Rate)을 학습하고 Python으로 분산 추적을 직접 구현합니다.

2026년 2월 12일·15분
인프라

1장: 관측 가능성의 진화와 OpenTelemetry

로깅에서 APM, 관측 가능성으로 이어지는 모니터링의 진화를 살펴보고, OpenTelemetry가 탄생한 배경과 3대 신호, 벤더 중립의 가치를 이해합니다.

2026년 2월 8일·18분
인프라

4장: 메트릭(Metrics) 수집과 분석

OpenTelemetry 메트릭의 종류(Counter, Gauge, Histogram), 카디널리티 관리, Exemplars를 통한 메트릭-트레이스 연결, Prometheus 호환을 학습합니다.

2026년 2월 14일·14분
이전 글1장: 관측 가능성의 진화와 OpenTelemetry
다음 글3장: 분산 추적(Distributed Tracing)

댓글

목차

약 16분 남음
  • 학습 목표
  • API와 SDK의 분리
    • API 계층 — 계측의 인터페이스
    • SDK 계층 — 처리와 내보내기의 구현
    • 3계층 아키텍처 전체 흐름
  • 컨텍스트 전파 — 분산 시스템의 접착제
    • W3C TraceContext 표준
    • Baggage — 사용자 정의 컨텍스트
    • 전파자(Propagator) 구성
  • 리소스(Resource) — 텔레메트리의 출처 식별
    • 인스트루멘테이션 스코프(Instrumentation Scope)
  • 시맨틱 컨벤션(Semantic Conventions)
    • 주요 시맨틱 컨벤션
    • 시맨틱 컨벤션 적용 예시
  • 배포 패턴 — Agent vs Gateway
    • Agent 모드 (사이드카)
    • Gateway 모드 (중앙 집중)
    • 실무 권장: Agent + Gateway 조합
  • OTLP — OpenTelemetry의 표준 프로토콜
  • 정리