
안드로이드 ViewModel은 화면 회전에도 값이 남게 해 주는 도구로 자주 소개됩니다. 하지만 더 중요한 역할은 Activity나 Fragment가 너무 많은 상태 관리 책임을 떠안지 않게 분리하는 것입니다.
핵심은 ViewModel이 UI에 필요한 상태를 화면 생명주기보다 오래 보관한다는 점입니다. 그래서 화면이 다시 만들어져도 같은 ViewModel을 통해 이전 상태를 이어갈 수 있습니다.
안드로이드 ViewModel이 필요한 문제
Activity는 화면 회전 같은 configuration change가 발생하면 다시 생성될 수 있습니다. 화면 객체가 다시 만들어질 때 입력값, 로딩 결과, 선택 상태를 Activity 필드에만 들고 있었다면 잃어버리기 쉽습니다.
class UserActivity : AppCompatActivity() {
private var query: String = "" // 화면 재생성 때 잃기 쉬운 상태
}이런 상태가 화면 생명주기에 너무 붙어 있으면 UI가 다시 만들어질 때 복구 코드가 복잡해집니다.
ViewModel은 화면 상태를 따로 보관한다
ViewModel은 Activity나 Fragment보다 오래 살아남을 수 있는 객체입니다. 그래서 UI가 다시 생성되어도 같은 화면 범위의 상태를 이어서 사용할 수 있습니다.
class UserViewModel : ViewModel() {
var query by mutableStateOf("")
private set
fun updateQuery(value: String) {
query = value
}
}Activity와 ViewModel의 책임을 나누자
- Activity/Fragment: 화면을 그리고 사용자 이벤트를 ViewModel에 전달
- ViewModel: UI 상태를 만들고 변경 규칙을 관리
- Repository: 데이터 소스 접근과 캐시/네트워크 처리
- Composable/View: 상태를 읽고 화면으로 표현
화면 회전과 프로세스 종료는 다르다
ViewModel은 configuration change에는 강하지만, 앱 프로세스가 종료된 뒤 모든 상태를 영구 보관해 주는 도구는 아닙니다. 프로세스 종료 후 복원이 필요한 작은 UI 상태는 SavedStateHandle이나 저장소 전략을 함께 검토해야 합니다.
class SearchViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
var query: String
get() = savedStateHandle["query"] ?: ""
set(value) { savedStateHandle["query"] = value }
}ViewModel에 넣지 않는 편이 좋은 것
- Activity나 View 같은 화면 객체 참조
- Context가 꼭 필요한 긴 생명주기 작업
- 단순히 한 번만 쓰고 버릴 지역 변수
- 영구 저장이 필요한 데이터를 ViewModel에만 보관하는 방식
정리
안드로이드 ViewModel은 상태를 오래 들고 있기 위한 저장소가 아니라, UI 상태와 화면 객체의 책임을 분리하는 구조입니다. 화면 회전에는 강하지만 영구 저장소는 아니므로 상태의 성격에 맞게 SavedStateHandle이나 Repository와 함께 사용해야 합니다.
내부 글은 Compose 상태 호이스팅은 언제 해야 할까, Android SavedStateHandle은 언제 필요할까, collectAsStateWithLifecycle 사용 기준와 함께 보면 좋습니다. 외부 기준은 Android Developers – ViewModel overview, Android Developers – Save UI states를 확인했습니다.