[개발일지] 230630 Spring WebClient (Mono)

지난 포스팅에 이어 Spring WebClient에 대해 정리해 보자.

 

Spring WebClient


WebClient는 Spring 5에서 도입된 클라이언트 측에서 HTTP 요청 작업을 처리할 때 사용되는 비동기, Non-Blocking 방식의 웹 클라이언트이다. Spring에서 제공하는 기존의 HTTP 클라이언트인 RestTemplate의 리액티브 버전으로 생각할 수 있다.

RestTemplate은 Blocking I/O를 기반이기 때문에 하나의 요청을 처리하는 동안에는 해당 스레드는 다른 작업을 처리할 수 없다는 특징이 있다.

 

반면, WebClient는 비동기적이고 Non-Blocking 기반이기 때문에 HTTP 요청을 보내고 응답을 비동기적으로 처리하는 것이 가능하다. 하나의 요청을 처리하는 동안에도 해당 스레드는 다른 작업을 계속 처리할 수 있다.

 

WebClient를 이용해서 작성한 간단한 예시 코드를 살펴보자.

 

@RestController
public class WelcomeController {
    private final WebClientApp webClientApp;

    public WelcomeController(WebClientApp webClientApp) {
        this.webClientApp = webClientApp;
    }

    @GetMapping(value = "/home")
    public Mono<String> welcome() {
        return webClientApp.getDataFromExternalService();
    }
}

 

@Service
public class WebClientApp {

    @Autowired
    private WebClient.Builder webClientBuilder;

    public Mono<String> getDataFromExternalService() {
        return webClientBuilder.build()
                .get()
                .uri("https://jsonplaceholder.typicode.com/todos/1")
                .retrieve()
                .bodyToMono(String.class);
    }
}

 

WebClient로 작성한 위 예제 코드에서 /home api를 get 요청하는 도중에 다른 네트워크 I/O나 다른 작업이 발생해도 WebClient는 Non-Blocking 기반으로 동작하기 때문에 다른 작업에 영향을 미치지 않아서 /home get 요청 작업에는 영향을 미치지 않는다.

즉, /home api를 호출하는 동안에도 다른 작업을 계속 진행할 수 있다는 이야기이다. (동시성 향상)

 

그리고 WebClient는 비동기처리를 하기 때문에 /home api 요청 작업이 전부 완료되지 않아도 또 다른 api 호출을 해도 /home api 요청 작업 완료를 기다리지 않고 또 다른 api 요청 작업을 할 수가 있다.

 

이러한 것들이 가능한 이유는 WebClient가 비동기적이고 non-blocking 방식으로 동작하기 때문이다. 이렇게 함으로써, 시스템은 더 많은 작업을 동시에 처리하고 더 빠르게 응답할 수 있다.

 

Mono


위 예시 코드에서 Mono라는 키워드를 볼 수 있는데 Mono에 대해 알아보자


Mono는 Reactor 타입 중 하나로, 비동기 처리 작업의 결과를 단일 값 또는 오류로 나타내는 데 사용된다. 

Mono는 0 또는 1개의 결과만을 가질 수 있어(최대 하나의 요소를 포함할 수 있다.) 비동기 작업의 결과를 받아 처리하는 데 유용하다.

 

아래 그림은 Mono에 대해 이해하기 쉽다.

 

 

"0"의 결과를 가질 수 있다는 의미는 Mono 스트림이 완료될 수 있지만 반환할 값이 없어 아무런 값을 리턴하지 않을 수 있다는 것을 의미한다. 즉, 작업이 성공적으로 완료되었지만 반환할 값이 없을 때 사용된다.

예를 들어, 데이터를 삭제하는 작업의 경우 성공적으로 완료되어도 반환할 값을 가지지 않을 수 있는데 이럴 경우에 Mono <Void>와 같이 사용된다.

 

"1"의 결과를 가질 수 있다는 의미는 Mono 스트림이 완료될 때 하나의 값만을 리턴한다는 것을 의미한다. 즉, 작업이 성공적으로 완료되었고, 그 결과로 하나의 값을 반환하는 경우에 사용된다.

 

 

 

 

References

https://docs.spring.io/spring-framework/reference/web/webflux-webclient.html

 

WebClient :: Spring Framework

Spring WebFlux includes a client to perform HTTP requests with. WebClient has a functional, fluent API based on Reactor, see Reactive Libraries, which enables declarative composition of asynchronous logic without the need to deal with threads or concurrenc

docs.spring.io

https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html

 

Mono (reactor-core 3.5.7)

static  Mono using(Callable  resourceSupplier, Function > sourceSupplier, Consumer  resourceCleanup, boolean eager) Uses a resource, generated by a supplier for each individual Subscriber, while streaming the value from a Mono derived from the same re

projectreactor.io