본문 바로가기

Spring Boot

로깅 : SLF4J, Logback

SLF4J, LogBack

 

 - SLF4J, Logback이 무엇인가??? 구조와 역할은?

 - Spring에서의 로깅 설정법, 고급 설정법

 - 로그 레벨 정책, 출력패턴, 파일 롤링 설정 등의 Logback 설정

 

 

SLF4J (Simple Logging Facade for Java)

SLF4J는 다양한 로깅 프레임워크(log4j, Logback)에 대한 추상화 계층임

애플리케이션은 SLF4J API를 사용해서 로깅을 작성하고, 실제 로그 출력은 구현체(Logback, log4j 등등..)가 담당함

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggerClass {
	private static final Logger logger = LoggerFactory.getLogger(ExampleClass.class);
    
    public void doSomething() {
    	logger.debug("Debug message");
        logger.info("Info message");
        logger.warn("Warning message");
        logger.error("Error message");
    }
}

 

SLF4J를 사용한다는 의미는 이렇게 파일을 생성해서 끌어다 쓰는게 아니고,

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

이 두가지를 import 시키는게 핵심~ 처럼 보인다.

애너테이션은 @Slf4j 를 사용하며 이 애너테이션을 원하는 Service나 Controller의 클래스명 위에 써주면?

log.debug / log.info 이런 형태의 로그 메서드를 사용할 수 있게 된다.

 

요구사항의

Lombok의 @Slf4j 어노테이션을 활용해 로깅을 쉽게 추가할 수 있도록 구성하세요.

이 말은 위 클래스를 만들라는 말이 아니고, 말 그대로 애너테이션 @Slf4j 를 활용해서 로깅을 쉽게 추가할 수 있게 하라는 말임

 

 

Logback

Logback은 SLF4J의 대표적 구현체이다

 - 빠른 처리속도, 낮은 메모리 사용

 - 설정 파일 자동 감지, 재로딩 지원

 - 시간 기반 또는 용량 기반의 로그 파일 롤링 가능

 - 조건부 필터링 및 다양한 출력 패턴 제공

 

여기서 시간 기반 또는 용량 기반의 로그 파일 롤링이 가능하다는 말은,

// application-yaml 파일의 logging/pattern/console:
"%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %ms%n"

 

이런 식으로 파일을 저장할 수 있다는 것을 의미함

또한 요구사항에서는 보이지 않지만 로그 파일의 최대 용량또한 지정할 수 있다. 10MB나, 10GB나 뭐 등등..

 

SLF4J와 Logback의 관계에 대해서

애플리케이션 코드 - > SLF4J API - > Logback(구현체) - > 로그 출력

의 형태로 로그가 출력된다.

 - SLF4J는 단순히 인터페이스(API)를 제공함

 - Logback은 실제 로깅 동작을 수행하는 구현체이다

 - SLF4J가 인터페이스 형태이기 때문에 프레임워크 교체 시 애플리케이션 코드는 수정하지 않아도 된다.

 

 

Spring Boot의 로깅 설정에 대해

스프링부트는 기본적으로 spring-boot-starter-logging에 의해 Logback을 사용한다. gradle에 implementation해야하나 싶기도 하지만, 따로 설정하지 않아도 slf4j는 잘 import되는걸 봐서 설정은 안해줘도 되는것 같다..

 

다만 이건 꼭 해줘야한다고 함

application.properties는 사용하지 않지만 적어두긴 하겠다.

logging.level.root=INFO # 루트 로거 레벨 설정
logging.level.com.example.myapp=DEBUG # 특정 패키지의 로그 레벨 설정
logging.file.name = myapp.log # 로그파일 경로 및 이름 설정
logging.pattern.console = %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
# 콘솔 로그 출력 형식,
# {년}-{월}-{일} {시}:{분}:{초}:{밀리초} [{스레드명}] {로그 레벨(5글자로 맞춤)} {로거 이름(최대 36글자)} - {로그 메시지}{줄바꿈}
# 예시
# 25-01-01 10:33:55.740 [main] DEBUG c.s.m.discodeit.DiscodeitApplication - Running with Spring Boot v3.4.0, Spring v6.2.0

 

