들어가며
무려 1년도 더 된 이전글이 항상 내 블로그 인기글 1위인걸 볼 때마다 마음에 걸렸다.
막 개발 공부하기 시작했을 즈음 webClient에 대한 자료가 별로 없어서 정리할 겸 작성했던 글인데 관련 키워드로 검색하면 저 글이 뜨는 걸 보고... 새롭게 알게된 내용들을 조금 더 추가하고, 현재는 어떻게 사용하고 있는 지에 대해 정리를 해보고자 한다.
기본 개념이나 RestTemplate과의 차이점 등등은 공식문서나 구글에 검색하면 깔끔하게 정리된 자료가 많기에 넘어가기로 하고, 내가 사용하면서 알게 된 개념들만 적어내려가보겠다!
WebClient
최종적으로 완성될 구조는 위와 같다. 각 step 이 뭐고 어떻게 사용하는 지는 천천히 설명하기로 하겠다.
이 구조를 사용하면 아래와 같이 코드를 사용할 수 있다.
/**
* API 호출
*
* @param baseUrl 특정 API 마다 baseUrl이 다를 수 있음.
* @param path path parameter
* @param request requestBody
* @param response responseBody의 class
* @return 응답 객체
*/
public Object callApi(String baseUrl, String path, T request, Class<?> response) {
return apiWebClientBuilder.request()
.post(baseUrl, path, request)
.connectBlock(this.getHeader(), response)
.toObjectCall();
}
이런 구조를 사용한 이유?
이런 각 step 구조로 만들게 된 이유는 회사 내의 OpenApi에서 범용적으로 사용할 수 있도록하고, 메서드 체이닝 방식을 사용해서 마치 라이브러리를 사용하는 것처럼 간편하게 사용할 수 있게 하기 위해서이다.
WebClient를 각 요청마다 매번 새롭게 생성해서 사용하기에는 반복되는 코드가 많아지는 문제가 있었고, bean에 등록해서 사용하기에는 WebClient는 Immutable하기 때문에 한번 Build를 하고나면 기존 객체를 mutate해서 사용해야했기 때문에 번거롭다는 생각이 들었다.
Webclient 공식문서에는 다음과 같은 내용이 기술되어있다.
Once built, a WebClient is immutable. However, you can clone it and build a modified copy as follows:
WebClient client1 = WebClient.builder() .filter(filterA).filter(filterB).build(); WebClient client2 = client1.mutate() .filter(filterC).filter(filterD).build(); // client1 has filterA, filterB // client2 has filterA, filterB, filterC, filterD
출처 : WebClient 공식문서
따라서 최종 목표는 bean등록을 함으로써 중복되는 코드를 줄이면서도 baseUrl은 동적으로 변경할 수 있도록 구현하는 것이었다. 또, 메서드 체이닝을 할 때 메서드 호출 순서를 강제하게 함으로써 예상치 못한 문제 또한 제거하고자 했다.
구현 예제
메서드 체이닝은 각 체이닝 단계별로 Interface와 구현체를 만들고, 순차적으로 다음 단계의 구현체를 리턴하는 방식으로 구현된다.
기존에는 Builder 패턴처럼 구현하려고 했었다. 위와 같은 방식을 사용하면 각 호출마다 새로운 객체를 생성하게 되어서 메모리 낭비가 될 우려가 있었기 때문이다. 하지만 Builder 패턴처럼 구현하게 되면 메서드 호출 순서를 강제할 수 없기 때문에 문제가 발생 가능성이 있었다.
마치며
지금까지 간단하게 내가 어떻게 WebClient를 사용하고 있는지 설명해보았다.
다음 글에서는 코드를 하나씩 살펴보면서 어떻게 구현했는 지를 설명해보려고 한다.
다음글
2023.08.26 - [Study/Spring boot] - [Spring boot] WebClient 사용해보기 2-2
출처 및 참고
'Study > Spring boot' 카테고리의 다른 글
[Spring boot] SSH 터널링 구현하기 (0) | 2023.10.13 |
---|---|
[Spring boot] WebClient 사용해보기 - 모듈화 1-2 (0) | 2023.08.26 |
[JPA] 프록시(Proxy), 지연 로딩(LAZY Loading), 즉시 로딩(EAGER Loading) (0) | 2022.06.23 |
[JPA] 영속성 관리 (0) | 2022.06.21 |
[JPA] JPA, Hibernate, Spring Data JPA의 차이점 (0) | 2022.06.20 |