[Spring Boot] CH 4 개인 프로젝트 요구사항 정리 Lv 5

박화랑·2025년 4월 19일

🔍 1. 문제 인식 및 정의

기존 어드민 API 요청 로깅은 AdminLoggingInterceptorAdminApiLoggingAspect 두 곳에 분산되어 있었음.

  • Interceptor에서 요청 정보를 로깅하고
  • AOP에서 응답을 로깅하는 방식이었지만,
    ✅ 두 곳 모두에서 중복된 로깅 포맷 처리, 필드 추출, 직접 로그 출력이 발생하고 있었음

내가 생각한 개선할 점 정리:

  • 로깅 책임이 분산되어 있고, 코드 중복 발생
  • 테스트 불가능한 로깅 로직이 여러 클래스에 퍼져 있음
  • 로깅 포맷 변경 시 모든 클래스 수정 필요
  • ObjectMapper 직접 호출, log.info(...) 직접 반복

💡 2. 해결 방안

2-1. 의사결정 과정

기존 구조를 유지하면서도 로깅 책임을 완전히 분리하기 위해 다음과 같은 구조를 설계:

  • Interceptor: 요청 정보를 수집하고 RequestLogContext에 담아 ThreadLocal에 저장
  • AOP: 로깅 실행만 담당하고, 로깅 내용은 전부 LoggingUtils에 위임
  • LoggingUtils: 로그 포맷, 바디 직렬화 등 모든 로깅 출력을 전담
  • RequestLogContextHolder: AOP ↔ Interceptor 사이의 안전한 데이터 전달 책임

2-2. 해결 과정

  • RequestLogContext 객체 생성: 요청 시간, URI, 메서드, 사용자 ID 등 포함
  • RequestLogContextHolder: ThreadLocal 기반으로 요청별 Context 보관
  • LoggingUtils: ObjectMapper를 이용해 args/response를 JSON으로 출력
  • AdminApiLoggingAspect → LoggingUtils 호출만 하도록 리팩토링
  • AdminLoggingInterceptor → Context만 set/clear

✅ 3. 해결 완료

3-1. 회고

  • 로깅 책임이 명확하게 분리되어 가독성, 유지보수성이 크게 향상
  • Interceptor는 "데이터 수집", AOP는 "흐름 제어", LoggingUtils는 "로깅 처리"라는 역할 구분이 생김
  • ObjectMapper가 한 곳으로 모여 JSON 직렬화 예외 처리도 쉬워짐

3-2. 전후 비교

항목개선 전개선 후
로그 출력 위치여러 클래스 직접 log.infoLoggingUtils 단일 진입점
중복 포맷 로직O (Interceptor + AOP 중복)X
테스트 가능성낮음LoggingUtils 단위 테스트 가능
확장성 (DB 저장 등)어려움LoggingUtils 확장 가능

📌 참고 로그 예시

🟡 [REQUEST] [2025-04-19T16:29:58.572894] DELETE /admin/comments/2, userId=1, role=ADMIN, body=[2]
🟢 [RESPONSE] [2025-04-19T16:29:58.572894] DELETE /admin/comments/2, userId=1, result=null

profile
개발자 희망생

0개의 댓글