이 글에서는 Spring Boot 전역 로그 관리와 예외 로그 설계 방법을 중심으로, 프레임워크 수준에서의 효율적인 로깅 체계 구축 방안과 실무 중심의 예외 처리 아키텍처를 상세히 안내해 드리겠습니다.
01. Spring Boot 로깅 프레임워크의 기본 구조
Spring Boot는 기본적으로 강력한 로깅 설정을 내장하고 있어 체계적인 로그 수집이 용이합니다.✓ 확인할 점
- 기본 로깅 구현체: Spring Boot는
SLF4J(Simple Logging Facade for Java)를 추상화 레이어로 사용하며, 내부 구현체로는Logback을 기본 채택하고 있습니다. - 설정 파일 위치: 단순한 레벨 설정은
application.yml또는application.properties에서 가능하며, 세부적인 파일 Rotation 및 템플릿 설정은logback-spring.xml파일을 사용합니다.
YAML
# application.yml 예시
logging:
level:
root: INFO
com.example.demo: DEBUG
file:
name: logs/application.log
02. spring 로그레벨 설정 및 프로필별 분리 전략
운영 환경에 따라 출력할 로그의 상세 정도를 다르게 구성해야 시스템 자원을 절약하고 보안 위험을 줄일 수 있습니다.✓ 주요 로그 레벨
- TRACE: 가장 상세한 정보로, 개발 단계에서 추적용으로 사용됩니다.
- DEBUG: 개발 환경의 문제 해결을 위해 유용한 상세 정보입니다.
- INFO: 일반적인 운영 정보(상태 변경, 시스템 시작/종료 등)를 나타냅니다.
- WARN: 당장 장애로 이어지지는 않으나 주의가 필요한 경고 메시지입니다.
- ERROR: 시스템 동작에 영향을 주는 예외 및 오류 상황입니다.
| 환경 (Profile) | 권장 Root 레벨 | 비즈니스 패키지 레벨 | 비고 |
| Local / Dev | INFO | DEBUG | 빠른 문제 해결을 위해 디버그 로그 활성화 |
| Staging | INFO | INFO | 운영 환경과 유사하게 설정하여 흐름 검증 |
| Production | WARN 또는 INFO | INFO | Disk I/O 과다 발생 방지 및 보안 강화 |
logback-spring.xml 내의 <springProfile> 태그를 이용하면 개발 환경에서는 콘솔 중심으로, 운영 환경에서는 파일/외부 로그 수집기 중심으로 유연하게 전환할 수 있습니다.03. @ControllerAdvice를 활용한 전역 예외 로그 설계
시스템 전역에서 발생하는 예외를 한곳에서 수집하고 규격화된 형태로 처리하는 것은 예외 로그 설계의 핵심입니다.✓ 설계 핵심 요소
- 규격화된 응답 객체(ErrorResponse): 클라이언트에 내부 스택 트레이스(Stack Trace)가 직접 노출되지 않도록 표준화된 에러 구조를 정의합니다.
- 전역 예외 핸들러(@RestControllerAdvice): Controller 계층에서 발생하는 모든 예외를 포착하여 일관된 로그를 기록합니다.
Java
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
// 비즈니스 예외 처리
@ExceptionHandler(CustomBusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(CustomBusinessException e) {
log.warn("Business Exception Occurred: {}", e.getMessage());
ErrorResponse response = ErrorResponse.of(e.getErrorCode());
return new ResponseEntity<>(response, e.getErrorCode().getStatus());
}
// 예상치 못한 알 수 없는 예외 처리
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleUnexpectedException(Exception e) {
log.error("Unhandled System Exception!", e);
ErrorResponse response = ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR);
return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
- 로그 레벨 분리 적용: 클라이언트의 잘못된 요청(예:
400 Bad Request,404 Not Found)이나 비즈니스 예외는WARN또는INFO레벨로 기록하여 로그 폭증을 막고, 서버 내부 오류(500 Internal Server Error)는ERROR레벨과 함께 스택 트레이스를 기록하여 즉시 인지할 수 있도록 합니다.
04. MDC(Mapped Diagnostic Context) 기반 다중 요청 추적
동시 요청이 다수 발생하는 웹 애플리케이션 특성상, 동일한 사용자의 요청 흐름을 식별하는 것은 매우 중요합니다.✓ MDC 구현 전략
- Trace ID 부여: 서블릿 필터(Filter)나 인터셉터(Interceptor)에서 요청이 들어올 때 난수 형태의
Trace ID를 생성하고 MDC에 저장합니다. - 로그 패턴에 포함:
logback-spring.xml의 로그 패턴에 MDC 키값을 등록하면, 모든 로그 줄마다 Trace ID가 함께 기록됩니다. - MDC 자원 해제: 요청 처리가 끝난 후
MDC.clear()를 호출해야 멀티스레드 환경(Thread Local)에서 이전 요청의 정보가 남는 메모리 누수 및 정보 오염 현상을 방지할 수 있습니다.
FAQ
Q1. logback-spring.xml과 application.yml 중 어느 곳에 로그 설정을 해야 하나요?A1. 간단한 로그 레벨 변경이나 파일명 지정은application.yml로 충분합니다. 하지만 로그 파일의 일별 Rotation, 압축 보관 정책, MDC 패턴 적용 등 세부적인 로깅 기능을 활용하려면 logback-spring.xml을 사용하는 것이 권장됩니다.Q2. 예외 로그 기록 시 log.error("...", e)와 log.error("...", e.getMessage()) 중 무엇을 써야 하나요?A2. System Error 수준의 예외는 반드시 예외 객체 자체(
e)를 넘겨 전체 스택 트레이스가 출력되도록 해야 원인 분석이 가능합니다. 단순히 e.getMessage()만 출력하면 에러가 발생한 위치와 상세 원인을 추적할 수 없습니다.Q3. 운영 환경에서 System.out.println을 사용하면 안 되는 이유는 무엇인가요?A3.
System.out.println은 동기식(Synchronous)으로 동작하며 I/O 병목을 유발하여 애플리케이션 전체 성능을 심각하게 저하시킵니다. 반면, Logback과 같은 로깅 라이브러리는 비동기(Asynchronous) 어펜더 및 버퍼링을 지원하여 시스템에 미치는 영향을 최소화합니다.