
onErrorResume Operator를 이용한 예외 처리onErrorResume은 리액티브 스트림에서 에러가 발생했을 때, 해당 에러를 Downstream으로 전파하지 않고 대체 Publisher를 통해 정상적인 흐름을 이어가는 방법이다.
특정 예외에 대해 분기 처리하거나, 에러 내용을 감싸서 새로운 응답을 만들 수 있다.
@Component
public class BookHandler {
public Mono<ServerResponse> createBook(ServerRequest request) {
return request.bodyToMono(BookDto.Post.class)
.doOnNext(post -> validator.validate(post)) // 오타 수정
.flatMap(book -> ServerResponse
.created(URI.create("/v1/books/" + book.getBookId()))
.build()
)
.onErrorResume(BusinessLogicException.class, error -> ServerResponse
.badRequest()
.bodyValue(new ErrorResponse(HttpStatus.BAD_REQUEST, error.getMessage()))
)
.onErrorResume(Exception.class, error -> ServerResponse
.unprocessableEntity()
.bodyValue(new ErrorResponse(HttpStatus.UNPROCESSABLE_ENTITY, error.getMessage()))
);
}
}
onErrorResume을 추가해야 하므로 중복 코드 증가ErrorWebExceptionHandler를 이용한 글로벌 예외 처리Spring WebFlux는 전역 예외 처리기로 ErrorWebExceptionHandler 인터페이스를 제공한다.
이 방식을 사용하면 모든 에러를 하나의 컴포넌트에서 공통 처리할 수 있어, 코드 중복을 줄이고 예외 처리 로직을 일원화할 수 있다.
@Component
@Order(-2) // 기본 WebExceptionHandler보다 우선순위를 높게 설정
public class GlobalExceptionHandler implements ErrorWebExceptionHandler {
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
HttpStatus status;
String message;
if (ex instanceof BusinessLogicException) {
status = HttpStatus.BAD_REQUEST;
message = ex.getMessage();
} else {
status = HttpStatus.INTERNAL_SERVER_ERROR;
message = "Internal Server Error";
}
ErrorResponse errorResponse = new ErrorResponse(status, message);
byte[] bytes = serializeToJsonBytes(errorResponse); // JSON 직렬화
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
exchange.getResponse().setStatusCode(status);
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
return exchange.getResponse().writeWith(Mono.just(buffer));
}
}
| 비교 항목 | onErrorResume | ErrorWebExceptionHandler |
|---|---|---|
| 사용 위치 | 개별 시퀀스 내부 | 전역 (모든 요청) |
| 장점 | 직관적, 유연한 흐름 제어 | 일관된 예외 처리, 중복 제거 |
| 단점 | 시퀀스마다 중복 처리 필요 | 흐름에 따른 유연한 대체 처리 어려움 |
| 적합한 경우 | 특정 흐름에 대한 예외 보정 필요할 때 | 전체 시스템에 일관된 에러 응답 필요할 때 |
둘 다 상황에 따라 병행 사용할 수 있으며, 전역 핸들러로 대부분의 예외를 처리하되, 예외적으로 흐름 복구가 필요한 경우에만 onErrorResume을 사용하는 방식이 일반적이다.