개발 메모장

[Java] 로그 구성하기 - Slf4j(logback, Log4j ...) 본문

Java

[Java] 로그 구성하기 - Slf4j(logback, Log4j ...)

yyyyMMdd 2023. 12. 19. 17:06
728x90

#. 개발하는 단계에서부터 시스템을 다룰 때까지 로그를 찍어보는 일은 무수히 많을 것입니다.

 

#. 이때 대부분 간단한 것들에 대해선 System.out.print 와 같은 자체 클래스를 이용해 로그를 확인하고 있을 것입니다.

 

#. 그러나 시스템이 운영에 배포된 후엔 사용자의 양에 따라 로그를 볼 수 없는 지경에 이를 수 있습니다.

 

#. 이럴 땐 로그에 대한 기록이 필요한 데 이때 사용하였으니 참고해 주시길 바랍니다.

 


#. Slf4j 란 무엇인가?

    - 다양한 Java 로깅 프레임워크에 대한 추상화 계층이라고 생각하면 좋을 듯합니다.

    - 로깅 작업을 위한 공통 I/F를 제공하여 개발자가 특정 로깅 구현에 바인딩하지 않고도 코드에 로그문을 작성하게끔 도와줍니다.

    - logback, Log4j, java.util.logging 등과 같은 기본 로깅 프레임워크 간 브리지 역할을 함으로써 일관성을 유지시키게 하는 통합 API입니다.

    - 다양한 수준에서 메시지를 기록하는 메서드가 포함되어 필요에 따라 사용하여 로그를 남길 수 있습니다.

    - 매개변수화된 로깅을 지원하여 아래와 같이 문자열 연결을 줄여 성능이 더 뛰어납니다.

String name = "kim";
int age = 30;
logger.info("User {} is {} years old.", name, age);
// System.out.println("User" + name + " is " + age + " years old.");

 


#. Slf4j의 이점

    1. 코드의 변경 없이 다양한 로깅 프레임워크 간 쉬운 전환을 도와주는 유연성

    2. 로깅 구현과 통합되어 사용이 가능케 하는 호환성

    3. 다양한 로깅 프레임워크 전반에 걸쳐 일관된 로깅 API를 제공하는 일관성

 


#. 로깅 수준

    - ERROR > WARN > INFO > DEBUG > TRACE 순으로 중요도를 정의하고 있습니다.

    - ERROR : 애플리케이션의 오류나 예외상황을 기록하는 데 사용합니다.

    - WARN : 주의가 필요할 수 있으나 심각한 오류는 아닌 잠재적 문제나 상황을 나타냅니다.

    - INFO : 애플리케이션의 상태나 중요 이벤트를 나타내는 정보 메시지로 사용합니다.

    - DEBUG : 애플리케이션 동작을 디버깅할 때 도움이 되는 자세한 정보를 제공하기 위해 사용합니다.

    - TRACE : 일반적인 디버깅 목적으로 사용 시 유용하며 매우 자세한 정보를 제공합니다.

 

    - 특정 수준에서 기록된 메시지는 계층 구조 모든 상위 수준에서도 기록됩니다.
      (로그레벨을 INFO로 설정 시 INFO, WARN, ERROR 레벨의 메시지는 기록되고 TRACE, DEBUG는 생략됩니다.)

    - 로깅 프레임워크에 따라 명칭이 다르거나 추가되는 것이 있으나 수준은 동일합니다.

 


 

#. 로깅 수준 설정

 

    - 로깅 프레임워크에 따라 구성파일을 다르게 지칭하며 보통 log4j의 경우 log4j.xml 또는 log4j.properties로, Logback의 경우 logback.xml을, JUL(java.util.logging)의 경우 logging.properties에서 처리합니다.

    - xml 파일에서의 예는 아래와 같습니다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <!-- 콘솔 -->
    <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
    	<!-- 패턴 설정.. -->
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}] [%c{1}:%L] [%p] %m %n"/>
        </layout>
    </appender>
    
    <!-- 파일 -->
    <appender name="file" class="org.apache.log4j.FileAppender">
        <!-- 경로 설정 -->
        <param name="File" value="logs/myapp.log"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}] [%c{1}:%L] [%p] %m %n"/>
        </layout>
	</appender>
    
    <root>
        <level value="DEBUG"/>
        <appender-ref ref="stdout"/>
        <appender-ref ref="file"/>
    </root>
</log4j:configuration>

 


    - application.properties에서 처리하는 경우는 아래와 같습니다.

logging.level.root = warn
logging.file.name=C:/Users/user/Pictures/logs/myapp.log

 


#. 사용방법

 

    - Slf4j - LoggerFactory

import ch.qos.logback.classic.Logger;
import org.slf4j.LoggerFactory;

public class test {
    private static final Logger logger = LoggerFactory.getLogger(test.class);
    
    public void test() {
        logger.trace("trace");
        logger.debug("debug");
        logger.info("info");
	logger.warn("warn");
	logger.error("error");
    }
}

 


    - log4j - LogManager

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class test {
    private static final Logger logger = LogManager.getLogger(test.class);
    
    public void test() {
        logger.trace("trace");
        logger.debug("debug");
        logger.info("info");
	logger.warn("warn");
        logger.error("error");
        logger.fatal("fatal");
    }
}

 


    - java.util.logging - Logger

import java.util.logging.Logger;

public class test {
    private static final Logger logger2 = Logger.getLogger(test.class.getName());
    
    public void test() {
        logger.finer("finer"); 		// debug
        logger.fine("fine");		// debug
        logger.config("config");	// info
	logger.info("info");		// info
        logger.warning("warning");	// warn
        logger.severe("severe");	// error
    }
}

 


#. 한마디로 Slf4j는 로거에 대한 추상체로 log4j, logback 등 구현체와 바인딩되어 구현된다고 보면 되겠습니다.

 

#. 추가로 롬복에서 제공하는 @Slf4j를 클래스에 추가하면 쉽게 사용이 가능합니다.

 

#. 참고로 2021년 11월 log4j 보안 취약점 발견으로 현재는 사용하지 않는 편이며, 이를 대체하기 위해 나온 logback이나 log4j2를 사용하는 것이 보안상 더 좋을 것입니다.

 

 

 

===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!

===========================================================

 

 

 

728x90