On this page
지난번 스프링부트 RestTemplate 예외처리를 알아보았는데요. RestTemplate
과 WebClient
는 HTTP 요청을 보내기 위한 두 가지 다른 도구이며, 예외 처리 방식에서도 차이가 있습니다. RestTemplate
은 동기식 HTTP 요청을 처리하고, WebClient
는 비동기식으로 HTTP 요청을 처리합니다. 두 가지 도구 모두 예외를 발생시키지만, 비동기식인 WebClient
의 예외 처리는 약간 다릅니다.
WebClient 예외 처리 개념 및 원리
WebClient
비동기적으로 요청을 처리하기 때문에 예외 처리도 비동기 방식으로 처리해야 합니다. 이를 위해 onStatus
, onErrorMap
, doOnError
등의 메서드를 사용하여 예외를 처리할 수 있습니다.
WebClient 설정 및 예외 처리
WebClient
를 사용할 때, 예외 처리를 위한 방법은 두 가지가 있습니다:
- 전역 예외 처리기 사용:
@ControllerAdvice
와@ExceptionHandler
를 사용하여 전역적으로 예외를 처리합니다. - WebClient 요청 내에서 예외 처리:
WebClient
요청 자체에서 예외를 처리합니다.
전역 예외 처리기 설정
전역 예외 처리기를 사용하여 WebClient
에서 발생한 예외를 처리할 수 있습니다. 이 방법은 주로 API 응답을 통합적으로 관리할 때 유용합니다.
예제 코드
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.reactive.function.client.WebClientResponseException;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(WebClientResponseException.class)
public ResponseEntity<String> handleWebClientResponseException(WebClientResponseException ex) {
String responseBody = ex.getResponseBodyAsString();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(ex.getHeaders().getContentType());
return new ResponseEntity<>(responseBody, headers, ex.getStatusCode());
}
}
WebClient 요청 내에서 예외 처리
WebClient
요청 자체에서 예외를 처리할 수 있습니다. 이를 통해 요청을 보낼 때마다 개별적으로 예외를 처리할 수 있습니다.
예제 코드
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;
public class WebClientService {
private final WebClient webClient;
public WebClientService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("<http://your-api-server-url>").build();
}
public Mono<String> requestAction(String requestActionSetDtoJson) {
return webClient.post()
.uri("/action/requestAction")
.bodyValue(requestActionSetDtoJson)
.retrieve()
.onStatus(HttpStatus::is4xxClientError, clientResponse ->
clientResponse.bodyToMono(String.class)
.flatMap(body -> Mono.error(new WebClientResponseException(
clientResponse.rawStatusCode(),
clientResponse.statusCode().getReasonPhrase(),
clientResponse.headers().asHttpHeaders(),
body.getBytes(),
null
)))
)
.onStatus(HttpStatus::is5xxServerError, clientResponse ->
clientResponse.bodyToMono(String.class)
.flatMap(body -> Mono.error(new WebClientResponseException(
clientResponse.rawStatusCode(),
clientResponse.statusCode().getReasonPhrase(),
clientResponse.headers().asHttpHeaders(),
body.getBytes(),
null
)))
)
.bodyToMono(String.class)
.doOnError(WebClientResponseException.class, ex -> {
// 추가적인 로깅이나 예외 처리
log.error("WebClientResponseException: ", ex);
});
}
}
WebClient와 RestTemplate의 차이
- 동기/비동기:
RestTemplate
은 동기식으로 작동하고,WebClient
는 비동기식으로 작동합니다. - 예외 처리:
RestTemplate
은 일반적인 예외 처리 방법을 사용하고,WebClient
는 비동기식 예외 처리 방법을 사용합니다. - 기능 확장성:*
WebClient
는 더 많은 기능을 제공하고, 비동기적이고 반응형 프로그래밍을 지원합니다.
결론
WebClient
와 RestTemplate
모두 예외 처리를 지원하지만, 사용 방법이 다릅니다. WebClient
는 비동기 방식으로 작동하므로 예외 처리도 비동기적으로 처리해야 합니다. 전역 예외 처리기를 사용하거나 개별 요청 내에서 예외를 처리하여 원하는 방식으로 예외를 처리할 수 있습니다.
이제 여러분도 WebClient
와 RestTemplate
를 활용하여 예외를 깔끔하게 처리할 수 있을 거예요. 도움이 필요하면 언제든지 댓글로 질문해 주세요! Happy coding! 😊