본문 바로가기

소프트웨어-이야기/프로그래밍 언어와 프레임워크

spring boot 3.2에서 HTTP 통신하는 방법 아는 체하기

RestClient

Restclient가 등장했다. 

https://docs.spring.io/spring-framework/reference/integration/rest-clients.html#rest-restclient 

restclient와 virtual thread 조합을 사용하면, non blocking 통신을 쉽게 구현할 수 있다. 

 

RestClient와 ClientRequestFactory

RestClient는 HttpClient를 사용한다. 그리고 이 값은 ClientRequestFactory으로 조정할 수 있다.

ClientRequestFactory와 관련 클라이언트 정보는 다음과 같다. 

Factory Client  
JdkClientHttpRequestFactory Java’s HttpClient  
HttpComponentsClientHttpRequestFactory Apache  HttpClient * HttpComponentsClientHttpRequestFactory을 사용하려면, Apache Client를 설치해야한다. 
* ConnectionPool 등 커넥션 정보를 미세조정하려면 HttpComponentsClientHttpRequestFactory를 사용해야한다.
* 고가용성이 필요한 서버에 추천한다. 
JettyClientHttpRequestFactory Jetty’s HttpClient  
ReactorNettyClientRequestFactory Reactor Netty’s HttpClient  
SimpleClientHttpRequestFactory simple default * SimpleClientHttpRequestFactory은 퍼포먼스에 문제가 생길 수 있다.
* 운영에서는 사용을 지양한다. 

RestClient는 빌드할 때, classpath에 Apache Client나 Jetty Client 라이브러리가 있으면, 이를 사용한다. 그렇지 않으면 기본 클라이언트를 사용한다. 

RequestFactory를 지정해줬으면 이 값을 사용한다.

없으면 HttpComponentsClientHttpRequestFactory → JettyClientHttpRequestFactory → JdkClientHttpRequestFactory 순으로 탐색한다. 만약 그마저도 없으면 SimpleClientHttpRequestFactory을 사용한다. 

 

RestClient 주의사항

(1) Client가 플랫폼 쓰레드를 만드는지 확인하자.

기본 RestClient은 기본적으로 플랫폼 쓰레드를 사용한다. 그래서 가상쓰레드를 적용하려면 HttpClient의 executor를 지정해야한다. 

RestClient.builder()
                .baseUrl(baseUrl)
                .requestFactory(new JdkClientHttpRequestFactory(
                        HttpClient.newBuilder()
                                  // 이렇게 가상쓰레드를 지정해야한다.
                                  .executor(Executors.newVirtualThreadPerTaskExecutor())  // Configure to use virtual threads
                                  .build()))
                .build();

Apache Client는 virtual thread에서 생성된 요청은 virtual thread으로 실행된다. (maybe..?)

 

(2) Client Http 버전을 확인하자. 

  • 기본 HttpClient의 HTTP 버전은 HTTP/2 이다. 
  • 반면, Apache Client의 HTTP 버전은 NEGOTIATE이다.
    • 상대 서버에서 HTTP/2를 지원하면, HTTP/2으로 통신한다. 그게 아니면 HTTP/1으로 통신한다. 

 

HTTP interface 

Http Interface를 사용하면 fegin client처럼 선언형으로 http 요청/응답 함수를 정의할 수 있다.

interface ChatGptClient {

	@GetExchange("/v1/chat/completions")
	ChatCompletionResponseDto getCompletions(ChatCompletionRequest Dto request);
}

 

 

interface를 정의했다고 Spring이 자동으로 client를 인식하지는 못한다.

아래와 같이 HttpServiceProxyFactory으로 인터페이스의 클라이언트를 만들어서 사용해야한다. 

RestClient openApiClient = RestClient.builder().baseUrl("https://api.openai.com").build();
RestClientAdapter adapter = RestClientAdapter.create(restClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();

// 인터페이스로 클라이언트 구현체 생성 
ChatGptClient chatGptClient = factory.createClient(ChatGptClient.class);

client는 bean으로 등록한 후, 서비스에서 주입받아 사용한다.

public class ChatServiceImpl implements ChatService {

	private final CahtGptClient chatGptClient; 

	public String chat(String message){
		...

		ChatCompletionResponseDto response = chatGptClient.getCompletion(request);
		..
        
		return message; 
	}
}

HTTP Interface의 클라이언트 구현체는 HttpClient, WebClient, RestTemplate 을 선택할 수 있다. 

 

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

 

참고