스프링에서 외부 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' 카테고리의 다른 글
[Spring] Multipart 전송 시 Json 데이터 같이 보낼 경우 주의점 (1) | 2024.01.04 |
---|---|
[Spring Rest Docs] Enum, 예외 코드 문서화를 위한 Custom Snippet 생성(AbstractFieldsSnippet) (0) | 2023.12.28 |
[Spring] IntelliJ 디버깅시 JPA 지연 로딩(Lazy Loading) 주의점 (0) | 2023.12.03 |
[Spring] 커스텀 Validator 적용 (ConstraintValidator) (0) | 2023.11.27 |
[Spring] 트랜잭션과 @Transacional 사용하는 이유 (0) | 2023.05.02 |