[Spring] Logging 구성 및 구현

앞 글을 통하여 Logging의 중요성과 어떤 Content들을 정리해야 하는지에 대하여 알아 보았다.

앞글의 내용을 바탕으로 Spring Application에 있어서 중요한 것들을 정리해 보았다.

  • 사용자 인증인가 정보(로그인 및 resource에 대한 접근 정보도 포함)
  • Exception 정보, 어떤 상황에 어떤 Exception이 발생하였는지를 추후 분석할 수 있을 정도면 충분할 것 같다.
  • Transation에 관련된 log, 데이터와 관계되는 부분이니 데이터 베이스 장애처리하는데 도움을 줄 수 있다
  • 이외에도 중요한 비즈니스 로직이나, 장애 발생 상황 등을 빠르게 판단할 수 있는 것들을 남겨야 한다.

위의것들을 잘 분류하여 주기적으로 삭제가능 혹은 영구 보존 등으로 등급을 나누어 관리 할 수 있다. 이 부분 내용은 추후 업데이트 할 예정이다. 이런 것들을 잘 구현 및 관리 하기 위해서는 체계적인 로그 구조가 필요하다. 로그 구조를 깊게 들어가지 전에 Spring boot에서 어떻게 Logging를 적용할 수 있을지에 대하여 알아보자.

Spring boot에서 Logback 사용

Spring에서는 기본적으로 SLF4J를 인터페이스로 한 Logback 구현체를 사용하고 있다. Logback에 대한 설명은 이 사이트를 참조하길 바란다.

위에서도 설명 했다싶다 로그를 체계적으로 관리하려면 계층구조로 나누고 각 구조에 적합하게 설계하고 구현 하야 한다. 현재 SLF4J에서는 5개 계층 구조를 제공하고 있다.(TRACE, DEBUG, INFO, WARN, ERROR, FATAL) 상위 계층은 하위 계층을 모두 포함한다.

Gradle 설정

dependencies {
    implementation group: 'io.github.microutils', name: 'kotlin-logging-jvm', version: '2.0.6'
}

kotlin-logging은 SKF4J를 사용하는 경량 프레임워크다. 이 글에서는 좀 더 kotlin스럽게 log를 사용하기 위해 kotlin-logging를 사용했다.

Appender 설정

기본적으로 logback에 대한 설정을 통하여 여러개의 appender를 설정하여 자유자재로 사용할 수 있다.

spring boot 프로젝트 하위의 resources폴더 아래에 logback-spring.xml 혹은 application.yml 파일에 아래와 같이 지정하고 이름을 다르게 사용 가능 하다.

logging:
  config: classpath:logback.xml

logback.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>

<configuration>

    <!-- 로그 파일을 적재할 디렉토리 경로를 지정 -->
    <property name="LOG_FILE_PATH" value="./logs"/>
    <!-- 로그 파일을 적재할 파일 이름을 지정 -->
    <property name="LOG_FILE_NAME" value="order_system"/>

    <!-- TEXT_CONSOLE 어펜더 정의 -->
    <!-- 개발 환경에 적합 -->
    <appender name="TEXT_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <Pattern>%d %-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
        </encoder>
    </appender>

    <!-- TEXT_FILE 어펜더 정의 -->
    <!-- 일자별 로그 저장 및 100MB 초과 시 삭제. 최대 7일 보관 -->
    <appender name="TEXT_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE_PATH}/${LOG_FILE_NAME}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE_PATH}/${LOG_FILE_NAME}_%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>100MB</maxFileSize>
            <maxHistory>7</maxHistory>
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d %-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

코드에서는 두개의 appender를 설정 했다, 위의 것은 개발에 적합한 것이고 아래 파일로 저장하는건 운영환경에 적합하다.

로그 사용

    val log = LogManager.getLogger()
    @Async("taskExecutor")
    fun creatUser(userDTO: UserDTO):CompletableFuture<String>{
        log.info("create User is called")
        var userInfo = userRepository.findOne(user.name.eq(userDTO.name))
        //이전 암호 체크와 새 비번으로 수정
        if(userInfo.isEmpty!=true){
            return  CompletableFuture.completedFuture("The user name already used")
        }
        else{
            val newUser = User(userDTO.name,userDTO.password)
            return  CompletableFuture.completedFuture(newUser.toString())
        }
    }

프로그램의 기본 중에 기본으로 여겨지는 Logging에 대하여 맛보기로 살펴 보았다. 다음에는 GELF 포맷을 이용으로 logging 하는법을 포스팅 할 예정이다.

Ref:

https://jsonobject.tistory.com/500

https://jsonobject.tistory.com/391

https://jessyt.tistory.com/127

'Spring boot' 카테고리의 다른 글

[Spring] Kotllin + Spring boot 시작하기  (0) 2021.12.08
[Spring] Transaction 정리  (0) 2021.11.24
[Spring] Async 대해  (0) 2021.11.22
[Spring] 사용자 Token 인증 방식  (0) 2021.11.20
[Spring] Spring AOP 개념 및 구현  (0) 2021.11.15