안드로이드로 앱 개발을 하다보면, ViewModel 이라는 단어를 자주 접하게 된다.
ViewModel의 종류에는 2가지, MVVM 뷰모델과 AAC 뷰모델이 있다.
하지만 두 단어가 모두 "뷰모델" 이라는 단어를 포함한다고 해서, 비슷한 개념이라고 착각하기 쉬운데, 그렇지 않다.
예를 들어 "파스타" 라는 대분류 안에 "토마토 파스타", "오일 파스타", "까르보나라" 등 다양한 파스타 종류가 소분류로서 존재하는 것이 아니다.
마치 "배" 라는 단어가 먹는 배, 타는 배, 사람의 배, 계산할 때의 배 등등 완전히 다른 것처럼 뷰모델도 이름만 같을 뿐 다른 역할을 한다고 생각하면 좋을 것이다.
MVVM 패턴은 마틴 파울러에 의해 나온 MVP 패턴에서 파생된 패턴이다. MVVM 패턴의 목표는 비즈니스 로직과 프레젠테이션 로직을 UI로부터 분리하는 것이다. 비즈니스 로직과 프레젠테이션 로직을 UI로부터 분리하게 되면 테스트, 유지 보수 측면에서 용이하다.
MVVM 패턴에서의 ViewModel은 View에 연결될 데이터와 메서드를 구현하고, 상태가 변화하게 되면 변경 알림 이벤트를 통해 View에게 상태 변화를 알려준다.
View는 ViewModel의 상태 변화를 옵저빙 한다.
옵저버 패턴을 사용하기 때문에 View에서는 ViewModel을 알고 있지만, ViewModel은 View를 알지 못한다.
ViewModel과 Model 사이의 관계는 1:n의 관계다. 따라서 View는 자신이 이용할 ViewModel을 선택하여 상태 변화 알림을 받게 된다. ViewModel은 View가 쉽게 사용할 수 있도록 Model의 데이터를 가공하여 View에게 제공한다.
AAC의 ViewModel은 안드로이드 애플리케이션의 화면 회전 같은 환경 변화에서 UI 데이터를 유지하는 데 집중하는 클래스다. 예를 들어, 사용자가 로그인한 정보를 화면 회전 후에도 유지할 수 있도록 도와준다. 화면 회전 시 Activity는 새로 생성되지만, ViewModel은 데이터를 그대로 유지하여 불필요한 데이터 재로딩을 방지해준다.
AAC Viewmodel은 딱 이 역할만 담당한다.
ViewModel을 생성하고 거기에 유저 로그인 정보를 넣었을 뿐, 그렇다고 이게 MVVM 패턴이 되지는 않는다.
대부분의 예제를 보면, MVVM을 구현할 때 AAC ViewModel을 사용한다.
AAC ViewModel은 MVVM의 ViewModel과 전혀 상관이 없다고 했는데, 인터넷에 올라온 예제들이 모두다 잘못된 예제일까?
그렇지 않다. AAC의 ViewModel을 MVVM의 ViewModel로써 사용할 수 있다.
MVVM의 뷰모델의 역할은 위에서 보았듯이 뷰와 모델 사이에서 데이터를 관리하고 바인딩해주는 것이다. 뷰모델이 가지고 있는 데이터를 옵저버블하게 해주고, 뷰에서는 데이터 바인딩으로 그것을 구독하고 있으면 되는 것이다.
AAC ViewModel이라고 그게 안될리가 없다. 오히려 화면 회전시 데이터를 유지시켜주는 기능까지 있으므로 더 좋다. AAC ViewModel에 LiveData를 사용하여 바인딩 시킬 수 있다.
안드로이드 개발을 하면서 MVVM패턴을 사용하려고 한다면, 꼭 AAC의 ViewModel을 사용하지 않아도 MVVM구현은 가능하다.
그러나 놓치지 말아야 할 것은, AAC의 뷰모델은 MVVM에서 말하는 ViewModel과 다르다는 것을 아는 것이다. 이걸 모르고 AAC ViewModel을 MVVM ViewModel처럼 사용한다면 개발 도중 어려움이 생길 가능성이 크다. 예를 들어, AAC ViewModel은 ViewModelProviders를 사용해서 ViewModel을 만드는데, 이렇게 만들어진 뷰모델은 그 액티비티에서 딱 하나만 존재하게 된다.
액티비티 한 개 내에서만 유효한 싱글톤인 셈이다. 이런 특성은 일반적인 MVVM에서는 강제되는 것이 아니기 때문에 혼란이 올 수 있다.
구분 | AAC ViewModel | MVVM에서의 ViewModel |
---|---|---|
주요 역할 | 화면 회전 등 환경 변화에서 UI 데이터를 유지 | UI와 모델을 분리하고, 데이터를 관리하고 바인딩 |
기능 | 데이터를 화면 회전 후에도 유지 | 데이터 바인딩, LiveData/StateFlow 등을 통해 UI 상태 관리 |
사용 목적 | UI 상태 유지, 화면 회전 후 데이터 복원 | UI와 비즈니스 로직 분리, 데이터 처리 및 상태 관리 |
권장 사항 | UI 상태 유지가 중요한 경우 사용 | UI와 비즈니스 로직을 명확히 분리하는 경우 사용 |
MVVM이나 AAC 둘 다 똑같은 ViewModel(import androidx.lifecycle.ViewModel)을 import 해서 사용한다. 그런데 어떻게 ViewModel이 2개로 나뉜다는건지 이해가 가지 않는다. import 하는게 각각 다르면 이해가 가는데, aac나 mvvm 둘 다 같은 뷰모델을 import 한다!
실제로 두 방식은 본질적으로 동일한 ViewModel 클래스를 사용한다.
차이점은 "사용 방식"과 "아키텍처 패턴"에 있다.
androidx.lifecycle.ViewModel
importviewModelScope
등 동일한 기능데이터 관리 방식
상태 표현 방법
// AAC ViewModel
class UserViewModel : ViewModel() {
// LiveData 사용
private val _users = MutableLiveData<List<User>>()
val users: LiveData<List<User>> = _users
}
// MVVM ViewModel
class UserViewModel : ViewModel() {
// StateFlow 사용
private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState: StateFlow<UiState> = _uiState
}
즉, 같은 ViewModel 클래스를 사용하지만 "어떻게 상태를 관리하고 표현하느냐"의 차이이다.
결론: 기술적으로 같은 ViewModel, 패러다임만 다를 뿐이다.
https://leveloper.tistory.com/216
https://medium.com/@jungil.han/%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-viewmodel-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-2e4d136d28d2
https://medium.com/kenneth-android/android-mvvm-viewmodel%EA%B3%BC-aac-viewmodel%EC%9D%98-%EC%B0%A8%EC%9D%B4-8c0d54922e07
https://wooooooak.github.io/android/2019/05/07/aac_viewmodel/