Spring - WebClient 사용해보기
개요
SpringBoot, Spring 환경에서 WebClient 를 사용하여 API Request 를 하는 클라이언트 프로젝트를 만들어보기.
서버와 API 통신을 위해 필요한게 무엇인지 알고 WebClient 의 기능사용해보기.
Why ?
WebClient 란? Spring 5.0에서 추가된 interface 이다. 이전 버전에서는 클라이언트로 RestTemplate 를 사용했으나,
비동기식 통신의 필요성으로 인해 WebClient 가 나오게 되었고, 현재 버전에서는 WebClient로 개발하는게 권장되는 상황이다.
그렇다면 RestTemplate 와 WebClient 가 어떤차이점이 있을까 ?
RestTemplate 와 WebClient 의 차이점을 보기쉽고 간편하게 볼 수 있도록 표로 비교해보자
Rest Template | Web Client |
Blocking IO, 동기식(Synchronous) | Non-Blocking IO, 비동기식(Asynchronous) |
RESTful 원칙을 사용하며 단순화된 통신 | JSON, XML 을 쉽게 받고 응답 |
멀티쓰레드 방식 | 싱글쓰레드 방식 |
JAVA Servlet API | Spring Reactive Framwork |
그리고 가장 중요한 점은 당장 RestTemplate 로 구현한 코드를 바꿀필요는 없지만, Spring 5.0 이후 버전에서
RestTemplate가 Deprecated 되었고, 앞으로 개발이 필요한 Client 의 경우 WebClient 를 사용하는 것이 좋다는 점이다.
그렇다면 어떻게 WebClient 를 사용할 수 있을지 알아보자.
의존성 설정
Gradle
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-webflux', version: '2.6.7'
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.6.7</version>
</dependency>
구현
String response = WebClient.create()
.post()
.uri("http//test.com")
.contentType(MediaType.APPLICATION_JSON) // Request Type JSON
.acceptCharset(Charset.forName("utf-8")) // CharSet Setting
.body(BodyInserters.fromMultipartData(builder.build())) // body : Request Params key&value , content type 'urlencode'
.retrieve().bodyToMono(String.class)
.block();
위 코드의 내용을 차근차근 살펴보자.
String response = WebClient.create()
먼저 WebClient.create() 를 통해 클라이언트를 생성한다고 선언하며,
.post()
.uri("http//test.com")
Request 를 보낼 Method가 Get, Post, Put, Delete 중 무엇인지 Method를 선언하고, 보내는 URL을 입력합니다.
.contentType(MediaType.APPLICATION_JSON) // Request Type JSON
.acceptCharset(Charset.forName("utf-8")) // CharSet Setting
혹시모를 상황에 대비해서 Content Type 과 Charset 설정을 위해 위와같이 JSON, UTF-8 이라는 설정을 추가합니다.
그리고 body, head등에 필요한 내용을 담을 수 있으나, 예제에서 저는 body만 사용했습니다.
.body(BodyInserters.fromMultipartData(builder.build())) // body : Request Params key&value , content type 'urlencode'
그리고 body에 BodyInserters.fromMultipartData 를 사용했는데, 이는 Body 에 File등 여러가지 타입의 정보를 넣어야할 때
반응 스트림, 서버 전송 이벤트, 리소스 등과 같은 다양한 본문을 작성하는 코드를 구현하기 위해 필요합니다. 그리고 그 안에
bulider.build() 를 사용했는데 예제의 경우 body를 JSON이 아닌 urlencode type으로 보내야했기때문에 builder를 사용했는데,
기본적으로 WebClient 에서는 JSON타입으로 DTO, 객체등 다양한 타입을 지원하기 때문에 별다른 처리를 안해줘도 되는 경우가 있다.
.retrieve().bodyToMono(String.class).block();
마지막으로 retrieve() 메소드는 내가 결과값으로 받을 응답값을 추출하는 방법을 선언하기 위한 chaning method이다.
toEntity() , bodyToMono(), bodyToFlux(), 등 다양한 방식으로 얻을 수 있는데,
Mono 가 무엇이냐면, 한개의 값만 리턴받으면 될 때 사용하며 복수의 리턴값을 받아야 할 경우에는 bodyToFlux 를 사용한다.
이처럼 하나하나 사용해보면 매우 직관적인 메소드를 지원하여 간편하게 Client를 구현할 수 있고, 비동기식의 안정적인 요청과 응답을 통해 서버에 가하는 리소스가 줄어들어 매우 효과적이다.
Spring이 새삼 얼마나 큰 Framework 인지 실감하는 부분이다.. 공부해야할게 많다.
참조
https://madplay.github.io/post/difference-between-resttemplate-and-webclient
https://tecoble.techcourse.co.kr/post/2021-07-25-resttemplate-webclient/