스프링에서 외부 API 호출을 위해 RestTemplate, WebClient을 제공하는데 스프링 부트 3.2 버전부터 정식으로 RestClient가 추가되었다.

  • 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.

WebClient, HttpInterface를 사용하면 직관적이고 깔끔하게 구현할 수 있지만 webflux 의존성을 추가해야 되는 단점이 있다. RestClient는 새로운 동기식 HTTP 클라이언트로 WebClient와 유사한 API로 사용할 수 있다. 이전에는 HttpInterface를 사용하려면  WebClient를 사용했어야 했는데 스프링 6.1부터 HttpExchangeAdapter의 구현체로 RestClientAdapter와 RestTemplateAdapter 둘 다 사용할 수 있게 되었다.

이번에 카카오맵 API를 사용하면서 RestClient, HttpInterface를 사용했는데 RestClient는 create() 혹은 builder를 통해 생성할 수 있고 builder를 사용하면 추가로 baseUrl, header, statusHandler 등 여러 설정을 할 수 있다.

 

 

build() 내부를 보면 설정이 없는 경우 여러 초기화 작업을 해준다. RestTemplate, RestClient는 내부적으로 HTTP 통신을 위해 Apache HttpComponents를 사용한다.

 

 

RestClient 설정시 ClientRequestFactory를 추가할 수 있는데 ClientHttpRequestFactory는 HttpClient, ConnectionManager 등의 설정을 할 수 있다.

RestClient.Builder에서 HttpComponents5 라이브러리를 직접 추가하지 않으면 SimpleClientHttpRequestFactory가 default로 들어간다. SimpleClientHttpRequestFactory를 그대로 사용하면 운영 환경에서 많은 문제가 생길 수 있어서 HttpComponentsClientHttpRequestFactory를 사용하는 것이 좋다.

(원래 HttpComponentsClientHttpRequestFactory가 default인데 라이브러리를 따로 추가하지 않은 경우 발생하는 문제이다.)

 

HttpComponentsClientHttpRequestFactory를 생성할 수가 없어서 주석을 보니 스프링 부트3 버전대에서 HttpComponents 5.1 이상 라이브러리를 추가로 필요로 한다고 나와있다.

 

HttpComponents 5.2.x 버전을 추가하고 다시 보면 default가 HttpComponentsClientHttpRequestFactory로 바뀌고 HttpComponentsClientHttpRequestFactory 또한 직접 생성해서 설정할 수도 있다.

 

하지만..! 스프링 부트 3.2 기준으로 HttpComponents 5.2.x 버전을 추가하면 HttpInterface Proxy 생성이 안 되는 문제가 있어서 최신 버전인 5.3으로 추가해야 한다

 

HttpComponentsClientHttpRequestFactory 내부에는 httpClient의 default ConnectionManager로 PoolingHttpClientConnectionManager가 주입이 되어 있다. PoolingHttpClientConnectionManager는 커넥션 풀을 사용하여 커넥션 관련 설정을 custom 할 수 있다.

 

 

HttpComponentsClientHttpRequestFactory는 상황에 따라 타임 아웃, 커넥션 풀 등의 설정을 통해 변경할 수 있다.

 

 

HttpInterface는 아래와 같이 인터페이스, 애노테이션 기반으로 정의를 해서 직관적으로 사용할 수 있다.

 

 

현재는 직접 해당 인터페이스의 프록시 구현체를 만들어서 Bean으로 등록해주어야 한다.

 

 

이렇게 설정한 외부 API 호출을 테스트하려면 @RestClientTest를 활용할 수 있다. 주의점은 RestTemplate, RestClient를 주입받는 Bean에서 파라미터로 RestTemplateBuilder or RestClient.Builder를 사용해야 한다. 그래서 위에 HttpInterface를 Bean으로 등록할 때 RestClient.Builder를 파라미터로 사용했다.

 

RestClientTest는 최소한의 Context로 테스트를 실행하기 때문에 테스트할 HttpInterface를 value에 추가해 주었다. MockRestServiceServer는 외부 API를 테스트하기 위한 Mock 서버이다

 

 

테스트는 간단하게 예상 Response 등을 설정해 주고 mockServer에 설정을 해준 뒤에 예상 경로로 요청이 가는지, 바인딩이 제대로 되는지 등의 테스트를 검증한다.

 

 

RestClient는 custom 메시지 컨버터를 추가할 수 있지만 default로 등록된 컨버터 중 MappingJackson2HttpMessageConverter가 json 응답을 객체에 바인딩해 준다.

 

 

[참고]

 

Spring Boot에서 외부 API 테스트하기

안녕하세요? 이번 시간엔 Spring Boot의 @RestClientTest 예제를 진행해보려고 합니다. 모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다. 1. 문제 상황 예를 들어 외부 API를

jojoldu.tistory.com

 

RestTemplate 사용시 주의사항 - Incheol's TECH BLOG

ResponseEntity response = restTemplate.exchange(" ", HttpMethod.GET, requestEntity, String.class);

incheol-jung.gitbook.io

 

Apache HttpComponent 제대로 사용하기

Java 어플리케이션에서 일반적으로 http호출을 할때 Apache HttpClient를 사용하며 http client가 버전업을 하여 Apache HttpComponent로 변경된것은 아마 다들 알고있는 사항일것입니다. (아주 옛날에 바꼈으니

inyl.github.io

 

+ Recent posts