로그 메시지 출력 SLF4J (@Slf4fj) 로 디버깅하기

1. SLF4J (@Slf4j) 사용 이유
디버깅에 필요한 정보를 출력할 때 System.out.println(...) 을 사용하곤 했는데, 사실 이는 바람직한 방법은 아니다.
1. 코드 유지보수 어려움
1-1. 디버깅이 끝나면 println 출력문을 일일이 제거해야 하고
1-2. 많은 출력문이 코드 곳곳에 남아있으면 가독성이 저하된다.
2. 성능 문제
2-1. System.out.println() 은 동기적으로 실행된다. 이는 I/O (input/output) 작업이므로 속도 저하를 초래할 수 있다.
특히 반복문에서 많이 호출될 경우 성능 저하가 심해질 수 있다.
3. 출력 관리의 어려움
3-1. 모든 출력이 콘솔(console)에 섞여 나오므로 필요한 정보를 찾기 어렵다.
가장 간단하지만 여러 문제를 초래하는 System.out.println(...) 의 디버깅 대안으로는
1. JUnit 단위 테스트 구현
2. 로그 메시지 출력 등이 있다.
이 포스트에서는 두번째 방법인 로그 메시지 출력 기능 SLF4J 를 다룬다.
2. SLF4J 란?
SLF4J(Simple Logging Facade for Java) 는 로깅 프레임워크에 대한 추상화(인터페이스) 역할을 하는 라이브러리다.
이게 무슨 소리냐.
Java 에서는 로그를 남길 때 log4j, logback, java.util.logging 같은 다양한 로깅 프레임워크를 사용할 수 있다.
그런데 프로젝트마다 다른 로깅 프레임워크를 쓰면 유지보수가 어려워진다.
이런 문제를 해결하기 위해 로깅 프레임워크의 공통 인터페이스 역할을 해주는 라이브러리가 바로 SLF4J 다.
SLF4J 를 사용하는 코드에서는 Logger 인터페이스만 사용하고, 실제로 어떤 로깅 프레임워크를 쓸지는 설정만 바꾸면 된다.
3. SLF4J 사용하기
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Controller
public class LoggingController {
private static final Logger log = LoggerFactory.getLogger(LoggingController.class);
@GetMapping("/")
public String index() {
log.info("info 레벨 로그 테스트");
return "logging";
}
}
위 코드는 slf4j 의 기본틀이다.
사용할 로깅 프레임워크로 설정하기만 하면 바로 로깅 시스템을 사용할 수 있다.

Spring Boot 는 logback 을 기본 로깅 프레임워크로 사용하며,
기본적으로 INFO 레벨부터 출력된다.
로그 레벨 | 설명 |
error | 에러 발생 |
warn | 에러까지는 아니지만, 큰 성능 하락 등 위험한 상황 |
info | 서버 시작, 연결 성공 등 중요한 이벤트 |
debug | 디버깅을 위해 필요한 여러가지 정보 출력 |
trace | 사소한 정보 출력 |
로그 레벨은 가장 심각한 error 단계부터 사소한 정보를 출력하는 trace 까지 존재한다.
기본 설정은 INFO 레벨부터 출력하기 때문에 debug 단계의 로그를 출력하기 위해선 application.properties 설정이 필요하다.
logging.level.root=info # 모든 패키지에 info 레벨 이상 로그 출력
logging.level.net.logging=debug # net.logging 패키지에 속한 클래스들만 debug 레벨 이상 로그 출력
전체 패키지에 로그 레벨을 설정할 수도 있고,
특정 패키지의 클래스에만 레벨을 설정할 수도 있다.
@GetMapping("/")
public String index() {
log.info("info 레벨 로그 테스트");
log.debug("debug 레벨 로그 테스트");
return "logging";
}

디버깅이 끝나면 application.properties 에 작성한 debug 설정만 지우면 된다.
디폴트 설정이 info 이므로 log.debug(...) 출력은 무시되기 때문이다.
4. @Slf4j 사용하기
Lombok 에서 제공하는 @Slf4j 로깅 어노테이션 사용으로 더 간편한 설정을 할 수 있다.
클래스에 자동으로 @SLF4J 기반의 Logger 객체를 생성해준다.
@Controller
@Slf4j
public class LoggingController {
@GetMapping("/")
public String index() {
log.info("info 레벨 로그 테스트");
log.debug("debug 레벨 로그 테스트");
return "logging";
}
}
Logger 인터페이스 사용 대신 @Slf4j 어노테이션만 붙여주면 된다.
간단한 예제로..
form 데이터를 서버로 전송받고, log.debug() 를 통해 로그로 출력해보자.
/* edit.html */
<form method="post" th:object="${student}" class="shadow">
<h1>학생 수정</h1>
<div class="row">
<label>학번:</label>
<input type="text" th:field="*{studentNo}" />
</div>
<div class="row">
<label>이름:</label>
<input type="text" th:field="*{name}" />
</div>
...
<button type="submit" class="btn">저장</button>
<span class="error" th:text="${ errorMsg }"></span>
</form>

웹브라우저에서 form 데이터에 위와 같이 입력 후 전송했다.
/* StudentController.java */
@PostMapping("edit")
public String edit(Model model, Student student) {
try {
log.debug(student.toString()); // 입력 받은 form 데이터 값(student) 출력
if (StringUtils.hasText(student.getStudentNo()) == false)
throw new Exception("학번을 입력하세요");
if (StringUtils.hasText(student.getName()) == false)
throw new Exception("이름을 입력하세요");
if (student.getDepartmentId() == 0)
throw new Exception("학과를 선택하세요");
// student 객체를 DB에 저장하는 구현 생략
return "redirect:list";
}
catch (Exception ex) {
model.addAttribute("errorMsg", ex.getMessage());
return "student/edit";
}
}

서버에 데이터를 전송하면, 다음과 같은 debug 단계의 로그를 확인할 수 있다.
'Programming > SpringBoot' 카테고리의 다른 글
[SpringBoot] 게시글 이미지(파일) 미리보기 & 업로드 (ver.팝업창) (0) | 2024.12.01 |
---|