본문 바로가기
Spring

[Spring] Spring에서 로그를 설정하는 방법

by 진꿈청 2024. 3. 27.

로그란?

  • 컴퓨터의 처리 내용이나 이용 상황을 시간의 흐름에 따라 기록
  • 개인용 컴퓨터 통신에서 통신 내용의 기록, 그 파일을 로그 파일
  • 통나무 목선 log on(승선), log out(하선)으로 유래

목적

  • 시스템 보안이나 유지보수 목적
    • 사고가 발생했을 때 데이터의 복원이나 사고 원인의 규명에 도움
    • 해킹 등의 사건이 발생했을 때, 로그 파일을 분석하여 사건의 원인 파악


로그를 설정하기에 앞서 로그는 로그 레벨로 나누어져 있다.

먼저, 로그 레벨에 관해 간단하게 알아보자.


로그 레벨이란?

  • 로그 레벨은 로그 메시지의 중요도를 나타내는 수준을 의미
  • 로그 레벨은 로깅 시스템에서 사용되며, 로그 메시지의 중요도에 따라 해당 메시지를 기록할지 결정

로그 레벨

  • TRACE
    • 가장 상세한 로그 레벨로, 애플리케이션의 실행 흐름과 디버깅 정보를 상세히 기록
    • 주로 디버깅 시에 사용
  • DEBUG
    • 디버깅 목적으로 사용되며, 개발 단계에서 상세한 정보 기록
    • 애플리케이션의 내부 동작을 이해하고 문제를 분석하는 데 도움을 줌
  • INFO
    • 정보성 메시지를 기록
    • 애플리케이션의 주요 이벤트나 실행 상태에 대한 정보를 전달
  • WARN
    • 경고성 메시지를 기록
    • 예상치 못한 문제나 잠재적인 오류 상황을 알리는 메시지
    • 애플리케이션이 정상적으로 동작하지만 주의가 필요한 상황을 알려줌
  • ERROR
    • 오류 메시지를 기록
    • 심각한 문제 또는 예외 상황을 나타내며, 애플리케이션의 정상적인 동작에 영향을 미칠 수 있는 문제를 알림
  • FATAL
    • 가장 심각한 오류 메시지를 기록
    • 애플리케이션의 동작을 중단시킬 수 있는 치명적인 오류를 나타냄
    • 일반적으로 이러한 오류는 복구가 불가능하거나 매우 어려움

 

TRACE < DEBUG < INFO < WARN < ERROR < FATAL

 

위 순서대로 로그 단계에 맞는 로그를 출력한다고 생각하면 좋다.

 

DEBUG 설정시

 

TRACE를 제외한 DEBUG 보다 높은 로그 레벨인 INFO, WARN, ERROR, FATAL 출력

 

 

여기까지 로그의 정의, 로그 레벨에 관해 간단하게 알아보았다.

 

Spring에서의 로그 설정

이제 본격적으로 한 개의 로그 파일을 가지고 스프링에서 로그 설정을 진행해보자.

Spring 프로젝트의 resources 폴더 내부에 logback-spring.xml 파일을 아래와 같이 만든다.

