0. 이 글을 쓰게된 이유
미션을 진행하며 (Rest)ControllerAdvice를 사용하여 예외를 처리하였다. 원래 (Rest)ControllerAdvice가 예외를 처리할 때에만 사용하는줄 알았는데 활용할 수 있는 부분이 많은 기능이었다. 그 부분에 대해 알아보기 위해 이 글을 쓰게 되었다.
1. @(Rest)ControllerAdvice란?
Spring 공식 문서에 따르면 @(Rest)ControllerAdvice가 붙은 빈은 모든 @Controller이 붙은 빈에서 사용하는 @ExceptionHandler, @InitBinder, @ModelAttribute(글 쓰기 쉽게 세가지 기능이라고 부르겠다.)가 붙은 메소드들을 한번에 처리할 수 있도록 해주는 기능이다.
Controller에서 @ExceptionHandler, @InitBinder, @ModelAttribute를 활용해서 각각의 기능을 처리할 수 있다. 이렇게 controller 내에서 정의된 세가지 기능들은 해당 controller에서만 적용된다. 만약 전역적으로 세가지 기능을 사용하고 싶다면 (Rest)ControllerAdvice를 활용하면 된다.
2. @(Rest)ControllerAdvice에서 사용할 수 있는 기능
위에서 얘기했듯이 (Rest)ControllerAdvice에서는 @ExceptionHandler, @InitBinder, @ModelAttribute를 사용할 수 있다. 간단하게 각각의 기능들에 대해서 알아보자.
2.1 @ExceptionHandler
@ExceptionHandler 는 @(Rest)Controller 가 적용된 Bean에서 발생하는 예외를 잡아서 하나의 메서드에서 처리해주는 기능이다.
만약 어떠한 예외처리를 모든 Controller에 대해 전역적으로 사용하고싶다면 @ExceptionHandler를 @ControllerAdvice가 붙은 빈에서 사용하면 된다.
아래는 예시이다.
@RestControllerAdvice
public class ControllerAdvice {
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<ExceptionDto> handleIllegalArgumentException(final IllegalArgumentException exception) {
final ExceptionDto exceptionDto = new ExceptionDto(exception.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(exceptionDto);
}
}
2.2 @InitBinder
@InitBinder는 @(Rest)Controller 가 적용된 Bean에서 바인딩 또는 검증 설정을 변경하고 싶을때 사용된다.
만약 그 바인딩 설정을 모든 Controller에 대해 전역적으로 사용하고싶다면 @InitBinder를 @ControllerAdvice가 붙은 빈에서 사용하면 된다.
아래는 예시이다.
@RestControllerAdvice
public class ControllerAdvice {
@InitBinder("RaceResult")
public void initBind(final WebDataBinder webDataBinder) {
webDataBinder.setDisallowedFields("id");
}
}
2.3 @ModelAttribute
@ModelAttirbute는 @Controller 가 적용된 Bean에서 웹 뷰로 넘겨주는 데이터 폼인 model의 attribute를 설정해주도록 한다. @ModelAttribute는 메소드와 파라미터에 붙을 수 있다.
만약 그 Model 설정을 모든 Controller에 대해 전역적으로 사용하고싶다면 @ModelAttribute @ControllerAdvice가 붙은 빈에서 사용하면 된다.
아래는 예시이다.
@ControllerAdvice
public class ControllerAdvice {
@ModelAttribute
public void handleRequest(HttpServletRequest request, Model model) {
String requestURI = request.getRequestURI();
model.addAttribute("appVer", Const.AppVer);
model.addAttribute("uri", requestURI);
}
}
이렇게 되면 모든 view의 model에서 appVer, uri는 공통적으로 사용할 수 있게 된다.
3. 주의점
@ControllerAdvice를 사용하게되면 주의할 점이 있다.
만약 @Controller에서 @ExceptionHandler, @InitBinder, @ModelAttribute를 사용하고 @ControllerAdvice에서 @ExceptionHandler, @InitBinder, @ModelAttribute를 사용하면 뭐가 우선순위를 가질까?
DispatcherServlet에서 Exception을 처리할 때 Controller에 있는 ExceptionHandler가 먼저 우선 순위를 가진다. 그래서 Controller에 있는 @ExceptionHandler가 먼저 실행되어서 처리하게 된다.
'Spring' 카테고리의 다른 글
[Spring] ViewResolver 코드 파보기 (0) | 2023.05.04 |
---|---|
[Spring] 필터(Filter)와 인터셉터(Interceptor) (0) | 2023.04.19 |
[Spring] @Valid, @Validated 동작 원리 (0) | 2022.10.20 |
[Spring] Spring Security에 대해서 알아보자(로그인 인증 구조) (0) | 2022.09.28 |
[Spring] Spring Security에 대해서 알아보자(동작 과정편) (0) | 2022.09.28 |