2025년 9월 7일 일요일

코틀린 Flow로 비동기 테이터 스트림 다루기

코틀린 Flow로 비동기 테이터 스트림 다루기

시간의 흐름에 따라 여러 개의 데이터가 연속적으로, 비동기적으로 발생하는 상황을 '데이터 스트림(Data Stream)'이라고 부릅니다. suspend 함수만으로는 이런 스트림을 처리하기가 까다롭습니다.

데이터 스트림을 코루틴안에서 효율적으로 다루기 위해 등장한 것이 Flow입니다.


Flow의 세 가지 핵심 역할


1. 생산자 (Producer) : 데이터를 만들어 내보내는 역할

flow { ... } 빌더를 사용해서 데이터 스트림을 만듭니다. emit() 함수를 사용해서 데이터를 하나씩 밖으로 내보냅니다.

// 1초마다 숫자를 0, 1, 2 ... 순서대로 발행(emit)하는 Flow
fun countNumbers(): Flow<Int> = flow {
    var count = 0
    while (true) {
        emit(count) // 데이터(count)를 흘려보낸다
        count++
        delay(1000) // 1초 대기
    }
}

2. (중간) 연산자 (Intermediate Operator) : 흐르는 데이터를 가공하는 역할

생산자가 보낸 데이터가 소비자에게 도달하기 전에 중간에서 데이터를 원하는 대로 가공할 수 있습니다.

map, filter처럼 컬렉션에서 자주 사용하던 익숙한 연산자들입니다.

countNumbers()
    .filter { it % 2 == 0 } // 짝수만 통과시키는 필터
    .map { "숫자는 바로 $it 입니다!" } // 숫자를 문자열로 가공

연산자는 '이렇게 처리할 것이다'라고 계획만 세워두는 것입니다.

실제로 데이터를 흘려보내고 처리하는 작업은 소비자가 구독을 시작해야만 실행됩니다. 이를 'Cold Stream'이라고 부릅니다.


3. 소비자 (Consumer) : 데이터를 받아서 사용하는 역할

collect라는 종단 연산자(Terminal Operator)를 사용해서 Flow가 발생하는 데이터를 받기 시작합니다.

collect가 호출되는 순간, 생산자는 데이터를 emit하기 시작하고, 중간 연산자는 가공을 시작합니다.

// viewModelScope 안에서 실행했다고 가정
viewModelScope.launch {
    countNumbers()
        .filter { it % 2 == 0 }
        .map { "숫자는 바로 $it 입니다!" }
        .collect { message -> // collect를 호출하는 순간부터 Flow가 동작 시작!
            // "숫자는 바로 0 입니다!"
            // (2초 후) "숫자는 바로 2 입니다!"
            // (2초 후) "숫자는 바로 4 입니다!"
            // ... 계속 UI에 메시지를 표시
            _myUiState.value = message
        }
}

안드로이드 개발자가 Flow를 좋아하는 이유


구조화된 동시성

Flow는 코루틴 스코프(lifecycleScope, viewModelScope)안에서 동작하기 때문에, 화면이 사라지는 등 스코프가 취소되면 Flow도 자동으로 함께 취소됩니다. 불필요한 작업이나 메모리 누수를 막아서 안전합니다.

백프레셔(Back-pressure)지원

만약 생산자가 데이터를 빨리 만들고 소비자가 처리하는 속도가 느리다면 어떻게 될까요? Flow는 이런 상황을 알아서 처리 해 주는 똑똑한 기능 (백프레셔)을 내장하고 있습니다. 앱이 갑자기 정지되거나 메모리가 누수 되는 문제를 방지해줍니다.

풍부한 연산자

map, filter 외에도 여러 Flow를 합치거나(zip, combin), 특정 시간 동안 들어온 값 중 마지막 값만 처리하는(debounce)등 실무에 유용한 수많은 연산자를 제공합니다.

Jetpack 라이브러리와 환성적인 궁합

Room, DataStore, Retrofit 등 많은 라이브러리들이 이제 Flow를 지원합니다. 데이터베이스에 변화가 생기면 자동으로 Flow를 통해 알려줍니다.



코루틴이 비동기 프로그래밍의 기본기라면, Flow는 그 안에서 연속적인 데이터를 자유자재로 다루는 응용기술이라고 할 수 있습니다.