WebClient에 대해...
WebClient가 단순히 RestTemplate를 대신해서 사용하는 기술이라고 생각하면 나와 같은 문제를 겪을 수 있다…
물론 RestTemplate이 장기적으로 Deprecate될 예정이고,
WebClient는 RestTemplate이 제공하지 않는 논블로킹을 지원하기 때문에
WebClient를 사용하는 편이 좋다는 것도 맞다.
WebClient의 반환 타입, Mono와 Flux
RestTemplate은 바로 Http의 응답인 ResponseEntity<?>를 반환하는 것과는 달리,
WebClient의 요청은 Mono<?> 나 Flux<?>를 반환한다.
하지만
RestTempltae의 ResponseEntity를 확인하면(디버거로 체크, 혹은 log로 찍어보면) 응답 값이 잘 나오지만,
WebClient의 Mono나 Flux를 확인해보면 응답 값을 찾을 수 없다.
Mono<Integer> mono = webClient.get()
.uri(uri)
.retrieve()
.bodyToMono(Integer.class);
- bodyToMono로 Mono 타입을 반환받더라도, mono 변수에는 응답 값이 담기지 않은 상태.
- WebClient는 이 상태로는 대상 서버를 호출조차 하지 않는다고 한다.
그래서 우선 응답 값을 확인이라도 하려면, 아래와 같이 block을 추가해주면 된다.
Integer response = mono.block();
논블로킹을 지원한다면서 굳이 또 block?
WebClient를 사용하는 이유 중, 논블로킹을 지원하는 것도 큰 부분이었는데…
정작 실제로는 사용할 때마다 block을 쓴다면 RestTemplate보다 성능적 이점이 없지 않은가? 하는 생각이 들었다.
→ 맞다. 이런 블로킹 방식을 사용하면, RestTemplate과 성능상 차이가 없고, 성능적 이점을 취하기 위해서는 아래와 같은 논블로킹 방식을 사용할 수도 있다.
논블로킹 방식
AtomicInteger response = new AtomicInteger();
List<Integer> responseList = new ArrayList<>();
webClient.get()
.uri(uri1)
.retrieve()
.bodyToMono(String.class)
.subscribe(e -> response.set(e));
webClient.get()
.uri(uri2)
.retrieve()
.bodyToFlux(String.class)
.subscribe(e -> responseList.add(e));
위 두 번의 WebClient 호출은 논블로킹으로 동작한다.
이에, 메인스레드가 종료되면 완료 여부와 무관하게 곧바로 종료된다.
때문에 메인스레드 입장에서 각 호출 처리완료를 기다려야 하고, 일반적으로 사용되는 방식은 아래와 같이 CountDownLatch를 사용하는 방식이다.
CountDownLatch cdl = new CountDownLatch(2);
AtomicInteger response = new AtomicInteger();
List<Integer> responseList = new ArrayList<>();
webClient.get()
.uri(uri1)
.retrieve()
.bodyToMono(String.class)
.subscribe(e -> response.set(e));
webClient.get()
.uri(uri2)
.retrieve()
.bodyToFlux(String.class)
.subscribe(e -> responseList.add(e));
cdl.await();
이 방식도 어차피 결과를 기다리는 거라면 블로킹이 발생하는 것인데… 또 굳이 아닌가? 하는 생각이 들 수도 있지만,
메인스레드 입장에서야 블로킹이지, 각 WebClient 호출은 논블로킹으로 호출되기 때문에 이득이 있다.
예를 들어 각 호출이 5초가 소요된다고 가정하면,
블로킹 방식은 5 + 5 = 10초가 소요되겠지만,
논블로킹 방식은 5초가 된다.
출처
[SpringBoot] SpringMVC 에서 WebClient 사용시 주의사항
https://t1.daumcdn.net/tistory_admin/favicon/tistory_favicon_32x32.ico
'코딩 > WEB 개발' 카테고리의 다른 글
Spring - RestTemplate deprecate 예정? (feat. WebClient, RestClient) (1) | 2024.02.04 |
---|---|
XSS 공격에 대해 (0) | 2023.08.20 |
Spring - RestTemplate vs. WebClient (0) | 2023.07.25 |
Spring - @PathVariable 에서 마지막 "~.com"이 짤리는 현상에 대해 (0) | 2023.07.19 |
HTTP Method의 스펙 (0) | 2023.06.28 |