쓰고 보니까 application.properties나 application.yaml이나 폴더 찾는 방식은 같아보인다.

 

밑에껀 application.yml 예시

logging:
  level:
    root: INFO
      com.example.myapp: DEBUG
  file:
    name: myapp.log
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
# {년}-{월}-{일} {시}:{분}:{초}:{밀리초} [{스레드명}] {로그 레벨(5글자로 맞춤)} {로거 이름(최대 36글자)} - {로그 메시지}{줄바꿈}

 

console쪽의 정규식을 익히기 위해 두 - 번 적었다

 

이보다 세부적인 설정, 고급 설정을 하기 위해선 logback-spring.xml 파일을 사용해서 설정하면 된다.

XML 형식이라 조금 보기 힘들다는 단점이 있다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<include resource="org/springframework/boot/logging/logback/base.xml"/>
    
    <appender name = "FILE" class = "ch.qos.logback.core.rolling.RollingFileAppender">
    	<file>logs/myapp.log</file> <!-- 만약 logs폴더가 없으면 자동 생성인가? -->
        <rollingPolicy class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        	<fileNamePattern>logs.myapp.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 이름 패턴 -->
            <maxHistory>30</maxHistory> <!-- 로그 보관 기간 -->
        </rollingPolicy>
        <encoder>
        	<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <root level = "INFO"> <!-- root 레벨 -->
    	<appender-ref ref = "FILE"/>
    </root>
    
    <logger name = "com.example.myapp" level = "DEBUG" additivity = "false"> <!-- logger 레벨 -->
    	<appender-ref ref = "CONSOLE" />
        <appender-ref ref = "FILE" />
    </logger>
</configuration>

 

아~ 직접 적어보니까 뭔가 다가오는것 같기도~

 

 

Logback 기본 설정

@Slf4j 애너테이션을 달고 사용하는 log 이후의 메서드명들에 대해서.. 인가.. 로그레벨이라고 한다.

TRACE : 가장 세부적인 로깅, 상세한 디버깅 정보 (심각도 매우 낮음)

DEBUG : 디버깅용 정보, 개발할때 주로 씀

INFO : 정상적인 애플리케이션 흐름에 대한 정보를 출력하고 싶을 때 씀

WARN : 잠재적 문제 상황에 대한 경고

ERROR : 예외 및 심각한 오류 발생 시 (심각도 매우 높음, 애플리케이션 꺼짐)

 

로깅 커스터마이징, application.yml 파일에서 설정할 수 있다, 혹은 Logback 설정 파일을 사용할 수도 있다(XML 파일)

logging:
 level:
  root: INFO # 디폴트는 info
  com.example.myapp.controller: DEBUG # 특정 패키지 로그 레벨 설정은 이렇게
  org.hibernate: WARN # hibernate에 대한 로그 레벨 설정

 

 

로그 출력 패턴에 대해서

정규식을 잘 알고 있으면 매우 편하다~

%d : 날짜, 시간 패턴

%thread : 스레드 이름 패턴

%-5level : 로그 레벨 패턴, 5라고 붙었으니 5자 고정

%logger{36} : 로거 이름에 대한 패턴, 36이라고 했으니 최대 36자이다

%msg : 메시지 내용 패턴

%n : 줄바꿈

console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
# {년}-{월}-{일} {시}:{분}:{초}:{밀리초} [{스레드명}] {로그 레벨(5글자로 맞춤)} {로거 이름(최대 36글자)} - {로그 메시지}{줄바꿈}

이거임

 

 

파일 출력, 관리 정책에 대해

운영 환경에서는 로그를 파일로 저장하고 적절히 관리하는게 필수적이고 매우 중요한데,

