Log4j2, Slf4j, Log4jdbc 설정 방법

deannn.Park·2024년 7월 6일
post-thumbnail

Log4j

Log4j는 Java 영역에서 로그를 쉽고 편리하게 기록할 수 있도록 도와주는 라이브러리이다.
Log4j2Log4j의 2 이상의 버전을 부르고, 이전에 발생한 Log4j 보안 이슈 때문에 Java 7 이하인 경우에는 2.13.3, Java 8 이상인 경우에는 2.17 이상의 버전을 사용하는 것이 좋다.
2.14 버전에서 문제가 발생했기에 못해도 2.15 이상의 버전을 사용하는 것이 좋고, 왠만하면 최신 버전을 사용하자.

Logback? 다른 라이브러리와의 차이점

Logback은 현재 Spring에서 기본으로 지원하는 Logger이다. Log4j 이후에 개발되어 Logback이 기본으로 등록되었지만, 이후에 Log4j2가 나오면서 Log4j2가 더 선호되는 경향이 있다.
Log4j2는 대부분의 상황에서 Logback보다 더 빠른 속도를 가지고 있다고 한다.

Slf4j란?

Slf4j는 다양한 Logger 구현체들 대신 호출되는 인터페이스 역할을 하는 라이브러리이다.
Slf4j를 사용하면 직접 Logback이나 Log4j2를 호출하지 않고 Slf4j를 호출하는 것 만으로도 간단하게 로그를 찍을 수 있다. 일종의 Bridge 역할이다.
Log4j2Slf4j, lombok 조합이면 클래스에 @Slf4j 어노테이션 하나 붙이는 것 만으로도 로그를 사용할 수 있다.

Log4j2 설정 방법

build.gradle 설정

Log4j2 의존성 추가 (Springboot)

Log4j를 사용하기 위해서는 dependency를 추가해야 한다. 본 글에서는 Gradle 기준으로 설명한다.

SpringBoot를 사용중이라면 SpringBoot에서 지원해주는 Log4j2 라이브러리가 존재한다. build.gradle에 해당 라이브러리를 추가해주면 된다.

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

Log4j2 의존성 추가 (Spring legacy)

Spring boot를 사용하지 않는다면, log4j-apilog4j-core를 추가해주면 된다.

dependencies {
	... 
    // log4j2
	implementation 'org.apache.logging.log4j:log4j-core:2.23.1'
    implementation 'org.apache.logging.log4j:log4j-api:2.23.1'

    ...
}

Logback 의존성 제거

Spring에서 기본적으로 사용하는 logback을 의존성 제거를 해줘야 한다. 그렇지 않으면 Slf4j에 구현체가 2개 이상이 등록되어 오류가 발생한다.

configurations {

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

	...
}

Slf4j 의존성 추가

build.gradle을 설정하는 김에 slf4j도 추가해준다.

dependencies {
	... 
    
    // slf4j
    implementation 'org.slf4j:slf4j-api:2.0.13'

    ...
}

yaml 설정 파일을 읽기 위한 의존성 추가

아래에서 log4j2 설정파일을 yaml 파일로 만든 예정인데, 이를 위한 의존성도 추가해준다.

dependencies {
	... 
    
    // log4j2-yaml
    implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.1'

    ...
}

그리고 buid.gradle reload를 시켜준다.

Log4j2 설정 파일 (Log4j2.yml)

보통 log4j2 설정을 할 때, xml로 주로 설정을 한다.
하지만 나는.. xml 태그가 귀찮으므로 yaml 파일로 만들어서 설정하려고 한다.
resources 폴더 바로 아래에 log4j2.yml이라고 파일을 만든다.

만약 실행 환경, 프로필 별로 설정 파일을 별도로 만들거나, log4j2.yml을 resources 바로 아래가 아닌 다른 곳에 위치시키던가 하려면 application.yml에 해당 위치를 명시시켜줘야 한다.

logging:
	config: classpath:log4j2.yml

일단 내가 설정한 log4j2.yml 내용을 아래와 같다.

Configutation:
  name: Default
  status: warn

  Properties:
    Property:
      - name: log-path
        value: "logs"
      - name: pattern
        value: "%d %highlight{[%-5level]} [%style{%t}{bright,blue}] %style{%C}{bright,yellow}: %msg%n%throwable"
      - name: charset-UTF-8
        value: "UTF-8"

  Appenders:
    Console:
      name: Console_Appender
      target: SYSTEM_OUT
      PatternLayout:
        charset: ${charset-UTF-8}
        pattern: ${pattern}
        disableAnsi: false
    File:
      name: File_Appender
      fileName: ${log-path}/logfile.log
      PatternLayout:
        charset: ${charset-UTF-8}
        pattern: ${pattern}
        disableAnsi: false
    RollingFile:
      - name: RollingFile_Appender
        fileName: ${log-path}/rollingfile.log
        filePattern: "logs/archive/rollingfile.log.%d{yyyy-MM-dd-hh-mm}.gz"
        PatternLayout:
          charset: ${charset-UTF-8}
          pattern: ${pattern}
          disableAnsi: false
        Policies:
          SizeBasedTriggeringPolicy:
            size: 200 KB
        DefaultRollOverStrategy:
          max: 30
  Loggers:
    Root:
      level: warn
      AppenderRef:
        - ref: Console_Appender
        - ref: RollingFile_Appender
    Logger:
      - name: com.demo.example
        additivity: "false"
        level: debug
        AppenderRef:
        - ref: Console_Appender
        - ref: RollingFile_Appender

name

설정 파일을 구분하는 이름

status

내부 이벤트에 대한 로그 레벨

Properties

로그 설정의 속성을 정의
해당 설정에서 속성을 미리 정의해서 변수처럼 사용 가능
name 속성이 키, value 속성이 값으로 생각하면 되고, 예시처럼 - 를 사용해서 여러 개를 지정할 수 있다.

