로그(log)란 컴퓨터 등에 접속한 기록이 컴퓨터 내에 남아있는 것을 의미하며, 로깅(logging)은 애플리케이션이 동작하는 동안 동작 정보를 시간순으로 기록하는 것을 의미한다.
로깅은 디버깅하거나 개발 이후 발생한 문제를 해결할 때 원인을 분석하는데 꼭 필요한 요소이다.
Logback은 자바 진영에서 가장 많이 사용되는 로깅 프레임워크이다.
스프링 부트에서는 간단히 application.properties에 값만 세팅해도 설정 가능 하지만, xml 설정파일을 만들어 설정을 해보자.
스프링 부트의 spring-boot-starter-web 라이브러리 내부에 내장돼 있어 별도의 의존성을 추가하지 않아도 사용할 수 있다.
- spring-boot-starter-web 안에 spring-boot-starter-logging에 구현체가 있다.
Logback을 사용하기 위한 설정 파일을 만들어야한다. 클래스패스에 있는 설정 파일을 자동으로 참조하므로 Logback 설정파일은 리소스 폴더 안에 생성한다. 일반적인 자바 또는 스프링 프로젝트에서는
logback.xml이라는 이름으로 참조하지만 스프링 부트에서는logback-spring.xml파일을 참조한다.
▶ TRACE < DEBUG < INFO < WARN < ERROR
- ERROR : 요청을 처리하는 중 오류가 발생한 경우 표시한다.
- WARN : 처리 가능한 문제, 향후 시스템 에러의 원인이 될 수 있는 경고성 메시지를 나타낸다.
- INFO : 상태변경과 같은 정보성 로그를 표시한다.
- DEBUG : 프로그램을 디버깅하기 위한 정보를 표시한다.
- TRACE : 추적 레벨은 Debug보다 훨씬 상세한 정보를 나타낸다.
- 로그에 설정할 수 있는 레벨은 총 5가지다.
- 위의 순서대로 높은 레벨을 가진다. 출력 레벨의 설정에 따라 설정 레벨 이상의 로그를 출력 한다.
- 예를 들어 로깅 레벨 설정을 "INFO"로 하였을 경우 "TRACE", "DEBUG" 레벨은 무시한다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_PATH" value="./logs"/>
<!-- Appenders -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger %msg%n</pattern>
</encoder>
</appender>
<appender name="INFO_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<file>${LOG_PATH}/info.log</file>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/info_${type}.%d{yyyy-MM-dd}.gz</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger %msg%n</pattern>
</encoder>
</appender>
<!-- TRACE > DEBUG > INFO > WARN > ERROR > OFF -->
<!-- Root Logger -->
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="INFO_LOG"/>
</root>
</configuration>
- 3번 라인: property영역
- 6~13, 15~28번 라인: appender영역
- 10~12, 25~27번 라인: encoder영역
- 11, 26번 라인: pattern영역
- 23~35번 라인: root영역
15~28번, 34번 라인은 파일로 로그를 저장하고자 할 때 설정한다.
Logback 설정에서 가장 중요한 Appender 영역과 Root 영역에 대해서 자세히 알아보자
Appender 영역: 로그의 형태를 설정하고 어떤 방법으로 출력할지를 설정하는 곳이다.
- Appender의 대표적인 구현체(Class)
- ConsoleAppender: 콘솔에 로그를 출력
- FileAppender: 파일에 로그를 저장
- RollingFileAppender: 여러개의 파일을 순회하면서 로그를 저장
- SMTPAppender: 메일로 로그를 전송
- DBAppender: 데이터베이스에 로그를 저장
- appender 요소의 class 속성에 각 구현체를 정의
- filter 요소로 Appender가 어떤 레벨로 로그를 기록하는지 지정
- encoder 요소를 통해 로그의 표현 형식을 pattern으로 정의
- 대표적인 패턴(pattern)
- %Logger{length} : Logger name을 축약할 수 있다. {length}는 최대 자리 수, ex)logger{35}
- %-5level : 로그 레벨, -5는 출력의 고정폭 값(5글자)
- %msg : 로그 메시지 (=%message)
- ${PID:-} : 프로세스 아이디
- %d : 로그 기록시간
- %p : 로깅 레벨
- %F : 로깅이 발생한 프로그램 파일명
- %M : 로깅일 발생한 메소드의 명
- %l : 로깅이 발생한 호출지의 정보
- %L : 로깅이 발생한 호출지의 라인 수
- %thread : 현재 Thread 명
- %t : 로깅이 발생한 Thread 명
- %c : 로깅이 발생한 카테고리
- %C : 로깅이 발생한 클래스 명
- %m : 로그 메시지
- %n : 줄바꿈(new line)
- %% : %를 출력
- %r : 애플리케이션 시작 이후부터 로깅이 발생한 시점까지의 시간(ms)
설정 파일에 정의된 Appender를 활용하려면 Root 영역에서 Appender를 참조해서 로깅 레벨을 설정한다.
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="INFO_LOG"/>
</root>
출력할 메시지를 Appender에게 전달할 Logger 객체를 각 클래스에 정의해 사용한다.
LOGGER 전역변수로 Logger 객체를 정의한다.
@RestController
@RequestMapping("/api/v1/get-api")
public class GetController {
// 예제 5.26
private final Logger LOGGER = LoggerFactory.getLogger(GetController.class);
}
다음과 같이 메서드에서 LOGGER.info("getHello 메소드가 호출되었습니다.");로 로그를 출력할 수 있다.
// http://localhost:8080/api/v1/get-api/hello
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String getHello() {
// 예제 5.27
LOGGER.info("getHello 메소드가 호출되었습니다.");
return "Hello World";
}

LOGGER.info("@PathVariable을 통해 들어온 값 : {}", variable);를 통해서 변수의 값을 로그로 출력할 수도 있다.
// http://localhost:8080/api/v1/get-api/variable1/{String 값}
@GetMapping(value = "/variable1/{variable}")
public String getVariable1(@PathVariable String variable) {
// 예제 5.28
LOGGER.info("@PathVariable을 통해 들어온 값 : {}", variable);
return variable;
}

참고 블로그: https://goddaehee.tistory.com/206 [갓대희의 작은공간:티스토리]