Spring Boot 로그 시스템 정리 – SLF4J, Logback, Log4j2 차이는 뭘까?
Spring Boot 프로젝트를 하다 보면 @Slf4j 써서 로그 찍고, logback-spring.xml 만들어서 설정하고, 가끔 누군가는 @Log4j2를 쓰기도 한다. 나도 Spring을 처음 배울땐 아무 생각 없이 @Slf4j 를 사용하고 있었고, 블로그 글을 보면서 대충 넘겼다. 시간이 많이 지난 지금에서야 내 블로그에 정리해본다.
1. SLF4J: 그저 추상화일 뿐
SLF4J(Simple Logging Facade for Java)는 말 그대로 Facade다. 즉, 진짜 로그를 찍는 애가 아니라, "찍어줘~"라고 부탁만 하는 애다.
개발자는 log.info("hello")라고 쓰면 되고, 실제로 어디에 어떻게 출력할지는 SLF4J 뒤에 있는 **구현체(Logback, Log4j, Log4j2 등)**가 알아서 처리한다.
장점?
- 코드에서는 SLF4J만 쓰면 되니까, 나중에 로깅 구현체를 바꿔도 코드 손댈 필요가 없다.
- 유연하고 중립적이다.
2. Logback: Spring Boot 기본값
Spring Boot는 기본적으로 Logback을 로깅 구현체로 쓴다.
이건 명시적으로 선언하지 않아도 spring-boot-starter-web만 넣으면 자동으로 따라온다. 왜냐하면 이 안에 spring-boot-starter-logging이 포함돼 있고, 그 안에 Logback 관련 의존성이 들어있기 때문이다.
그리고 설정은 logback-spring.xml로 한다.
이 파일을 보면 <appender>나 <springProfile> 같은 태그가 있고, 로그 패턴이나 저장 경로, 파일 롤링 등을 세세하게 지정할 수 있다.
장점?
- Spring Boot랑 찰떡궁합
- 별도 설정 없이도 바로 동작
- 대부분의 프로젝트에 무난하고 안정적임
3. Log4j2: 성능 괴물
Log4j의 후속 버전인 Log4j2는 성능에 진심이다. 아파치에 따르면 멀티쓰레드 환경에서 비동기 로거의 경우 처리량이 18배 높고 대기시간이 더 짧다.
GC 영향 적은 구조, 비동기 로깅, 커스텀 Appender 등 고급 기능이 많다. 로그양이 많거나 성능 튜닝이 필요한 경우엔 Logback보다 낫다.
근데 Spring Boot에서 기본으로 안 쓰기 때문에 Logback을 제거하고 Log4j2로 갈아끼워야 한다.
갈아끼우는 법은?
- spring-boot-starter-logging 제거
- spring-boot-starter-log4j2 추가
- 설정 파일도 log4j2-spring.xml로 바꿔야 함
설정 문법도 완전 다르다. <Configuration>부터 <Appenders>, <Loggers> 같은 구조로 되어 있어서, Logback 쓰던 감성으로는 안 된다.
4. @Slf4j vs @Log4j2
Lombok이 제공하는 이 로그 어노테이션들… 똑같아 보이지만 내부는 다르다.
@Slf4j | SLF4J API (org.slf4j.Logger) |
@Log4j2 | Log4j2 API (org.apache.logging.log4j.Logger) |
즉, @Slf4j는 어떤 구현체가 뒤에 있든 상관없이 SLF4J 인터페이스만 쓴다.
유연하고 유지보수하기 좋다. 나중에 Logback → Log4j2로 갈아탈 때도 코드 안 고쳐도 된다. 설정만 바꾸면 된다.
@Log4j2는 아예 Log4j2 전용이다.
5. 정리
- SLF4J는 그냥 추상화. 실제로 로그는 안 찍는다.
- Logback은 Spring Boot의 기본 로깅 구현체. logback-spring.xml로 설정.
- @Slf4j는 SLF4J 기반이라 유연함. @Log4j2는 Log4j2 전용.
- Log4j2를 쓰면 될 듯 하다. 하지만 ThreadContext등 Log4j2 전용 기능을 사용하면 구현체(Log4j2)에 강하게 묶이게 될 수 있다.
덧붙임
“왜 로그 라이브러리 하나에 이렇게 복잡해?”라고 생각할 수도 있다.
근데 나중에 로그가 수천 줄씩 터질 때, 누가 메모리를 많이 잡아먹는지, 비동기로 돌릴 수는 있는지 등등이 중요해진다.
언젠가 꼭 필요한 개념이다.
'Spring' 카테고리의 다른 글
JPA에서 save()는 언제 의미가 있을까? – 더티 체킹과의 차이 (1) | 2025.06.17 |
---|---|
Spring Boot 통합 테스트 가이드 (1) | 2025.06.13 |
SpringBoot static 변수에 @value 사용 (0) | 2025.01.17 |
JPA - SELECT 보다 UPDATE 쿼리가 먼저 나가는 경우 (flush, 변경감지) (0) | 2025.01.07 |