Tech Log

[Android] ViewModel 개념 본문

Android/etc

[Android] ViewModel 개념

yuhee kim 2022. 8. 23. 19:56

MVC와 같은 아키텍처 패턴을 본격적으로 프로젝트에 적용하기 전에, ViewModel이라는 것을 알게 되었다. UI 컨트롤러와 데이터 관리를 분리하기 위해 사용되는 것으로 일단은 알고 있다. 더 정확하게 ViewModel의 개념을 알기 위해 이번에 ViewModel에 대해서 공부하고 블로깅해보려 한다. 또한, ViewModel을 제대로 공부하는 것이 아키텍처 패턴을 알맞게 적용하는데 (당연하지만)큰 도움이 될 것이라 생각한다.

 

 

들어가기 전에 앞서서, 구분해야 할 것이 있다.

 

MVVM 패턴에 사용되는 개념 중에 ViewModel 이라는 것이 있다.

그리고 안드로이드 Jetpack에 포함되는 클래스 중에 ViewModel 이라는 것이 있다.

(또한 Jetpack 클래스의 ViewModel은 Android Architecture Components(AAC)에 포함된다)

 

여기서는 일단 JetPack에 포함된 ViewModel에 중점을 두고 설명할 것이다.

 

아키텍처 패턴에서의 ViewModel은 MVVM 패턴을 설명하는 포스팅에서 자세히 설명을 해봐야 할 것 같다.

 

1. ViewModel 이란?

(AAC)ViewModel은 LifeCycle(생명, 수명주기)를 인지하고 UI와 관련한 데이터를 저장하고 관리할 수 있도록 한다. 

위 설명이 구글에서 말하는 ViewModel 클래스의 정의다.

 

ViewModel은 데이터를 독립적으로 관리하기 위해서 만들어졌다는 것이다.

Activity나 Fragment에서 UI 컨트롤과 함께 데이터를 저장, 관리하면서 문제가 있었기 때문이다.

 

1.1 ViewModel이 만들어지기 이전의 문제

Activity와 같은 View에서 종료되기 직전,

onSaveInstanceState() 메소드가 호출된다.

 

onSaveInstanceState()를 통해서 데이터를 저장할 수 있지만

이때 저장되는 데이터는 대용량의 데이터는 적합하지 않고, 소용량(직렬화했다가 다시 직렬화할 수 있는 정도의 용량)의 데이터가 적합하다고 한다.

 

그러면 큰 용량의 데이터는 어떻게 저장해야 하는가?의 문제가 생겨난 것이다.

 

그리고 또 다른 문제가 있었다.

Activity, Fragment와 같은 UI 컨트롤러에서 많은 역할을 하고 있어 호출 시에 시간이 굉장히 오래걸릴 수 있다는 것이다.

UI 컨트롤러는 본래 UI에 데이터를 표시하고 사용자와 상호작용을 하는 것이 역할이다.

그러나, 본래 역할에서 DB에서 데이터 로드까지 하게 한다면 너무 많은 책임을 떠안게 될 것이다.

(이렇게 되면 추가적으로 UI 컨트롤러가 비동기 호출, 메모리 누수 방지 관리를 해줘야 한다)

 

이러한 문제로 인해서, 이를 해결할 수 있는 것이 없을까하고 생겨난 것이 ViewModel 클래스다.

 

2. ViewModel 사용하기

ViewModel은 Activty, Fragment와 같은 UI 컨트롤러가 나타내야 하는 데이터를 저장, 관리하게 된다.

또한 Configuration Change(ex. 화면이 회전되는 경우)로 Activty가 재생성돼도 데이터를 유지시켜준다.

 

그렇다면 실제로 안드로이드에서 ViewModel 클래스는 어떻게 사용할까?

 

2.1 gradle 의존성 추가

// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"

ViewModel에서 LiveData를 사용해서 데이터를 관리할 것이라 LiveData도 추가해준다.

lifecycle_version에는 최신 버전을 써주면 된다.

필자는 현재 기준으로 2.5.1이 최신인 것 같아 2.5.1로 해주었다.

 

2.2 ViewModel 클래스 만들기

class MyViewModel : ViewModel() {
    private val users: MutableLiveData<List<User>> by lazy {
        MutableLiveData<List<User>>().also {
            loadUsers()
        }
    }

    fun getUsers(): LiveData<List<User>> {
        return users
    }

    private fun loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

구글에서 가져온 예시다.

ViewModel 클래스를 만들고, 그 안에 LiveData를 만들었다.

비동기적으로 loadUsers()에서 데이터를 가져오면 users라는 LiveData에 데이터가 들어간다.

그리고 getUsers() getter로 데이터를 담은 users를 가져올 수 있다.

 

2.3 ViewModel 인스턴스 생성 후 데이터 가져오기

class MyActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        val model: MyViewModel by viewModels()
        model.getUsers().observe(this, Observer<List<User>>{ users ->
            // update UI
        })
    }
}

데이터를 표시할 UI 컨트롤러에서 방금 만든 MyViewModel 객체를 만든다.

MyViewModel의 getUsers() getter로 users를 가져올 수 있으므로,

getUsers()가 반환하는 값을 observe해서 데이터에 변동이 있을 때마다 UI를 업데이트하는 로직이 된다.

(observer에 대한 포스팅도 작성해봐야할 것 같다)

 

이러한 ViewModel의 특징은,

ViewModel도 LifeCycle이 있는데, UI 컨트롤러가 살아있는 한 ViewModel도 살아있다.

 

주의할 점은 ViewModel에서 Activity, Fragment를 절대로 참조해서는 안된다는 것이다.

Activity, Fragment는 Configuration Change에서 사라지고 재생성되기 때문이다.

 

3. ViewModel의 활용

  • Coroutine과 함께 사용할 수 있다.
  • Fragment 간에 데이터를 공유할 때 사용될 수 있다.

자세한 활용 방법은 다른 포스팅으로 정리해봐야 할 것 같다.

 

 

참조

 

'Android > etc' 카테고리의 다른 글

[Android] Context  (0) 2023.03.28
[Android] SharedPreferences와 싱글톤 패턴  (0) 2023.03.27
[Android] Fragment 생명 주기  (0) 2022.06.25
[Android] Jetpack  (0) 2022.06.21
[Android] SharedPreferences  (0) 2022.06.15
Comments