비동기 데이터를 다루는 가장 코틀린스러운 방법.
Flow는 비동기적으로 여러 값을 순차적으로 내보내는(emit) 데이터 스트림이에요.
데이터를 한 번에 다 가져오지 않고, 필요할 때마다 값을 흘려보내는 구조라고 보면 됩니다.
| 구분 | 설명 | 예시 |
|---|---|---|
| Cold Flow | collect가 호출될 때 비로소 실행됨 | flow { emit() }, asFlow() |
| Hot Flow | 구독 여부와 상관없이 계속 동작 | StateFlow, SharedFlow |
→ 대부분의 경우 Cold Flow로 충분하며,
Hot Flow는 UI 상태 관리(ViewModel) 나 이벤트 전달용으로 사용됩니다.
Flow는 데이터의 “흐름(stream)”을 구성하는 3단계로 이루어져 있어요.
| 역할 | 키워드 | 설명 |
|---|---|---|
| 생산자 (Producer) | flow { emit(...) } | 데이터를 생성하고 내보냄 |
| 중개자 (Intermediate Operator) | map, filter, onEach | 데이터를 가공하거나 필터링 |
| 소비자 (Consumer) | collect { ... } | 최종 데이터를 받아 처리 |
flow {
emit(1) // 생산자: 데이터 방출
emit(2)
emit(3)
}.filter { it % 2 == 1 } // 중개자: 홀수만 통과
.map { "값: $it" } // 중개자: 형식 변경
.collect { println(it) } // 소비자: 최종 처리
출력:
값: 1
값: 3
emit()은 Flow 내부에서 데이터를 방출(내보내는) 함수예요.
생산자가 emit()으로 값을 보내고, 소비자는 collect()로 받습니다.
val flow = flow {
emit("첫 번째 데이터")
emit("두 번째 데이터")
}
즉, emit = 생산자 → 소비자 방향으로 “데이터 신호를 보냄”
기본적으로 Flow는 collect가 실행되는 코루틴 컨텍스트에서 동작합니다.
데이터 생성은 백그라운드에서, 수집은 UI 스레드에서 하고 싶다면 flowOn()을 사용합니다.
flow {
emit(loadData()) // I/O
}.flowOn(Dispatchers.IO)
.collect { updateUI(it) } // Main
LiveData 대체로 UI 상태 관리에 자주 사용private val _uiState = MutableStateFlow("Loading")
val uiState: StateFlow<String> = _uiState
_uiState.value = "Success"
Snackbar, Toast, Navigation 이벤트 등 단발성 알림에 적합private val _event = MutableSharedFlow<String>()
val event = _event.asSharedFlow()
viewModelScope.launch {
_event.emit("데이터 저장 완료!")
}
MutableListFlow는 관용적으로 부르는 이름으로,
정식 타입은 MutableStateFlow<List<T>>입니다.
리스트를 상태로 관리할 때 자주 쓰입니다.
private val _items = MutableStateFlow<List<String>>(emptyList())
val items: StateFlow<List<String>> = _items
fun addItem(newItem: String) {
_items.value = _items.value + newItem
}
기존 리스트를 수정하는 대신 새 리스트로 교체해야 UI가 갱신됩니다.
| 개념 | 역할 |
|---|---|
Flow | 비동기 데이터 스트림 |
emit() | Flow 내부에서 데이터 방출 |
collect() | Flow의 데이터를 수집 |
flowOn() | 생산자 스레드 변경 |
StateFlow | UI 상태 관리용 Hot Flow |
SharedFlow | 이벤트 전달용 Hot Flow |
MutableListFlow | 리스트 형태의 상태 관리 패턴 |
| 상황 | 권장 Flow 타입 |
|---|---|
| 네트워크/DB 데이터 스트림 | flow {} / asFlow() |
| UI 상태(State 관리) | StateFlow |
| 이벤트(단발성 알림, SnackBar 등) | SharedFlow |
| Room 데이터베이스 | Flow<List<T>> (자동 업데이트) |
LiveData보다 더 강력하고 코루틴 친화적)collectAsState() 와 완벽하게 호환됨 → Compose 전환 시 필수 개념