Appenders

Appenders는 로그 메세지를 출력하는 방법을 정의하는 곳이다.
Appender의 종류로는 Console, File, RollingFile 등이 있다. 주로 Console, RollingFile이 많이 사용된다.

Appenders - PatternLayout

PatternLayout은 출력 결과 포맷을 지정하는 값이다.
자세한 문법은 공식 홈페이지를 참조

Loggers

클래스 별로 로그를 찍을지 설정하는 곳이다.

Loggers - Root

Root는 필수이다. 기본 설정을 이곳에 한다.

Loggers - Logger

추가적으로 설정하는 곳이다.

  • name: 클래스명
  • level: 로그 레벨을 설정. 로그의 레벨이 설정한 레벨 이상인 경우에만 출력한다.
    - 로그 레벨: ERROR > WARN > INFO > DEBUG > TRACE
  • AppendefRef: ref값을 통해 Appender를 지정한다.
  • additivity: Log 설정이 중복된 경우에 두번 이상 출력될 수 있는데, 이를 방지하는 옵션이다. 기본값이 true이고, false로 하게 되면 로그가 중복되는 것을 막을 수 있다.

추가적인 정보는 공식 홈페이지 매뉴얼을 참고하자.

YAML 작성 시 주의 할 점

yaml 1.2 버전에서는 기존 1.1 버전에 의해 boolean 타입이 엄격하게 허용된다고 한다.
따라서 boolean 타입은 따옴표로 감싸서 'true' / 'false' 로 작성해야 한다.
만약 log level을 OFF 로 지정하고 싶은 경우에도 "OFF"로 적어줘야 오류가 발생하지 않는다.

Log4j2, Slf4j 사용법

설정을 다 하고 나면 Java Class에 @Slf4j 어노테이션을 사용한 후에 로그 사용이 가능하다.

log.debug("로그내용");
log.info("변수 사용 {}", stringVal);

위와 같은 형식으로 사용 가능하다.

간단한 컨트롤러를 만들어서 로그가 정상적으로 찍히는지 테스트를 해보려고 한다.

테스트 소스

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
@Slf4j
public class LogTest {

    @GetMapping("/log")
    public String logTest() {
        log.trace("logtest - trace");
        log.debug("logtest - debug");
        log.info("logtest - info");
        log.warn("logtest - warn");
        log.error("logtest - error");
        log.error("logtest - {}", "ERROR");
        
        return "index";
    }

}

 

결과

Log4jdbc?

Mybatis를 통해 DB 연결을 하면 기본적으로 로그는 나온다.
하지만

SELECT * FROM USER WHERE USER_ID = ? AND USER_NAME = ?

이런식으로 찍히기 때문에 정확한 쿼리를 보기가 어렵다. 이를 위해 Log4jdbc를 사용한다.

Log4jdbc 설정 방법

일단 Log4jdbc 설정에 앞서, db 설정이 되어 있는 상태에서 시작한다.

의존성 추가

build.gradle에 dependency를 추가하자.

dependencies {
	... 
    
    // log4jdbc
	implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16'

    ...
}

DB 연결정보 (datasource) 수정

DB 접속 정보가 적힌 application.yml (또는 properties) 파일에서 driver-class-nameurl을 수정해준다.

수정 전

spring:
  datasource:
    driver-class-name: org.mariadb.jdbc.Driver
    url: jdbc:mariadb://localhost:8080/test?CharacterEncoding=UTF-8
    username: user
    password: 1111

수정 후

spring:
  datasource:
    driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
    url: jdbc:log4jdbc:mariadb://localhost:8080/test?CharacterEncoding=UTF-8
    username: user
    password: 1111

log4jdbc 설정 파일 추가

resources 폴더 아래에 log4jdbc.log4j2.properties 파일을 추가하고 안에 아래와 같이 내용을 추가한다.

log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
log4jdbc.dump.sql.maxlinelength=0

log4j2.yml 수정

log4j2가 정상적으로 log4jdbc의 쿼리 로그를 출력할 수 있도록, loggers 부분에 아래와 같이 logger 내용을 추가한다.

  Loggers:
    Root:
      level: "warn"
      AppenderRef:
        - ref: Console_Appender
        - ref: RollingFile_Appender
    Logger:
      - name: com.demo.example
        additivity: "false"
        level: "debug"
        AppenderRef:
        - ref: Console_Appender
        - ref: RollingFile_Appender
        
      # 이 아래 부분부터 추가
      - name: jdbc.connection
        additivity: "false"
        level: "warn"
        AppenderRef:
          - ref: Console_Appender
          - ref: RollingFile_Appender
      - name: jdbc.audit
        additivity: "false"
        level: "off"
        AppenderRef:
          - ref: Console_Appender
          - ref: RollingFile_Appender
      - name: jdbc.resultset
        additivity: "false"
        level: "warn"
        AppenderRef:
          - ref: Console_Appender
          - ref: RollingFile_Appender
      - name: jdbc.sqlonly
        additivity: "false"
        level: "off"
        AppenderRef:
          - ref: Console_Appender
          - ref: RollingFile_Appender
      - name: jdbc.resultsettable
        additivity: "false"
        level: "off"
        AppenderRef:
          - ref: Console_Appender
          - ref: RollingFile_Appender
      - name: jdbc.sqltiming
        additivity: "false"
        level: "debug"
        AppenderRef:
          - ref: Console_Appender
          - ref: RollingFile_Appender

결과

참고
https://adjh54.tistory.com/388
https://velog.io/@osh8242/SpringBoot에-Log4jdbc-사용하기

profile
컴퓨터 관련 여러 분야 공부중

0개의 댓글