Spring/Spring Boot
RestTemplate, WebClient
100win10
2020. 7. 13. 01:56
- 스프링 부트는 Rest Template을 쉽게 사용할 수 있도록 빈을 등록해준다.
- 이때 빈은 RestTemplateBuilder를 빈으로 등록해 준다.
- Builder를 주입받아서 필요시마다 Build를 하고 RestClient를 생성해서 사용할 수 있다.
- WebClient는 WebClient.Builder를 빈으로 등록해준다.
RestTemplate과 WebClient의 차이?
RestTemplate
Blocking I/O 기반의 Synchronous API
순서가 있는 처리
WebClient
Non-Blocking I/O 기반의 Asynchronous API
순서 없는 처리
- 다음과 같이 "/hello" URI는 5초를 쉬고 "/world" URI는 3초를 쉬는 핸들러를 만들어보자.
- 그리고 이 API 서버에 클라이언트를 가정하고 RestRunner를 만들자.
- 다음과 같은 RestRunner는 restTemplateBuilder를 주입받은 후 "/hello"와 "/world"를 호출할 것이다.
- restTemplate을 통해 해당 결과들을 String 타입으로 바로 받아올 수 있다.
- restTemplate은 Blocking Synchronous I/O이기 때문에 "/hello"를 마친다음에 "/world"를 가게 된다.
- 즉 순차 실행이며 메서드가 처리되기 전까지 다음 라인으로 가지 않는다.
- 결과를 보면 5초 후에 helloResult를 출력하고 3초 후에 worldResult를 출력하게 될 것이다.
- 따라서 총 8초가 걸리게 된다.
WebClient를 살펴보자.
- WebClient를 사용하기 위해서는 webflux 의존성을 넣어주어야 한다.
1
2
3
4
|
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
|
cs |
- RestRunner을 다음과 같이 바꾸어주자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
@Component
public class RestRunner implements ApplicationRunner {
@Autowired
WebClient.Builder builder;
@Override
public void run(ApplicationArguments args) throws Exception {
WebClient webClient = builder.build();
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// TODO /hello
Mono<String> helloMono = webClient.get().uri("http://localhost:8080/hello")
.retrieve()
.bodyToMono(String.class);
helloMono.subscribe(s -> {
System.out.println(s);
if(stopWatch.isRunning()) {
stopWatch.stop();
}
System.out.println(stopWatch.prettyPrint());
stopWatch.start();
});
// TODO /world
Mono<String> worldMono = webClient.get().uri("http://localhost:8080/world")
.retrieve()
.bodyToMono(String.class);
worldMono.subscribe(s -> {
System.out.println(s);
if(stopWatch.isRunning()) {
stopWatch.stop();
}
System.out.println(stopWatch.prettyPrint());
stopWatch.start();
});
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
}
}
|
cs |
- subscribe를 통해 요청을 보내는데 요청을 보내는 동안 응답이 오면 asynchronous 하게 처리가 된다.
- 따라서 응답처리를 기다리지 않는다. 이는 '/hello' URI가 앞에 있지만 world가 먼저 찍혀서 나온 이유다.