Flow? CallbackFlow?

eunsong·2024년 11월 23일

Android

목록 보기
6/9

Flow 는 Cold stream 이며, emit 방출하는 코드와 collect 소비하는 코드가 같은 코루틴 내에 실행될 것을 기대한다.
-> 이는 데이터 흐름을 순차적으로 보장하고, 데이터 방출 및 수집 간의 상태를 쉽게 추적할 수 있도록 한다.

왜 다른 CoroutineContext에서 emit을 사용할 수 없을까?

flow{} 블록 내부 코드는 동일한 CoroutineContext 에서 실행되도록 설계되었습니다.
다른 CoroutineContext 를 사용할 경우, Flow 일관성을 깨뜨릴 수 있다. 특히, Flow 는 순차적 데이터 흐름과 쓰레드 안정성을 보장하기 위해 설정된 제약이 있습니다.

만약 다른 CoroutineContext 에서 값을 방출하려고 하면 아래와 같은 에러가 발생한다.

val incorrectFlow = flow {
    withContext(Dispatchers.IO) { // 다른 CoroutineContext
        emit("This will cause an error!") // 오류 발생
    }
}
java.lang.IllegalStateException: Flow invariant is violated..

에러 해결 방법

1) 동일한 CoroutineContext 에서 emit 하기

val correctFlow = flow {
    val result = withContext(Dispatchers.IO) { // 데이터를 가져올 때만 Context 변경
        fetchDataFromNetwork() // 네트워크 호출
    }
    emit(result) // emit은 동일한 CoroutineContext에서 호출
}

2) callbackFlow 사용

val safeFlow = callbackFlow {
    withContext(Dispatchers.IO) { // 다른 Context에서 값 생성
        send("This is allowed!") // 안전하게 값 방출
    }
    awaitClose { /* 리소스 정리 */ }
}

둘의 차이점은?

Flow

  • cold stream 으로, 데이터를 하나씩 순차적으로 방출하며, collect 함수로 데이터를 소비합니다. 주로 동기적이고 순차적인 데이터 흐름을 처리할 때 사용된다.
    • emit 은 동일한 CoroutineContext 에서 실행되어야 한다
    • collect 호출 전에는 동작하지 않는다(cold stream)

CallbackFlow

  • hot stream 으로, 콜백 기반 API 를 Flow 로 변환할때 주로 사용된다. 데이터를 방출(send) 할 때 다른 CoroutineContext 에서도 안전하게 동작하며, 내부적으로 Channel 을 활용한다.

번외) 면접에 자주나오는..

HotFlow vs ColdFlow

ColdFlow :

profile
A place to study and explore my GitHub projects: github.com/freeskyES

0개의 댓글