박서희연구소

log4j vs. logback vs. log4j2 본문

○ Programming [Web]/Library

log4j vs. logback vs. log4j2

SEOHUI PARK 2021. 5. 6. 19:00
반응형

[문제]

백엔드 개발 시, 로깅은 굉장히 중요하다.

다양한 Java Logging Framework 가 있고, 이들이 가지고 있는 특징과 역사가 다르다.

[목표]

Java Loggin Frameworklog4j, logback, log4j2 의 특징과 역사를 알아보고 비교해본다. 

[해결]

생산적 문제를 분석해야 한다면, 좋은 로깅을 유지해야 하는 것이 얼마나 중요한지 알고 있을 것이다.

좋은 로깅은 다음 3가지의 것들이 요구된다.

 

  1. 로그 메시지는 애플리케이션 내부적으로 수행하는 작업을 이해하는데 필요한 정보를 제공해야 한다.
  2. 로그 메시지 작성은 애플리케이션의 성능에 영향을 주지 않도록 최대한 효율적이어야 한다.
  3. 다른 배포 환경과 상황에 맞게 상세한 로깅 정보를 조정할 수 있어야 한다.

각각의 사용 사례에 따라 어떤 로그 메시지를 작성해야하는지 스스로 결정을 해야 하는 문제지만, 적어도 요구사항 2번과 3번 문제에 대해 걱정할 필요는 없다.

다양한 Logging framework 들이 이미 기술적인 요구사항을 해결했기 때문이다.

그것들 중 하나를 선택하고 사용해서, 로그 메시지를 작성하면 된다.

 

더 좋은 로깅을 위해, SLF4J 는 이런 프레임워크 대부분에서 어떤 방식으로든 구현되는 표준화된 API 를 제공한다.

이 API 를 통해 코드를 바꾸는 것 없이 로깅 프레임워크를 변경할 수 있다.

유일하게 필요로 하는 것은, SLF4J 인터페이스를 구현하는 다른 프레임워크로 종속성을 바꾸는 것이다.

 

SLF4J 를 사용해 로그 메시지를 작성하기

SLF4J 를 사용해 로그 메시지를 작성하는 것은 매우 쉽다.

먼저 LoggerFactory 에서 getLogger 메서드를 호출하여 새 Logger 객체를 인스턴스화 한다.

Logger 에서 fatal 또는 error, warning, info, debug 등의 메서드 중 하나를 호출해, 해당 로그 레벨의 로그 메시지를 작성할 수 있다.

public class MyClass { 
    Logger log = LoggerFactory.getLogger(this.getClass().getName());
 
    public void myMethod() { 
        log.info("This is an info message"); 
        // ... 
    } 
}

만일 이 프레임워크를 쉽게 교체할 수 있다면, 어떤 프레임워크를 선택해야 할까?

 

이 질문에 대한 답은 예상만큼 쉽지 않다는 것이다.

이 글에서는 Log4J 와 그의 두 가지 후속 Log4j2Logback 에 대해서 소개할 것이다. 

 

Apache Log4j

Apach Log4j 는 매우 오래된 로깅 프레임워크이고 수년간 가장 인기있었으며,

최신 로깅 프레임워크에서 여전히 사용하는 계층적 로그 레벨과 로거와 같은 기본 개념을 도입했다.

 

Log4j 의 개발팀은 2015년을 끝으로 Log4j 단종을 발표했다.

많은 레거시 프로젝트에서 이를 사용하지만, 새 프로젝트를 시작한다면, 이 글에서 논의한 다른 프레임워크 중 하나를 선호해야 한다.

 

Logback 및 Log4j2 에 대해 이야기하기 전에 필요한 종속성 및 구성을 간략하게 살펴보자.

 

필요한 종속성

애플리케이션에 Log4j 사용을 원한다면, log4j.jar 파일을 클래스 경로에 추가해야 한다.

아래 코드에서 필수 Maven 종속성을 확인하라.

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

Log4j 는 기본적으로 SLF4J 를 지원하지 않는다.

표준화된 인터페이스를 통해 Log4j 를 사용하려면 다음 종속성도 추가해야 한다.

<dependency> 
    <groupId>org.slf4j</groupId> 
    <artifactId>slf4j-log4j12</artifactId> 
    <scope>test</scope> 
</dependency>

 

Log4j 설정

log4j.jar 파일 외에도, log4j.properties 파일 에서 로그 레벨로 appender 및 로거를 정의해야 한다.

이 appender 는 파일 또는 데이터베이스 같은 대상에 로그 메시지를 작성한다.

로거와 레벨은 로그 파일 작성에서 로그 메시지의 단위를 정의한다.

 

다음 코드 스니펫은 Hibernate 를 객체 관계형 매퍼로 사용하는 애플리케이션 개발 시스템에 대한 일반적인 Log4j 구성을 보여준다.

모든 로그 메시지를 app.log 파일에 쓰고 일반 로그 수준을 INFO 로 설정한다.

이 구성은 로거 org.hibernate.SQL 의 로그 수준을 DEBUG 로 설정하고 org.hibernate.type.descriptor.sql 범주를 TRACE 로 설정한다.

이 구성은 실행된 SQL 문과 해당 bind 매개 변수 값을 구성된 파일 appender 에 쓰는 Hibernate 의 로거 중 2가지를 사용했다.

log4j.appender.file=org.apache.log4j.FileAppender 
log4j.appender.file.File=app.log 
log4j.appender.file.layout=org.apache.log4j.PatternLayout 
log4j.appender.file.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] - %m%n 

log4j.rootLogger=info, file 
# basic log level for all messages 
log4j.logger.org.hibernate=info 

