Spring 어플리케이션에서 HTTP 요청을 할 땐 주로 RestTemplate 을 사용했었습니다. 하지만 Spring 5.0 버전부터는 RestTemplate 은 유지 모드로 변경되고 향후 deprecated 될 예정입니다.
RestTemplate 의 대안으로 Spring 에서는 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
Reactive 환경과 MSA를 생각하고 있다면 WebClient 사용을 적극 권장해 드리며, 기본 설정부터 Method 별 사용법까지 차근차근 알아보도록 하겠습니다.
1. RestTemplate이란?
spring 3.0 부터 지원한다. 스프링에서 제공하는 http 통신에 유용하게 쓸 수 있는 템플릿이며, HTTP 서버와의 통신을 단순화하고 RESTful 원칙을 지킨다. jdbcTemplate 처럼 RestTemplate 도 기계적이고 반복적인 코드들을 깔끔하게 정리해준다. 요청보내고 요청받는데 몇줄 안될 정도..
특징
- 기계적이고 반복적인 코드를 최대한 줄여줌
- RESTful형식에 맞춤
- json, xml 를 쉽게 응답받음
2. RestTemplate 의 동작원리
org.springframework.http.client 패키지에 있다. HttpClient는 HTTP를 사용하여 통신하는 범용 라이브러리이고, RestTemplate은 HttpClient 를 추상화(HttpEntity의 json, xml 등)해서 제공해준다. 따라서 내부 통신(HTTP 커넥션)에 있어서는 Apache HttpComponents 를 사용한다. 만약 RestTemplate 가 없었다면, 직접 json, xml 라이브러리를 사용해서 변환해야 했을 것이다.
- 어플리케이션이 RestTemplate를 생성하고, URI, HTTP메소드 등의 헤더를 담아 요청한다.
- RestTemplate 는 HttpMessageConverter 를 사용하여 requestEntity 를 요청메세지로 변환한다.
- RestTemplate 는 ClientHttpRequestFactory 로 부터 ClientHttpRequest 를 가져와서 요청을 보낸다.
- ClientHttpRequest 는 요청메세지를 만들어 HTTP 프로토콜을 통해 서버와 통신한다.
- RestTemplate 는 ResponseErrorHandler 로 오류를 확인하고 있다면 처리로직을 태운다.
- ResponseErrorHandler 는 오류가 있다면 ClientHttpResponse 에서 응답데이터를 가져와서 처리한다.
- RestTemplate 는 HttpMessageConverter 를 이용해서 응답메세지를 java object(Class responseType) 로 변환한다.
- 어플리케이션에 반환된다.
예제
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
public class RestTemplateTest {
public static void main(String[] args) {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setReadTimeout(5000); // 읽기시간초과, ms
factory.setConnectTimeout(3000); // 연결시간초과, ms
HttpClient httpClient = HttpClientBuilder.create().setMaxConnTotal(100) // connection pool 적용
.setMaxConnPerRoute(5) // connection pool 적용
.build();
factory.setHttpClient(httpClient); // 동기실행에 사용될 HttpClient 세팅
RestTemplate restTemplate = new RestTemplate(factory);
String url = "http://testapi.com/search?text=1234";
Object obj = restTemplate.getForObject("요청할 URI 주소", "응답내용과 자동으로 매핑시킬 java object");
System.out.println(obj);
}
}
1. WebClient이란?
WebClient는 Spring5 에 추가된 인터페이스다. spring5 이전에는 비동기 클라이언트로 AsyncRestTemplate를 사용을 했지만 spring5 부터는 Deprecated 되어 있다. 만약 spring5 이후 버전을 사용한다면 AsyncRestTemplate 보다는 WebClient 사용하는 것을 추천한다. 아직 spring 5.2(현재기준) 에서 AsyncRestTemplate 도 존재하긴 한다.
기본 문법
기본적으로 사용방법은 아주 간단하다. WebClient 인터페이스의 static 메서드인 create()를 사용해서 WebClient 를 생성하면 된다. 한번 살펴보자.
@Test
void test1() {
WebClient webClient = WebClient.create("http://localhost:8080");
Mono<String> hello = webClient.get()
.uri("/sample?name={name}", "wonwoo")
.retrieve()
.bodyToMono(String.class);
StepVerifier.create(hello)
.expectNext("hello wonwoo!")
.verifyComplete();
}
@Test
void test2() {
WebClient webClient = WebClient.create();
Mono<String> hello = webClient.get()
.uri("http://localhost:8080/sample?name={name}", "wonwoo")
.retrieve()
.bodyToMono(String.class);
StepVerifier.create(hello)
.expectNext("hello wonwoo!")
.verifyComplete();
}
@Test
void test1_3() {
WebClient webClient = WebClient.create();
Mono<String> hello = webClient.get()
.uri("http://localhost:8080/sample?name=wonwoo")
.retrieve()
.bodyToMono(String.class);
StepVerifier.create(hello)
.expectNext("hello wonwoo!")
.verifyComplete();
}
@Test
void test1_3() {
WebClient webClient = WebClient.create("http://localhost:8080");
Mono<String> hello = webClient.get()
.uri("/sample?name={name}", Map.of("name", "wonwoo"))
.retrieve()
.bodyToMono(String.class);
StepVerifier.create(hello)
.expectNext("hello wonwoo!")
.verifyComplete();
}
@Test
void test1_3() {
WebClient webClient = WebClient.create("http://localhost:8080");
Mono<String> hello = webClient.get()
.uri("/sample?name={name}", "wonwoo")
.retrieve()
.bodyToMono(String.class);
StepVerifier.create(hello)
.expectNext("hello wonwoo!")
.verifyComplete();
}
@Test
void test1_3() {
WebClient webClient = WebClient.create("http://localhost:8080");
Mono<String> hello = webClient.get()
.uri(it -> it.path("/sample")
.queryParam("name", "wonwoo")
.build()
).retrieve()
.bodyToMono(String.class);
StepVerifier.create(hello)
.expectNext("hello wonwoo!")
.verifyComplete();
}
'JAVA' 카테고리의 다른 글
java 리스트간 비교, 값 체크 (0) | 2021.02.24 |
---|---|
Kafka (0) | 2021.02.24 |
비동기, 동기, 블로킹, 논블로킹 (0) | 2021.02.19 |
JAVA11 (0) | 2019.10.04 |
Oracle JDK 라이센스 전환 (0) | 2019.10.04 |