ABOUT ME

-

오늘
-
어제
-
-
  • SpringBoot - RestClient
    Back-end/Spring 2020. 6. 28. 00:12

    RestClient

    Rest를 클라이언트에서 요청하였을 때 어떻게 응답할지 결정하는 방식입니다.
    RestClient에는 두 종류가 있는데 각각의 특징과 사용법을 학습해보겠습니다.

    • RestTemplate

    • Blocking I/O 기반의 Synchronous(동기식) API입니다.

    • RestTemplateAutoConfiguration에서 자동설정 됩니다.

    • 프로젝트에 spring-web 의존성이 있다면 RestTemplate​Builder​를 빈으로 등록합니다.

    • 참고자료 : 스프링공식문서

    • WebClient

    • Non-Blocking I/O 기반의 Asynchronous(비동기식) API

    • WebClientAutoConfiguration에서 자동설정 됩니다.

    • 프로젝트에 spring-webflux 의존성이 있다면 WebClient.​Builder​를 빈으로 등록합니다.

    • 참고자료 : 스프링공식문서

    RestTemplate 사용하기

    동기식으로 응답하는 RestTemplate을 사용해보겠습니다.
    Web 의존성을 추가한 프로젝트를 생성합니다.

    Controller 클래스

    @RestController
    public class SampleController {
    
       @GetMapping("/hello")
       public String hello() throws InterruptedException {
           Thread.sleep(5000l);
           return "hello";
       }
    
       @GetMapping("/world")
       public String world() throws InterruptedException {
           Thread.sleep(3000l);
           return "world";
       }
    }

     

    RestClient

    Thread를 활용하여 hello는 5초, world는 3초의 시간을 줍니다.
    그리고 클라이언트 입장에서 값을 받기 위해 ApplicationRunner를 사용할 클래스를 생성하고 생성된 클래스에 구현합니다.

    ApplicationRunner 클래스

    클라이언트의 요청을 가정하여 두 가지의 방법을 사용해보겠습니다.

    RestTemplate

    @Component
    public class RestRunner implements ApplicationRunner {
    
        @Autowired
        RestTemplateBuilder restTemplateBuilder;
    
        @Override
        public void run(ApplicationArguments args) throws Exception {
            RestTemplate restTemplate = restTemplateBuilder.build();
    
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
    
            String helloResult = restTemplate.getForObject("http://localhost:8080/hello", String.class);
            System.out.println(helloResult);
    
            String worldResult = restTemplate.getForObject("http://localhost:8080/world", String.class);
            System.out.println(worldResult);
    
            stopWatch.stop();
            System.out.println(stopWatch.prettyPrint());
        }
    }

    RestTemplate를 사용할 떈 RestTemplateBuilder 의존성을 주입받습니다.
    그리고 build()함수를 사용하여 변수에 담고 변수의 기능을 사용해서 REST 요청시 String 값을 가져오도록 하고 출력합니다.

    RestClient

    위처럼 맨 처음 요청한 hello의 5초 + 다음 world 요청인 3초 = 총 8초 정도의 시간에 응답을 완료했다고 출력됩니다.

    이처럼 RestTemplate은 요청이 들어오면 다음 코드로 넘어가지 않고 완료되면 넘어가는 동기식 응답을 하는 것을 볼 수 있습니다.

    WebClient

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

    webflux 의존성을 추가해야만 사용할 수 있습니다.

    @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();
    
            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();
            });
    
    
            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();
            });
        }
    }

    WebClient는 WebClient.Builder로 의존성을 주입받습니다.
    여기선 Stream API를 사용할 것인데 Subscribe하기 전 까지 작동하지 않고 대기하다가 Callback이 오면 로직을 수행합니다.
    현재 로직에선 Rest 요청이 들어오면 String을 Mono 타입으로 변경 후 대기하다가 subscribe를 하게되면 출력한다고 생각하면 됩니다.

     

    RestClient

    먼저 출력된 world 3초 + hello 2초 = 총 5초가 소요되었고 비동기로 출력된 것을 볼 수 있습니다.

    이처럼 동기식보다 시간적 효율성이 높고 응답 시간도 빨라 개발자들은 보통 WebClient를 선호합니다.

    댓글