위의 이미지를 보면 ViewModel의 LifeCycle이 Activity/Fragment보다 길기때문에
ViewModel에서 참조한 View들이 destroyed가 된 view일수도 있다 이렇게 된다면 Memory leak이 일어나거나 Crash가 발생합니다.
또한 ViewModel에서는 View뿐만 아니라 Activty의 Context를 참조하고 있는 Class도 참조해서는 안됩니다.
Google에서 권장하는 방식은 하나의 ViewModel만을 사용하는 것을 권장합니다.
상황에 따라서는 각 View에 맞는 ViewModel을 만들 수 도 있지만 하나의 View에 여러 개의ViewModel이 존재한다면 View의 복잡도가 높아지고 클래스들이 많아져 효율적이지 못한 코드가 생성됩니다.
제가 진행중인 박카스 프로젝트에서도 ViewModel이 각각의 View마다 필요하냐라는 문제가 제기되었습니다.
abstract class BaseFragment<VM: BaseViewModel, VB: ViewBinding>: Fragment() {
abstract val viewModel: VM
...
}
abstract class BaseActivity<VM : BaseViewModel, VB : ViewBinding> : AppCompatActivity() {
abstract val viewModel: VM
...
}
해당 코드는 저희 프로젝트의 BaseActivity/BaseFragment의 일부분 입니다. 저희
코드에서 viewModel을 할당을 받게 만들었고 그렇기에 생성되는 View마다 ViewModel
주입해야했습니다. 맡은 부분의 코드를 작성할 때 ViewModel을 View마다 만들었고 ViewMdoel을 최소한으로 하여 클래스를 줄이는게 맞다라는 결과가 코드리뷰에서 나왔습니다. 처음 ViewModel을 줄이는 부분에서 많은 이야기가 오고갔습니다. 추후에 이 이야기에 대한 글을 따로 작성할 예정이고 대략적으로 말씀드리자면
AAC에서 말하는 ViewModel과 MVVM에서 말하는 ViewModel의 차이가 있었고 AAC ViewModel를 MVVM ViewModel에 wrap하여 활용할 수 있지만 두 ViewModel의 차이는 1:n 이냐 1:1 매칭이냐 하는 차이입니다. 이 부분의 조금 전 말씀 드린 것처럼 추후 따로 글을 작성하겠습니다. 끝은 저희는 1:n으로 구현이 가능하고 효율적이라면 그게 맞다라는 결론을 내렸고 해당부분에 대한 수정 작업을 진행중에 있습니다.
작업이 완료된다면 Before/After로 차이를 보여드리겠습니다.
class CSListViewModel (
private val csRepository: CSRepository
): BaseViewModel() {
private val _csListData = MutableLiveData<List<CSModel>>()
val csListData : LiveData<List<CSModel>>
get() = _csListData
MutableLiveData는 말 그대로 변할 수 있는 LiveData라는 데이터입니다.
해당 코드에서의 동작을 설명한다면
1. _csListData에는 CSModel에 있는 데이터를 받아와 저장을 하게됩니다.
2. csListData는 getter로 데이터를 _csListData를 받아옵니다.
3 getter로 데이터를 받아오는 csListData는 읽을 수 만있게되고 데이터의 변경이 불가능합니다.
즉 데이터가 변경이 된다면 MutableLiveData에서 변경이되는 것이고 변경된것을 csListData에서 받아 바뀐 모습을 View에 건네줄 데이터를 csListData가 가지고 있는 것입니다. 여기서 주제 3의 내용처럼 Public으로 바꾸게 된다면 어떻게 될까요?
정답은 Public이기에 view에서 _csListData를 불러올 수 있게되고 데이터의 변경 또한 가능하게 됩니다. MVVM패턴에 위배되는 동작(View에서 Model에 대해 직접적으로 데이터를 받고 수정하는)이 가능하다는 것입니다. 그렇기에 Private로 선언을 하여 View에서 직접 참조를 하지 못하도록 하는 것입니다.
MVVM 패턴에 대해 공부를 하고 알아가는게 많아질 수록 내가 작성을 해왔던 코드가 잘못된 부분이 있었으며 그 문제에 대한 해결방법을 생각하거나 팀 프로젝트에서 주제로 정해 리뷰를 함으로서 토의를 하고 테스트를 하여 검증으로 문제 해결하는것이 단순 검색을 통한 문제해결 보다 더 오래 걸리지는 몰라도 문제 해결을 위해 크롬창을 키는 것이 아닌 동작과정 및 문제부분에 관찰과 생각을 먼저하는 습관이 생기는 것 같다. A->B라는 결과가 있다면 A는 B구나라는 결과보다는 A가 왜 B이고 왜 이렇게 되는지에 대한 과정을 먼저 생각하는 개발자가 되는것이 개발자가 가져야하는 습관이라고 생각한다 꾸준하게 공부하고 팀 프로젝트를 통해 느리지만 단단하게 발전하는 개발자가 되고싶다.