# SQL statements and parameters 
log4j.logger.org.hibernate.SQL=debug 
log4j.logger.org.hibernate.type.descriptor.sql=trace

이 구성을 기반으로 SLF4J API 를 사용하여 로그 메시지를 작성할 수 있다.

자세한 내용은 Matt Watson 의 Ultimate Log4j Tutorial 을 참고하라.

 

Logback

LogbackLog4j 를 구현한 같은 개발자가 작성했다.

Log4j 와 동일한 개념을 따르지만 성능을 개선하고 SLF4J 를 기본적으로 지원하며, 고급 필터링 옵션 및 로깅 구성의 자동 리로딩과 같은 여러 다른 개선 사항을 구현하기 위해 다시 작성되었다.

 

이 프레임워크는 3가지 파트로 구성된다.

 

  1. logback-core
  2. logback-classic
  3. logback-access

Logback-core 는 로깅 프레임워크의 핵심 기능을 제공한다.

Logback-classic 은 핵심 기능에 더 많은 기능을 추가한다.(예 : SLF4J 에 대한 기본 지원)

Logback-access 는 HTTP 엑세스 로그를 작성하는데 사용할 수 있도록 서블릿 컨테이너와 통합한다.

 

필요한 종속성

logback-classic 에 대한 종속성만 정의하면 된다. 이는 logback-core 및 SLF4J API 에 대한 종속성을 전이적으로 포함한다.

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

 

Logback 구성

Logback 은 구성이 필요하지 않다.

기본적으로 DEBUG 수준 이상의 모든 로그 메시지를 표준 출력에 기록한다.

XML 또는 Groovy 형식의 사용자 지정 구성 파일을 사용하여 변경할 수 있다.

 

Logback 은 Log4j 와 동일한 개념을 사용한다.

따라서 다른 파일 형식을 사용하더라도 구성이 매우 유사하다는 것에 그리 놀라지 않아도 된다.

다음 코드 스니펫은 Log4j 에서 사용한 것과 동일한 구성을 보여준다.

<configuration> 
    <appender name="FILE" class="ch.qos.logback.core.FileAppender"> 
        <file>app.log</file> 
        <encoder> 
            <pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern> 
        </encoder> 
    </appender> 
    <logger name="org.hibernate.SQL" level="DEBUG" /> 
    <logger name="org.hibernate.type.descriptor.sql" level="TRACE" /> 
    <root level="info"> 
        <appender-ref ref="FILE" /> 
    </root> 
</configuration>

필수 종속성을 추가하고 Logback 을 구성한 후 이를 사용하여 SLF4J API 를 통해 로그 메시지를 작성할 수 있다.

따라서 Logback 에서 제공하는 개선 사항을 활용하려면 Log4j 를 Logback 으로 대체하기 위해 코드를 변경할 필요가 없다.

 

Apache Log4j2

Apache Log4j2 는 이 세 가지 프레임워크 중에 가장 최근에 나온 프레임워크이며, 목표는 Logback 에 포함된 일부 개선 사항을 포함하여 Log4j 에 자체 개선 사항을 제공하고, Log4j 및 Logback 의 문제를 방지하여 두 프레임워크를 모두 개선하는 것이다.

 

따라서 Logback 과 마찬가지로 Log4j2 는 SLF4J 에 대한 지원을 제공하며, 로깅 구성을 자동으로 다시 로드하며 고급 필터링 옵션을 지원한다.

이러한 기능 외에도 람다 표현식을 기반으로 로그 statement 를 lazy evaluation 할 수 있고, 지연 시간이 짧은 시스템을 위한 비동기 로거를 제공하며, garbage collector 작업으로 인한 지연을 방지하기 위해 garbage 가 없는 모드를 제공한다.

 

필요한 종속성

Log4j 는 API 와 구현을 두 개의 개별 jar 파일로 패키지화 한다.

log4j-api.jar 를 사용하여 애플리케이션을 구현하고 빌드할 수 있으며, 런타임에 추가적인 log4j-core.jar 를 제공해야 한다.

SLF4J API 를 사용하려면, 두 API 간의 브리지를 포함하는 log4j-slf4j-impl.jar 파일도 필요하다.

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.15.0</version>
</dependency>

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.15.0</version>
</dependency>

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.15.0</version>
    <scope>test</scope>
</dependency>

 

Log4j2 구성

Log4j2 의 구성은 이전의 두 로깅 프레임워크 구성과 동일한 원칙을 따르므로 매우 비슷해 보인다.

<Configuration status="info"> 
    <Appenders> 
        <File name="FILE" fileName="app.log"> 
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> 
        </File> 
    </Appenders> 
    <Loggers> 
        <Logger name="org.hibernate.SQL" level="DEBUG"> 
            <AppenderRef ref="FILE"/> 
        </Logger> 
        <Logger name="org.hibernate.type.descriptor.sql" level="TRACE"> 
            <AppenderRef ref="FILE"/> 
        </Logger> 
        <Root level="info"> 
            <AppenderRef ref="FILE"/> 
        </Root> 
    </Loggers> 
</Configuration>

 

결론

Log4j, Logback 및 Log4j2 는 널리 사용되는 좋은 로깅 프레임워크다. 그렇다면 어느 것을 사용해야 할까?

 

나의 추천은 Log4j2 이다. 세 가지 프레임워크 중 가장 빠르고 가장 진보된 프레임워크이다.

하지만 성능이 최우선 순위가 아니라면 Logback 은 여전히 좋은 옵션이다. 

 

- 끝 - 

 

이 글은 https://stackify.com/compare-java-logging-frameworks/ 를 학습하고 작성하였다.

반응형
Comments