WebClient에 대하여

송성우·2023년 12월 19일

기업프로젝트에서 캐시서버를 만들면서 서버 간의 통신이 필요하게 되었다.
보통의 웹과 서버의 통신이 아닌, 서버와 서버끼리의 통신을 위해 찾아보게 되었다.

  • RestTemplate : Blocking방식
  • WebClient : Blocking/Non-Blocking방식

동기와 blocking, 비동기와 Non-blocking은 다르다.

이 두가지로 통신을 할 수 있다
여기서 더 좋다고 하는 WebClient에 대해 알아보겠다.(추가로 UriComponentsBuilder => URI 조립)


역사

기존의 Spring에서는 HTTP 요청을 할 때 RestTemplate을 사용했다.
하지만 버전이 새로 나오면서 WebClient를 강력히 권고하고 있다.

WebClient의 특징은 다음과 같다.

  • Non-blocking I/O
  • Reactive Streams back pressure
  • High concurrency with fewer hardware resources
  • Functional-style, fluent API that takes advantage of Java 8 lambdas
  • Synchronous and asynchronous interactions
  • Streaming up to or streaming down from a server

사용법

0. 의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-webflux'

1. Configration에 추가

작성방법

  • Static factory를 통하 WebClient 생성
    WebClient.create();

  • 추가적인 작업을 위해서는 Builder클래스를 통해 생성하는 것이 좋다.

@Configuration
public class WebClientConfig {

	DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();

	HttpClient httpClient = HttpClient.create()
		.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000); // HttpClient 총 연결 시간: 10초

	@Bean
	public WebClient webClient() { // WebClient 인스턴스를 생성하기 위한 Bean 설정
		return WebClient.builder()
			.uriBuilderFactory(factory)
			.baseUrl("http://mainHost:8080") // WebClient의 기본 URL 설정
			.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024)) // 응답 데이터를 저장하기 위한 최대 메모리를 2MB로 제한 
			.clientConnector(new ReactorClientHttpConnector(httpClient)) // WebClent에 대한 클라이언트 커넥션 설정
			.build();
	}
    @Bean
    public ConnectionProvider connectionProvider() { // 커넥션 풀에서 연결을 관리하는데 사용
        return ConnectionProvider.builder("http-pool")
                .maxConnections(100) // 커넥션 풀의 개수
                .pendingAcquireTimeout(Duration.ofMillis(0)) // 풀에서 커넥션을 얻기 위해 기다리는 최대 시간
                .pendingAcquireMaxCount(-1) // 풀에서 커넥션을 가져오기 위한 시도 횟수
                .maxIdleTime(Duration.ofMillis(1000L)) // 연결이 제거되기 전에 풀에서 유휴 상태를 유지하는 시간
                .build();
    }
    
}

2. 메소드별 사용법

들어가기 앞서, Response를 받기 위한 방법은 2가지가 있다

  • retrieve() : repsonse를 받아 디코딩하는 가장 간단한 메소드

    • bodyToMono() : Response의 body만 받아온다
    • toEntity() : Response의 header, status, body를 받아온다.
  • exchange() : 5.3버전에서 deprecated되었으며, exchangeToMono 혹으 exchangeToFlux를 사용하자

2.1 GET

return webClient.get()
			.uri("")
			.retrieve()
			.bodyToMono(String.class)
			.log()
			.block();

GET에서는 RequestBody를 제공 X

2.2 POST

return webClient.post()
			.uri("")
            .bodyValue(body)
			.retrieve()
			.bodyToMono(String.class)
			.log()
			.block();

2.3 DELETE

return webClient.delete()
			.uri("")
			.retrieve()
			.bodyToMono(String.class)
			.log()
			.block();

DELETE에서는 RequestBody를 제공 X

2.4 PUT

return webClient.put()
			.uri("")
            .bodyValue(body)
			.retrieve()
			.bodyToMono(String.class)
			.log()
			.block();

UriComponentsBuilder 사용법

Reference

profile
소통을 지향하며 성장하는 것이 목표입니다.

0개의 댓글