본문 바로가기
자바,스프링 - Java,Spring Framework

Java프로젝트에 lo4j2 적용하기

by devscb 2024. 11. 9.
반응형

 

java진영의 로깅 라이브러리는 log4j2가 굉장히 효율적입니다. (https://devscb.com/post/253)
그러나, 많이 사용되고 있는 springboot에서는 logback을 기본 로깅라이브러리로 사용하고 있습니다.
단순히 dependency 추가하면 되는것 아닌가 싶지만, 바로 빌드가 안되던 경험이 있어서 공유합니다.

maven을 사용할 경우

pom.xml의 dependencys 엘리먼트 하위에 아래 내용을 추가해줍니다.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

그런데, 이렇게만 하면 spring boot 실행시 다음과 같은 붉은 메시지를 확인할 수 있습니다.

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/username/.m2/repository/ch/qos/logback/logback-classic/1.2.11/logback-classic-1.2.11.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/username/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.17.2/log4j-slf4j-impl-2.17.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]

이 메시지의 뜻은 log4j2와 logback 두 가지를 찾았으나, 실질적으로 사용하는것은 logback이라는 뜻입니다.
즉, log4j2를 사용하도록 정상적으로 반영이 안되었다는 뜻입니다.
이러한 메시지가 발생하는 이유는,
spring-boot-starter-logging에서 logback을 이미 채택하여 사용하고 있기때문에 정상동작이 안되는 것입니다.
이를 위해, spring-boot-starter-logging을 spring-boot-starter-web 프로젝트에서 아래와 같이 dependency에서 제외하도록(exclusion) 합니다.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 <exclusions>
  <!--
   스프링 부트에서 Log4j2를 사용하기위해선 내부로깅에서 쓰이는 의존성을 제외해주어야 합니다.
   기본적으로 Spring은 Slf4j라는 로깅 프레임워크를 사용합니다.
   구현체를 손쉽게 교체할 수 있도록 도와주는 프레임 워크입니다.
   Slf4j는 인터페이스고 내부 구현체로 logback을 가지고 있는데,
   Log4j2를 사용하기 위해 exclude 해야 합니다.
   -->
  <exclusion>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-logging</artifactId>
  </exclusion>
 </exclusions>
</dependency>

gradle을 사용할 경우

build.gradle의 dependencies와 configurations 쪽에 아래와 같이 각각 내용을 입력해줍니다.
(log4j2 포함, spring-boot-starter-logging 제외)

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-log4j2")
}

configurations {
    all {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
}

설정파일 추가 - log4j2.xml

src/main/resources에 log4j2.xml 파일을 만들고,
아래와 같은 내용으로 작성해줍니다.
콘솔창으로는 모든 에러를 표시하고,
에러 로그가 발생하면 D:/spring_logs 경로에 파일로 남겨두며,
로그 파일 크기가 5MB이거나 1일 이후면 파일을 rolling 하며,
20개까지의 파일을 유지한다는 내용입니다.

<?xml version="1.0" encoding="UTF-8" ?>
<configuration status="INFO">
    <Properties>
     <Property name="LOG_LEVEL">info</Property>
        <Property name="LOG_PATH">C:/spring_logs</Property>   
        <Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} thr=%thread severity=%-5level logger=%c{1} %msg%n</Property>
    </Properties>
    <Appenders>
        <Console name="ConsoleAppender" target="SYSTEM_OUT">
            <PatternLayout disableAnsi="false" pattern="${LOG_PATTERN}"/>
        </Console>

        <RollingFile name="ErrorFileAppender"
                     fileName="${LOG_PATH}/spring.log"
                     filePattern="${LOG_PATH}/spring-%d{yyyy-MM-dd}-%i.log">
            <!-- JsonLayout complete="false" compact="false" charset="UTF-8">
                <KeyValuePair key="service" value="simple" />
            </JsonLayout-->
            <PatternLayout disableAnsi="false" pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" />
                <SizeBasedTriggeringPolicy size="5MB" />
            </Policies>
            <DefaultRolloverStrategy max="20" fileIndex="min" />
        </RollingFile>
    </Appenders>


    <Loggers>
        <Root level="${LOG_LEVEL}">
            <AppenderRef ref="ConsoleAppender" />
            <AppenderRef ref="ErrorFileAppender" level="error" />         
        </Root>
    </Loggers>
</configuration>

라이브러리 추가후, 로깅 코드 작성

sr/main/java 쪽에 아래와 같이 컨트롤러를 만들고,
Logger 클래스 객체를 만들어서 error와 info 로그를 출력하도록 코딩합니다.


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    private static final Logger logger = LoggerFactory.getLogger(TestController.class);

    @RequestMapping("/test")
    public String test(){
      logger.error("error_log");
      logger.info("info_log");
      return "test";
    }
}

로깅확인

앞서 코딩한 내용을 브라우저에서 실행하면,
콘솔창에 로그가 찍한것을 볼 수 있고,
파일에는 에러 로그만 찍한것을 확인할 수 있습니다.

728x90
반응형

댓글