리저브콜드브루 2025. 2. 14. 13:32
728x90
반응형

ViewModel

  • Android Jetpack의 아키텍처 컴포넌트 중 하나
  • UI 데이터를 관리하고 저장하기 위해 설계된 클래스
  • ViewModel은 Activity나 Fragment의 생명 주기를 고려하여 데이터를 효과적으로 관리할 수 있게 해준다.
  • 화면 회전과 같은 이벤트로 인해 Activity/Fragment가 재생성되더라도 데이터를 유지하고, 불필요한 네트워크 호출이나 데이터 처리 방지

 

주요 특징

  • UI 생명 주기 인식
    • ViewModel은 UI 컨트롤러(Activity/Fragment)와 연결되어 있으며, UI 생명 주기를 알고있다.
    • UI가 destroy되기 전까지 메모리에 데이터를 유지한다.
    • 화면 회전, 구성 변경 등으로 인해 Activity/Fragment가 재생성될 때 데이터를 다시 초기화하지 않아도 된다.
  • UI 데이터 저장 및 관리
    • UI 데이터를 저장하고 관리하는 데 최적화되어 있다.
    • 데이터가 Activity/Fragment의 생명 주기에 영향을 받지 않고 유지된다.
  • 메모리 관리 최적화
    • ViewModel은 메모리에 데이터를 유지하면서 Activity/Fragment의 메모리 누수를 방지
    • UI 요소(Activity, Fragment)와 직접적으로 참조하지 않으므로 메모리 릭이 발생하지 않는다.
  • 비동기 작업 관리
    • ViewModel은 코루틴과의 통합을 지원하여 비동기 작업(API 호출, 데이터베이스 쿼리 등)을 처리하는 데 적합하다.
    • UI 생명 주기와 독립적으로 작업을 관리하므로, 예를 들어, 사용자가 화면을 떠났더라도 네트워크 작업이 중단되지 않고 계속 진행된다.

생명 주기

Activity/Fragment의 생명 주기를 따르고, onCleared() 메서드를 통해 생명 주기가 끝날 때 리소스를 해제한다.

 

생명 주기 흐름

  • 생성 (Initialization)
    • ViewModel은 Activity/Fragment와 연결되며, 생명 주기 시작 시 생성된다.
    • ViewModelProvider 또는 ViewModelProvider.Factory를 통해 생성된다.
  • 활성 상태 (Active)
    • Activity/Fragment가 활성 상태일 때 데이터 관리 및 제공 역할을 수행
    • UI를 관찰하는 LiveData 객체를 통해 데이터를 제공
  • 해제 (Cleared)
    • Activity/Fragment가 완전히 소멸되면 ViewModel의 onCleared() 메서드가 호출되며 리소스가 정리된다.
    • 메모리 누수를 방지하기 위해 비동기 작업을 취소하거나 데이터 스트림을 중지한다.

핵심 구성 요소

 

LiveData

  • ViewModel은 UI와 데이터를 연결하기 위해 LiveData를 사용한다.
  • LiveData는 관찰 가능한 데이터 홀더(Observable Data Holder)로, UI 데이터 변화를 관찰하고 자동으로 업데이트한다.
  • MutableLiveData를 통해 내부에서 값을 변경하고, 외부에는 LiveData로 읽기만 가능하게 제공한다.
class ExampleViewModel : ViewModel() {
    private val _data = MutableLiveData<String>()
    val data: LiveData<String> get() = _data

    fun updateData(newData: String) {
        _data.value = newData
    }
}

 

Coroutine과 VieModelScope

  • 비동기 작업(API 호출, 데이터베이스 쿼리 등)을 안전하게 실행하기 위해 ViewModelScope를 제공한다.
  • ViewModelScope는 ViewModel의 생명 주기와 연결되어 있으며, 생명 주기가 끝날 때 모든 작업을 자동으로 취소한다.
class ExampleViewModel : ViewModel() {
    fun fetchData() {
        viewModelScope.launch {
            val result = someRepository.getData()
            _data.postValue(result)
        }
    }
}

 

onCleared()

ViewModel이 소멸될 때 호출되는 메서드로, 리소스 해제 및 정리 작업을 수행한다.

override fun onCleared() {
    super.onCleared()
    // 리소스 해제 로직
}

 

ViewModel과 Activity/Fragment의 관계

  • ViewModel은 Activity/Fragment와 연결되지만, 독립적으로 동작한다.
  • 동일한 ViewModel을 여러 Fragment에서 공유할 수도 있다.
class SharedViewModel : ViewModel() {
    private val _sharedData = MutableLiveData<String>()
    val sharedData: LiveData<String> get() = _sharedData

    fun updateData(newData: String) {
        _sharedData.value = newData
    }
}

// Activity에서 ViewModel 초기화
val sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)

// Fragment에서 ViewModel 접근
val sharedViewModel = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)

 

단점

  • 장기 저장 불가
    • ViewModel은 일시적 데이터 관리에 적합하며, 앱 종료 후에도 유지되어야 하는 데이터에는 적합하지 않음.
    • 영구 저장이 필요한 데이터는 SharedPreferences, DataStore, Room 같은 저장소를 사용해야 함
  • 생명 주기 제약
    • ViewModel은 UI 생명 주기 내에서만 동작한다. 전역적으로 사용되는 데이터 관리에는 적합하지 않다.
  • 복잡한 상태 관리
    • 상태가 복잡해질 경우, LiveData나 StateFlow 같은 추가 도구 필요
728x90
반응형