webflux에서 if else문으로 switchIfEmpty를 주로 사용하는데, empty가 아닌 경우에도 switchIfEmpty를 항상 호출합니다. 왜 그러는 것인지, 어떻게 하면 호출을 안 하게 할 수 있는지 알아보겠습니다.
1: String str = "str";
2: Mono.just(str)
3: .map(s -> {
4: System.out.println(s);
5: return s;
6: })
7: .switchIfEmpty({
8: System.out.println("defaultStr");
9: return Mono.just("default");
10: })
11: .subscribe();
위 코드를 보면 str이 비어 있지 않으니 문자열 "str"만 출력할 것이라고 생각하겠지만, 실제로는 "defaultStr", "str" 둘 다 출력이 됩니다.
<console>
defaultStr
str
자바는 보통 메서드 매개변수의 값을 미리 결정시켜놓으려고 합니다(eager evaluation). 그래서 실제 map을 실행하기 전에 switchIfEmpty를 먼저 실행시켜 값을 만들어 놓기때문에 실제 실행 순서는 (1 - 2 - 3 - 4 - 5)가 아닌 (1 - 2 - 7 - 8 - 3 - 4 - 5)가 됩니다.
만약 switchIfEmpty 안에 실행되는 메서드가 비용이 크고, 실제로 Mono.just가 empty를 반환하지 않는다면, 굳이 실행되지 않아도 되는 비싼 비용의 메서드를 호출해야 합니다. 이럴 때 우리는 불필요한 연산을 피하는 lazy evaluation 전략을 사용하여 switchIfEmpty 안의 실행을 실제 필요 시점으로 미룰 수 있게 할 수 있습니다.
String str = "str";
Mono.just(str)
.map(s -> {
System.out.println(s);
return s;
})
.switchIfEmpty(Mono.defer(() -> {
System.out.println("defaultStr");
return Mono.just("default");
}))
.subscribe();
String str = "str";
Mono.just(str)
.map(s -> {
System.out.println(s);
return s;
})
.switchIfEmpty(Mono.fromSupplier(() -> {
System.out.println("defaultStr");
return "default";
}))
.subscribe();
위와 같이 Mono.defer 혹은 Mono.fromSupplier를 사용하면 해당 메서드의 매개변수로 Supplier를 넘기기 때문에 미리 값을 만들어 놓지 않고, 실제 호출되는 시점으로 실행을 지연시킬 수 있습니다.
- just : 즉시 시퀀스를 생성.
- fromSupplier : 구독시점에 시퀀스를 생성. return type이 Supplier<? extends T>.
- defer : 구독 시점에 시퀀스를 생성. return type이 Supplier<? extends Mono<? extends T>> 이므로 Mono로 반환되는 메서드에 사용하는 것이 좋음.
[Reference]
https://projectreactor.io/docs/core/3.2.16.RELEASE/kdoc-api/reactor.core.publisher/switch-if-empty.html
https://coding-start.tistory.com/372
https://stackoverflow.com/questions/54373920/mono-switchifempty-is-always-called
'spring > spring webFlux' 카테고리의 다른 글
[WebFlux] Mono에 담긴 List를 하나로 합치기 (0) | 2023.07.13 |
---|---|
[Spring] WebMVC에서 WebFlux 사용 (with WebClient) (0) | 2023.07.13 |
[SpringBoot] Reactive RESTful Web Service 구축 실습 (0) | 2021.02.18 |
[Spring] Reactive Programming (1) - Reactor 3, WebFlux (0) | 2021.02.18 |
댓글