86장. X-Ray — 분산 트레이싱
이 장에서 말하고자 하는 것
마이크로서비스에서 한 사용자 요청이 통과하는 경로는 길다.
사용자 → CloudFront → API Gateway → ALB
→ orders → users (호출)
→ payments (호출)
→ DB · 외부 결제 API
운영 중 “이 한 요청은 어디서 1.5초가 걸렸나?” 가 자주 묻는 질문이다.
이 답을 주는 도구가
분산 트레이싱(Distributed Tracing)
이고, AWS의 옵션이
AWS X-Ray
다.
1. Trace · Segment · Subsegment
Trace (한 요청의 전체 이야기)
├─ Segment: API Gateway
├─ Segment: orders 서비스
│ ├─ Subsegment: DB query
│ └─ Subsegment: users 서비스 호출
│ └─ Segment: users 서비스
│ └─ Subsegment: DB query
└─ Segment: payments 서비스
└─ Subsegment: 외부 결제 API
각 구간이 얼마나 걸렸는지 시각적으로 펼쳐진다.
2. trace_id — 한 요청을 따라가는 끈
요청이 시작될 때 발급되는 ID.
Trace ID: 1-abcd1234-...
모든 다운스트림 호출에 이 ID가 헤더로 전달된다.
X-Amzn-Trace-Id: Root=1-abcd1234-...
각 서비스의 로그에도 trace_id를 같이 기록한다.
로그 + 트레이스 + 메트릭이 trace_id 로 한 줄에 묶인다
이게 운영 관측성의 핵심 연결고리
3. AWS X-Ray SDK · OpenTelemetry
X-Ray SDK
AWS 전용. 비교적 단순.
OpenTelemetry (OTel) + AWS Distro (ADOT)
업계 표준. AWS · Datadog · Honeycomb 등 어디든 보낼 수 있다.
새 프로젝트는 거의 항상 OpenTelemetry 부터
AWS 종속을 줄이고 다른 백엔드로 옮기기 쉬움
4. 자동 계측 vs 수동 계측
자동 계측
프레임워크 / 라이브러리가 알아서 트레이스를 만든다.
- HTTP 요청
- DB 쿼리
- AWS SDK 호출
- HTTP 클라이언트
수동 계측
비즈니스 로직 안에서 명시적으로 구간을 만든다.
tracer.startActiveSpan("calculate-shipping", (span) => {
span.setAttribute("order.weight", weight);
...
span.end();
});
자동 계측을 먼저, 비즈니스적으로 의미 있는 구간만 수동 추가
5. ECS · API Gateway · ALB와의 통합
- API Gateway — 한 줄로 X-Ray 활성화
- ALB — 자동 trace_id 전파 헤더
- ECS / Fargate — X-Ray 데몬 사이드카 또는 OTel Collector
- Lambda — Tracing 옵션을 켜면 자동
활성화는 어렵지 않다 — 코드는 SDK 한 줄
6. Service Map
X-Ray가 자동으로 그려주는 서비스 의존성 그래프.
[client] → [API Gateway] → [orders]
├─ → [users]
├─ → [payments] → [외부 API]
└─ → [RDS]
- 평균 지연 · 에러율을 노드에 표시
- 어느 노드가 느린지 / 에러를 만드는지 한눈에
7. 우리 서비스에서
모든 서비스가 OpenTelemetry로 계측
↓ OTLP
[ADOT Collector 사이드카]
↓
[X-Ray] (운영)
[추가로 Datadog/Honeycomb 도 옵션]
각 서비스 로그에 trace_id 필수 필드
- p95 가 튀는 시점 → X-Ray에서 trace 한 건 클릭 → 어느 구간에서 느렸나 즉시 파악
8. 직접 확인해보기
ECS Task에 X-Ray 사이드카 추가
{
"name": "xray-daemon",
"image": "public.ecr.aws/xray/aws-xray-daemon:latest",
"essential": false,
"portMappings": [{ "containerPort": 2000, "protocol": "udp" }]
}
애플리케이션 코드 (Node.js, X-Ray SDK)
const AWSXRay = require("aws-xray-sdk");
const express = require("express");
const app = express();
app.use(AWSXRay.express.openSegment("orders"));
app.use(routes);
app.use(AWSXRay.express.closeSegment());
OpenTelemetry 권장 패턴
import { NodeSDK } from "@opentelemetry/sdk-node";
import { AwsXrayIdGenerator } from "@opentelemetry/id-generator-aws-xray";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
const sdk = new NodeSDK({
idGenerator: new AwsXrayIdGenerator(),
traceExporter: new OTLPTraceExporter({ url: "http://localhost:4317" }),
});
sdk.start();
9. 코드로는 이렇게 생겼다 — Terraform (API Gateway X-Ray)
resource "aws_apigatewayv2_stage" "prod" {
api_id = aws_apigatewayv2_api.main.id
name = "$default"
auto_deploy = true
default_route_settings {
detailed_metrics_enabled = true
logging_level = "INFO"
throttling_burst_limit = 5000
throttling_rate_limit = 10000
}
}
# X-Ray 활성화는 통합 단계에서 설정
# Terraform 에서는 IAM 권한과 ADOT Collector 사이드카 추가가 핵심
10. 이렇게 쓰면 망한다 — 안티패턴
안티패턴 1. trace_id 를 로그에 안 넣는다
트레이스와 로그가 분리돼 운영에서 서로를 못 찾는다.
모든 로그 한 줄에 trace_id 필수
안티패턴 2. 샘플링을 안 한다
모든 요청을 트레이싱하면 비용 폭증. X-Ray 기본은 1초당 1건 + 5%.
운영 부하에 맞춰 샘플링 조정
안티패턴 3. 외부 호출은 안 추적한다
가장 느린 구간이 외부 결제 API · S3 같은 곳에 있는데 보이지 않는다.
AWS SDK · HTTP 클라이언트 자동 계측 켠다
안티패턴 4. 트레이스가 있는데 안 본다
운영 회의나 사고 보고에서 추측만 한다.
사용자 영향 큰 사고는 항상 트레이스로 시작
11. 한 줄로 정리
X-Ray는 한 요청의 여행을 시각화하는 도구이며,
trace_id 가 로그 · 메트릭 · 트레이스를 한 줄로 묶는 끈이다
12. 이 장의 핵심 정리
- 분산 트레이싱은 한 요청의 다중 서비스 흐름을 따라간다.
- Trace ID가 운영 관측성의 핵심 연결고리다.
- OpenTelemetry + AWS Distro (ADOT) 가 새 프로젝트의 표준이다.
- 자동 계측을 먼저, 의미 있는 구간만 수동 추가.
- Service Map으로 의존성과 지연을 한눈에 본다.
- 모든 로그 한 줄에 trace_id 를 넣는 게 가장 큰 차이를 만든다.