
이번 글에서는 코드 리뷰에서 나온 질의응답에 대해서 작성해보려고 합니다.
보면 ViewLifecycle은 View의 생명주기의 상태를 가지고 있는 것이고 this@HomaMainFragment는 Fragment의 생명주기의 상태를 가지고 있다.

Fragement의 경우 onCreate()에서 CREATED 되어 onDestroy() DESTROYED 반면 View의 경우
onCreateView()에서 INITIALIZED가 되어 onDestroyView() DESTROYED된다
즉 View Lifecycle가 Fragment Lifecycle 보다 생명주기가 짧다
HomeMainFragment에서 Lifecycle을 this@HomeMainFragment로 설정한 상태에서 화면을 전환을 하게 된다면 onDestroy()가 되는 것이 아니기 때문에 LiveData를 계속 observe하게 되고 onCreateView()에서 observe가 생성되기 때문에 observer가 계속 추가되는 문제가 발생한다.
그렇기에 View의 Lifecycle를 observe에 넣어주어 화면전환 했을 때 onDestroyView()에서 observer가 종료되었다가 onCreateView()에서 observe가 생성되어도 메모리 쪽에서 문제가 없다.
MVVM ViewModel은 제가 작성한 MVVM패턴 글에 자세히 나와있어 간단히 설명한다면 View와 Model사이에서 데이터를 관리해주고 바인딩해주는 역할을 한다. 그렇기에 View는 ViewModel을 통해서만 데이터를 전송 받을 수 있다.
반면
etLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
// Clear out the available context
mContextAwareHelper.clearAvailableContext();
// And clear the ViewModelStore
if (!isChangingConfigurations()) {
getViewModelStore().clear(); // ViewModelStore를 Clear
}
}
}
});
AAC(Android Architecture Components)에는 총 5개의 라이브러리로 구성되어 있는데 그 중 하나가 ViewModel이다. AAC의 ViewModel은 화면 회전이 일어나도 데이터를 보관하고
Activity에서는 LifecycleEventObserver()로 Fragment에서는 FragmentStateManager로View의 LifeCycle을 지속적으로 observe하여 Activity/Fragment가 종료된다면(onDestroy) .clear()을 통해 데이터를 해제하는 역할을 한다.
위의 설명대로는 ViewModel이라는 이름은 같지만 하는 역할은 다른 셈이다. 그렇기에 ViewModel에 대해 공부하다보면 AAC의 ViewModel을 MVVM의 ViewModel이라고 설명하는 글도 존재했다.
AAC의 ViewModel은 단일 Activity에 단일 ViewModel의 사용을 권장하고 MVVM의 ViewModel은
단일 View에 여러개의 ViewModel이 있어도 문제가 되지않는다. 이러한 차이점이 있기 때문에 AAC의 ViewModel과 MVVM ViewModel은 다르다고 할 수 있다.
그렇다고 MVVM 패턴을 사용중에 AAC의 ViewModel을 쓰려면 어떻게 해야할까?
많은 개발자들이 사용하는 방법인 AAC의 ViewModel에 MVVM ViewModel의 역할까지 부여하는 것이다. 이렇게 한다면 화면 회전이 일어나도 데이터를 보존하고(MVVM의 패턴에서도 가능은 하나 로직을 추가로 구현해야한다.) LiveData를 활용하여 Model에서 받아온 데이터를 View에 전송해준다면 두 역할을 할 수 있는 ViewModel이 된다.
처음 개발을 시작할 때 Base가 될 코드에서 ViewModel과 Binding을 주입해주었는데 ViewModeld을 모든 View에 주입해주다보니 각각 개별의 ViewModel이 필요로 해졌고 View가 늘어남에 따라 ViewModel의 개수 또한 늘어나는 결과가 나타났습니다.
개선 전
class MyInfoFragment : BaseFragment<MyInfoViewModel, FragmentMyInfoBinding>()
실제로 필요로하지않은 ViewModel들이 말입니다. 그래서 Base가 되는 코드들에서 ViewModel을 주입해주는걸 제거하고 필요로하는 View에서만 생성해 주입하기로 하였습니다
개선 후
class CSFragment : BaseFragment<FragmentCsBinding>()
View에 ViewModel을 참조할 때 선언
private val viewModel by viewModel<CSListViewModel> { ... }
이렇게 개선을 하고 난 후 불필요한 클래스 많이 줄었으며 이는 곧 어플리케이션 경량화 라는 결과로 돌아왔습니다.
개발자는 어떠한 기능을 구현 하는 것도 중요한 일이지만 해당 기능을 구현할 때 더 효율적이고 간편하게 구현할 수 있는 방법이 더 중요하다는 것을 코드 리뷰를 통해 느끼게 되었습니다.