당신의 로깅 방식은 틀렸다.
You're logging wrong [FIXED] by Theo - t3․gg
전통적인 로깅(Logging) 방식의 한계와 비효율성을 지적하며, 현대적 아키텍처에서 문제를 신속하게 해결하기 위한 와이드 이벤트(Wide Events) 및 정규 로그 라인(Canonical Log Lines) 중심의 새로운 로깅 철학과 실천 방안을 제시합니다.
-
로깅의 근본적인 문제점과 역사적 배경
- 기존의 로그는 모놀리스(Monolith) 시대, 단일 서버 환경에서 로컬 재현이 가능하던 시절에 설계되었습니다.
- 현재는 단일 요청이 수십 개의 서비스, 데이터베이스, 캐시를 거치는 분산 시스템 환경임에도 로깅 방식은 2005년 수준에 머물러 있습니다.
- 파일 시스템이 계층 구조를 고집하듯, 로그도 혁신 없이 과거의 방식을 답습하여 현대의 복잡한 문제를 해결하지 못하고 있습니다.
-
로그 카오스(Log Chaos)와 검색의 한계
- 사용자 요청이 많아지면 여러 요청의 로그가 뒤섞여 특정 사용자의 행동 흐름을 파악하기 불가능해집니다.
- 문자열 검색(String Search) 은 로그를 단순한 문자열 덩어리로 취급하며, 구조적 관계나 서비스 간의 상관관계를 이해하지 못합니다.
- 로그에 사용자 ID를 일관되게 포함하지 않으면, 특정 오류 상황에서 전체 맥락을 파악하기 위해 여러 번의 검색을 반복하는 탐정 놀이를 해야 합니다.
- 로그는 쓰기(Writing) 에는 최적화되어 있으나, 정작 필요한 조회(Querying) 에는 최적화되어 있지 않습니다.
-
핵심 용어 정의 및 개념 확장
- 구조적 로깅(Structured Logging) : 로그를 단순 문자열이 아닌 JSON과 같은 키-값 쌍으로 배출하는 방식입니다. 필수적이지만 이것만으로는 부족합니다.
- 카디널리티(Cardinality) : 필드가 가질 수 있는 고유 값의 개수입니다. 사용자 ID와 같은 고해상도(High Cardinality) 데이터가 디버깅에 결정적인 역할을 합니다.
- 차원성(Dimensionality) : 로그 이벤트에 포함된 필드의 개수입니다. 차원이 높을수록 더 정교한 질문에 답할 수 있습니다.
- 와이드 이벤트(Wide Events) : 서비스 요청당 수십 개의 필드(50개 이상)를 가진 단일 컨텍스트 로그를 생성하는 방식입니다.
- 정규 로그 라인(Canonical Log Lines) : 특정 요청에 대한 권위 있는 기록 역할을 하는 단 하나의 로그 라인입니다.
-
오픈 텔레메트리(OpenTelemetry, OTEL)에 대한 오해
- OTEL은 데이터 수집과 전송을 표준화하는 도구일 뿐, 무엇을 로그로 남길지 결정해 주지 않습니다.
- 비즈니스 컨텍스트(구독 등급, 장바구니 가치 등)를 직접 추가하지 않으면, 표준화된 형식의 나쁜 데이터만 양산하게 됩니다.
- OTEL은 배관(Plumbing)과 같으며, 그 배관을 통해 어떤 데이터를 흐르게 할지는 개발자의 몫입니다.
-
개선된 로깅 전략: 속성(Attributes) 기반 로깅
- 코드의 동작을 기록하는 일기장 방식에서 벗어나, 비즈니스 이벤트의 구조적 기록으로 사고를 전환해야 합니다.
- 요청의 시작부터 끝까지 컨텍스트를 쌓아 올린 뒤, 마지막에 단 한 번 와이드 이벤트를 배출합니다.
- 컨텍스트 구성 요소:
- 요청 컨텍스트: Trace ID, Span ID, 메서드, 경로, 쿼리 파라미터 등.
- 사용자 컨텍스트: 사용자 ID, 세션 ID, 구독 등급, 계정 생성일 등.
- 비즈니스 컨텍스트: 주문 ID, 카드 ID 등 비즈니스 특정 데이터.
- 인프라 컨텍스트: Git Hash, 배포 ID, 지역(Region) 등.
- 성능 컨텍스트: DB 쿼리 횟수 및 소요 시간, 캐시 히트율 등.
-
실제 구현 및 데이터 관리
- T3 Chat의 사례: 58억 개의 레코드와 7.3TB의 로그 데이터를 관리하며, Axiom과 같은 현대적인 분석 도구를 활용합니다.
- 프런트엔드에서 생성된 Span ID를 백엔드로 전달하여 전체 요청 경로를 하나의 트레이스로 묶습니다.
- 샘플링(Sampling) 전략:
- 비용 절감을 위해 모든 로그를 보관하는 대신 특정 비율만 저장합니다.
- 테일 샘플링(Tail Sampling) : 요청 완료 후 결과에 따라 보관 여부를 결정합니다. 오류가 발생한 요청, 느린 요청, 중요 사용자의 요청은 반드시 보관합니다.
- 현대적 데이터베이스 활용: ClickHouse나 Axiom과 같은 컬럼 지향 데이터베이스는 고해상도 데이터를 빠르게 쿼리하는 데 최적화되어 있습니다.
-
결론: 디버깅에서 분석으로의 전환
- 와이드 이벤트를 잘 구현하면 디버깅은 고고학적 발굴이 아닌 데이터 분석의 영역이 됩니다.
- "누가 오류가 났는지 검색"하는 대신 "새 결제 플로우를 사용하는 프리미엄 유저 중 오류 코드별 발생 빈도"를 1초 내에 쿼리할 수 있게 됩니다.
- 로그는 더 이상 거짓말을 하지 않고, 시스템의 진실을 온전하게 말해주기 시작합니다.
토픽:
프로그래밍