ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RestTemplate, WebClient
    Spring/Spring Boot 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가 먼저 찍혀서 나온 이유다.

     

Designed by Tistory.