본문 바로가기
Android/Flow

[Android] Flow에서 비동기 처리를 병렬로 하는 방법

by 태크민 2025. 4. 13.

안드로이드 개발을 하다 보면 여러 개의 비동기 작업(API 호출 등)을 동시에 병렬로 실행하고, 그 결과를 Flow로 처리하고 싶은 경우가 자주 발생합니다. Kotlin의 Flow는 기본적으로 순차적 처리에 최적화되어 있지만, 병렬 처리를 위해 몇 가지 강력한 방법들을 제공합니다.

이 글에서는 Kotlin Flow에서 비동기 API를 병렬로 호출하는 주요 방법을 세 가지로 정리해보겠습니다.

 


flow에서 비동기 처리를 병렬로 하는 방법

ID 목록을 받아 각 ID에 대해 비동기 API 호출을 병렬로 처리하고 결과를 수집하는 상황을 가정해봅니다.

fun idsFlow(): Flow<Int> = flowOf(1, 2, 3, 4, 5)

suspend fun fetchData(id: Int): String {
    delay(1000) // 비동기 API 호출을 시뮬레이션
    return "Data for $id"
}

 

1. flatMapMerge 사용 (권장)

fun main() = runBlocking {
    idsFlow()
        .flatMapMerge(concurrency = 3) { id ->
            flow { emit(fetchData(id)) }
        }
        .collect { result ->
            println("✅ 결과: $result")
        }
}

 

설명

  • flatMapMerge는 여러 Flow를 병렬로 실행해주는 연산자입니다.
    • flatMapConcat은 순차, flatMapMerge는 동시, flatMapLatest는 가장 최신 값만 유지
  • concurrency 파라미터를 통해 동시 실행 수 제한 가능
    • concurrency = N → 최대 N개의 코루틴을 동시에 실행할지 (코루틴 동시 실행 수 제한)
    • 하지만 이 코루틴들이 몇 개의 스레드를 사용할지는 디스패처(Dispatcher) 설정에 따름
      • 예: Dispatchers.Default라면 공통 스레드 풀 위에서 돌아가고,
      • Dispatchers.IO면 IO 스레드 풀 위에서 돌아갑니다.
  • Flow 내에서 자연스럽게 병렬 비동기 처리 구현 가능

2. map + async + awaitAll 조합

fun main() = runBlocking {
    val results = coroutineScope {
        idsFlow()
            .map { id -> async { fetchData(id) } }
            .toList() // Deferred 리스트로 변환
            .awaitAll() // 병렬 결과 수집
    }

    results.forEach { println("✅ 결과: $it") }
}

 

설명

  • map { async { ... } }로 병렬로 작업 실행
  • awaitAll()을 통해 전체 결과를 모아서 한 번에 처리
  • 단점: 이 방식은 Flow가 아니라 List로 결과를 받게 됨 (일괄 처리 시 적합)
    • Flow로 직접 collect하지 않기 때문에 일괄 처리에 적합

3. channelFlow + launch 조합

fun fetchMultipleData(ids: List<Int>): Flow<String> = channelFlow {
    ids.forEach { id ->
        launch {
            val data = fetchData(id)
            send(data)
        }
    }
}

fun main() = runBlocking {
    fetchMultipleData(listOf(1, 2, 3, 4, 5))
        .collect { println("✅ 결과: $it") }
}

 

설명

  • channelFlow는 내부에서 send()를 사용해 비동기 데이터를 보낼 수 있습니다.
  • launch를 통해 각 비동기 작업을 병렬 실행
  • 복잡한 병렬 흐름을 제어할 때 유용


정리

방법 병렬성 특징
flatMapMerge 가장 직관적이고 Flow 친화적 병렬 처리 방식
map + async + awaitAll 비동기 결과를 한꺼번에 수집할 때 적합
channelFlow 복잡한 병렬 흐름이나 커스텀 처리에 유리

 

 

 

끝.