[Coroutine Flow] flatMapConcat을 사용해 flow를 다른 flow로 변환하기

2021. 12. 27. 20:30· Coroutines/Flow
목차
  1. Flow의 Flattening Operator
  2.  flatMapConcat 은 무엇을 하는가?
  3. flatMapConcat 내부 살펴보기
  4. flatMapConcat 사용 예시
  5. flatMapConcat의 한계점
반응형

Flow의 Flattening Operator

flow는 데이터 파이프라인이다. 코드 상에서 데이터 파이프라인은 그 자체로 사용되는 경우는 거의 없으며 보통 다른 데이터 파이프라인들과 합쳐져 하나의 데이터 파이프라인을 완성한다. flow 또한 여러 flow가 합쳐져 하나의 flow로 만들어지기 위한 연산자를 제공하는데 데이터 파이프라인을 합치는(Flatten) 연산자여서 Flattening Operator(하나로 만드는 연산자)라 한다.

 

우리는 이번 글에서 가장 대표적인 Flattening Operator인 flatMapConcat에 대해 다뤄볼 것이다.

 

 

 flatMapConcat 은 무엇을 하는가?

flatMapConcat은 여러 flow를 연결하는(concatenating) 연산자이다. 이름에서 알 수 있듯이 flatMapConcat은 flow를 연결해 새로운 flow를 만드는 역할을 한다. flow간에 연결이 필요할 경우 flatMapConcat을 이용해 연결을 하면 된다.

 

 

flatMapConcat 내부 살펴보기

public fun <T, R> Flow<T>.flatMapConcat(transform: suspend (value: T) -> Flow<R>): Flow<R> =
    map(transform).flattenConcat()

 

flatMapConcat은 내부에서 두 개의 과정을 통해 flow를 flatten(합치기)한다.

1. transform 람다식(변수)을 받아 transform 변수에 대한 map을 수행해 flow에서 발행된 데이터를 flow로 변환한다. 이 단계에서는  flow에서 발행되는 각 데이터가 flow로 변환되어 여러개의 flow가 생성된다.

2. 1에서 생성된 flow들이 flattenConcat()을 통해 합쳐져 하나의 flow가 된다.

 

즉, flatmapConcat은 데이터를 변환하여 flow들을 새로 생성한 후 생성된 flow들을 합쳐 하나의 flow를 만들어낸다. 

 

*참조 : map 내부와 flattenConcat 내부

더보기
public inline fun <T, R> Flow<T>.map(crossinline transform: suspend (value: T) -> R): Flow<R> = transform { value ->
   return@transform emit(transform(value))
}
public fun <T> Flow<Flow<T>>.flattenConcat(): Flow<T> = flow {
    collect { value -> emitAll(value) }
}

 

flatMapConcat 사용 예시

예를들어 다음과 같은 flow가 있다고 해보자. 이 flow는 단순히 1과 5를 emit 하는 flow이다.

 

val flow = flow<Int> {
    emit(1)
    emit(5)
}

 

 만약 이 flow에서 발행하는 값에에 대해  +1, +2, +3 을 된 값을 생성하는 flow가 있다고 해보자. 우리는 flow에서 발행하는 값을 받아 새로운 flow를 만들어야 하고 새로운 flow에서 발행되는 값은 +1,+2,+3이 수행된 값이다. 즉 1에 대해서는 2,3,4가 발행되는 flow가 생성되고 5에 대해서는 6,7,8이 발행되는 flow가 생성되어야 한다. 마지막으로 새로 생성된 2개의 flow는 하나의 flow로 합쳐져야 한다. 

 

우리는 이를 위해 flatMapConcat을 다음과 같이 사용할 수 있다.

1. CoroutineScope 내에서 flatMapConcat 수행

2. flow로부터 emit되는 데이터를 다시 flow에서 받아서 emit하기

 

fun collectWithFlatMapConcat() {
    viewModelScope.launch {
        flow.flatMapConcat { intValue -> // 1. CoroutineScope 내에서 flatMapConcat 수행
            flow { // 2. flow로부터 emit되는 데이터를 다시 flow에서 받아서 emit하기
                emit(intValue + 1)
                emit(intValue + 2)
                emit(intValue + 3)
            }
        }.collect {
             println("printed value >> $it")
        }
    }
}

 

위를 수행한 결과는 다음과 같다.

 

그림1. flatMapConcat

 1에 대한 변환이 모두 수행된 후 5에 대한 변환이 수행됨(순차적으로 처리됨)을 확인할 수 있다.

 

flatMapConcat의 한계점

flatMapConcat은 원 flow에서 발행된 데이터가 순차적으로 처리되어 새로운 flow를 만들어낸다. 이 말은 데이터 처리하는데 오래 걸리는 연산이 변환 값으로 들어올 경우 데이터가 처리되는데 오래 걸릴 것임을 뜻한다. 예를 들어 아래처럼 flatMapConcat의 변환 연산자에 delay를 줄 경우 변환 처리 과정에서 10초이상 걸리게 된다. 만약 1초에 수십개의 데이터가 flow를 통해 들어올 경우 변환된 데이터의 발행 시점과 변환되기 전 데이터의 발행 시점 사이에 많은 차이가 생길 수 있다. 

flow.flatMapConcat { intValue ->
    flow {
        emit(intValue + 1)
        delay(10000)
        emit(intValue + 2)
        emit(intValue + 3)
    }
}.collect {
     println("printed value >> $it")
}

 

