본문 바로가기
  • 개발하는 곰돌이
Development/Spring & Spring Boot

[WebClient] Mono에 담긴 List를 하나로 합치기

by 개발하는 곰돌이 2023. 5. 14.

문제 상황

Spring WebClient를 통해 외부 API를 호출하는 과정에서 파라미터만 바꿔서 동일한 API를 여러 번 호출할 일이 있었다. 이 과정에서 각 API 호출 응답으로 받은 JSON을 DB에 저장하기 위해 엔티티 형태에 맞게 변경하여 엔티티의 리스트로 만들었다.

 

문제는 모든 API 호출을 비동기로 진행했기 때문에 실제 반환값은 엔티티의 리스트가 담긴 Mono 객체였다. 평범한 리스트였다면 그냥 List.addAll()을 통해 합칠 수 있겠지만 Mono 객체라서 불가능했다.

해결 방법

그렇게 방법을 찾던 중에 Stack Overflow에서 방법을 찾았다. Mono의 flatMapMany()와 Flux의 fromIterable()을 사용하면 Mono 객체를 Flux 객체로 변환할 수 있다.

Mono<List<Integer>> listMono1 = Mono.just(List.of(1, 2, 3, 4, 5));
Mono<List<Integer>> listMono2 = Mono.just(List.of(6, 7, 8, 9, 10));

이와 같은 형태의 리스트를 담은 Mono 객체가 존재할 때 flatMapMany()fromIterable()을 사용하면

Flux<Integer> intFlux1 = listMono1.flatMapMany(Flux::fromIterable);
Flux<Integer> intFlux2 = listMono2.flatMapMany(Flux::fromIterable);

이런 식으로 리스트를 풀어서 Flux 객체에 담게 된다. 정확히는 Flux.fromIterable()에서 Iterable 객체를 풀어서 Flux 형태로 변환하고, Mono의 flatMapMany()는 이 결과로 나온 Flux 객체를 반환하게 된다.

 

이제 이렇게 나온 Flux 객체들을 Flux.merge()로 합친 후에 collectList()를 사용하면 여러 개의 Mono 객체에 담긴 리스트들을 하나로 합친 Mono 객체를 반환한다.

Mono<List<Integer>> mergedListMono = Flux.merge(intFlux1, intFlux2).collectList();

참조 링크

 

Scatter-gather: combine set of Mono<List<Item>> into single Mono<List<Item>>

Can I combine a list of Mono<List<Item>> data sources into a single Mono<List<Item>> containing all items without blocking? In my JDK 9 Spring Boot 2 with Lombok scatter-ga...

stackoverflow.com

 

댓글