FR-10은 web 요청도 가능한 범위(Next.js 서버 런타임 한정)에서 BE trace에 합류시키는 것이다. 이 과제는 UI 기능이 아니다 — Next.js 서버 런타임(Server Component·Route Handler)에 OpenTelemetry를 계측하고, BFF가 BE를 호출할 때 traceparent(W3C Trace Context)를 전파해 BE(Micrometer Tracing)가 같은 trace로 잇게 한다.
Overview
무엇을: web/에 instrumentation.ts로 OTel을 등록하고, OTLP로 Collector에 span을 보낸다. BFF fetch(lib/server/be-client.ts)가 나가는 요청에 traceparent를 실어 BE와 trace를 합류시킨다.
왜: 현재 web trace가 전무해, 사용자 요청이 web BFF → BE를 거칠 때 어느 구간이 병목인지 하나의 trace로 볼 수 없다. FR-10은 web ↔ BE 경계를 잇는 최소 조각이다.
어떻게: @vercel/otel(Next 1급 지원)로 서버 런타임 계측 + global fetch 자동 계측(traceparent 주입). Next 14.2는 experimental.instrumentationHook 활성이 필요. env 태그는 신규 키 없이 BE 규약(deployment.environment)과 동일 값 체계 사용.
UI·화면·테마 토큰: 해당 없음. FR-10은 서버 런타임 계측이라 렌더되는 화면·컴포넌트·색이 없다. 따라서 화면 목록·와이어프레임·상태 표·테마 토큰 매핑은 이 과제에 존재하지 않는다(private-tdd FE 섹션 중 UI 항목은 “해당 없음 + 사유”로 대체). 브라우저 RUM 풀 계측은 PRD Non-Goals.
# web 환경변수
OTEL_EXPORTER_OTLP_ENDPOINT = http://otel-collector:4318 # 미설정 시 export no-op (앱 정상)
OTEL_SERVICE_NAME = sports-web # BE는 sports-application — 구분
APP_ENV = local|dev|prod # BE와 동일 값 체계 (신규 키 없음)
# resource attribute
deployment.environment = ${APP_ENV} # BE TDD env 태그 규약과 동일 (FR-8)
BE 계약 정합: BE TDD “인터페이스·엔드포인트 계약”의 otel-collector:4318(HTTP) 수신·deployment.environment resource attr과 일치. web span은 service.name=sports-web로 BE(sports-application)와 구분되며, 같은 deployment.environment로 대시보드에서 env 필터된다.
traceparent 전파 흐름 (Sequence)
sequenceDiagram
participant B as 브라우저
participant W as Next 서버(BFF)
participant C as OTel Collector
participant E as BE(Spring)
B->>W: 페이지/Route Handler 요청
W->>W: OTel span 생성 (root)
W->>E: beClient fetch (traceparent 주입)
E->>E: Micrometer Tracing이 traceparent로 합류
E-->>W: 응답 (동일 trace)
W->>C: web span OTLP export
E->>C: BE span OTLP export
W-->>B: 응답
Component Diagram
flowchart LR
subgraph Web["Next 서버 런타임"]
Instr["instrumentation.ts"]
BFF["be-client fetch"]
end
Collector["OTel Collector :4318"]
BE["BE Spring (Micrometer Tracing)"]
Instr -->|registerOTel| BFF
BFF -->|"fetch + traceparent"| BE
BFF -->|OTLP span| Collector
BE -->|OTLP span| Collector
실패 경로·동시성·멱등
시나리오
영향
설계 대응
감지
OTEL_EXPORTER_OTLP_ENDPOINT 미설정
web span export 안 됨
no-op — 앱·요청 정상(BE TDD 플래그 등가)
로컬 로그 경고 없음(정상)
Collector 다운
web span 유실
export best-effort, 요청 처리 무영향(장애 격리)
Collector self-scrape(BE TDD)
traceparent 미전파
web↔BE trace 분리
fetch 자동 계측 검증 테스트로 회귀 감지
E2E 샘플 trace 연결 검사
Edge 런타임 Route
@vercel/otel Node 전제
대상 Route는 Node 런타임 유지(기본), Edge 미사용
빌드/런타임 확인
동시성/멱등: 계측은 앱 상태를 바꾸지 않는다(읽기 전용 관측). 락·멱등 키 불필요.
상태 전이
해당 없음 — 관측 계측, 상태 머신 없음.
Testing Plan (implementer TDD 입력)
레벨
대상
케이스
build
package.json/next.config
@vercel/otel 설치·해석; experimental.instrumentationHook 존재; 빌드 성공
unit
otel-resource
APP_ENV→deployment.environment 매핑; 미설정 시 기본값(local)
unit(계측 검증)
be-client fetch
나가는 요청 헤더에 traceparent가 존재(활성 span 컨텍스트 하에서); OTLP 미설정 시에도 요청 성공
integration
instrumentation 등록
register() 호출 시 예외 없이 OTel 등록; endpoint 미설정 no-op
scenario(E2E/수동)
합류율
임의 10건 web 요청 → Tempo에서 web+BE span이 동일 trace로 조회(9/10↑, NFR 99%)
핵심 실패 경로: ① OTLP 미설정에서 앱이 정상 부팅·요청 처리되는가(장애 격리) ② traceparent가 실제 BE 요청에 실리는가(회귀 감지) ③ instrumentationHook 누락 시 계측이 로드되지 않음을 빌드/실행으로 확인.
Release Scenario — 무중단 (BE TDD와 정합)
배포 순서: web 계측 코드 배포 → Collector 준비 후 OTEL_EXPORTER_OTLP_ENDPOINT 주입으로 활성. endpoint 미주입이면 export no-op이라 Collector 없이도 web 정상.
플래그 등가: endpoint 환경변수 = ON/OFF 스위치. 문제 시 언셋 → 즉시 no-op(앱 무영향).
롤백: 계측 자체 문제 시 @vercel/otel 의존성·instrumentation.ts revert(단일 PR). traceparent 전파만 문제면 endpoint 언셋.
기존 BFF·화면 동작 무변경(순수 가산). 회귀 위험은 fetch 계측이 헤더에 traceparent를 더하는 것뿐 — BE는 이를 수용(isObservationEnabled)하므로 안전.
Open Questions
web service.name을 sports-web으로 확정 — BE/INFRA 합의 필요 → 확정됨 (2026-07-03, senior-pm #5): service.name 규약 = BE sports-application / web sports-web. ⑤ TDD “인터페이스·엔드포인트 계약” 표와 INFRA-03(collector/prometheus config)에 반영됨. Grafana/Tempo 대시보드가 service 라벨로 두 서비스를 구분(INFRA-04). 두 서비스 모두 deployment.environment=${APP_ENV} 공유.
Route별 Node/Edge 런타임 점검 — 현재 전부 Node 기본이나, 향후 Edge Route 추가 시 @vercel/otel 미적용 구간 발생 가능(문서화).
Document History
날짜
변경 내용
2026-07-03
최초 작성 — FR-10 서버 런타임 OTel 계측, traceparent 전파, UI 없음 명시, BE OTLP/env 규약 소비
2026-07-03
senior-pm #5 — service.name 규약(BE=sports-application/web=sports-web) 확정으로 Open Question 종결