티스토리 뷰

log4j는 한때 위용을 떨쳤던 강력한 logging framework였다. 하지만 세월이 흐르고 기술은 발전하여 더 나은 logging framework들이 등장했다. 성능적인 측면이나 기능적인 측면에 더욱 발전하여 전환은 선택이 아닌 필수가 되었다. 그중 springboot 공식 logging framework로 사용될만큼 인정을 받은 logback으로 전환을 하는 방법에 대해 알아보자. 더불어 다음부터는 쉽게 logging framework 전환을 쉽게 하기 위해 slf4j 를 사용하도록 하자. 


pom.xml library 변경

log4j

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

 

slf4j + logback

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

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

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>jcl-over-slf4j</artifactId>
  <version>1.7.25</version>
</dependency>

 

기존에는 log4j 라이브러리 하나만 필요했다면 slf4j+logback으로 전환을 하기 위해서는 3개의 라이브러리가 필수로 필요하다. logback-classic 은 logback, slf4j-ap는 slf4j, 그리고 jcl-over-slf4j는 이 두녀석을 연결해 주는 역할을 한다. 버전은 최신 버전으로 받아서 사용하면 된다. 


web.xml 변경

log4j

<context-param>
  <param-name>log4jConfigLocation</param-name>
  <param-value>classpath:config/log/log4j.xml</param-value>
</context-param>

<listener>
  <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

 

slf4j + logback

<context-param>
  <param-name>logbackConfigLocation</param-name>
  <param-value>classpath:config/log/logback.xml</param-value>
</context-param>

<listener>
  <listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
</listener>

 

web.xml 변경도 간단하다. log4j는 resources의 바로 하위에 이 파일들을 둘것이 아니라면 위처럼 지정하여 사용할 수 있다. log4j.xml 을 logback.xml 로 변경해주고 listener도 변경된 logback listener로 넣어준다. 


log 설정파일 변경

 

log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="true" 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][%13F:%L] %m%n" />
        </layout>
    </appender>
    <appender name="file" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="C:/sampleproject/sample.log" />
        <param name="Encoding" value="UTF-8" />
        <param name="DatePattern" value="'.'yyyy-MM-dd" />
        <param name="ImmediateFlush" value="true" />
        <param name="Append" value="true" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%d][%p] %m%n" />
        </layout>
    </appender>
    
    <logger name="org.springframework">
        <level value="info" />
        <appender-ref ref="file" />
        <appender-ref ref="console" />
    </logger>
     <logger name="sample">
        <level value="debug" />
        <appender-ref ref="file" />
        <appender-ref ref="console" />
    </logger>
    
    <root>
        <level value="info" />
    </root>
</log4j:configuration>

 

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">

  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>[%d{HH:mm:ss.SSS}][%-5level][%logger{36}.%method:line%line] - %msg%n</pattern>
    </encoder>
  </appender>
				
  <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>C:/sampleproject/sample.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>C:/sampleproject/sample.%d{yyyy-MM-dd}.log</fileNamePattern>
      <maxHistory>180</maxHistory>
    </rollingPolicy>
    <encoder>
      <pattern>[%d{HH:mm:ss.SSS}][%-5level][%logger.%method:line%line] - %msg%n</pattern>
    </encoder>
  </appender>	
					
  <logger name="org.springframework" level="info" additivity="false">
    <appender-ref ref="file" />
    <appender-ref ref="console" />
  </logger>
  <logger name="sample" level="debug" additivity="false">
    <appender-ref ref="file" />
    <appender-ref ref="console" />
  </logger>	
					
  <root level="info">
    <appender-ref ref="console" />
  </root>
				
</configuration>	

 

파일은 log4j.xml 파일은 없애고 logback.xml 파일을 추가시켜줘야한다. 세세한 패턴까지 다 동기화를 시키지는 않았다. 하지만 log4j의 설정 방법이 logback에서는 어떻게 변하는지 충분히 알수 있을것이다. 거의 동일한 용어로 쓰이지만 log4j의 layout은 logback에서는 pattern으로 변경이 되는것이 가장 큰 차이라고 할수 있다. 조금씩만 다를뿐 거의 유사하다. 


사용법

log4j 사용법

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

...

private static final Log LOG = LogFactory.getLog(SampleClass.class);

...

LOG.debug("test log4j");

 

logback 사용법

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

...

private static final Logger LOG = LoggerFactory.getLogger(Sample.class);

...

LOG.debug("test log4j");

 

slf4j를 사용하며 slf4j의 api를 이용한 로깅을 해야한다. logback 사용법처럼 바꿔 놓으면 추후 다른 logging framework로 전환한다 하더라도 소스레벨에서의 변경은 하지 않아도 된다. 이것이 바로 slf4j를 사용하는 이유이다. 

 

이 부분이 가장 큰 공수가 드는데 전체 replace 하는 방식으로 금방 다 바꿀 수 있다. 예를 들면 org.apache.commons.logging.Log; 로 search 하여 org.slf4j.Logger; 로 전체 replace를 해준다. 이런식으로 바꾼다면 금방 바꿀수 있다. 


그외

그 외에도 아무래도 log4j와 slf4j의 문법이 조금 다른 부분이 있을수가 있다. 예를들면 param을 받는 방법이라던지 spring을 append 하는 방법이라던지 조금씩 차이가 있다. 이러한 부분들은 위의 과정을 다 바꾸고 나면 컴파일 에러로 나타날테니 보면서 하나씩 고치는 방법밖에 없다. 

 

프로젝트가 엄청나게 크지 않다면 그래도 비교적 쉽게 전환을 할 수 있다. 생각보다 성능차이가 많이 나고 편리한점이 많다. 이제 log4j는 그만 쓰도록 하자. 

 

끝!

 

댓글
최근에 올라온 글
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31