@ControllerAdvice는 Spring MVC에서 전역적으로 예외 처리를 하거나, 컨트롤러의 공통 기능을 분리하여 관리하기 위해 사용하는 어노테이션이다.
특히 예외 처리에 대해 서술하면, 컨트롤러에서 발생하는 예외를 전역적으로 처리하기 위해 사용된다. 이때 컨트롤러에서 예외가 발생한다고 하는 이유는, 컨트롤러가 서비스 로직을 호출하고, 그 호출 과정에서 발생한 예외도 컨트롤러로 전파되기 때문이다. 전파된 예외의 흐름은 다음과 같다.
예외 처리 메서드에서 @ExceptionHandler와 함께 사용할 수 있고, 특정 예외만 따로 처리도 가능하다.
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception ex) {
return new ResponseEntity<>("Error: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@RestControllerAdvice는 @ControllerAdvice에 @ResponseBody가 더해진 것으로 REST API를 처리하는 컨트롤러에 특화된 전역 설정을 제공한다. 다음과 같이 DTO를 반환하여 JSON으로 응답할 수 있다.
@RestControllerAdvice
public class ExceptionController {
/**
* MethodArgumentNotValidException은 Spring Validation를 사용할 때
* 요청 본문에서 전달된 데이터가 유효성 검사에 실패하면 발생한다.
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ErrorResponse exceptionHandler(MethodArgumentNotValidException e) {
ErrorResponse response = ErrorResponse.builder()
.code("400")
.message("잘못된 요청입니다.")
.build();
e.getFieldErrors().forEach(error ->
response.addValidation(error.getField(), error.getDefaultMessage()));
return response;
}
}
위에서 작성한 ExceptionController는 클라이언트의 잘못된 요청이 Spring Validation에 의해 검증되며 MethodArgumentNotValidException이 발생하는데 이 예외를 처리하게 된다. 이때 ErrorResponse는 다음과 같은 JSON 형태이다.
/**
{
"code": "400",
"message": "잘못된 요청입니다.",
"validation": {}
}
테스트를 위해서 회원가입 로직을 작성해 /api/join에 잘못된 요청을 보내본다.
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
@PostMapping("/api/join")
public void join(@RequestBody @Validated JoinRequest request) {
memberService.join(request);
}
}
POST http://localhost:8080/api/join
Content-Type: application/json
{
"email": "",
"name": "테스트",
"password": "1234"
}
우선 ExceptionController가 없다면 다음과 같이 Spring Boot의 기본적인 예외 응답 포맷으로 반환된다.
{
"timestamp": "2024-12-08T09:27:31.835+00:00",
"status": 400,
"error": "Bad Request",
"path": "/api/join"
}
ExceptionController를 정상적으로 작성하면 다음과 같이 예외 응답을 커스텀할 수 있다.
{
"code": "400",
"message": "잘못된 요청입니다.",
"validation": {
"email": "이메일을 입력해 주세요."
}
}
@ControllerAdvice는 주로 View 기반의 애플리케이션에서 사용되며, 뷰 리졸버(View Resolver)를 통해 HTML, JSP와 같은 뷰를 반환한다.@RestControllerAdvice는 REST API에 최적화되어 있으며, @ResponseBody가 기본으로 포함되어 있어, HTTP 응답 본문에 데이터를 직접 반환한다.