본문 바로가기

SpringFramework/Spring

Spring - Log4j2

log4j2, logback과 같은 로깅시스템은 왜사용할까??

자바에서는 출력을 System.out으로도 할 수 있는데 문제는 운영이다. 개발시에 개발자가 출력한 System.out구문을 모두 제거하지 않았다면 운영시에 계속 로그가 출력되고 이것은 리소스 낭비를 초래한다. 그렇다고 개발자가 배포시에 모두 찾아서 지우는것 또한 일이다. 또한 운영시에 중대한 오류가 발생하였다고 했을때, 출력되는 로그가 없다고하면 그것 또한 문제를 찾기 위해 엄청난 시간과 노력이 들어간다. 이처럼 운영상에 로그를 남기지 않고 개발시에만 로그를 남김으로써 리소스 낭비를 줄일 수 있고 필요시에는 로그를 남겨서 오류 추적시에 사용될 수 있다.

log4j의 프로젝트는 이미 종료되었고 추가적인 업데이트가 이루어지지 않는다. 현재는 log4j2가 사용되고 있고 이는 log4j를 기반으로 만들어졌기 때문에 log4j와 사용방법은 동일하고 설정에서 약간의 차이가 발생하지만 둘을 비교해서 보면 그렇게 어렵지 않으며 바꾸는 것도 어렵지 않다.

 

Spring-Boot의 기본 Log Tool은 spring-boot-starter-web 안에 logback(spring-boot-starter-logging)이 구성되어있다.

logback은 스프링부트에서 추천하는 로거지만,

1] log 사용시, 람다식 작성가능 및 사용자 정의로그 지원

2] 가비지없는 로깅을 지원

3] 멀티쓰레드 환경에서 처리량(=성능)이 압도적으로 높다.

(참고: https://logging.apache.org/log4j/2.x/performance.html)

 

Log4j2의 의존 설정

build.gradle

// logback을 제외시키고, log4j2를 주입한다.
configurations {
   all {
      exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
   }
} 

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-log4j2' // Log4j2
}

 

log4j2의 설정파일

json, xml, yml 등의 다양한 방식으로 사용할 수 있다.

application.yml (외부설정파일)에 [logging.config: classpath:설정파일명.확장자]로 읽어들일 파일을 설정해두자.

설정 파일 경로는 main/resources폴더 시작 기준이다.

 

exam.xml 예제코드

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
 
    <!-- 공통적으로 사용하기 위한 속성값 정의 -->
    <Properties>
        <Property name="logFileName">ep-java-exam</Property>
        <Property name="consoleLayout">%style{%d{ISO8601}} %highlight{%-5level }[%style{%t}{bright,blue}] %style{%C{1.}}{bright,yellow}: %msg%n%throwable</Property>
        <Property name="fileLayout">%d [%t] %-5level %c(%M:%L) - %m%n</Property>
    </Properties>
 
    <!-- 로그가 실제로 찍혀지는 방법(layout) -->
    <Appenders>
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="${consoleLayout}" />
        </Console>
        <!-- file 생성에 대한 정책 -->
        <RollingFile name="file" fileName="logs/${logFileName}.log" filePattern="logs/${logFileName}.%d{yyyy-MM-dd}.log">
            <PatternLayout pattern="${fileLayout}" />
            <Policies>
                <TimeBasedTriggeringPolicy modulate="true" interval="24" /><!-- 시간별 로그 파일 생성-->
            </Policies>
            <DefaultRolloverStrategy max="10" fileIndex="min" /><!-- 롤링 파일 10개 까지 생성 -->
        </RollingFile>
    </Appenders>
 
    <!-- 어떤 패키지의 로그를 Appender에 붙여줄 것인가를 정의 -->
    <Loggers>
        <!-- 전체: root, 스프링 프레임워크: org.springframework -->
        <Logger name="root" level="info" additivity="false" > <!-- additivity=false: 로깅메시지 중복 방지 -->
            <AppenderRef ref="console" />
            <AppenderRef ref="file" />
        </Logger>
 
        <!-- rolling file에는 debug, console에는 info 분리하여 처리 가능하다. -->
        <Logger name="com.test.epdev" additivity="true" >
            <AppenderRef ref="console" level="info" />
            <AppenderRef ref="file" level="debug" />
        </Logger>
    </Loggers>
</Configuration>

설정완료후, 어플리케이션 실행시, 아래와 같이 로그파일이 만들어진다.

 

로그내용..

 

LoggerFactory를 이용하여 원하는 대상에 로그값을 남길 수도 있다.

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

@RestController
public class UserController {
    private static Logger log = LoggerFactory.getLogger(UserController.class); // 해당 Class를 Logger에 추가한다

    @GetMapping(value = "/test")
    public void test() {
        log.info("logging test"); // log를 남긴다.
    }
}

 

로그 결과 ==>

 

private static Logger log = LoggerFactory.getLogger(UserController.class); 대신에, @Slf4j 어노테이션으로 대신하여 사용할 수도 있다.

 

@RestController
@Slf4j
public class UserController {

    @GetMapping(value = "/test")
    public void test() {
        log.info("logging test"); // log를 남긴다.
    }
}

위와같이 기록되는 로그 또한, 설정이 되어있다면 .log 파일에 기록된다.

'SpringFramework > Spring' 카테고리의 다른 글

Spring - ErrorController  (0) 2021.10.15
Spring - Filter, InterCeptor, AOP  (0) 2021.10.13
Spring - Swagger  (0) 2021.10.08
Spring - RestTemplate  (0) 2021.10.08
Spring - ResponseEntity  (0) 2021.10.08