1. 로그 레벨이란?
로그 레벨은 “이 로그가 얼마나 상세하거나, 얼마나 심각한지”를 구분하는 기준이다.
보통 아래 순서로 많이 설명한다.
TRACE
DEBUG
INFO
WARN
ERROR
그리고 일부 로깅 프레임워크에서는 여기에 FATAL까지 포함해 설명하기도 한다.
다만 이 부분은 프레임워크마다 다르다.
Logback은 공식적으로 ERROR, WARN, INFO, DEBUG, TRACE를 기본 레벨로 정의한다. [1]
반면 Log4j 2는 FATAL, ERROR, WARN, INFO, DEBUG, TRACE를 기본 레벨로 둔다. [2]
즉, 아래처럼 이해하는 것이 정확하다.
Spring Boot 기본(Logback) = TRACE, DEBUG, INFO, WARN, ERROR
Log4j 계열 설명까지 넓게 포함 = TRACE, DEBUG, INFO, WARN, ERROR, FATAL
2. 레벨은 어떤 방향으로 심각해질까?
일반적으로 아래로 갈수록 더 심각한 로그라고 보면 된다.
TRACE -> DEBUG -> INFO -> WARN -> ERROR -> FATAL
Log4j 2 공식 문서는 FATAL이 애플리케이션이 계속 실행될 수 없게 만드는 치명적 이벤트라고 설명하고, ERROR는 복구 가능할 수도 있는 오류라고 설명한다. [2]
Logback 공식 문서는 TRACE가 가장 세밀하고, ERROR가 가장 높은 기본 레벨이라고 정의한다. [1]
즉, 프레임워크 차이를 빼고 의미만 보면,
- 위쪽 레벨일수록 더 자세한 개발용 로그
- 아래쪽 레벨일수록 더 심각한 운영 이슈 로그
라고 이해하면 된다.
3. TRACE
추적
TRACE는 가장 상세한 수준의 로그이다.
코드가 어떤 순서로 실행되는지, 메서드 내부에서 어떤 분기와 경로를 타는지까지 세밀하게 남길 때 사용한다.
Logback 공식 문서는 TRACE를 가장 세밀한 정보를 담는 레벨로 둔다. [1]
실무에서는 보통 상시로 켜두지 않는다. 이유는 아래와 같다.
- 로그 양이 너무 많아진다.
- 저장 비용이 커진다.
- 필요한 핵심 정보가 다른 로그에 묻힐 수 있다.
즉, TRACE는 특정 문제를 짧은 시간 동안 추적할 때 일시적으로 켜는 용도로 이해하면 된다.
4. DEBUG
디버그
DEBUG는 시스템의 동작 상태를 상세하게 기록하는 레벨이다.
예를 들어 아래 같은 정보가 여기에 들어간다.
- 주요 변수 값
- 외부 API 요청/응답 요약
- 분기 진입 여부
- SQL 실행 전후 상태
- 버그 분석에 필요한 내부 상태
Log4j 2 공식 API 문서는 DEBUG를 일반적인 디버깅 이벤트라고 설명한다. [2]
주로 개발 환경이나 테스트 환경에서 많이 켜두고, 운영 환경에서는 로그 양 때문에 제한적으로 사용하는 경우가 많다.
5. INFO
정보
INFO는 시스템이 예상한 흐름대로 작동하고 있음을 보여주는 기본 로그이다.
예를 들어 아래 같은 경우가 INFO에 해당한다.
- 서버 시작 완료
- 사용자 로그인 성공
- 배치 작업 시작/종료
- 주요 비즈니스 이벤트 처리 완료
Log4j 2 공식 API 문서는 INFO를 정보 제공 목적의 이벤트라고 설명한다. [2]
운영 환경에서는 보통 INFO를 기본 레벨로 두는 경우가 많다.
어떤 레벨로 찍어야 할지 애매하다면 INFO를 우선 고려할 수는 있다.
다만 너무 자주 찍으면 중요한 정보가 묻히므로 남발하면 안 된다.
즉, INFO는 “운영에서 기본적으로 볼 가치가 있는 정상 흐름” 정도로 이해하면 된다.
6. WARN
경고
WARN은 지금 당장 장애는 아니지만, 문제가 될 가능성이 있는 상황을 남기는 레벨이다.
Log4j 2 공식 API 문서는 WARN을 오류로 이어질 수 있는 이벤트라고 설명한다. [2]
예를 들어 아래 같은 상황이 WARN에 해당할 수 있다.
- 외부 API 응답 속도가 계속 느려지는 상황
- 재시도가 여러 번 발생한 상황
- 예상보다 큰 데이터가 반복적으로 들어오는 상황
- 만료 예정 설정이나 deprecated 기능 사용
즉, WARN은 “아직 시스템이 멈추진 않았지만 계속 두면 나중에 문제가 될 수 있다”는 신호다.
7. ERROR
에러
ERROR는 특정 요청이나 기능이 정상적으로 처리되지 못한 상황을 뜻한다.
Log4j 2 공식 API 문서는 ERROR를 애플리케이션의 오류이며, 경우에 따라 복구 가능할 수도 있다고 설명한다. [2]
예를 들어 아래 같은 상황이 ERROR에 해당한다.
- DB 저장 실패
- 결제 API 호출 실패
- 파일 업로드 중 예외 발생
- 메시지 처리 중 비즈니스 예외 발생
중요한 점은 ERROR가 곧 “시스템 전체 다운”을 뜻하는 것은 아니라는 점이다.
일부 요청 실패, 일부 기능 오류도 ERROR가 될 수 있다.
즉, ERROR는 “사용자 요청 또는 내부 작업 하나 이상이 정상 완료되지 못했다”는 의미로 보면 된다.
8. FATAL
치명적 오류
FATAL은 모든 프레임워크에 공통으로 있는 기본 레벨은 아니다.
이 점이 가장 중요하다.
Log4j 2는 FATAL을 공식 레벨로 제공하고, 이를 “애플리케이션이 계속 실행될 수 없게 만드는 치명적 이벤트”라고 설명한다. [2]
반면 Logback은 기본 레벨 집합에 FATAL이 없다. [1]
즉, Spring Boot 기본 로깅(Logback) 기준으로는 보통 아래 5개만 기본으로 본다.
TRACE, DEBUG, INFO, WARN, ERROR
그리고 FATAL은 아래처럼 이해하면 된다.
- Log4j 계열에서는 별도 치명적 레벨로 사용 가능
- Logback 기반 애플리케이션에서는 보통
ERROR로 기록하거나 별도 알림 체계를 붙여 처리
예시로는 아래 같은 상황이 FATAL에 가깝다.
- 애플리케이션이 더 이상 부팅되지 못하는 상태
- 필수 인프라 장애로 서비스 전체 지속이 불가능한 상태
- 메모리 부족 등으로 프로세스가 사실상 계속 살아 있을 수 없는 상태
즉, FATAL은 “치명적 장애”라는 개념 설명으로는 유용하지만, Spring Boot 기본 환경에서는 실제 코드 레벨에서 항상 직접 쓰는 로그 레벨이라고 보면 안 된다.
9. 실무에서는 어떻게 구분하면 될까?
입문 단계에서는 아래 정도로 나누면 충분하다.
| 레벨 | 언제 쓰는가 |
|---|---|
TRACE |
아주 세밀한 실행 경로 추적이 필요할 때 |
DEBUG |
개발 중 변수 값, 내부 상태, 디버깅 정보 확인 |
INFO |
정상적인 주요 흐름 기록 |
WARN |
아직 장애는 아니지만 주의가 필요한 상황 |
ERROR |
요청이나 기능 처리 실패 |
FATAL |
프레임워크에 따라 제공되면 시스템 지속이 어려운 치명적 장애 |
이때 중요한 것은 로그를 “많이 찍는 것”이 아니라 “구분이 되게 찍는 것”이다.
예를 들어 모든 로그를 INFO로만 남기면
- 정상 로그와 장애 로그가 뒤섞이고,
- 운영자가 중요한 문제를 빨리 찾기 어려워지고,
- 알림 정책을 레벨별로 나누기도 어려워진다.
그래서 레벨을 구분해서 찍는 습관이 중요하다.
정리
로그 레벨은 로그의 상세도와 심각도를 구분하기 위한 기준이다.
핵심만 정리하면 아래와 같다.
- Spring Boot 기본 Logback에서는
TRACE,DEBUG,INFO,WARN,ERROR를 기본 레벨로 본다. - Log4j 계열까지 포함하면
FATAL도 별도 레벨로 사용된다. TRACE와DEBUG는 개발/추적용 성격이 강하다.INFO는 운영에서 보는 기본 정상 흐름 로그다.WARN은 잠재적 문제,ERROR는 실제 실패를 의미한다.FATAL은 프레임워크에 따라 존재 여부가 다르므로 개념과 구현을 구분해서 이해해야 한다.
즉, 로그 레벨을 잘 구분해두면 개발 중 디버깅도 쉬워지고, 운영 중 장애 대응도 훨씬 수월해진다.
출처
- Logback API, “Level”, https://logback.qos.ch/apidocs/ch.qos.logback.classic/ch/qos/logback/classic/Level.html
- Apache Log4j 2 API, “Level”, https://logging.apache.org/log4j/2.x/javadoc/log4j-api/org/apache/logging/log4j/Level.html
- Spring Boot Reference, “Logging”, https://docs.spring.io/spring-boot/reference/features/logging.html