Logback은 시간기반, 용량기반 등 롤링 정책을 제공하고 있다(Rolling Policy)

 

 

롤링 정책에 대해서

Rolling Policy는 로그 파일이 너무 커지거나 오래 저장되지 않도록 자동으로 분할(archive)하고, 오래된 로그를 삭제하거나 압축하는 관리전략을 말함

하나의 로그 파일을 봤을 때 막 1년짜리, 2년짜리를 들여다보면 찾기도 힘들고 보기도 힘들고.. 그쵸?

 - 로그 파일이 계속 하나의 파일에 쌓이면 수십 기가바이트까지 커질 수 있어서 매우 위험하기도 하고 관리도 참 힘들듯

 - 이로 인해 디스크 용량을 갉아먹거나, 로그 열람 속도가 매우 느릴 수 있음

 - 운영 환경에서는 오래된 로그를 일정 기간만 보관하고 자동으로 삭제하는게 일반적이라고 한다. 쪼개둔걸 한 1년~2년정도면 될듯

 

롤링 정책의 주요 유형

 - 시간 기반 롤링 : 하루, 한주, 한달 등 시간단위로 새로운 로그 파일을 생성함

 - 크기 기반 롤링 : 파일이 일정 크기(10MB 등)를 넘으면 새로운 로그 파일을 생성하게끔 구성

 - 시간 + 크기 기반 롤링 : 시간단위 + 크기 기준을 모두 만족할 때 파일을 분리하게끔 구성할수도 있음

 

보통 롤링정책은 XML파일에서 하는것 같다. yml파일이 아니에요~

 

시간 기반 롤링 파일 설정

<appender name = "FILE" class = "ch.qos.logback.core.rolling.RollingFileAppender">
	<file>logs/myapp.log</file>
    <rollingPolicy class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 롤링정책 -->
    	<fileNamePattern>logs/myapp.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 파일 이름 -->
        <maxHistory>30</maxHistory> <!-- 최대 30일 보관-->
    </rollingPolicy>
    <encoder>
    	<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

 

** fileNamePattern : 하루마다 logs/myapp.2025-08-12.log, logs/myapp.2025.08-13.log 처럼 새로운 파일이 생성됨

** maxHistory : 생성일로부터 30일이 지난 로그는 자동으로 삭제된다

 

크기 기반 + 시간 기반 롤링 설정

<appender name = "SIZE_FILE" class = "ch.qos.logback.cor.rolling.RollingFileAppender">
	<file>logs/myapp.log</file>
    <rollingPolicy class = "ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
    	<fileNamepattern>logs/myapp.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
        <maxFileSize>10MB</maxFileSize> <!-- 로그 파일 크기 -->
        <maxHistory>14</maxHistory> <!-- 14일 -->
    </rollingPolicy>
    <encoder>
    	<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

<fileNamepattern>logs/myapp.%d{yyyy-MM-dd}.%i.log</fileNamePattern> 에서

%i << 숫자가 들어감

이 %i는 maxFileSize에서 10MB라고 정해뒀으니 로그파일이 10MB를 초과하면 새롭게 로그 파일이 만들어지며 숫자가 갱신된다.

1, 2, 3, .. 이렇게..

 

* logback-spring.xml을 사용할때는 반드시 spring-boot에서 지원하는 <springProfile>을 활용해서 환경별 설정을 해야한다고 함

* 로그 파일은 /logs폴더를 만들고 외부로 분리해서 관리하면 운영 환경에서 모니터링 및 수집 도구와 연동하기 쉽다고 함

* 운영 환경에서는 로그 레벨은 INFO 또는 WARN으로, 개발 환경에서는 DEBUG로 설정하는게 일반적이다.

* 로그 메시지에는 절대로 민감한 정보를 포함해서는 안된다.

 

음.. 요구사항에 절대로 써먹어봐야겠지..