Production Backend API Capstone
Metrics, Logs and Traces Answer Different Questions
한국어 원문으로 표시합니다.
한 줄 요약
메트릭은 전체 추세와 경보를, 구조화 로그는 한 사건의 문맥을, 트레이스 식별자는 경계를 지난 인과관계를 설명한다. 세 신호는 같은 요청에서 나온 안전한 상관 필드로 연결되어야 한다.
왜 로그 한 줄로 장애를 풀 수 없는가
error happened라는 문자열은 얼마나 자주, 어느 경로에서, 어떤 상태로 실패했는지 알려 주지 않는다. 주문 생성 수와 HTTP 지연 시간 메트릭은 변화와 임계치를 보여 준다. JSON 로그의 event, route, status, duration_ms는 개별 요청을 검색하게 한다. 응답 헤더와 로그에 같은 trace ID를 넣으면 사용자가 제보한 요청을 정확히 찾을 수 있다. 서비스가 여러 개라면 이 ID를 다음 호출에 전파한다.
메트릭 이름은 orders_created_total, http_request_duration_seconds처럼 단위와 누적 의미가 드러나야 한다. 사용자 ID나 주문 ID를 메트릭 라벨로 쓰면 카디널리티가 폭발한다. 그런 고유 값은 필요한 경우 로그에 넣되 개인정보와 비밀값 정책을 적용한다. 인증 헤더, 쿠키, 비밀번호, 연결 문자열, 내부 서비스 DNS는 어느 신호에도 기록하지 않는다.
현장에서 검증하는 방법
채점기는 서버에 생성 요청을 보내 응답의 trace ID를 얻고, /metrics에서 두 핵심 지표를 읽는다. 서버 종료 후 각 로그 줄을 JSON으로 파싱해 같은 trace ID, /orders 경로, 201 상태, 숫자 duration_ms가 한 레코드에 있는지 확인한다. 단순히 소스에 json이나 trace_id 문자열이 있는지는 증거가 아니다. import 시 출력이 생기거나 토큰 원문이 로그에 나타나도 실패한다.
세 신호를 어디에 쓰는지 나누기
로그·지표·추적을 다 모으라는 말은 흔하지만, 무엇을 물을 때 어느 것을 보는지 정해 두지 않으면 셋 다 있는데도 장애 때 헤맨다.
| 질문 | 보는 것 | 이유 |
|---|---|---|
| 지금 문제가 있는가 | 지표 | 값이 싸고 전체를 덮는다. 경보는 여기서만 건다 |
| 어디가 느린가 | 추적 | 요청 하나가 지나간 구간별 시간 |
| 왜 그렇게 됐는가 | 로그 | 그 순간의 맥락. 가장 비싸므로 마지막에 본다 |
경보는 지표에만 건다. 로그 문자열로 경보를 걸면 메시지를 조금만 바꿔도 조용히 안 울리고, 그 사실을 장애 때 알게 된다.
세 신호를 하나의 식별자로 잇는다. 요청마다 추적 ID 를 만들어 로그에도 넣고, 지표의 예시(exemplar)로도 붙인다. 그러면 "느린 요청 하나" 에서 그 요청의 로그로 바로 갈 수 있다. 이 연결이 없으면 시각으로 로그를 뒤지게 되고, 그 방식은 트래픽이 많아지는 순간 쓸모가 없다.
카디널리티는 지표에서만 문제가 된다. 사용자 ID 를 로그에 넣는 것은 괜찮지만 지표 라벨에 넣으면 시계열이 폭발한다. 높은 기수의 값은 로그와 추적에 두고, 지표에는 낮은 기수만 둔다.
측정은 사용자 쪽에서 한 번 더 한다. 서버가 200을 돌려줘도 사용자는 실패할 수 있다. 프런트엔드에서 재는 값이나 밖에서 도는 합성 모니터링을 하나 두면, "내부 지표는 정상인데 문의가 들어오는" 상황이 사라진다.
남길 것을 정하는 기준은 "이걸로 무슨 결정을 하는가" 다. 결정을 바꾸지 않는 지표는 대시보드를 어지럽히고 비용만 든다. 대시보드를 만들 때마다 그 화면을 보고 할 행동을 한 줄로 적어 두면 절반이 사라진다.
실무 판단 기준
좋은 관측성은 사후 디버그 문장을 많이 찍는 것이 아니라 운영 질문을 먼저 정하고 낮은 비용의 신호를 설계하는 일이다. 성공률, 오류율, 지연 시간, 트래픽을 메트릭으로 보고 특정 이상을 trace와 로그로 좁힌다. 이어지는 배포 레슨에서는 이 신호가 정상이어도 준비되지 않은 파드로 트래픽을 보내지 않도록 프로브와 실행 보안 경계를 설계한다.