[Kotlin][Flow] Flow 결합 연산자 zip, combine

sana·2022년 9월 17일
1

코틀린 flow에는 여러 개의 flow를 하나로 결합시키는 연산자들이 있다.
이 글에서는 그 중 zipcombine에 대해 알아보도록 하겠다.

zip

우선 마블 다이어그램을 보자.
첫번째 flow에서는 숫자 1, 2, 3을 방출하고 있고, 두번째 flow에서는 문자 "A", "B", "C", "D"를 방출하고 있다.
두 flow를 zip 연산자를 통해 결합하면 1A, 2B, 3C 가 나온다.


이를 코드로 구현하면 다음과 같다.

val numberFlow = flowOf(1, 2, 3).onEach { delay(10) }
val letterFlow = flowOf("a", "b", "c", "d").onEach { delay(15) }
numberFlow.zip(letterFlow) { i, s -> i.toString() + s }.collect {
    println(it)
}

numberFlowletterFlow 두 flow를 zip 연산자를 통해 결합시켜주면,
람다식의 첫번째 인자에 숫자 i가, 두번째 인자에 문자 s가 전달된다.
이 람다식 안에서 원하는 형태로 flow를 변환시켜줄 수 있는데 여기서는 간단하게 i와 s를 이어붙였다.
그 결과 flow를 collect 연산자를 통해 수집하여 출력하면 아래와 같이 나온다.


1a
2b
3c

결과에서 볼 수 있듯이 zip 연산자는 두 flow에서 한 쌍(Pair)을 만든다.
1과 a가 방출되어 결합된 결과 1a가 나오고, (1a)
2는 다른 문자가 방출될 때까지 기다려 b와 결합된다. (2b)
3도 마찬가지로 b가 이미 2와 결합되었으므로 새로운 문자 c가 나올 때 결합된다. (3c)

그리고 numbeFlow는 더 이상 방출할 값이 없으므로 완료되는데, 이 때 결과 flow도 즉시 완료된다.
그럼 남은 letterFlow는 어떻게 될까?
더 이상 결합할 flow가 없으므로 취소되고, 따라서 쌍을 이루지 못하고 남겨진 "d"는 결국 손실되고 방출되지 않는다.


정리하자면, zip 연산자는

  • 두 flow에서 한 쌍을 만들어 변환한 결과 flow를 반환한다.
  • 하나의 값이 발행되면 다른 플로우의 값이 발행되기까지 기다린다.
  • 하나의 flow가 완료되면 결과 flow는 즉시 완료되고, 나머지 flow에서는 취소가 호출된다.


combine

앞의 예시와 동일하게 문자와 숫자가 발행되는 flow가 있다.
zip과 동일하게 두 flow의 값을 결합하여 변환한 후 그 결과를 보낸다.
그런데 combine 연산자로 결합했더니 zip보다 훨씬 많은 값들이 방출된다.


val numberFlow = flowOf(1, 2, 3).onEach { delay(10) }
val letterFlow = flowOf("a", "b", "c", "d").onEach { delay(15) }
numberFlow.combine(letterFlow) { i, s -> i.toString() + s }.collect {
    println(it) 
}

코드 역시 zip연산자가 combine으로 변경된 것을 제외하고 동일하다.
하지만 결과는? 다르다.

1a
2a
2b
3b
3c
4c
4d

하나씩 살펴보자.
1과 a가 방출되어 결합된 결과 1a가 나오는 것까지는 zip과 동일하다. (1a)
하지만 다음으로 방출된 2는 letterFlow가 새로운 값을 방출할 때까지 기다리지 않고, 가장 최근에 내보낸 값 a와 결합한다. (2a)
이후 b가 방출되었을 때도 마찬가지로 numberFlow의 최신값인 2와 결합된다.(2b)
이런 식으로 combine 연산자는 한 flow에서 새로운 요소가 방출되었을 때, 다른 flow의 이전 요소와 함께 결합되면서 모든 요소가 방출된다.
따라서 combine은 두 flow가 모두 종료될때까지 값이 방출되기 때문에 모든 변경사항을 관찰할 수 있다.


정리하자면, combine 연산자는

  • 각 flow의 가장 최신값을 결합하여 변환한 결과 flow를 반환한다.
  • 두 flow가 모두 종료될때까지 값이 방출되기 때문에 모든 값이 방출된다.


[참고자료]

https://flowmarbles.com/
https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/

1개의 댓글

comment-user-thumbnail
2022년 11월 22일

정리 감사합니다!

답글 달기