webflux로 서비스를 만들어보면서 map과 flatMap을 언제 써야 할지 헷갈릴 때가 있어 공부한 내용을 정리함.
map과 flatMap은 둘 다 스트림의 중간에 값을 변환해주는 역할을 한다.
map은 1 : 1로 반환을 보증하고 flatMap은 1 : N을 변환할 수 있다.
요청에 대해 N개를 병렬로 실행할 경우가 많지 않아 map을 많이 쓸 것 같지만 개발을 하다 보면 대다수의 경우 flatMap을 사용하게 된다.
flatMap을 사용하는 경우
flatMap을 사용하게 되는 경우는 다음과 같다.
Mono<T> -> Mono<U> 또는 Mono<T> -> Flux<U>로 변환이 필요한 경우
map과 flatMap의 설명을 보면 다음과 같다.
Publisher | method | |
Mono | map | Transform the item emitted by this Mono by applying a synchronous function to it. |
flatMap | Transform the item emitted by this Mono asynchronously, returning the value emitted by another Mono (possibly changing the value type). | |
Flux | map | Transform the items emitted by this Flux by applying a synchronous function to each item. |
flatMap | Transform the elements emitted by this Flux asynchronously into Publishers, then flatten these inner publishers into a single Flux through merging, which allow them to interleave |
map 은 반환 값이 대상 Object이고 flatMap은 reactor의 Publisher (Mono / Flux)이다.
Mono<T> -> Mono<U>의 flatMap의 경우 성능 상 이점이 아닌 Publisher 객체 타입 변환이 목적이기 때문에 flatMap을 사용한다.
Mono<T> -> Flux<U>의 flatMap의 경우 Publisher 객체 타입도 변환하고 변환된 이후 비동기로 병렬 동작하는 publisher를 사용하는 경우 forEach를 통한 동기로 실행하는 경우보다 빠른 처리가 가능해진다.
Mono<T> -> Mono<T>의 flatMap의 경우 비동기로 처리하는 의미가 없기 때문에 굳이 flatMap을 쓸 이유는 없다.
Flux<T> -> Flux<T> 또는 Flux<T> -> Flux<U>인 경우
Mono와 달리 Flux는 N개를 비동기로 병렬 동작하는 publisher를 사용하는 경우 성능 상 이점이 많기 때문에 되도록 map을 쓰지 않는 게 좋다.
method를 호출하는 경우
어차피 reactive한 개발을 하면 사용하는 모든 method의 반환은 Publisher 형태가 된다.
이렇게 반환된 결과값을 이어 사용해야 하는 경우는 map을 쓰지 않고 flatMap을 쓰는 게 자연스럽게 이어진다.
이 경우 때문에 Mono<T> -> Mono<T>의 경우에도 flatMap을 쓰게 된다.
return value가 Object인 경우
reactive를 사용하면 기존 처럼 Object의 경우 반환 값으로 null을 반환받아 reactive flow내에서 사용할 수 없다.
null이 반환되면 reactive flow가 중지되기 때문에 Mono.empty(), Flux.empty()와 같이 지정된 빈 값 반환 처리를 해야 한다.
이 경우 map을 사용하면 reactive의 빈 객체 반환 정의를 할 수 없게 되기 때문에 flatMap을 사용한다.
결국 위에 열거한 이런저런 이유로 인해 대부분의 경우 flatMap을 사용하게 되지만 무조건 flatMap을 써야 한다가 아닌 위와 같은 이유로 flatMap을 쓰게 된다는 점을 이해하고 개발하는 게 좋을 것 같다.
'Study > Java' 카테고리의 다른 글
재미로 보는 Spring Project release train naming (0) | 2020.02.07 |
---|---|
OOP 개발 원칙 (0) | 2020.01.31 |
RestTemplate Generic responseType 사용 (0) | 2020.01.28 |
Reactor 언제 어떤 Operator를 써야 할까? (4) | 2020.01.21 |
java backend developer roadmap (0) | 2020.01.19 |
Spring Boot @PropertySource 호출 순서 지정하기 (0) | 2020.01.09 |
STS 4.5.0 spring boot application 실행 불가 현상 (0) | 2020.01.03 |
Reactor 레퍼런스 문서 공부 (0) | 2020.01.02 |
Reactor 공부하기 위한 프로젝트 설정 (0) | 2019.12.20 |
Spring Data R2DBC 써보기 (0) | 2019.12.11 |