즉, 변환을 하는데 시간이 오래 소모될 경우 아래 그림3과 같이 변환이 완료된 새로운 데이터 파이프라인의 발행 시점이 점점 밀리게 된다. 즉, 첫 데이터 파이프라인의 데이터 발행 시점과 소비자(Consumer)의 데이터 소비 시점 사이에 많은 차이가 생기게 될 수 있다.

그림2. flatMapConcat의 한계점

 

Kotlin Coroutines 공식 기술 문서 번역이 GitHub 오픈소스로 배포되었습니다. Starganizer가 되어 오픈소스를 지지해주세요.

 

Kotlin Coroutines 공식 문서 번역을 시작하며 · GitBook

Kotlin Coroutines 공식 문서 번역을 시작하며 Kotlin Coroutines는 Kotlin을 위한 강력한 비동기 솔루션이다. 안드로이드 실무에서는 한동안 높은 점유율을 자랑한 RxJava를 Coroutines가 대체하고 있으며, 새로

seyoungcho2.github.io

 

반응형
저작자표시 비영리 변경금지
  1. Flow의 Flattening Operator
  2.  flatMapConcat 은 무엇을 하는가?
  3. flatMapConcat 내부 살펴보기
  4. flatMapConcat 사용 예시
  5. flatMapConcat의 한계점


 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com

'Coroutines/Flow' 카테고리의 다른 글
  • [Coroutine Flow] flatMapMerge 을 사용해 flow 변환 동시 처리하기
  • [Coroutine Flow] flatMapLatest 이용해 최신 데이터만 사용해 flow 변환하기
  • [Coroutine Flow] conflate를 이용해 최신 데이터 collect 하기
  • [Coroutine Flow] buffer 이용해 발행과 소비를 위한 Coroutine 분리하기
Dev.Cho
Dev.Cho
'조세영의 Kotlin World'는 Kotlin를 전문적으로 다루는 개인 기술 블로그입니다. Kotlin 세계에 대한 양질의 자료를 제공하며 Kotlin, Android, Spring, CI, CD 분야에 대해 다룹니다.
Dev.Cho
조세영의 Kotlin World
Dev.Cho
전체
오늘
어제

블로그 메뉴

  • LinkedIn
  • GitHub
  • 분류 전체보기 (491)
    • Kotlin (104)
      • Class and Interface (19)
      • Variable and Function (8)
      • Modifier (5)
      • Collection (14)
      • Time (8)
      • 동시성 제어 (7)
      • Reactive Programming (2)
      • Paradigm (2)
      • Kotlin 자료구조 (15)
      • Design Patterns (11)
      • Algorithm (3)
      • Exception (1)
      • 기타 (9)
      • Update History (0)
    • Coroutines (32)
      • Coroutine Basics (18)
      • Flow (9)
      • CoroutineScope (3)
      • Debugging (2)
    • Testing Codes (28)
      • Test 기본 (3)
      • JUnit5 (9)
      • MockK (6)
      • Testing Coroutines (1)
      • Testing Android (8)
      • Test 기타 (1)
    • Spring (50)
      • Dependency Injection (18)
      • Settings (5)
      • REST API (0)
      • DevTools (1)
      • MVC (18)
      • Error (2)
      • MongoDB (2)
      • Database (4)
    • Android (39)
      • Architecture (2)
      • Component (5)
      • Manifest (1)
      • Lifecycle (2)
      • Dependency Injection (17)
      • Resource (1)
      • Storage (1)
      • Security and Optimization (1)
      • WebView (2)
      • Error (6)
    • Android Jetpack Compose (33)
      • Compose (6)
      • Compose Modifier (13)
      • Compose Resource (4)
      • Compose State (4)
      • Compose Side Effect (6)
    • Android Jetpack Compose UI (48)
      • Compose Layout (14)
      • Compose Text (10)
      • Compose Button (5)
      • Compose Dialog (2)
      • Compose TextField (0)
      • Compose UIs (4)
      • Compose Animation (1)
      • Compose Canvas (12)
    • Android Jetpack (10)
      • Datastore (5)
      • ViewModel (4)
      • LiveData (1)
      • Paging (0)
    • KMP (5)
    • Programming (4)
    • Machine (9)
      • JVM (7)
      • Linux (2)
    • CI, CD (74)
      • Gradle (12)
      • Groovy Gradle (5)
      • Git (25)
      • Git Remote (5)
      • GitHub (5)
      • GitHub Actions (21)
    • Network (33)
      • GraphQL (12)
      • HTTP (11)
      • Basic (9)
    • 오픈소스 (3)
    • Database (3)
      • MongoDB (3)
    • IDE (6)
      • Android Studio (2)
      • Intellij (4)
    • Firebase (1)
    • Javascript (9)

공지사항

  • 코틀린 코루틴 완전 정복 강의 in 인프런 오픈
  • 코틀린 코루틴의 정석 책 출간
  • Kotlin Coroutines 공식 기술 문서 한국어 번⋯
  • GitHub에서 조세영의 Kotlin World를 Foll⋯
  • 문의&제안

인기 글

태그

  • Android Compose
  • Spring boot
  • Jetpack Compose
  • junit5
  • 안드로이드
  • 의존성 주입
  • compose
  • 코틀린
  • gradle
  • Android
  • 코루틴
  • flow
  • dagger2
  • github actions
  • Spring
  • kotlin spring
  • java
  • GraphQL
  • Class
  • Unit Testing
  • 스프링
  • junit
  • GIT
  • 유닛 테스팅
  • Dependency Injection
  • github
  • Coroutine
  • Kotlin
  • HTTP
  • junit4

최근 글

반응형
hELLO · Designed By 정상우.v4.3.0
Dev.Cho
[Coroutine Flow] flatMapConcat을 사용해 flow를 다른 flow로 변환하기
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.