|

Android SavedStateHandle은 언제 필요할까: 화면 회전과 프로세스 죽음을 구분해서 이해하기

Android SavedStateHandle은 언제 필요할까: 화면 회전과 프로세스 죽음을 구분해서 이해하기
Android SavedStateHandle은 언제 필요할까: 화면 회전과 프로세스 죽음을 구분해서 이해하기

SavedStateHandle은 Android ViewModel에서 화면 상태를 복원하기 위한 작은 저장 공간입니다. 특히 화면 회전과 process death를 구분해서 이해해야 언제 필요한지 선명해집니다.

많이 헷갈리는 지점은 ViewModel이 이미 화면 회전을 버티는데 왜 SavedStateHandle이 필요하냐는 질문입니다. 답은 간단합니다. ViewModel은 configuration change에는 강하지만, system-initiated process death까지 장기 저장해 주는 도구는 아닙니다.

SavedStateHandle 역할 카드
SavedStateHandle은 ViewModel 상태 중 복원에 필요한 작은 단서를 저장한다

SavedStateHandle을 이해하려면 두 상황을 나눠야 한다

Android 공식 상태 저장 문서는 configuration change와 system-initiated process death를 나누어 상태 저장 전략을 설명합니다.

이 주제는 기존의 rememberSaveable과 SavedStateHandle 차이 글과 이어서 보면 더 이해하기 쉽습니다.

첫 번째는 화면 회전 같은 configuration change입니다. Activity나 Fragment가 다시 만들어져도 ViewModel은 유지될 수 있습니다. 이때는 ViewModel 안의 UI state가 그대로 남아 있으므로 SavedStateHandle이 꼭 필요하지 않을 수 있습니다.

두 번째는 시스템이 앱 프로세스를 종료했다가 나중에 복원하는 상황입니다. 이때 ViewModel 인스턴스는 메모리에 남아 있지 않습니다. 화면을 다시 만들려면 어떤 데이터를 다시 불러와야 하는지 알 수 있는 작은 단서가 필요합니다.

  • 검색 화면의 query 문자열
  • 상세 화면의 itemId
  • 탭이나 필터의 선택값
  • 사용자가 입력 중이던 짧은 폼 값

ViewModel과 SavedStateHandle의 역할 차이

ViewModel은 화면에 필요한 상태를 메모리에서 관리합니다. 네트워크 결과, DB에서 읽어온 목록, 화면 로딩 상태처럼 UI를 그리는 데 필요한 값을 담기 좋습니다.

SavedStateHandle은 그 상태 전체를 저장하는 곳이 아닙니다. 다시 로드할 수 있는 최소 단서를 저장하는 곳에 가깝습니다. 예를 들어 상품 상세 화면에서는 상품 객체 전체보다 productId를 저장하고, 복원 뒤 productId로 다시 조회하는 방식이 더 안전합니다.

class DetailViewModel(
    private val savedStateHandle: SavedStateHandle,
    private val repository: ProductRepository
) : ViewModel() {
    private val productId: String = checkNotNull(savedStateHandle["productId"])

    val uiState: StateFlow<DetailUiState> =
        repository.observeProduct(productId)
            .map { DetailUiState(product = it) }
            .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), DetailUiState())
}

rememberSaveable과는 무엇이 다를까

Compose의 rememberSaveable은 composable 안의 저장 가능한 UI 상태를 보존하는 데 유용합니다. 예를 들어 텍스트 필드의 임시 입력값이나 접힘/펼침 상태처럼 UI 가까이에 있는 값에 잘 맞습니다.

반면 SavedStateHandle은 ViewModel이 복원에 필요한 값을 들고 있어야 할 때 자연스럽습니다. 특히 navigation argument와 연결되거나, ViewModel 로직이 그 값을 기준으로 데이터를 다시 불러와야 한다면 SavedStateHandle 쪽이 더 낫습니다.

  • UI 안에서만 쓰는 작은 상태: rememberSaveable
  • ViewModel 로직이 다시 로드해야 하는 단서: SavedStateHandle
  • 앱의 실제 데이터 원본: Room, DataStore, 서버, 파일 저장소

SavedStateHandle에 넣지 말아야 할 것

SavedStateHandle은 편리하지만 모든 상태를 넣는 저장소가 아닙니다. 큰 리스트, 이미지, 복잡한 도메인 객체, 장기간 유지해야 할 데이터는 적절하지 않습니다. Android 공식 문서도 saved state 계열 API를 장기 저장소로 보지 말고, UI 상태를 다시 로드하는 데 필요한 작은 데이터에 쓰는 방향을 안내합니다.

  1. 복원에 꼭 필요한 최소값인지 확인한다
  2. 그 값으로 원본 데이터를 다시 불러올 수 있는지 본다
  3. 크거나 복잡한 객체라면 저장하지 않는다
  4. 장기 보존이 필요하면 DB나 DataStore를 쓴다

정리

SavedStateHandle은 ViewModel을 대체하는 저장소가 아닙니다. ViewModel이 사라진 뒤 화면을 다시 만들기 위한 작은 단서를 남기는 도구입니다.

화면 회전만 걱정한다면 ViewModel로 충분한 경우가 많습니다. 하지만 process death 이후에도 사용자가 보던 화면을 적절히 복원해야 한다면 SavedStateHandle을 설계에 포함하는 것이 좋습니다.

함께보면 좋은 글