내부에서 실행된 람다를 다시 Publisher에 담아서 반환해준다. 즉, 동기 작업을 기존 Publisher에 덧붙여준다. 여기서 중요한건 해당 동기 작업을 실행하는게 아님. 그 작업을 조립해준다.
Mono.just("John").map { it.uppercase() } // Mono<String> -> "JOHN"
Flux.just(1, 2, 3).map { it * 2 } // Flux<Int> -> 2, 4, 6
내부 람다가 Publisher를 반환할때, 그 Publisher를 다시 Publisher로 감싸는게 아니라 말 그대로 하나의 Publisher로 평탄화해준다. 즉 이말은 flatMap을 써야할 자리에 그냥 map을 쓰면 Mono<Mono<..>> 가 된다는 말인데, 안쪽 Mono는 아무도 구독안해줘서 실행이 안되는 최악의 케이스가 된다.
내부 람다가 반환한 새 Pulbisher를 flatMap 이 구독하도록 조립되는 방식임. 즉 바깥쪽 Publisher가 구독되면, 내부에 연결된 flatMap이 다시 안쪽 Publisher를 구독해서 실행시켜버리게 한다.
// 각 유저 id마다 비동기 DB/네트워크 조회 → Mono 반환 → flatMap
Flux.just(1, 2, 3)
.flatMap { id -> userService.findById(id) } // findById: (Int) -> Mono<User>
// 결과: Flux<User>
flatMap이 구독한 안쪽의 Publisher들 중 누가 먼저 작업을 끝낼지는 알 수 없다. 또한 구독은 동시에 이뤄진다. 따라서 flatMap은 순서를 보장할 수 없다.