JSON 로깅, MDC, logstash-logback-encoder, 분산 추적, 로그 마스킹, Loki
| 구분 | 선택 | 이유 |
|---|---|---|
| JSON 인코더 | logstash-logback-encoder |
필드명·마스킹 커스터마이징 풍부, Collector 경유 없음 |
| traceId/spanId | Micrometer Tracing |
Spring Boot 3 네이티브, W3C 표준, Zipkin/Tempo 연동 가능 |
| HTTP 컨텍스트 | ObservationHandler |
메트릭·트레이스와 동일 Observation 기반, Filter 불필요 |
| User/Client 컨텍스트 | Handler + ArgumentResolver | client_ip/user_agent는 Handler, user_id/auth_session_id는 Resolver(검증 로직 중복 없음) |
| WebSocket 컨텍스트 | WebSocketTracingChannelInterceptor 확장 | traceId와 동일 생명 주기, 별도 Interceptor 불필요 |
| MDC 필드 네이밍 | http.*, websocket.* |
프로토콜.필드 패턴으로 일관성, Loki 필터링 용이 |
| 완료 로그 레벨 | HTTP INFO, WebSocket CONNECT/SUBSCRIBE/SEND INFO, heartbeat DEBUG | 운영에서 유저 요청 추적 가능, heartbeat 로그량 억제 |
배경: Spring Boot 기본 Logback으로 평문 로그가 출력됨. Loki 등과 연동하려면 파싱 가능한 형식이 필요함.
후보 비교:
결정: logstash-logback-encoder — 필드명·패턴·마스킹 풍부, Collector 경유 없어 성능 우수, trace_id는 MDC 별도 주입
적용: LOGGING_FORMAT 환경변수로 출력 형식 지정(json/plain). application.properties의 logging.format=${LOGGING_FORMAT:json}
목적: 요청 단위로 로그를 묶어 Loki 등에서 trace_id로 검색 시 동일 요청의 모든 로그를 한 번에 조회.
후보: (1) 수동 MDC Filter, (2) OTel Java Agent, (3) Micrometer Tracing
결정: Micrometer Tracing — trace_id/span_id 자동 주입, Spring Boot 3.x 네이티브, W3C 표준, Zipkin/Tempo 연동 시 유리. 의존성 1개·설정 1줄·코드 0줄로 도입 부담 낮음.
배경: MDC는 ThreadLocal 기반이라 스레드가 바뀌면 traceId/spanId가 사라짐.
| 상황 | 처리 |
|---|---|
| 비동기 (@Async, AsyncRunner) | ContextPropagatingTaskDecorator 적용 |
| WebSocket (clientInboundChannel) | WebSocketTracingChannelInterceptor — preSend에서 span 생성·MDC 설정, afterSendCompletion에서 정리 |
| @Scheduled, ThreadPoolTaskScheduler | SpanRunner.runWithSpan() / ScheduledSpanAspect |
| Redisson topic listener | AsyncRunner.runAsync로 콜백 본문을 taskExecutor에서 SpanRunner.runWithSpan + publishEvent 처리 |
목적: 비밀번호, 토큰, 시크릿 등 민감 정보가 로그에 노출되지 않도록 마스킹.
결정: 필드 기반 마스킹(PathMask / FieldNameBasedFieldMasker) 우선 적용. logstash-logback-encoder 7.0+ MaskingJsonGeneratorDecorator 사용.
마스킹 대상: password, secret, token, accessToken, refreshToken, authorization, cookie, apiKey, api_key
목적: HTTP 요청 처리 시 로그에 method, path, status, duration 포함.
결정: Micrometer Observation — Spring Boot 3 관찰성 모델과 일치, traceId/spanId와 동일한 Observation 기반. ObservationHandler<ServerRequestObservationContext> 구현.
MDC 필드: http.method, http.path, http.status_code, http.duration_ms
목적: 감사·디버깅·보안 분석을 위해 사용자·클라이언트 식별 정보 포함.
결정: Handler 확장 + ArgumentResolver 조합
CommonAuthInfoArgumentResolver에서 JWT 검증 시점에 MDC.put (검증 로직 중복 없음)MDC 필드: user_id, auth_session_id, client_ip, user_agent
목적: WebSocket 메시지 처리 시 websocket.command, session_id, destination 등으로 Loki에서 필터·추적 가능하게 함.
결정: WebSocketTracingChannelInterceptor 확장 — traceId/spanId와 동일한 메시지 단위 생명 주기. StompHeaderAccessor로 command, sessionId, destination, sessionAttributes 추출.
MDC 필드: websocket.command, websocket.session_id, websocket.destination, websocket.start_time, websocket.end_time, websocket.duration_ms
완료 로그 레벨: heartbeat(null command) → DEBUG, CONNECT/SUBSCRIBE/SEND → INFO (로그량 억제)
어떠한 날카로운 피드백이더라도 환영합니다. 사소한 의견도 괜찮습니다.
citron0137@gmail.com 또는 LinkedIn 을 통해 피드백을 보내주세요.