본문 바로가기
Android/Android Core

[Android/Kotlin] ViewModel 개념과 ViewModelStore를 통한 구성 변경 시 상태 유지 원리

by quessr 2025. 3. 10.

 

안드로이드 컴포넌트의 생명 주기에 따라 데이터가 유실되지 않도록 하기 위해 ViewModel을 사용하는 것이 일반적이지만, 문득 구성 변경(Configuration Change)으로 인해 Activity가 파괴되는데도 어떻게 ViewModel이 유지될 수 있을까? 하는 궁금증이 들었습니다.

ViewModel이 어떻게 상태를 관리하고 구성 변경 시에도 유지될 수 있는지 이해하기 위해 내부 코드를 직접 분석하고 정리한 내용을 공유하겠습니다. 또한, ViewModel의 개념과 사용 시 고려해야 할 사항들도 함께 정리하겠습니다.


ViewModel이란?

  • 구성 변경이 발생해도 데이터를 유지하도록 설계된 컴포넌트입니다.
  • Activity나 Fragment보다 생명 주기가 깁니다.
  • 하지만 앱이 종료되면 ViewModel도 함께 종료됩니다.
  • 예시: 화면 회전 시에도 UI 상태를 유지하는 데 활용됩니다.

ViewModel의 상태 유지

ViewModel을 활용하면 구성 변경 시에도 데이터를 유지할 수 있지만, 백그라운드에서도 데이터를 보존하려면 SavedStateHandle을 활용해야 합니다.

class MyViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
    private val _count = savedStateHandle.getLiveData("count", 0)
    val count: LiveData<Int> get() = _count

    fun increaseCount() {
        _count.value = _count.value?.plus(1)
        savedStateHandle.set("count", _count.value)
    }
}
  • SavedStateHandle을 이용하면 프로세스 종료 후 복원 시에도 상태를 유지할 수 있습니다.

ViewModel 사용 시 유의사항

1. ViewModel의 목적은 구성 변경 시 상태 유지

  • 화면 회전 등으로 인해 Activity 또는 Fragment가 재생성되더라도 데이터를 유지할 수 있습니다.
  • 하지만 앱이 종료되면 ViewModel도 함께 종료됩니다.

2. 영구적인 데이터 저장에는 적합하지 않음

  • ViewModel은 메모리 내에서만 데이터를 관리하므로 영구 저장소로 활용하면 안 됩니다.
  • 데이터를 영구적으로 저장하려면:
    • 로컬 저장소(Room, SharedPreferences 등)
    • 원격 서버(Firebase, API 서버 등)
    • 위와 같은 저장 매체를 활용해야 합니다.

3. Activity Context 참조 금지 (메모리 누수 방지)

  • ViewModel은 Activity보다 오래 살아남으므로 ActivityContext를 직접 참조하면 메모리 누수가 발생할 수 있습니다.
  • 만약 Context가 꼭 필요하다면 ApplicationContext를 사용해야 합니다.
class MyViewModel(application: Application) : AndroidViewModel(application) {
    private val context = getApplication<Application>().applicationContext
}
  • AndroidViewModel을 사용하면 안전하게 ApplicationContext를 참조할 수 있습니다.

4. UI에 대한 의존성을 최소화해야 함

  • ViewModel은 UI와 독립적이어야 하며, UI 관련 로직을 포함해서는 안 됩니다.
  • UI 상태는 LiveData 또는 StateFlow 등을 통해 관리하고, UI에서 이를 구독하는 방식이 권장됩니다.

5. ViewModel을 다른 클래스, 함수에 전달하지 않기

  • ViewModel 인스턴스는 시스템에서 관리되므로, 다른 일반 클래스나 함수에 전달하면 예기치 않은 문제가 발생할 수 있습니다.
  • ActivityFragmentUI 시스템에 가깝게 배치하는 것이 바람직합니다.

ViewModelStore란?

ViewModelStoreViewModel 인스턴스를 저장하고 관리하는 역할을 하는 객체입니다. 즉, ViewModel을 생성하고 유지하며, 구성 변경 시에도 동일한 ViewModel을 반환할 수 있도록 도와주는 저장소입니다.

ViewModelStore의 역할

  1. ViewModel을 저장하고 관리
    •    ViewModelProvider새로운 ViewModel을 생성하거나 기존 ViewModel을 ViewModelStore에서 찾아 반환할 수 있도록 합니다.
  2. 구성 변경 시에도 ViewModel을 유지
    •    Activity가 화면 회전 등으로 파괴되더라도 ViewModelStore는 유지됩니다.
    •    새로 생성된 Activity가 기존 ViewModelStore를 참조하여 기존 ViewModel을 다시 사용합니다.
  3. 필요 없을 때 ViewModel을 정리
    •    Activity가 완전히 종료되면, ViewModelStore도 제거되면서 ViewModel도 함께 정리됩니다.

ViewModelStore 내부 동작 분석

1. viewModels() 함수와 ViewModelStore의 관계

위 코드는 내부적으로 viewModels() 확장 함수를 사용하여 ViewModel을 초기화합니다. 해당 함수는 다음과 같은 과정을 거칩니다.

viewModels 안으로 들어가보면, 아래와 같은 코드가 나옵니다.

  • viewModelStore를 이용해 ViewModel을 가져오며, 기존에 생성된 ViewModel이 있다면 이를 반환합니다.
  • ViewModelStoreOwner를 사용하여 현재 Fragment 또는 Activity의 ViewModelStore를 참조합니다.

여기서 다시 viewModelStore 코드 안으로 들어가 보겠습니다.

2. ViewModelStore의 내부 동작

  • ViewModelStore는 내부적으로 map을 사용하여 ViewModel을 저장하고 관리합니다.
  • put()을 통해 새로운 ViewModel을 저장하고, 기존 ViewModel이 있다면 onCleared()를 호출하여 정리합니다.
  • clear()를 호출하면 모든 ViewModel이 제거됩니다.

즉, ViewModelStore를 유지하면서 기존 ViewModel을 재사용하는 구조입니다.


마무리

  • ViewModelStore는 ViewModel을 저장하고 관리하는 역할을 합니다.
  •  Activity가 파괴되더라도 ViewModelStore가 유지되면 ViewModel을 계속 사용할 수 있습니다.
  •  Activity가 완전히 종료되면 ViewModelStore도 삭제되며, ViewModel도 정리됩니다.
  •  ViewModelStore 내부적으로 클래스를 키로 사용하여 Activity/Fragment별로 ViewModel을 구별합니다.

참고: https://developer.android.com/reference/androidx/lifecycle/ViewModelStore 

 

ViewModelStore  |  API reference  |  Android Developers

androidx.appsearch.builtintypes.properties

developer.android.com

 

반응형