새소식

반응형
Spring/etc

[Spring] 예외처리 @ExceptionHandler @ControllerAdvice

  • -
반응형

Unchecked Exception 발생 시 처리하는 방법이 다양하게 존재합니다.

그중에서도 @ControllerAdvice @ExceptionHandler를 조합해서 사용하는 방법을 가장 많이 사용하는 것 같습니다.

해당 방법에 대해서 정리해보도록 하겠습니다.

 

@ControllerAdvice

ControllerAdvice 여러 컨트롤러에 대해 전역적으로 ExceptionHandler 적용해줍니다.

ControllerAdvice 어노테이션에는 @Component 어노테이션이 있어서 ControllerAdvice 선언된 클래스는 스프링 빈으로 등록됩니다.

에러를 핸들링하는 클래스를 만들어 @ControllerAdvice 어노테이션을 붙여주면 에러 처리를 위임할 있습니다.

 

범위 설정

@ControllerAdvice는 모든 에러를 잡아주기 때문에, 일부 에러만 처리하고 싶을 경우에는 따로 설정을 해주면 됩니다.

  1. annotations
  2. basePackages
  3. assignableTypes
// 1.
@ControllerAdvice(annotations = TestController.class)
public class TestExampleAdvice1 {
}

// 2.
@ControllerAdvice("org.test.example.controllers")
public class TestExampleAdvice2 {
}

// 3.
@ControllerAdvice(assignableTypes = {TestControllerInterface.class, TestAbstractController.class})
public class TestExampleAdvice3 {
}

 

Spring은 스프링 예외를 미리 처리해둔 ResponseEntityExceptionHandler를 추상 클래스로 제공하고 있습니다. ResponseEntityExceptionHandler에는 스프링 예외에 대한 ExceptionHandler가 모두 구현되어 있으므로 ControllerAdvice 클래스가 이를 상속받게 하면 됩니다. 

 

만약 추상 클래스를 상속받지 않는다면 스프링 예외들은 DefaultHandlerExceptionResolver 처리하게 되는데,

그러면 자신이 개발한 예외 처리방식과 기본적으로 제공하는 예외 처리기가 달라지므로

클라이언트가 일관되지 못한 에러 응답을 받지 못하므로 ResponseEntityExceptionHandler 상속시키는 것이 좋습니다.

또한 이는 기본적으로 에러 메세지를 반환하지 않으므로, 스프링 예외에 대한 에러 응답을 보내려면 ResponseEntityExceptionHandler의 몇몇 메서드를 오버라이딩 하는것이 좋습니다.

 

(https://docs.spring.io/spring-framework/docs/5.3.23/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html

 

@ExceptionHandler

@ExceptionHandler는 다음에 어노테이션을 추가함으로써 에러를 손쉽게 처리할 수 있습니다.

  • 컨트롤러의 메서드
  • @ControllerAdvice @RestControllerAdvice 있는 클래스의 메소드

Exception 클래스들을 속성으로 받아 처리할 예외를 지정할 있습니다.

만약 ExceptionHandler 어노테이션에 예외 클래스를 지정하지 않는다면, 파라미터에 설정된 에러 클래스를 처리하게 됩니다.

( https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html )

 

 

사용 예시

@RestController
@RequiredArgsConstructor
public class ProductController {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {
        ...
    }

}
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.