노트

로그 레벨과 Logback

Log Levels and Logback

백엔드#spring · 연결된 개념 5개

쉽게 말하면

로그 레벨은 구멍 크기를 고를 수 있는 체 같아요. 평소엔 INFO 이상 굵직한 기록만 걸러 보고, 문제를 찾을 땐 구멍을 좁혀 DEBUG 같은 잔챙이까지 받죠. 코드를 고치지 않고 설정만 바꿔요.

비유의 한계 체에 붓기 전에 기록을 만드는 비용도 있어요. 그래서 문자열을 직접 이어 붙이지 않고 {} 자리표시자를 써야 꺼진 레벨에선 문자열을 아예 만들지 않아요. 비밀번호·토큰은 어떤 레벨에도 남기지 않아요.

스프링 부트는 로깅 퍼사드(logging facade) SLF4J(Simple Logging Facade for Java)와 구현체 Logback을 기본으로 쓴다. 코드는 SLF4J API로 로그를 남기고, 어떤 레벨을 어디에 어떤 형식으로 쓸지는 설정으로 정한다.

레벨

레벨용도
ERROR요청 실패 등 즉시 봐야 할 문제
WARN동작은 하지만 이상한 상황
INFO시작·종료·주요 업무 이벤트 (기본)
DEBUG개발 중 진단 정보
TRACE아주 세밀한 흐름

설정한 레벨과 그보다 심각한 레벨만 출력된다. 기본은 INFO라 DEBUG·TRACE는 나오지 않는다. FATAL은 Logback에 없고 ERROR로 다룬다.

설정

logging:
  level:
    root: INFO
    com.example.order: DEBUG
    org.hibernate.SQL: DEBUG        # 실행되는 SQL 보기
  group:
    web: org.springframework.web, org.springframework.security
  • 패키지별, 그룹별로 레벨을 다르게 준다. debug=true는 스프링 내부 로거 일부만 DEBUG로 올린다
  • 기본은 콘솔 출력만 한다. 파일은 logging.file.name이나 logback-spring.xml에서 롤링 정책(rolling policy: 날짜·크기별 분할, 보관 개수)을 정한다
  • 운영에서는 사람이 읽는 형식보다 JSON 구조화 로그(structured logging)가 수집·검색에 유리하다

코드에서

@Slf4j                                   // Lombok: private static final Logger log 생성
public class OrderService {
    void pay(Order o) {
        log.info("결제 요청 orderId={}", o.getId());   // 문자열 결합 대신 {} 자리표시자
        log.debug("상세 {}", o);                       // DEBUG가 꺼져 있으면 toString 호출 안 함
    }
}
  • {} 자리표시자(placeholder)는 레벨이 꺼져 있으면 문자열을 만들지 않는다
  • 예외는 마지막 인자로 넘겨야 스택 트레이스(stack trace)가 남는다: log.error("실패 orderId={}", id, e)
  • 비밀번호·토큰·개인정보는 로그에 남기지 않는다

예외를 잡고 로그만 남긴 채 넘어가는 실수는 예외 삼키기, 디버깅에서 로그의 역할은 디버깅 포켓 가이드 (개요)을 본다. @Slf4j는 Lombok이 만든다.

출처: Spring Boot 문서: Log Levels · Log Groups · File Rotation · Structured Logging

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • JDBC와 JdbcTemplate

    JDBC(Java Database Connectivity)는 자바가 여러 DB와 통신하기 위한 표준 API이고, Hibernate·MyBatis·스프링 JDBC 모두 그 위에 있다. JdbcTemplate은 스프링이 JDBC의 반복 작업(연결 열고 닫기, 예외 변환, 결과 순회)을 대신해 주는 클래스다.

  • 저장소 역할 분담 (DB·캐시·큐·검색)

    서버 애플리케이션 옆에는 거의 늘 관계형 DB, 인메모리 캐시, 메시지 브로커(message broker), 검색 엔진이 붙는다. 하나로 다 하지 않는 이유는 데이터의 성격(영구성·속도·전달·검색)마다 잘하는 도구가 다르기 때문이다.

  • 롱 태스크

    메인 스레드를 50ms 넘게 붙잡는 작업. W3C Long Tasks 명세는 이벤트 루프 태스크(뒤따르는 마이크로태스크 처리 포함), 렌더링 갱신 단계, 이벤트 루프 밖에서 브라우저가 UI 스레드로 하는 일 가운데 50ms를 넘는 것을 롱 태스크로 본다. 태스크는 도중에 끊기지 않으므로 그동안 클릭·키 입력 처리와 화면 갱신이 모두 밀린다(이벤트 루프).

  • 동기·비동기와 블로킹·논블로킹

    동기·비동기는 결과를 언제 어떻게 받느냐, 블로킹·논블로킹은 기다리는 동안 호출한 스레드가 멈추느냐의 문제다.

  • 낙관적 잠금과 비관적 잠금

    낙관적 잠금(Optimistic Locking)은 충돌이 드물다고 보고 읽을 때 잠그지 않는 동시성 제어 방식이다. 쓸 때 읽어 둔 버전(또는 타임스탬프)과 지금 값을 비교해, 그사이 다른 쪽이 바꿨으면 쓰기를 실패시킨다. 두 사용자가 같은 행을 읽고 차례로 저장해 먼저 저장한 변경이 사라지는 갱신 손실(lost update)을 막는다.

보기 옵션