오늘은 Kotlin의 `kotlinx.coroutines.flow`에서 제공하는 강력한 상태 관리 도구인 StateFlow에 대해 알아보려고 해요. 이 글을 통해 `StateFlow`의 개념부터 실제 활용 사례까지 자세히 살펴볼게요.
1. StateFlow란 무엇인가요?
`StateFlow`는 `kotlinx.coroutines.flow`에서 제공하는 특별한 종류의 `Flow`로, 상태 관리에 최적화된 Hot Stream이에요. 항상 현재 상태를 보유하며, 상태가 변경될 때 구독자들에게 이를 알리는 데 사용돼요.
특히 Jetpack Compose와 같이 상태 기반의 UI 프레임워크에서 유용하게 활용할 수 있어요. 뷰모델에서 상태를 관리하고, UI는 이를 구독해서 자동으로 상태를 반영하도록 설계할 때 적합해요.
2. StateFlow의 특징
- 항상 현재 값을 유지
`StateFlow`는 항상 최신 상태 값을 보유하고 있어요. 구독자가 구독을 시작하면 가장 최신 값을 즉시 받을 수 있어요. - Hot Stream
`StateFlow`는 구독자가 없어도 최신 값을 유지해요. 이는 일반 `Flow`(Cold Stream)와의 주요 차이점이에요. - 중복 방지
동일한 값으로 상태를 변경하려고 해도 구독자들에게 이벤트가 전달되지 않아요. 이는 불필요한 상태 업데이트를 방지하는 데 유용해요. - `MutableStateFlow`를 통한 상태 변경
`StateFlow`는 읽기 전용으로 제공돼요. 상태를 변경하려면 `MutableStateFlow`를 사용해야 해요. - UI와의 강력한 연동
Jetpack Compose의 `collectAsState()` 함수와 결합하면 매우 간단하게 상태 기반 UI를 구축할 수 있어요.
3. StateFlow의 기본 사용법
1. 선언과 초기화
// ViewModel 내부
private val _state = MutableStateFlow(0) // 초기값 설정
val state: StateFlow<Int> = _state // 외부에는 읽기 전용 StateFlow 제공
2. 상태 변경
_state.value = 1 // 값을 업데이트
_state.value = 2 // 또 다른 상태값
3. 상태 구독
lifecycleScope.launch {
viewModel.state.collect { value ->
// 상태값을 UI에 반영
textView.text = value.toString()
}
}
4. StateFlow와 LiveData의 차이
특성 | StateFlow | LiveData |
코루틴 지원 | 코루틴 기반으로 설계됨 | 코루틴과의 통합이 제한적 |
백프레셔 처리 | 항상 최신 상태만 유지 | 백프레셔 관리 필요 없음 |
구독 상태 | 최소 1개의 활성 구독자 필요 | 구독자가 없어도 상태 유지 가능 |
Thread Safety | 완전히 코루틴 기반으로 안전 | UI Thread에서만 동작하도록 설계됨 |
5. StateFlow의 활용 예시
1. ViewModel에서 상태 관리
뷰모델에서 상태를 관리할 때 `StateFlow`를 사용하면 UI와 상태를 쉽게 동기화할 수 있어요.
class MyViewModel : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState: StateFlow<UiState> = _uiState
fun fetchData() {
viewModelScope.launch {
try {
val data = repository.getData()
_uiState.value = UiState.Success(data)
} catch (e: Exception) {
_uiState.value = UiState.Error("데이터 로드 실패")
}
}
}
}
sealed class UiState {
object Loading : UiState()
data class Success(val data: List<String>) : UiState()
data class Error(val message: String) : UiState()
}
2. UI에서 상태 구독 (Jetpack Compose)
Jetpack Compose에서 상태를 구독해 UI를 업데이트하는 방법이에요.
@Composable
fun MyScreen(viewModel: MyViewModel) {
val uiState by viewModel.uiState.collectAsState()
when (uiState) {
is UiState.Loading -> Text("로딩 중...")
is UiState.Success -> LazyColumn {
items((uiState as UiState.Success).data) { item ->
Text(item)
}
}
is UiState.Error -> Text("에러: ${(uiState as UiState.Error).message}")
}
}
참고자료
'Kotlin' 카테고리의 다른 글
[Kotlin] 언더스코어(_)를 변수 이름에 붙이는 이유 (1) | 2024.09.03 |
---|---|
[Kotlin] Coroutine Suspend function (0) | 2024.03.25 |
[Kotlin] Data class, Sealed class (0) | 2024.03.06 |
[Kotlin] Scope functions(let, run, with, apply, also) (0) | 2024.03.05 |
[Kotlin] object, companion object (0) | 2024.03.05 |