Jetpack Compose에서 상태 관리하기: remember, Flow, StateFlow
Jetpack Compose는 선언형 UI 프레임워크로, 상태(state)를 효율적으로 관리하는 것이 매우 중요합니다. Compose에서 자주 사용되는 remember, Flow, StateFlow를 비교하며 각각의 역할과 활용 방법을 알아보겠습니다.
1. remember란?
remember는 컴포저블 함수에서 상태를 유지하는 데 사용됩니다. 특정 값이 재구성(Recomposition)될 때 초기화되지 않도록 저장하는 역할을 합니다.
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Column {
Text(text = "Count: $count")
Button(onClick = { count++ }) {
Text("Increase")
}
}
}
remember 사용 예시
위 코드에서 count는 remember를 통해 유지되므로, 버튼을 클릭할 때마다 증가한 상태가 유지됩니다.
하지만 remember는 화면 회전과 같은 구성 변경(Configuration Change) 시 상태가 유지되지 않습니다. 이를 해결하려면 rememberSaveable을 사용해야 합니다.
2. Flow란?
Flow는 Kotlin의 코루틴을 활용한 비동기 데이터 스트림입니다. 지속적으로 변경되는 데이터를 처리하는 데 유용하며, LiveData와 유사하지만 더 강력한 기능을 제공합니다.
Flow 사용 예시
fun timerFlow(): Flow<Int> = flow {
var count = 0
while (true) {
emit(count++)
delay(1000L) // 1초마다 값 방출
}
}
위 코드는 매초 증가하는 숫자를 방출하는 Flow입니다. Compose에서 Flow를 UI와 연결하려면 collectAsState를 사용할 수 있습니다.
@Composable
fun TimerScreen() {
val count by timerFlow().collectAsState(initial = 0)
Text(text = "Timer: $count")
}
3. StateFlow란?
StateFlow는 Flow의 일종으로, 상태를 저장하고 변경이 발생할 때 최신 값을 방출하는 특성을 가집니다. LiveData와 비슷하지만 코루틴 친화적인 방식으로 동작합니다.
StateFlow 사용 예시
class TimerViewModel : ViewModel() {
private val _timer = MutableStateFlow(0)
val timer: StateFlow<Int> = _timer
init {
viewModelScope.launch {
while (true) {
_timer.value += 1
delay(1000L)
}
}
}
}
ViewModel에서 StateFlow를 정의하고 관리할 수 있습니다.
Compose에서 이를 구독하려면 collectAsState()를 사용합니다.
@Composable
fun TimerScreen(viewModel: TimerViewModel = viewModel()) {
val count by viewModel.timer.collectAsState()
Text(text = "Timer: $count")
}
결론
Jetpack Compose에서 상태 관리는 매우 중요합니다. remember는 간단한 UI 상태를 유지하는 데 유용하고, Flow는 비동기 데이터 스트림을 처리할 때 적합합니다. StateFlow는 Flow를 기반으로 최신 상태를 보장하면서도 ViewModel과 함께 사용하기 좋아 LiveData를 대체할 수 있는 강력한 옵션입니다.