일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 캠프
- JPA 동시성
- 서버개발캠프
- 개발
- spring security
- 디자인 패턴
- component
- 낙관적락 비관적락 차이
- JPA 낙관적락
- spring security 인증
- 안드로이드
- spring
- bean
- 스마일게이트
- Pessimistic Lock
- Redis
- 스프링
- Transaction isolation level
- 스프링 로그
- JPA 비관적락
- 서버
- Inno DB
- 스프링 log
- JPA
- flask
- JPA Lock
- Android
- annotation
- Optimistic Lock
- 암호화
- Today
- Total
모르는게 많은 개발자
[스프링] 로깅 개념/설정 예제(feat. Logback) 본문
스프링 개발을 하다보면 자연스레 Lombok의 @Slf4j
를 사용해 log.info()
등 로그를 남겼다. 이번 기회에 Jcl
, Log4j
, Slf4j
, Logback
용어 정리와 많이 사용되는 Logback
설정에 대해 정리해놓고자한다.
스프링 부트는 어떤 Logger를 사용하고 있나
스프링에는 크게 Jcl(Jakarta Common Logging)
, Slf4j
두개의 로깅 추상화 라이브러리가 있다.
두개 모두 인터페이스만 존재하기에 구현체가 필요한데 Jcl
의 구현체는 Log4j
, Slf4j
의 구현체는 Logback
이 있다.
스프링 부트는 기본적으로 Jcl
에 구현체 Logback
이 사용된다.spring-boot-starter
의존성에 spring-boot-starter-logging
이 들어있고 안에는 logback
의존성이 들어있다.
하지만 Logback
은 Slf4j
의 구현체인데 어떻게 같이 사용되나 궁금할 수 있다.
다른 여러글을 찾아보면 모두 jcl-over-slf4j
의존성의 어댑터 패턴을 사용해 연결했다 써있지만 내가 쓰고 있는 스프링부트 버전에는 보이지 않아 직접 어댑터 부분을 찾아봤다.
먼저 Slf4j
Logger
의 구현체는 다음처럼 logback
을 패키지를 사용한걸 볼 수 있다.
이제 JCL
을 로그를 사용해보자
JCL
로그의 구체적 클래스는 다음과 같이 LogAdapter
의 Slf4jLocationAwareLog
이 출력된다.
LogAdapter
의 Slf4jLocationAwareLog
객체를 생성하는 부분이다.
Slf4jLocationAwareLog
의 생성자 인자로 LocationAwareLogger
를 받는데 이는 위 Slf4j
와 같은 slf4j.Logger
를 상속받아 사용한다.
결론은 JCL
을 사용해도 결국 LogAdapter
를 통해 Slf4j
의 Logback
을 사용하게 된다.
하지만 JCL
은 명확한 단점(로그레벨 처리, 문자열 연산 등)들이 존재하기에 많은 개발자들이 Lombok
@Slf4j
를 사용할 것 이다. @Slf4j
를 사용하면 JCL
을 사용하지 않고 바로 Slf4j
추상 라이브러리를 사용할 수 있다.
Logback 설정
Log Level
로그를 작성할 때 레벨을 설정해 원하는 로그만 출력시킬 수 있다. 로그 레벨은 총 5단계다.
TRACE
< DEBUG
< INFO
< WARN
< ERROR
위 순서대로 레벨을 가진다.
예를 들어 출력 레벨을 INFO
로 설정시 TRACE
, DEBUG
레벨은 무시한다.
출력 레벨은 application.yml
을 통해 설정할 수 있다.
logging:
level:
root: debug
debug
로 설정했기 때문에 trace
는 출력되지 않음을 확인할 수 있다.
만약 특정 패키지부분만 다르게 하고싶다면 다음과 같이 패키지 경로에 레벨을 설정한다.
logging:
level:
root: debug
jpabook.jpashop.test: trace #특정 패키지 경로
logback-spring.xml
위처럼 .yml
을 통해 로그를 설정할 수 있지만 자세한 동작 변경을 원한다면 .xml
파일을 이용한다.
먼저 src/main/resources
하위에 logback-spring.xml
파일을 생성하자.
사용되는 태그의 의미는 다음과 같다.
<appender>
: 로그 형태 설정, 로그 메세지 출력 대상(콘솔, 파일) 결정<encoder>
:<appender>
하위에 위치해 로그메세지 변환 역할<pattern>
:<encoder>
하위에 위치해 로그의 출력 포맷설정<root>
: 로그 전역 설정 로그를 출력할 패키지, 레벨 설정<logger>
: 로그 지역 설정additivity
값은<root>
설정 상속 유무<file>
: 로그 기록할 파일명, 경로<rollingPolicy>
: 로그 파일을 교체하는 정책을 정하는 태그<fileNamePattern>
:rollingPolicy
하위에서 로그 파일 패턴 설정<property>
: 값을 정하는 프로퍼티<springProperty>
:application.yml
의 값을 가져올 수 있는 태그<springProfile>
: 스프링 프로필에 따라 값 설정하는 태그<timeBasedFileNamingAndTriggeringPolicy>
: 파일 교체하는 트리거 내용 설정<maxFileSize>
: 파일 최대 크기 설정(<timeBasedFileNamingAndTriggeringPolicy>
하위 설정)<maxHistory>
: 파일 최대 저장 기한 설정(<timeBasedFileNamingAndTriggeringPolicy>
하위 설정)<totalSizeCap>
: 파일 전체 크기를 설정해 넘을시 오래된 파일부터 삭제(<timeBasedFileNamingAndTriggeringPolicy>
하위 설정)
콘솔 로그 출력 설정
<!-- logback.spring.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 로그 출력 패턴 property -->
<property name="LOG_PATTERN" value="%-5level %d{yy-MM-dd HH:mm:ss}[%thread] [%logger{0}:%line] - %msg%n"/>
<!-- application.yml의 source에 해당하는 값 가져옴 -->
<springProperty scope="context" name="LOG_LEVEL" source="logging.level.test"/>
<!-- ch.qos.logback.core.ConsoleAppender클래스를 지정하여 콘솔에 로그 출력 설정 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- 위에 정의한 LOG_PATTERN으로 패턴 설정 -->
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- jpabook.jpashop.test 패키지 지역의 로그 설정 -->
<logger name="jpabook.jpashop.test" level="warn" additivity="true">
<appender-ref ref="CONSOLE"/>
</logger>
<!-- 프로젝트 전역 로그 설정 -->
<root level="info">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
#application.yml
logging:
level:
test: warn
jpabook.jpashop.test
결과
위 결과를 보면 warn
2번, error
두번이 출력됐다.
이유는 <logger>
태그에 additivity=true
가 선언됐기 때문인데 additivity
는 부모 <logger>
, <root>
의 appender
를 상속할지 여부이다.
additivity=true
이면 <logger>
의 부모인 <root>
의 appender
도 표현되기 때문에 두번씩 출력되는 결과를 볼 수 있다. 다시 말하면 additivity=false
이면 <root>
로 전달되지 않고 <logger>
의 appneder
만 출력된다.
파일 로그 출력 설정
<!-- logback-spring.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 로그 패턴 -->
<property name="LOG_PATTERN" value="%-5level %d{yy-MM-dd HH:mm:ss}[%thread] [%logger{0}:%line] - %msg%n"/>
<!-- application.yml의 source에 해당하는 값 가져옴 -->
<springProperty scope="context" name="LOG_LEVEL" source="logging.level.test"/>
<!-- profile이 local인 경우 property 설정-->
<springProfile name="local">
<property name="PATH" value="./logs/test-local.log"/>
</springProfile>
<!-- ch.qos.logback.core.rolling.RollingFileAppender클래스를 지정하여 여러 파일을 순회하며 로그 저장 설정 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 파일 경로 및 이름 -->
<file>${PATH}</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<!-- 로그파일을 교체하는 정책 TimeBasedRollingPolicy: 시간 단위 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 파일 이름 -->
<fileNamePattern>./logs/time.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 특정 액션에 따라 파일 교체 -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 최대 사이즈 -->
<maxFileSize>5KB</maxFileSize>
<!--<maxHistory>10</maxHistory>--> <!-- 파일의 최대 저장 기한 -->
<!--<totalSizeCap>3GB</totalSizeCap>--> <!-- 전체 파일 크기를 제어하며, 용량을 초과하면 가장 오래된 파일 삭제 -->
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<root level="info">
<appender-ref ref="FILE"/>
</root>
</configuration>
#application.yml
spring:
profiles:
active: local
logging:
level:
test: info
위에서 보면 <springProfile>
을 local
로 설정했기에 test-local.log
라는 이름으로 로그 파일 생성된 것을 볼 수 있다.
참고
'스프링' 카테고리의 다른 글
[JPA] 낙관적, 비관적 Lock 개념/예제 (0) | 2023.04.02 |
---|---|
[스프링] 멀티 모듈(Multi Module) 개념/예제 feat. Gradle (3) | 2021.12.19 |
[Kafka] Kafka Connect 개념/예제 (0) | 2021.10.16 |
[Spring Cloud] Eureka 개념 및 예제 (0) | 2021.09.13 |
[스프링] Validation 방법(Validator, Bean Validation) 설명/예제 (0) | 2021.08.07 |