SLF4J 정리

SLF4J 는 실제 로깅을 수행하는 라이브러리가 아니라 다른 로깅 라이브러리(logj4j, logback)를 호출해서 로깅하는 중간 역할을 한다. 안써도 될 것 같은데 굳이 왜 쓰나?

뭐 딱히 그럴일은 없겠지만 요렇게 SLF4J의 org.slf4j.Logger를 사용했을 경우, 로깅 라이브러리를 변경하고 싶을때 기존 소스코드는 가만 냅두고 살짝 pom.xml 과 설정파일만 쫌 바꿔주면 쉽게 로깅 라이브러리를 교체할 수 있다.

요즘 log4j 가 업그레이드된 log4j2 가 뜬다고 함… 고럿다면 한번 써볼까 ‘ㅗ’? (예를들면 이런 경우?)

이것뿐 아니라 뭐 다른 이유도 많이 있겠지만…

package io.github.stove99.demo;

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

public class Demo {
    private static Logger log = LoggerFactory.getLogger(Demo.class);

    public static void main(String[] args) {
        log.debug("logging test : {}", "first log");
    }
}

시작

위 샘플은 org.slf4j.Logger 이런 클래스가 없어서 컴파일이 되지 않는다. 컴파일 하기 위해 pom.xml 에 일단 slf4j 메인인 slf4j-api 를 추가한 다음 위 샘플을 실행해 보자

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.26</version>
</dependency>

고러면 slf4j 가 사용할 실제 로깅 라이브러리가 없다면서 요런 에러가 난다.

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

고럿다면 이제 쪽바로 작동할 수 있도록 실제 로깅 라이브러리를 설정해 보자.

첫번째로 고전적인 log4j 를 로깅 라이브러리로 설정해 보기

먼저 실제 로깅을 수행할 라이브러리인 log4j 를 pom.xml 에 추가한다.

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

딸랑 요렇게만 추가해 주면 끝나는게 아니라 slf4j 가 log4j 를 호출할 수 있도록 연결해 주는 라이브러리(slf4j binding)가 필요하다. 요 바인딩은 실제 로그를 수행할 로깅 라이브러리에 따라 다르기 때문에 맞춰서 설정해 주면 된다.

※ 당연한 이야기 지만 slf4j binding 라이브러리는 하나만 써야 된다. log4j 와 logback 을 동시에 쓸 수 없지 않은가?

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.26</version>
</dependency>

요렇게 pom.xml 에 3가지 디펜던시를 추가하면 라이브러리 설정은 끝이고 log4j 설정 파일인 log4j.xml 파일을 classpath 루트에 폿 맹글어 준 다음 위 샘플을 실행하면 정상적으로 로그가 출력된다.

log4j.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="console" class="org.apache.log4j.ConsoleAppender">
         <layout class="org.apache.log4j.PatternLayout">
              <param name="ConversionPattern" value="%d %p [%c{5}] %m%n" />
         </layout>
    </appender>

    <root>
        <level value="DEBUG" />
        <appender-ref ref="console" />
    </root>
</log4j:configuration>

logback 을 로깅 라이브러리로 설정해 보기

slf4j 로 logback 을 사용해서 로깅하도록 하는 설정은 매우 쉽다.

pom.xml 에 logback-classic 만 딸랑 하나 추가해 주면된다.

고러면 slf4j-api 와 실제 로깅 라이브러리인 logback-core, slf4j binding 역할을 하는 logback-classic 이 세가지 라이브러리가 클래스패스에 추가된다.

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

logback.xml

<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
            </Pattern>
        </layout>
    </appender>

    <root level="debug">
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>

클래스패스 루트에 logback.xml 뽓 맨들어 준다음에 위 샘플을 실행해 보면 logback으로 출력되는 로그가 잘 찍힌다.

고러면 xxx-over-slf4 는 무엇임?

jcl-over-slf4j, log4j-over-slf4j 요런거를 pom.xml 파일에서 자주 볼 것이다.

죠것들은 기존 소스파일에서 org.apache.log4j.Logger 요렇게 사용하고 있던걸 소스 수정없이 slf4j 로 연결해 주기 위한 라이브러리 시리즈이다.

import org.apache.log4j.Logger;

private static Logger logger = Logger.getLogger(Main.class.getName());

내가 관리하는 소스야 싹 찾아서 slf4j 로 바꿔주면 되는데 가져다 쓰는 다른 라이브러리에서 log4j 를 사용해서 로깅처리를 하고 있다면 살짝 곤란해 진다. 고런 문제를 해결해주는 것이 xxx-over-slf4j 시리즈임.