Spring Boot 예외 처리 @ControllerAdvice, @ExceptionHandler

Spring Boot 예외 처리 @ControllerAdvice, @ExceptionHandler

728x90

반응형

'스프링 부트 @ControllerAdvice, @ExceptionHandler를 이용한 예외 처리'

프로그래밍에서 예외처리는 아주 중요한 부분입니다. 예외가 발생할 수 있는 부분에서 예외를 잡아서 세밀하게 처리해준다면 클라이언트 측면에서와 서버 측면에서 모두 더 안정적인 프로그램이 될 수 있습니다.

일반적으로 예외를 처리해야 하는 상황에서 각각의 예외들을 메서드 단에서 try-catch 또는 throw로 처리하게 되면 코드가 복잡해질 수밖에 없습니다. 이러한 문제를 개선하기 위해 Spring Boot에서는 @ExceptionHandler, @ControllerAdvice(+ @RestControllerAdvice)를 사용합니다.

@RestController @RequiredArgsConstructor @RequestMapping("/webClient") public class WebClientController { ... @ExceptionHandler(IllegalStateException.class) public ResponseEntity catchException(Exception e) { System.out.println("e class" + e.getClass()); return null; } }

@ExceptionHandler

먼저 @ExceptionHandler 같은 경우에는 @Controller, @RestController가 적용된 Bean 내에서 발생하는 예외를 잡아 하나의 메서드에서 처리해주는 기능을 합니다.

(Controller 단에서만 사용 가능하며, @Service 등 다른 곳에서는 사용할 수 없습니다.)

@ExceptionHandler({IllegalStateException.class, NullPointerException.class})

사용법은 @ExceptionHandler 어노테이션 안에 인자로 캐치하고 싶은 예외 클래스를 등록해주면 되며, 위 같은 방식으로 두 개 이상의 예외도 등록할 수 있습니다.

* 정리하자면 해당하는 Controller 안에서 발생하는 Exception 중 ExceptionHandler에 등록된 Exception을 모두 해당 메서드를 통해 처리하는 방식입니다.

(WebClientController 안에서 발생하는 모든 IllegalStateException을 catchException() 메서드에서 처리합니다.)

@RestControllerAdvice public class ExceptionAdvice { ... @ExceptionHandler(NotFoundException.class) public ResponseEntity notFoundException() { ... } @ExceptionHandler(SecurityException.class) public ResponseEntity SecurityException(Exception e) { ... } @ExceptionHandler public ResponseEntity defaultException(Exception e) { ... } }

@ControllerAdvice, @RestControllerAdvice

다음으로 프로젝트 전역에서 발생하는 예외를 한 곳에서 처리하는 방법입니다.

@ControllerAdvice 어노테이션을 통해 모든 컨트롤러에서 발생하는 예외를 잡습니다. 그리고 @ExceptionHandler 어노테이션을 통해 발생하는 예외의 종류마다 처리할 메서드를 정의합니다. 설정이 완료되면 Controller에서 예외 처리하는 코드를 작성하지 않아도 @ControllerAdvice 어노테이션이 적용된 ExceptionAdvice 클래스에서 예외를 잡아서 처리하게 됩니다.

(만약 예외가 발생하는 메서드에서 try-catch를 통해 예외를 직접 처리하면 가까이 있는 try-catch의 예외처리가 우선순위로 작동합니다.)

@RestControllerAdvice("com.example.exception.api.test")

위 코드처럼 @ControllerAdvice 어노테이션 안에 범위를 지정해줌으로써 패키지 단위로 예외를 잡을 수도 있습니다.

(패키지 구성과 예외 범위를 생각해서 구조를 짜면 잘 활용할 수 있습니다.)

***

@ControllerAdvice와 @RestControllerAdvice의 차이는 무엇일까요?

먼저 알아야할 것은 @Controller에서 발생하는 예외를 @RestControllerAdvice에서 잡을 수 있고, 반대로 @RestController에서 발생한 예외를 @ControllerAdvice에서 잡을 수 있다는 것입니다.

@RestControllerAdvice 어노테이션에는 @ControllerAdvice 어노테이션과 @ResponseBody 두 개의 어노테이션이 모두 포함되어 있습니다. 이것은 @ControllerAdvice와 동일한 역할 즉, 예외를 잡아 핸들링할 수 있도록 하는 기능을 수행하면서 @ResponseBody를 통해 객체를 리턴할 수도 있다는 의미입니다.

결론적으로 API 서버의 역할로 에러 응답 객체를 리턴해야 한다면 JSON 형식으로 변환하기 위해 @RestControllerAdvice 어노테이션을 사용해야 하고, viewResolver를 통해서 바로 예외 처리 페이지를 보여준다고 하면 @ControllerAdvice 어노테이션을 사용해야 합니다.

@ResponseStatus(code = HttpStatus.NOT_FOUND) @ResponseStatus(code = HttpStatus.FORBIDDEN)

@ResponseStatus

예시에서 자주 함께 등장하는 @ResponseStatus는 컨트롤러나 예외에 사용하여 HTTP 응답 코드를 설정할 수 있는 어노테이션입니다.

< 함께 보면 좋은 자료 >

< 참고 자료 >

728x90

반응형

from http://wildeveloperetrain.tistory.com/108 by ccl(A) rewrite - 2021-12-30 01:27:51