1. MVVM의 배경
기존의 패턴인 MVC, MVP의 경우 Model이 확실하게 독립적인 요소로 분리되었으나, View와 Controller, View와 Presenter의 의존성은 여전히 존재했다. 하지만 MVVM은 단방향 데이터 흐름을 가장 잘 구현할 수 있는 패턴으로, 단방향 데이터 흐름을 통해 View와 ViewModel 간의 의존성을 소거하였다.
단방향 데이터 흐름
상위 객체는 하위 객체의 상태를 읽을 수 없고, 하위객체로 이벤트를 보낼 수도 없다. 하위 객체는 상위 객체의 이벤트를 직접적으로 읽을 수 없다. MVVM에 대입하면, View는 사용자의 입력을 전달만 하고, 결과는 받지 않는다. 대신 간접적으로 상태 변경을 통보받는다.
2. MVVM의 구조
2 - 1. View
View는 사용자에게 보이는 UI 화면이다. View와 Activity, Fragment가 해당되며, 사용자의 입력이 들어오는 부분이다. View는 사용자의 입력을 ViewModel로 전달하며, ViewModel의 상태 변화를 체크하여 변경이 발생하면 상태 업데이트를 진행한다. 대부분의 MVVM의 경우 DataBinding을 활용하여 View를 업데이트 하며, DataBinding을 사용하지 않는다면, 효율적이지 않은 순환 이벤트 흐름이 발생할 수 있다. 순환 이벤트 흐름 : View에서 이벤트를 ViewModel로 전달 -> ViewModel은 이벤트 처리 후 View로 간접 전달 -> View가 새로운 값 갱신
2 - 2. ViewModel
ViewModel은 View가 가지고 있는 UI 상태를 저장하고, View에 필요한 데이터를 Model에서 가져와 처리하며, 해당 데이터를 View로 간접 전달한다. 간접 전달의 방법에는 두 가지가 있는데, ViewModel에서 LiveData와 같은 관찰가능한 객체에 데이터를 저장하고, View가 해당 객체를 관찰하는 방법과 DataBinding을 통해서 데이터와 View를 동기화 하는 방법이다.
2 - 3. Model
Model은 데이터를 처리하며 위의 그림에서과 같이 Model(Local DB), Repository, Remote Data Source가 해당한다. ViewModel에서 받은 요청을 처리하여 반환한다.
3. AAC(Android Architecture Component) ViewModel
MVVM의 ViewModel과 별개로 안드로이드 컴포넌트의 ViewModel이 존재한다. 해당 ViewModel은 여러가지 특징을 가지고 있는데, ViewModel의 생명주기, ViewModelScope에서 코루틴 동작이 그 예이다.
ViewModel의 생명주기
ViewModel의 경우 Activity(Fragment도 포함)와 다르게 Activity가 ViewModel을 초기화한 시점에서 부터 시작되며, Activity가 파괴될 때 함께 제거된다. 특이한 점은 설정 변경이 발생했을 때 이전의 생명주기로 돌아가는 Activity와 다르게 ViewModel은 여전히 메모리상에 존재한다.
ViewModelScope에서 코루틴 동작
ViewModel은 viewModelScope에서 Coroutines이 실행할 수 있는 환경을 제공하는데, 이는 viewModelScope가 ViewModel의 생명주기를 따르는 내장 CoroutineScope이기 때문이다. 생명 주기가 끝나고 ViewModel이 삭제될 때 ViewModel은 CoroutineScope를 취소한다.
private fun increaseScore(){
_score.value += SCORE_INCREASE
viewModelScope.launch {
repository.updateScore(_score.value)
}
}
위와 같이 viewModelScope내에서 repository의 suspend function을 호출할 수 있다.
MVVM의 단점
- 무자비한 러닝커브 : 모든 이벤트 및 데이터가 비동기로 처리되기 떄문에 LiveData, Coroutines, Flow 와 같은 개념과 DataBinding, 그림 2에서 Repository, DataSource 패턴과 같은 개념의 학습이 필요하다.
- Fat ViewModel : View와 ViewModel이 1 : N을 가지더라도 ViewModel의 크기는 비대해질 수 있다.
- 순환 이벤트 흐름의 한계 : DataBinding을 사용할 수 없는 Navigation과 같은 시스템
아래와 같은 예제를 통해 안드로이드 MVVM 아키텍처에 대해 학습할 수 있다.
https://developer.android.com/courses/pathways/android-basics-kotlin-unit-3-pathway-3?hl=ko
아키텍처 구성요소 | Android Basics in Kotlin - Navigation - Architecture components | Android Developers
테스트 및 유지관리할 수 있는 강력한 앱을 디자인하도록 돕는 라이브러리 모음인 Android Jetpack 아키텍처 구성요소를 사용하는 방법을 알아봅니다.
developer.android.com