Jetpack Compose에서 ViewModel의 생명주기는 ViewModelStoreOwner에 의해 결정됩니다.
즉, ViewModel 자체가 화면이 아니라 소유자(owner) 에 묶여서 살아있다가, owner가 사라질 때 같이 파괴됩니다.
ViewModel은 화면의 생명주기(Lifecycle) 와는 조금 다릅니다.
실제로는 ViewModelStoreOwner(예: Activity, NavBackStackEntry)에 묶여서 유지됩니다.
일반적인 경우:
// Activity 범위 ViewModel
val vm = viewModel<MainViewModel>()
// → Activity가 살아있는 동안 계속 유지됨.
// → 다른 화면 전환 후에도 같은 인스턴스 사용 가능.
// Navigation backStackEntry 범위 ViewModel
val vm = viewModel<MainViewModel>(backStackEntry = navBackStackEntry)
// → 이 backStackEntry가 pop될 때 ViewModel이 파괴됨.
// → 화면 전환 시 다른 인스턴스로 교체 가능.
backStackEntry를 사용하는 이유NavBackStackEntry라는 owner를 가짐.viewModel(backStackEntry)로 지정하면ViewModel.onCleared() 호출 후 메모리에서 제거됨.composable(route) { backStackEntry -> ... } 구문에서backStackEntry가 곧 ViewModelStoreOwner 역할을 합니다.viewModel() 함수는 현재 Composition의 LocalViewModelStoreOwner를 자동으로 가져와 사용합니다.| ViewModel 범위 | 소유자(ViewModelStoreOwner) | 파괴 시점 |
|---|---|---|
| Activity 범위 | Activity | Activity 종료 시 |
| Navigation 범위 | NavBackStackEntry | backStackEntry pop 시 |
| Fragment 범위 | Fragment | Fragment 종료 시 |
📌 핵심
네, 정확하게 이해하셨습니다.
같은 ViewModel 클래스라도 ViewModelStoreOwner가 다르면
서로 완전히 독립된 ViewModel 인스턴스가 만들어지고, 각 인스턴스는 서로 다른 상태 데이터를 가집니다.
ViewModel은 클래스 이름으로 인스턴스를 공유하는 게 아니라(ViewModelStoreOwner + ViewModel 클래스) 조합으로 고유하게 관리됩니다.ViewModelStoreOwner가 ViewModelStore라는 저장소를 갖고 있고,Map 형태로 보관합니다.// Activity 범위 ViewModel
val vm1 = viewModel<MyViewModel>() // owner = Activity
// Navigation 범위 ViewModel (다른 화면 backStackEntry)
val vm2 = viewModel<MyViewModel>(owner = backStackEntryA)
val vm3 = viewModel<MyViewModel>(owner = backStackEntryB)
vm1, vm2, vm3는 모두 MyViewModel 클래스지만 완전히 다른 인스턴스입니다.vm2와 vm3의 state 데이터는 서로 전혀 공유되지 않습니다.ViewModelStoreOwner가 다르면 다른 저장소에 저장 → 다른 인스턴스 생성.LiveData, State, MutableStateFlow 등)도 각 인스턴스별로 독립.ViewModel 공유 여부는 ViewModelStoreOwner를 누구로 지정하느냐에 달려 있음.