본문으로 바로가기

[Spring] Spring MVC Project logback 적용

category Backend/Spring 2021. 10. 28. 15:35

목차

    0. 환경

    • windows10
    • openjdk version "1.8.0_242"
    • STS4 TooL (이클립스) 
    • Spring Framework 4.3.8 released
    • Spring MVC Project (Legacy Project) 

    1. maven 추가 (pom.xml)

    • logback-classic
    • logback-core
    <!-- Logback -->
    <dependency>
    	<groupId>ch.qos.logback</groupId>
    	<artifactId>logback-classic</artifactId>
    	<version>1.2.3</version>
    </dependency>
    
    <dependency>
    	<groupId>ch.qos.logback</groupId>
    	<artifactId>logback-core</artifactId>
    	<version>1.2.3</version>
    </dependency>

    [logback]

    • 기본적으로 log4j 가 적용되어 있지만 안정성과 관리를 위해 Logging framewor인 Slf4j 와 그 구현체로써 Logback을 주로 사용합니다.
    • 속도와 유연성을 고려하여 디자인되었으며, 속도에 최적화되어 있습니다.
    • 멀티스레드 환경에서 사용해도 안전합니다.
    • 6가지의 로그 메시지 레벨을 사용합니다. (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
    • 빠른 디버깅 가능합니다.
    • 로그 이력을 파일, DB 등으로 남길 수 있습니다.

    2. maven 삭제 (pom.xml)

    • 기존 log4j가 실행될 수 있으므로 해당 내용을 주석하거나 지워줍니다.
    • log4j가 동작하게 되면 설정한 logback이 동작하지 않습니다.
    • 추가적으로 처음 생성되어 있는 log4j.xml(/src/main/resources/log4j.xml) 파일도 제거해줍니다.
    <!--
    <dependency>
    	<groupId>org.slf4j</groupId>
    	<artifactId>slf4j-log4j12</artifactId>
    	<version>${org.slf4j-version}</version>
    	<scope>runtime</scope>
    </dependency>
    -->

    3. logback 설정(logback.xml)

    /src/main/resources/logback.xml 파일을 생성합니다.

    <?xml version="1.0" encoding="UTF-8"?>
    
    <configuration scan="true" scanPeriod="30 seconds">
    	<property name="LOGS_PATH" value="D:\logs" />	
    
    	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    		<encoder>
       			<pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n</pattern>
    			<charset>UTF-8</charset>
    		</encoder>
    	</appender>
    	
    	<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    		<!-- 파일경로 설정 -->
    		<file>${LOGS_PATH}/logback.log</file>
    	
    		<!-- Rolling 정책 -->	
    		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    			<!-- 일자별 로그파일 최대 보관주기(일) -->
    			<maxHistory>60</maxHistory>
    			<!-- 파일 쓰기가 종료된 log 파일명의 패턴을 지정, (.gz,.zip 등을 넣으면 자동 일자별 로그파일 압축) -->
    			<fileNamePattern>${LOGS_PATH}/logback.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
    			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
    				<!-- 파일당 최고 용량 -->
    				<maxFileSize>100MB</maxFileSize>
    			</timeBasedFileNamingAndTriggeringPolicy>
    		</rollingPolicy>
    		
    		<!-- 출력패턴 설정-->
    		<encoder>
      			<pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n</pattern>
    			<charset>UTF-8</charset>
    		</encoder> 
    	</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>${LOGS_PATH}/error.log</file>
    		<!-- Rolling 정책 -->	
    		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    			<!-- 일자별 로그파일 최대 보관주기(일) -->
    			<maxHistory>60</maxHistory>
    			<!-- 파일 쓰기가 종료된 log 파일명의 패턴을 지정, (.gz,.zip 등을 넣으면 자동 일자별 로그파일 압축) -->
    			<fileNamePattern>${LOGS_PATH}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>	
    			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
    				<!-- 파일당 최고 용량 -->
    				<maxFileSize>100MB</maxFileSize>
    			</timeBasedFileNamingAndTriggeringPolicy>		   	
    		</rollingPolicy>
    		<!-- 출력패턴 설정-->
    		<encoder>
    			<pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n</pattern>
    			<charset>UTF-8</charset>
    		</encoder> 	    
    	</appender>
    
        <logger name="com.test.controller" level="INFO" additivity="false">
    		<appender-ref ref="ROLLING" />
    		<appender-ref ref="STDOUT" />
    		<appender-ref ref="Error" />    	
        </logger>
         
        <root level="INFO">
    		<appender-ref ref="ROLLING"/>
    		<appender-ref ref="STDOUT" />
    		<appender-ref ref="Error" />
        </root>
    </configuration>

    4. 로그 확인(테스트)

    • 컨트롤러를 호출해 테스트를 해 봅니다.
    • private static final Logger logger = LoggerFactory.getLogger(BasicController.class); 선언을 해줘야 합니다.
    package com.test.controller;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController 
    public class BasicController {
    
    	private static final Logger logger = LoggerFactory.getLogger(BasicController.class);
    	
    	@GetMapping("/")
    	public void root() {
    		logger.trace("/testApi");
    		logger.debug("/testApi");
    		logger.info("/testApi");
    		logger.warn("/testApi");
    		logger.error("/testApi");	
    	}
    }

     

    다음과 같이 설정을 해둬서 debug, trace 로그는 출력이 되지 않는 것을 확인할 수 있습니다.

    <logger name="com.test.controller" level="INFO" additivity="false">
    	<appender-ref ref="ROLLING" />
    	<appender-ref ref="STDOUT" />
    	<appender-ref ref="Error" />    	
    </logger>

    로그 출력
    파일 생성

    5. logback 로그 레벨

    [로그 레벨]
    TRACE  <  DEBUG  <  INFO  <  WARN  <  ERROR

    1. ERROR: 오류 로그
    2. WARN: 경고성 로그
    3. INFO:  정보성 로그
    4. DEBUG: 디버깅 로그
    5. TRACE: 추적 로그

    6. appender

    로그 출력 형태, 저장될 로그 파일명, 한 파일당 용량, 압축 처리, 최대 파일 생성 개수 등을 설정합니다.

     

    [모든 로그 출력 및 저장 설정 appender]

    <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    	<!-- 파일경로 설정 -->
    	<file>${LOGS_PATH}/logback.log</file>
    
    	<!-- Rolling 정책 -->	
    	<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    		<!-- 일자별 로그파일 최대 보관주기(일) -->
    		<maxHistory>60</maxHistory>
    		<!-- 파일 쓰기가 종료된 log 파일명의 패턴을 지정, (.gz,.zip 등을 넣으면 자동 일자별 로그파일 압축) -->
    		<fileNamePattern>${LOGS_PATH}/logback.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
    		<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
    			<!-- 파일당 최고 용량 -->
    			<maxFileSize>100MB</maxFileSize>
    		</timeBasedFileNamingAndTriggeringPolicy>
    	</rollingPolicy>
    	
    	<!-- 출력패턴 설정-->
    	<encoder>
    		<pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n</pattern>
    		<charset>UTF-8</charset>
    	</encoder> 
    </appender>

     

    [에러 로그 출력 및 저장 설정 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>${LOGS_PATH}/error.log</file>
    	<!-- Rolling 정책 -->	
    	<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    		<!-- 일자별 로그파일 최대 보관주기(일) -->
    		<maxHistory>60</maxHistory>
    		<!-- 파일 쓰기가 종료된 log 파일명의 패턴을 지정, (.gz,.zip 등을 넣으면 자동 일자별 로그파일 압축) -->
    		<fileNamePattern>${LOGS_PATH}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>	
    		<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
    			<!-- 파일당 최고 용량 -->
    			<maxFileSize>100MB</maxFileSize>
    		</timeBasedFileNamingAndTriggeringPolicy>		   	
    	</rollingPolicy>
    	<!-- 출력패턴 설정-->
    	<encoder>
    		<pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n</pattern>
    		<charset>UTF-8</charset>
    	</encoder> 	    
    </appender>

    <file> 기록할 파일명과 경로를 설정

    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 일자별 적용

    <fileNamePattern> 파일 쓰기가 종료된 log 파일명의 패턴을 지정, .gz, .zip 등을 넣으면 자동 일자별 로그파일 압축

    <maxHistory> 일자별 로그파일 최대 보관 주기

    <maxFileSize> 파일당 최고 용량

    <encoder> 로그 출력을 변환 설정

    <pattern> 로그 출력 패턴 설정

    <Filter> 로그 필터링 설정

     

    [pattern]

     %m : 로그내용이 출력
     %p : trace > debug > info > warn > error 등의 priority 출력
     %r : 어플리케이션이 시작되어 로깅이벤트가 발생하는 시점까지의 경과시간을 밀리세컨드로 출력
     %c : 예) 카테고리가 a.b.c 처럼 되어있다면 %c{2}는 b.c가 출력됩니다.
     %n :  플랫폼 종속적인 개행문자가 출력된다. \r\n 또는 \n 일것이다
     %d : 로깅이벤트가 일어나 날짜 출력 ( 프로그램의 실행속도를 느리게 한다.)
         예) %d{HH:mm:ss} 또는 %d{dd MMMM yyyy HH:mm:ss}
     %C : 호출자의 클래스명 출력
        예) 클래스구조가 org.apache.xyz.SomeClass 처럼 되어있다면 %C{2}는 xyz.SomeClass 가 출력됩니다
     %M : 로깅이 발생한 method 이름을 나타냅니다.
     %F : 로깅이 발생한 프로그램 파일명을 나타냅니다.
     %l : 로깅이 발생한 caller의 정보를 나타냅니다 
     %L : 로깅이 발생한 caller의 라인수를 나타냅니다 
     %x : 로깅이 발생한 thread와 관련된 NDC(nested diagnostic context)를 출력합니다. 
     %X : 로깅이 발생한 thread와 관련된 MDC(mapped diagnostic context)를 출력합니다. 
     %% : % 표시를 출력하기 위해 사용한다.  
     %t : 로그이벤트가 발생된 쓰레드의 이름을 출력합니다
     %Logger{length}			: Logger name을 축약할 수 있다. {length}는 최대 자리 수  
     %thread 			: 현재 Thread 이름
     %-5level 			: 로그 레벨, -5는 출력의 고정폭 값
     %msg 				: 로그 메시지 (=%message)
     ${PID:-}			: 프로세스 아이디

    7. logger 

    설정한 appender를 참조하여 package와 level을 설정한다.

     

    [전역 설정]

    ★ 지역적으로 선언된 logger 설정이 있다면 해당 지역 logger 설정이 default로 적용됩니다.

    <root level="INFO">
    	<appender-ref ref="ROLLING"/>
    	<appender-ref ref="STDOUT" />
    	<appender-ref ref="Error" />
    </root>

    [지역 설정]

    additivity 값은 root 설정 상속 유무 설정.(default = true)

    <logger name="com.kamp.controller" level="INFO" additivity="false">
    	<appender-ref ref="ROLLING" />
    	<appender-ref ref="STDOUT" />
    	<appender-ref ref="Error" />    	
    </logger>​