Spring WebFlux에서 글로벌 예외 처리를 구현하는 방법은 기존의 Spring MVC와 동일하게 @ControllerAdvice와 @ExceptionHandler를 사용하는 것이다.
@ControllerAdvice는 @Controller 애노테이션이 적용된 모든 클래스에 대한 전역적인 처리를 제공한다. 이 클래스 내부에 @ExceptionHandler애노테이션을 사용하여 특정 예외 타입에 대한 핸들링 로직을 정의할 수 있다.
애플리케이션의 모든 예외를 처리할 @ControllerAdvice 클래스를 생성한다. 이 클래스는 @RestControllerAdvice로 선언하여 @ResponseDoby를 포함시킬 수도 있다.
@RestControllerAdvice
public class GlobalExceptionHandler {
// 예외 처리 메서드를 작성
}
GlobalExceptionHandler 클래스 내부에 특정 예외를 처리할 메소드를 @ExceptionHandler와 함께 작성한다.
이 메소드는 예외 타입(ex: IllegalArgumentException)을 인자로 받으며, Mono<ResponseEntity<?>>를 반환한다.
@RestControllerAdvice
public class GlobalExceptionHandler {
// 사용자 정의 예외 처리
@ExceptionHandler(IllegalArgumentException.class)
public Mono<ResponseEntity<String>> handleIllegalArgumentException(IllegalArgumentException ex) {
return Mono.just(ResponseEntity.badRequest().body("잘못된 요청입니다: " + ex.getMessage()));
}
// 일반적인 예외 처리
@ExceptionHandler(Exception.class)
public Mono<ResponseEntity<String>> handleAllExceptions(Exception ex) {
// 모든 종류의 예외를 처리하는 핸들러
return Mono.just(ResponseEntity.internalServerError().body("서버 오류가 발생했습니다: " + ex.getMessage()));
}
}
위와 같이 IllegalArgumentException과 같은 특정 예외를 처리하는 핸들러와 그 외의 모든 예외를 처리하는 일반적인 핸들러를 함께 정의할 수 있다.
다음은 @ControllerAdvice를 사용하여 클로벌 예외 처리를 구현한 전체 예제이다.
// Controller
@RestController
public class InvalidExceptionController {
@GetMapping("/users/{id}")
public Mono<String> getUser(@PathVariable String id) {
if ("유효하지 않은 ID".equals(id)) {
// "invalid" ID에 대해 의도적으로 예외 발생
return Mono.error(new IllegalArgumentException("유효하지 않은 사용자 ID입니다."));
}
return Mono.just("User " + id + " found");
}
}
// Global Exception Handler
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
public Mono<ResponseEntity<String>> handleIllegalArgumentException(IllegalArgumentException ex) {
// HTTP 400 Bad Request와 함께 에러 메시지 반환
return Mono.just(ResponseEntity.badRequest().body("잘못된 요청: " + ex.getMessage()));
}
@ExceptionHandler(Exception.class)
public Mono<ResponseEntity<String>> handleAllExceptions(Exception ex) {
// HTTP 500 Internal Server Error와 함께 에러 메시지 반환
return Mono.just(ResponseEntity.internalServerError().body("서버 오류: " + ex.getMessage()));
}
}
이 예제에서 /users/invalid 엔드포인트로 요청이 오면 InvalidExceptionController는 IllegalArgumentException을 발생시킨다.
이 예외는 GlobalExceptionHandler의 handleIllegalArgumentException메소드에 의해 감지되어 400 응답이 클라이언트에게 반환된다.