/src/main/resources/logback-spring.xml

 

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 60초마다 설정 파일의 변경을 확인하여 변경시 갱신 -->
<configuration scan="true" scanPeriod="60 seconds">


    <!-- Environment 내의 프로퍼티들을 개별적으로 설정할 수도 있다. -->
    <springProperty scope="context" name="LOG_LEVEL" source="logging.level.root"/>

    <!-- log file path -->
    <property name="LOG_PATH" value="./logs"/>
    <!-- log file name -->
    <property name="LOG_FILE_NAME" value="logs"/>
    <!-- err log file name -->
    <property name="ERR_LOG_FILE_NAME" value="err_log"/>
    <!-- pattern -->
    <property name="CONSOLE_LOG_PATTERN"
              value="%green(%d{yyyy-MM-dd HH:mm:ss.SSS}) %magenta([%thread]) %highlight(%5level) %cyan(%logger) - %msg%n"/>
    <property name="FILE_LOG_PATTERN"
              value="%-5level %d{yy-MM-dd HH:mm:ss}[%thread] [%logger{0}:%line] - %msg%n"/>

    <!-- Console Appender -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <!-- File Appender -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 파일경로 설정 -->
        <file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>
        <!-- 출력패턴 설정-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${FILE_LOG_PATTERN}</pattern>

        </encoder>
        <!-- Rolling 정책 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
            <fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log.zip</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 파일당 최고 용량 kb, mb, gb -->
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거-->
            <!--  <maxHistory>30</maxHistory>-->
            <!--<MinIndex>1</MinIndex> <MaxIndex>10</MaxIndex>-->
        </rollingPolicy>
    </appender>

    <!-- 에러의 경우 파일에 로그 처리 -->
    <appender name="Error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <file>${LOG_PATH}/${ERR_LOG_FILE_NAME}.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
        <!-- Rolling 정책 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
            <fileNamePattern>${LOG_PATH}/${ERR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 파일당 최고 용량 kb, mb, gb -->
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거-->
            <!--  <maxHistory>30</maxHistory>-->
        </rollingPolicy>
    </appender>

    <logger name="capstone.communityservice" level="DEBUG"/>
    <!-- root레벨 설정 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="Error"/>
    </root>

<!--    <logger name="org.apache.ibatis" level="DEBUG" additivity="false">-->
<!--        <appender-ref ref="CONSOLE"/>-->
<!--        <appender-ref ref="FILE"/>-->
<!--        <appender-ref ref="Error"/>-->
<!--    </logger>-->

    <!-- SQL문과 해당 SQL을 실행시키는데 수행된 시간 정보(milliseconds)를 포함한다. -->
    <logger name="jdbc.sqltiming" level="DEBUG"/>


</configuration>

 

  • <configuration scan=... />
    • 이 태그는 Logback 설정 파일이 자동으로 갱신되도록 한다.
    • 위의 설정에서는 설정 파일을 60초마다 스캔하여 변경사항이 있을 경우 갱신한다.
  • <springProperty scope="context" name="LOG_LEVEL".../>
    • Spring의 환경 설정 파일에서 logging.level.root 값을 읽어와 Logback의 로그 레벨로 사용.
    • 이를 통해 애플리케이션의 로그 레벨을 동적으로 관리할 수 있다.
  • <property> 태그들
    • 로그 파일의 위치, 이름, 패턴 등을 설정하는 데 사용.
    • 이런 속성들은 설정 파일 내에서 변수처럼 사용되어 다양한 Appender에서 참조
    • 위에선 LOG_PATH, LOG_FILE_NAME, ERR_LOG_FILE_NAME
  • Appender 설정
    • Console Appender: 콘솔에 로그를 출력하는 Appender.
      • PatternLayoutEncoder를 사용하여 로그 메시지의 형식을 지정
      • 위에서는 ${CONSOLE_LOG_PATTERN} 등에서 지정된 패턴을 사용
    • File Appender: 로그를 파일에 기록하는 Appender.
      • RollingFileAppender는 로그 파일의 크기나 날짜에 따라 새로운 로그 파일을 생성하는 롤링 정책을 지원
      • TimeBasedRollingPolicy와 SizeAndTimeBasedFNATP 정책을 사용해 로그 파일명 패턴, 로그 파일 최대 크기 설정
    • Error Appender: 에러 로그만 별도의 파일에 기록하기 위한 Appender.
      • LevelFilter를 사용해 에러 레벨의 로그만 수집.
  • 로그 레벨 및 출력 설정
    • <root level="..."/>
      • 애플리케이션 전체에 적용될 기본 로그 레벨 설정.
      • 쉽게 전체에 적용된다고 생각하면 된다.
        • 그래서 level을 낮게 설정하면 스프링 프레임워크의 싱글톤 객체 생성부터 자세하게 볼 수 있다.
      • appender-ref
        • 참조해서 사용할 appender를 등록한다.
    • <logger>
      • 특정 패키지 또는 클래스에 관한 로그 레벨 및 Appender 설정을 구체화한다.
    • jdbc.sqltiming 로거
      • SQL 실행 시간 정보를 포함하는 로그를 DEBUG 레벨로 출력.

 

 

알면 좋은 것들

만약, 아래와 같이 로그 패턴을 등록할 때 색깔을 지정해주지 않으면 그냥 흑백으로 이루어진 로그가 출력된다.

<property name="CONSOLE_LOG_PATTERN"
              value="%green(%d{yyyy-MM-dd HH:mm:ss.SSS}) %magenta([%thread]) %highlight(%5level) %cyan(%logger) - %msg%n"/>

 

위에선 FILE_LOG_PATTERN이 그 예이다.(FILE로 저장할 때는 색깔이 이스케이프 문자등으로 처리돼서 예쁜 로그를 보긴 어렵다)

 

그렇기에 우리는 위처럼 색깔을 지정해주어 좀 더 로그 파악이 쉽게 해준다.

 

우리처럼 logback-spring.xml 파일을 만들지 않으면 Spring은 base.xml를 기준으로 로그를 작성한다.

 

base.xml를 확인하면(Windows: CTRL + N, macOS: CMD + O)

 

위처럼 되어있다. 그럼 defaults.xml도 들어가보자.

 

defaults.xml를 확인해보면 clr이라는 이름으로 conversionRule이 선언되어 있다.

 

또한, 로그 레벨을 지정하는 부분을 clr이라는 색으로 지정한 것을 알 수 있다.

 

그래서, 만약 기존의 로그 설정을 사용하고 싶다면

 

그냥 아래처럼 설정해줘도 된다.

<include resource="org/springframework/boot/logging/logback/defaults.xml"/>

<!-- Console Appender -->
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>

 

 

그리고 만약, Spring application.yml 프로필 별로 로그를 관리하고 싶다면

<springProfile name="dev">
        <include resource="logback/file-hibernate-appender.xml"/>
        <include resource="logback/file-debug-appender.xml"/>
        <include resource="logback/file-warn-appender.xml"/>
        <include resource="logback/file-error-appender.xml"/>

        <root level="INFO">
            <appender-ref ref="FILE_WARN"/>
            <appender-ref ref="FILE_ERROR"/>
        </root>

        <logger name="com.mapbefine.mapbefine" level="DEBUG">
            <appender-ref ref="FILE_DEBUG"/>
        </logger>
        <logger name="org.hibernate.SQL" level="DEBUG">
            <appender-ref ref="FILE_HIBERNATE"/>
        </logger>
    </springProfile>

    <springProfile name="prod">
        <include resource="logback/file-info-appender.xml"/>
        <include resource="logback/file-warn-appender.xml"/>
        <include resource="logback/file-error-appender.xml"/>
        <include resource="logback/slack-error-appender.xml"/>

        <root level="INFO">
            <appender-ref ref="FILE_WARN"/>
            <appender-ref ref="FILE_ERROR"/>
            <appender-ref ref="SLACK_ERROR"/>
        </root>

        <logger name="com.mapbefine.mapbefine" level="INFO">
            <appender-ref ref="FILE_INFO"/>
        </logger>
    </springProfile>

 

이런식으로 해주면 된다.

 

 

또한, 로그 파일의 패키지 명, 클래스 명이 너무 길다면 축약하는 것도 가능한데

%-40.40logger{39}

이런식으로하면 최대 39자까지 출력하고 39자를 넘으면 축약한다는 의미이다.

 

 

마지막으로, 로그 파일을 파일에 저장할 때는 .gitignore에 log 파일을 추가해주는 것이 좋다.

불필요한 로그 파일들이 깃허브에 올라가기 때문

 

 

그래서 .gitignore 파일에 아래와 같이 추가해주자.

### log ###
**/*.log

 

 

참고 블로그

https://typo.tistory.com/entry/Spring-Boot-Slf4j-%EB%A1%9C%EA%B7%B8-%ED%8C%8C%EC%9D%BC%EB%A1%9C-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0

 

Spring Boot | Slf4j 로그 파일로 저장하기

resource 파일 아래에 다음 파일을 생성해준다. /src/main/resources/logback-spring.xml ${LOG_PATTERN} ${LOG_PATH}/${LOG_FILE_NAME}.log ${LOG_PATTERN} ${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log.zip 10MB error ACCEPT DENY ${LOG_PATH}/${ER

typo.tistory.com

https://breakcoding.tistory.com/400

 

[Spring] logback 파헤치기 (로그 레벨 설정, 프로필별 로그 설정, 글자 색상 변경)

안녕하세요 오늘은 logback을 통해 로그를 관리하는 방법을 알아보겠습니다. 목차 - 로그 색상 바꾸기 - 프로필에 따라 로그 레벨 다르게 설정하기 - 로그 파일을 분할해서 저장하기 - JPA SQL을 로그

breakcoding.tistory.com