WebClient 사용하기

Yeeun_Kim·2023년 7월 18일
0
post-thumbnail

0. 개요

공공데이터 포탈에서 데이터를 조회하고 그에 따른 데이터를 받기 위해 어떠한 방식으로 API요청을 보내고 데이터를 받는 것이 성능적인 측면에서 더 좋은 성능을 낼 수 있을지 고찰해보았다.


1. RestTemplate VS WebClient

1-1. Rest Template 란?

HTTP 통신에서 사용하는 템플릿으로 HTTP 서버와의 단순한 통신을 위한 함수를 제공하는 클래스다.

  • Spring 3.0부터 지원
  • RESTful 형식 지원
  • HTTP 요청을 수행하는 동기식(Synchronous) 클라이언트(Blocking I/O 기반)

1-2. WebClient 란?

웹에서 API를 호출하기 위해 사용하는 Http Client 모듈 중 하나로 기존의 동기식 API 방식 뿐만 아니라 Non-Blocking 및 비동기 방식을 지원한다.

  • Spring 5.0부터 지원
  • Single Thread방식을 사용
  • Non-Blocking 방식 사용
  • 리액티브 타입의 전송과 수신(Mono, Flux)

공식문서에 따르면 확장성이 넓은 WebClient를 RestTemplate 대신 사용하라고 명시되어 있다.


2. WebClient 사용

WebClient를 사용하기 위해 WebClient에 대한 설정을 해주었다.

WebClientConfig.java

@Configuration
public class WebClientConfig {
    @Value(value = "${base-url}")
    private String baseUrl;

    @Bean
    public WebClient webClient() {
        HttpClient httpClient = HttpClient.create()
                //Connection Timeout 설정
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
                //Read and Write Timeout 설정
                .doOnConnected(conn -> conn
                        .addHandlerLast(new ReadTimeoutHandler(10))
                        .addHandlerLast(new WriteTimeoutHandler(10)))
                //응답 Timeout 설정
                .responseTimeout(Duration.ofSeconds(2));

        return WebClient.builder()
                .baseUrl(baseUrl)
                //Spring WebFlux에서 Application Memory문제 피하기 위해 in-memory buffer 값이 256KB로 기본 설정
                //256KB보다 큰 HTTP 메시지 처리 시도 -> DataBufferLimitException 에러 발생 : in-memory buffer 값 늘리기
                .codecs(configurer -> {
                    configurer.defaultCodecs().maxInMemorySize(1024 * 1024); //1MB
                })
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .build();
    }
}

여러 WebClient에 대한 글과 공식문서를 참고하여 위와 같이 WebClient를 설정하였다.

NtsOpenApiService.java

@Service
@RequiredArgsConstructor
public class OpenApiService {
    @Value(value = "${secret}")
    private String secretKey;

    private final WebClient webClient;

    private final String path = "/~/해당 path data";

	//POST API 요청 예시
    public StatusDto getApiData(String param){

        MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
        formData.add("param", param);

        return webClient.post()
                .uri(uriBuilder -> uriBuilder.path(path + "/add-path").queryParam("serviceKey", secretKey).build())
                .bodyValue(formData)
                .retrieve()
                // 에러가 발생 했을 경우 Exception 발생
                .onStatus(HttpStatus::isError, clientResponse ->
                        clientResponse.bodyToMono(Error.class).flatMap(error -> Mono.error(
                                new AbleRuntimeException(error.getMessage())
                        )))
                .bodyToMono(StatusDto.class)
                .block();
    }
}

formData에 param으로 보낼 데이터를 넣고, POST방식으로 WebClient를 사용한 코드이다.

WebClient와 RestTemplate의 가장 큰 차이점은 WebClient는 Non-Blocking방식이고, RestTemplate Blocking방식인 것이지 않을까 생각한다. 또한 현재 공식문서에서는 RestTemplate보다 WebClinet의 사용을 권장하고 있기 때문에 WebClient를 사용하여 외부 API를 호출하는 것이 더 좋을 것이라 생각한다.

0개의 댓글