텍스트 로그와 구조화된 로그
이 텍스트 로그에는 아래 구조화된 로그와 같은 정보가 들어 있습니다.message와 order_id로 필터링합니다. 메시지는 주문마다 같으므로 개수도 셀 수 있습니다.
로그 형식 선택하기
JSON을 사용하고 한 줄에 객체 1개를 쓰세요. 모든 서비스에서 같은 필드 이름을 사용하세요. 이 표는 기본 필드와, OpenTelemetry 로그 데이터 모델과 LogBrew에서 대응하는 이름입니다.
OpenTelemetry 심각도 숫자는 1부터 24까지입니다.
INFO는 9, WARN은 13, ERROR는 17, FATAL은 21에서 시작합니다. LogBrew는 OTLP 로그를 바로 받습니다. OpenTelemetry 데이터 보내기를 참고하세요.
로깅 모범 사례
메시지 고정하기
"payment failed"라고 쓰고 주문 ID는 필드에 넣으세요. 메시지가 고정되면 이벤트 유형 1개로 묶고, 세고, 알림을 설정할 수 있습니다.
필드마다 이름 하나만 쓰기
order_id와 orderId 중 하나를 한 번 정하고 모든 서비스에서 사용하세요. http.response.status_code처럼 흔한 필드에는 OpenTelemetry 시맨틱 규칙의 이름을 사용하세요.
필요한 대응에 따라 레벨 고르기
error는 작업이 실패했다는 뜻입니다. warning은 프로그램이 복구했다는 뜻입니다. info는 정상 작업을 확인합니다. debug는 문제를 찾는 동안에만 사용하세요.
시간은 UTC로 쓰기
2026-11-07T14:21:19.773+00:00처럼 밀리초와 오프셋이 있는 RFC 3339를 사용하세요. UTC와 밀리초가 없으면 시간대가 다른 레코드나 같은 초에 쓴 레코드가 잘못된 순서로 정렬됩니다.
트레이스 ID와 스팬 ID 추가하기
이 ID가 있으면 요청 1개의 로그를 여러 서비스에 걸쳐 모두 읽을 수 있습니다.서비스, 환경, 릴리스는 한 번만 설정하기
호출할 때마다가 아니라 시작할 때 설정하세요. 릴리스가 없으면 어떤 배포가 변화를 일으켰는지 알 수 없습니다.오류는 처리하는 곳에서 한 번만 기록하기
오류 유형과 메시지를 추가하세요. 같은 오류를 계층마다 다시 기록하지 마세요.시크릿과 개인정보 빼기
비밀번호, 토큰, 쿠키, 요청 본문, 쿼리 문자열이 있는 전체 URL을 기록하지 마세요. 로거의 가리기 기능을 사용하세요. 로그 마스킹을 참고하세요.고정된 필드 이름 사용하기
{"ord_1001": "failed"}처럼 값을 필드 이름으로 쓰지 마세요. 그러면 새 값마다 필드가 새로 생기고, 필터 1개로 모든 주문을 찾을 수 없습니다.
프로덕션에서는 표준 출력에 JSON 쓰기
읽기 쉬운 형식은 개발 환경에서만 사용하세요.Python의 구조화된 로깅
표준logging 모듈에는 JSON 포매터가 없습니다. 이 포매터는 기본 필드와 extra={"fields": {...}}의 값을 씁니다.
LogBrewLoggingHandler를 추가하세요. 이 핸들러는 메시지, 레벨, 로거를 필드로 보내고, extra의 원시 값을 메타데이터로 보냅니다. Python 로깅을 참고하세요.
Node.js의 구조화된 로깅
Pino는 기본적으로 레코드마다 JSON 1줄을 씁니다. Winston은winston.format.json()으로 JSON을 씁니다. 둘 다 호출에서 받은 필드와 자식 로거의 필드를 유지합니다. 두 설정 방법과 Express 로그의 트레이스 ID는 Node.js 로깅을 참고하세요.
