안녕하세요 오늘은 웹플럭스에서 사용할 수 있는 기능들을 리뷰해 보겠습니다.
https://rhgustmfrh.tistory.com/90
웹플럭스에 대한 간단한 소개를 참고하시려면 해당 글에서 확인 하실 수 있습니다.
1. .doFinally() 와 .then() 의 차이
doFinally는 리액티브 스트림이 완료되거나,
에러가 발생했을 때 호출되는 콜백 메서드입니다.
이 메서드는 스트림의 최종 상태를 인자로 받아서 사이드 이펙트를 수행합니다.
그러나 doFinally는 리턴 값을 제공하지 않습니다.
그것은 Mono나 Flux를 변환하거나 생성하는 것이 아니라,
해당 스트림의 종료 시점에 어떤 동작을 수행할 것인지를 정의합니다.
then 메서드는 원래의 스트림이 완료되면 실행되는 연산자입니다.
이 메서드는 원래의 스트림의 결과를 무시하고,
새로운 Mono 또는 Flux를 반환합니다.
then 메서드는 주로 원래의 스트림의 완료 시그널을 기다린 후,
새로운 동작을 수행하는데 사용됩니다.
예를 들어, 데이터베이스에 데이터를 저장한 후,
다른 작업을 수행하려는 경우에 사용할 수 있습니다.
doFinally와 then은 둘 다 리액티브 스트림이 완료될 때 수행되는 동작을 정의하는 메서드이지만,
그들이 사용되는 방식과 목적이 다릅니다.
doFinally: 이 메서드는 스트림이 종료될 때 (성공적으로 완료되거나, 에러가 발생하거나, 취소되거나)
호출되는 콜백 함수를 등록합니다.
이 메서드는 사이드 이펙트를 수행하는데 사용되며,
원래의 스트림을 변형하지 않습니다.
예를 들어, 리소스를 해제하는 데 사용할 수 있습니다.
doFinally는 원래의 스트림을 반환합니다.
then: 이 메서드는 원래의 스트림이 완료될 때 수행되는 동작을 정의하지만,
원래의 스트림의 결과를 무시하고 새로운 Mono 또는 Flux를 반환합니다.
이 메서드는 원래의 스트림이 완료된 후에 새로운 동작을 수행하려는 경우에 사용됩니다.
요약하자면, doFinally는 스트림이 종료될 때 사이드 이펙트를 수행하는데 사용되며,
원래의 스트림을 변형하지 않습니다.
반면에 then은 원래의 스트림이 종료된 후에 새로운 동작을 수행하려는 경우에 사용되며,
새로운 Mono 또는 Flux를 반환합니다.
다음은 예제입니다.
flux.doFinally(signalType -> {
// 리소스 정리 코드
})
Mono.just("Hello")
.doOnNext(System.out::println)
.then(Mono.just("World"))
.doOnNext(System.out::println);
결과 : Hello
World
2. 재시도 함수 .retryWhen()
Reactive Streams 프로그래밍에서 에러가 발생했을 때 재시도 로직을 결정하기 위해 사용됩니다.
이 함수는 에러가 발생할 때마다 호출되며, 어떤 조건에서 재시도할지 결정하는 로직을 제공합니다.
.retryWhen() 함수는 Flux 또는 Mono에서 에러가 발생했을 때 호출되며,
인자로 Function을 받습니다. 이 Function은 Flux<Throwable>를 인자로 받아 Publisher<?>를 반환합니다.
Flux<Throwable>는 에러가 발생할 때마다 이벤트를 발생시키는 Flux이며,
Publisher<?>는 재시도를 결정하는 시그널을 제공하는 Publisher입니다.
예를 들어, 다음은 최대 3번의 재시도를 수행하는 예제입니다.
Flux.range(1, 5)
.map(i -> {
if (i <= 3) throw new RuntimeException("Got to 3");
return i;
})
.retryWhen(errors -> errors.zipWith(Flux.range(1, 3), (n, i) -> i))
.subscribe(System.out::println);
저는 해당 함수를 실전에서 웹요청 재시도 로직에 삽입하였습니다.
webclient.post()
...생략
.doOnError(throwable -> {
log.error("Token Request Error : {}", throwable.getMessage());
// result.set(false);
})
.retryWhen(Retry.backoff(86400, Duration.ofSeconds(30))
.filter(throwable -> throwable instanceof Exception)
.doAfterRetry(retrySignal -> {
log.info("Token failed after it was just retried...");
}))
.block();
토큰 요청 로직인데 에러가 발생하면 1일동안 30초마다 webclient.post()부터 다시 시작하게됩니다.
재요청후 로그를 확인하기 위해 doAterRetry 메서드를 사용하였고
.block()을 쓴 이유는 해당 토큰로직이 완료되어야 나머지 기능들이 동작되어야하기 때문에
동기성을 이유로 사용하였습니다.
3. Mono에 빈값을 반환할 때 .switchIfEmpty()
메소드는 원본 Mono 또는 Flux가 아무런 아이템도 방출하지 않을 때 대체할 Mono 또는 Flux를 제공하는데 사용됩니다.
.switchIfEmpty()는 인자로 Publisher를 받으며,
이 Publisher는 원본 Mono 또는 Flux가 아무런 아이템도 방출하지 않을 때 대신 방출됩니다.
예를 들어, 다음 코드는 .switchIfEmpty()를 사용하여 원본 Mono가 아무런 아이템도 방출하지 않을 때 대체할 값을 제공하는 예입니다
Mono.justOrEmpty(Optional.empty())
.switchIfEmpty(Mono.just("Hello, World!"))
.subscribe(System.out::println);
위의 메서드는 내가 작업하던 Mono가 빈값일 때 (기존이면 null point exception이 나는 경우) 처리할 수 있는
유용한 메서드입니다.
감사합니다.
'스프링부트' 카테고리의 다른 글
Java 및 Spring의 최신 탐색 : Java 17 및 Spring 3 가이드 (0) | 2024.02.17 |
---|---|
액세스 및 리프레쉬 토큰을 사용한 JWT 전략 구현 (0) | 2024.02.17 |
스프링 부트에서 Slack으로 실시간 모니터링하기 (2) (0) | 2023.11.29 |
스프링 부트에서 Slack으로 실시간 모니터링하기 (1) (0) | 2023.11.29 |
Swagger로 API 문서 자동화: 실습 후기와 튜토리얼 (0) | 2023.11.28 |
댓글