ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Mono.just()와 Mono.defer()에 대한 이해
    Spring/Spring 2021. 7. 30. 13:26

    리액티브 프로그래밍을 위해 스프링 WebFlux를 사용할 때, Mono를 사용하여 단일 값을 비동기적으로 처리하는 경우가 많다. 이때 Mono.just()와 Mono.defer()는 매우 유용한 메서드이다. 이 글에서는 Mono.just()와 Mono.defer()의 차이점과 사용 사례를 살펴보겠다.

     

     

    Mono.just()란?

    Mono.just()는 단일 값을 즉시 감싸서 Mono로 반환한다. 값을 이미 알고 있고, 그 값을 비동기적으로 반환해야 할 때 유용하다. 예를 들어, 이미 계산된 값이나 상수를 Mono로 반환하고자 할 때 사용된다.

    public Mono<String> getFixedValue() {
        return Mono.just("Hello, World!");
    }

    위의 코드에서 Mono.just("Hello, World!")는 문자열 "Hello, World!"를 즉시 감싸서 반환한다. 이 경우 "Hello, World!"는 이미 계산된 값이다.

     

    Mono.defer()란?

    Mono.defer()는 Supplier<Mono<?>>를 받아서 구독 시점에 새로운 Mono를 생성한다. 이는 값을 지연 계산하고, Mono가 구독될 때 비로소 계산이 이루어지도록 할 때 유용하다.

    public Mono<String> getDeferredValue() {
        return Mono.defer(() -> Mono.just("Hello, Deferred World!"));
    }

    위의 코드에서 Mono.defer(() -> Mono.just("Hello, Deferred World!"))는 Mono가 구독될 때마다 "Hello, Deferred World!"를 반환하는 새로운 Mono를 생성한다.

     

     

    두 메서드의 차이점

    1. 실행 시점:
      • Mono.just(): 값을 즉시 계산하고 반환한다. Mono가 생성되는 시점에 값이 이미 존재한다.
      • Mono.defer(): 값을 지연 계산하여 Mono가 구독될 때 반환한다. Mono가 구독되는 시점에 값을 계산한다.
    2. 비동기성:
      • Mono.just(): 주로 동기적 값을 반환하며, 비동기적으로 값을 계산할 필요가 없는 경우에 사용된다.
      • Mono.defer(): 비동기적으로 실행되어야 하거나, 값을 지연 계산해야 하는 경우에 사용된다.

     

    사용 예시

    Mono.just()는 주로 이미 계산된 값을 반환할 때 사용된다. 예를 들어, 단순한 상수를 반환하거나 이미 존재하는 데이터를 Mono로 감쌀 때 적합하다

    public Mono<String> getConstantValue() {
        return Mono.just("Constant Value");
    }

    Mono.defer()는 주로 값의 계산이 지연되어야 하거나, 구독 시점에 실행되어야 하는 비즈니스 로직이 있을 때 사용된다

    public Mono<String> getDynamicValue() {
        return Mono.defer(() -> Mono.just(generateValue()));
    }
    
    private String generateValue() {
        // 복잡한 비즈니스 로직
        return "Generated Value";
    }

    이 예시에서 generateValue() 메서드는 복잡한 비즈니스 로직을 수행하며, Mono.defer()는 구독 시점에 이 로직이 실행되도록 한다.

     

     

     

    분기 로직에서의 차이 예시

    분기 로직에서 Mono.just()와 Mono.defer()를 사용하는 경우의 차이를 예시로 살펴보겠다.

     

     

    - Mono.just()를 사용하는 경우:

    public Mono<String> getResult(boolean condition) {
        String value1 = calculateValue1(); // 항상 실행됨
        String value2 = calculateValue2(); // 항상 실행됨
    
        if (condition) {
            return Mono.just(value1);
        } else {
            return Mono.just(value2);
        }
    }
    
    private String calculateValue1() {
        // 복잡한 계산 로직
        return "Value1";
    }
    
    private String calculateValue2() {
        // 복잡한 계산 로직
        return "Value2";
    }

    위 코드에서 condition 값에 상관없이 calculateValue1()과 calculateValue2()가 모두 실행된다. 그런 다음, 조건에 따라 value1 또는 value2가 Mono.just()로 반환된다. 따라서, 불필요한 계산이 발생할 수 있다.

     

     

    - Mono.defer()를 사용하는 경우:

    public Mono<String> getResult(boolean condition) {
        if (condition) {
            return Mono.defer(() -> Mono.just(calculateValue1()));
        } else {
            return Mono.defer(() -> Mono.just(calculateValue2()));
        }
    }
    
    private String calculateValue1() {
        // 복잡한 계산 로직
        return "Value1";
    }
    
    private String calculateValue2() {
        // 복잡한 계산 로직
        return "Value2";
    }

     

    위 코드에서 condition 값에 따라 해당 분기의 계산 로직만 실행된다. Mono.defer()를 사용하면 Mono가 구독될 때 비로소 calculateValue1() 또는 calculateValue2()가 실행되므로, 불필요한 계산을 피할 수 있다.

     

    Mono.just()와 Mono.defer()는 각각의 사용 목적과 상황에 따라 선택되어야 한다. 값을 즉시 반환해야 하는 경우에는 Mono.just()를 사용하고, 값을 지연 계산해야 하거나 비동기적으로 실행되어야 하는 경우에는 Mono.defer()를 사용하는 것이 적합하다. 이를 통해 리액티브 프로그래밍의 장점을 극대화할 수 있다.

     

     

    - Mono.fromCallable()를 사용하는 경우:

    public Mono<String> getResult(boolean condition) {
        if (condition) {
            return Mono.fromCallable(() -> calculateValue1());
        } else {
            return Mono.fromCallable(() -> calculateValue2());
        }
    }
    
    private String calculateValue1() {
        // 복잡한 계산 로직
        return "Value1";
    }
    
    private String calculateValue2() {
        // 복잡한 계산 로직
        return "Value2";
    }

    위 코드에서 condition 값에 따라 해당 분기의 계산 로직만 실행된다. Mono.fromCallable()는 비즈니스 로직이 구독 시점에 실행되도록 한다. Mono.defer()와 유사하다.

     

     

    출처:


    Reactor Documentation

     

    Reactor 3 Reference Guide

    10:45:20.200 [main] INFO reactor.Flux.Range.1 - | onSubscribe([Synchronous Fuseable] FluxRange.RangeSubscription) (1) 10:45:20.205 [main] INFO reactor.Flux.Range.1 - | request(3) (2) 10:45:20.205 [main] INFO reactor.Flux.Range.1 - | onNext(1) (3) 10:45:20.

    projectreactor.io

     


    Spring WebFlux Documentation

     

    Spring Framework Documentation :: Spring Framework

    Rod Johnson, Juergen Hoeller, Keith Donald, Colin Sampaleanu, Rob Harrop, Thomas Risberg, Alef Arendsen, Darren Davison, Dmitriy Kopylenko, Mark Pollack, Thierry Templier, Erwin Vervaet, Portia Tung, Ben Hale, Adrian Colyer, John Lewis, Costin Leau, Mark F

    docs.spring.io

     

Designed by Tistory.