Jetpack Compose에서 UI 상태 저장 및 관리
Jetpack Compose에서 UI 상태 저장 및 관리
Jetpack Compose에서 UI 상태를 보존하는 것은 매끄러운 사용자 경험을 유지하기 위해 필수적입니다. 특히 구성 변경(configuration changes)이 발생하거나 시스템이 프로세스를 종료(process death)한 뒤 앱이 복원되는 상황에서 상태가 유실되면 사용자 경험이 크게 저하될 수 있습니다. Compose에서는 상태가 UI 로직에 해당하는지, 비즈니스 로직에 해당하는지에 따라 서로 다른 API를 제공하여 리컴포지션(Recomposition)과 생명주기 이벤트에 걸쳐 상태를 유지할 수 있도록 설계되어 있습니다.
이번 면접 질문을 통하여 아래 내용들을 학습하실 수 있습니다.
rememberSaveable을 활용하여 구성 변경과 프로세스 사망 시에도 UI 상태를 유지하는 방법- 원시 타입이 아닌 커스텀 타입에 대해
Saver를 직접 구현하는 방법 ViewModel에서SavedStateHandle을 사용하여 프로세스 사망에도 비즈니스 로직 상태를 보존하는 방법SavedStateHandle과StateFlow를 결합하여 반응형 상태 유지를 구현하는 방법- 상태의 소유권과 범위에 따라 적절한 API를 선택하는 기준
UI 상태를 위한 rememberSaveable
펼침/접힘 플래그, 텍스트 입력, 스크롤 위치 등 UI에 직접 관련된 상태를 다룰 때는 rememberSaveable이 가장 적합한 도구입니다. rememberSaveable은 내부적으로 인스턴스 상태 Bundle을 활용하여 Activity가 재생성될 때에도 데이터를 유지합니다. 실무에서 화면 회전이나 다크 모드 전환 같은 구성 변경이 발생하면 Activity가 파괴되었다가 다시 생성되는데, 이때 remember로만 관리하던 상태는 모두 초기화되므로 반드시 rememberSaveable을 사용해야 합니다.
@Composable
fun ChatBubble(message: Message) {
// rememberSaveable로 상태를 저장하면 화면 회전 등 구성 변경 시에도 상태가 유지됩니다
var showDetails by rememberSaveable {
mutableStateOf(false)
}
ClickableText(
text = AnnotatedString(message.content),
onClick = { showDetails = !showDetails }
)
if (showDetails) {
Text(message.timestamp)
}
}
rememberSaveable은 원시 타입, String, Parcelable 객체에 대해 별도 설정 없이 자동으로 동작합니다. Bundle에 직접 직렬화할 수 없는 커스텀 타입을 저장해야 할 때는 Saver를 제공하면 됩니다.
@Composable
fun rememberLazyListState(
initialFirstVisibleItemIndex: Int = 0,
initialFirstVisibleItemScrollOffset: Int = 0
): LazyListState {
return rememberSaveable(saver = LazyListState.Saver) {
LazyListState(
initialFirstVisibleItemIndex,
initialFirstVisibleItemScrollOffset
)
}
}
rememberSaveable에 크거나 복잡한 객체를 저장하는 것은 반드시 피해야 합니다. Bundle에는 크기 제한이 있으며, 이를 초과하면 TransactionTooLargeException이 발생합니다. 비트맵이나 대형 리스트를 직접 저장하는 대신, 가벼운 식별자나 플래그만 저장한 뒤 실제 데이터는 데이터베이스, 네트워크 캐시, DataStore 등의 영속 계층에서 다시 불러오는 것이 모범 사례(best practices)입니다.
면접 팁: 면접에서
rememberSaveable에 대해 답변하실 때, 단순히 "구성 변경에도 상태가 유지된다"는 수준에서 그치지 마시고,Bundle크기 제한과TransactionTooLargeException까지 언급하시면 깊이 있는 답변이 됩니다.