RestTemplate 의 maintenance mode로 전환
Spring 에서 주로 사용했던 HTTP Client인 RestTemplate이 maintenance mode 로 들어가고, Webclient 로 대체해서 사용하길 권장한다는 것이다. 아래는 spring docs 의 한 부분이다.
NOTE:
As of 5.0 this class is in maintenance mode, with only minor requests for changes and bugs to be accepted going forward. Please, consider using the
org.springframework.web.reactive.client.WebClient
which has a more modern API and supports sync, async, and streaming scenarios.
RestTemplate 를 모두 사용해 봤다면 알겠지만 RestTemplate 은 사용이 꽤나 불편하다. Client 클래스가 아니라 Template 클래스이기 때문이다. 이를 해결하기 위해 Webflux 위에서 동작하는 WebClient 를 개발했고, 이를 적극적으로 사용할 것을 권장했다.
하지만, 문제가 있었다. Webflux 위에서 동작하기 때문에 이 무거운 의존성을 포함해야 하기 때문이었다. 동기적으로만 HTTP Client 를 간단하게 사용할 사람은 의존성을 포함하는 것이 무겁게 느껴졌다.
그래서 Spring 6.1 그리고 Spring Boot 3.2 부터 새로운 HTTP Client인 RestClient가 추가되었다.
스프링 공식문서에서 다음과 같이 설명한다.
The Spring Framework provides the following choices for making calls to REST endpoints:
RestClient - synchronous client with a fluent API.
WebClient - non-blocking, reactive client with fluent API.
RestTemplate - synchronous client with template method API.
HTTP Interface - annotated interface with generated, dynamic proxy implementation.
모든 내용들은 스프링 공식문서에서 참고했다. https://docs.spring.io/spring-framework/reference/integration/rest-clients.html
REST Clients :: Spring Framework
WebClient is a non-blocking, reactive client to perform HTTP requests. It was introduced in 5.0 and offers an alternative to the RestTemplate, with support for synchronous, asynchronous, and streaming scenarios. WebClient supports the following: Non-blocki
docs.spring.io
RestClient
사용하려면, 먼저 다음과 같이 RestClient를 생성해야 한다.
RestClient restClient = RestClient.builder()
.requestFactory(new HttpComponentsClientHttpRequestFactory())
.messageConverters(converters -> converters.add(new MyCustomMessageConverter()))
.baseUrl("https://example.com")
.defaultUriVariables(Map.of("variable", "foo"))
.defaultHeader("My-Header", "Foo")
.requestInterceptor(myCustomInterceptor)
.requestInitializer(myCustomInitializer)
.build();
그 후, 이 restClient를 사용한다.
ResponseEntity<String> result = restClient.get()
.uri("/home")
.retrieve()
.toEntity(String.class);
System.out.println("Response status: " + result.getStatusCode());
System.out.println("Response headers: " + result.getHeaders());
System.out.println("Contents: " + result.getBody());
사용방법은 정말 어렵지 않다.
HttpExchange
HttpExchange 어노테이션은 Spring6에서 제공된 기능으로 인터페이스 기반으로 자동으로 구현해주는 기능이다. open feign 과 유사하게 간편한 방식을 Spring 에서 공식적으로 지원하지만, 이전까지는 WebClient 만을 지원해서 Webflux 를 포함해야 하는 점이 문제였다. 이제 HttpExchange가 RestClient 도 지원하므로 다음과 같이 설정하면 쉽게 사용할 수 있다.
아래의 코드는 다음 프로젝트에서 사용한 알라딘 오픈 API 를 통해 책 정보를 받아오는 코드이다.
https://github.com/BookitList/BookitList_backend
GitHub - BookitList/BookitList_backend: BookitList_backend
BookitList_backend. Contribute to BookitList/BookitList_backend development by creating an account on GitHub.
github.com
먼저, 인터페이스부터 만든다.
메소드에는 @GetExchange 등의 어노테이션과 baseUrl 이후의 부분을 적으면 된다. 그리고 @RequestParam과 파라미터에 들어갈 것들을 적어주면 된다.
@Component
@HttpExchange
public interface AladinComponent {
@GetExchange("/ItemSearch.aspx")
String findAllByQuery(@RequestParam String TTBKey, @RequestParam String Query, @RequestParam String Output, @RequestParam int Start, @RequestParam int MaxResults, @RequestParam int Version);
@GetExchange("/ItemLookUp.aspx")
String findByIsbn13(@RequestParam String TTBKey, @RequestParam String ItemId, @RequestParam String ItemIdType, @RequestParam String Output, @RequestParam int Version);
}
이제 이 인터페이스를 구현할 설정 클래스를 작성한다.
baseUrl 과 함께 RestClient를 만들고, HttpServiceProxyFactory 를 통해 위에 코딩한 인터페이스를 구현해서 스프링 빈으로 등록하면 된다.
@Configuration
public class RestClientConfig {
@Bean
public AladinComponent aladinService() {
RestClient restClient = RestClient.builder()
.baseUrl("http://www.aladin.co.kr/ttb/api")
.build();
RestClientAdapter adapter = RestClientAdapter.create(restClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
return factory.createClient(AladinComponent.class);
}
}
이제 인터페이스에 작성한 메소드를 다음과 같이 사용하면 된다.
밑의 코드는 응답을 그대로 객체로 deserialize 하지 않고, 파싱한 후에 객체로 만들어야 하기 때문에 JSONObject 를 사용했다.
JSONObject json = new JSONObject(aladinComponent.findAllByQuery(aladinKey, keyword, "JS", start, maxResults, 20131101));
마지막에 소개한 이 방법이 현재 Spring 에서 사용하는 HTTP Client 방법 중 가장 좋은 방법이라고 생각된다.
RestTemplate 의 직관적이지 않은 템플릿 메소드의 단점, Open Feign 의 공식적으로 지원하지 않는 단점, WebClient 의 Webflux 를 추가해야 하는 단점을 모두 해결한 방법이다.
'Spring Boot' 카테고리의 다른 글
Auto Increment에서 Tsid로의 전환 (0) | 2024.11.23 |
---|---|
JWT 총정리 (2) - Access Token, Refresh Token (1) | 2024.03.08 |
JWT 총정리 (1) - JWT의 원리와 흐름 (1) | 2023.10.09 |
Git in IntelliJ - 인텔리제이에서 Git의 모든 것 (2) (0) | 2023.02.03 |
Git in IntelliJ - 인텔리제이에서 Git의 모든 것 (1) (0) | 2023.01.27 |