프로그래밍/Android

Mastering Android ViewModels: init {} 블록에서 상태를 초기화하는 것을 피하라

Lou Park 2024. 6. 23. 11:55

ViewModel의 init {} 블록에서 상태를 초기화하는 것은 편리해보인다.

나도 프로젝트에서 종종 그렇게 해 오고는 했는데, 그렇게 하지말라는 이유는 다음과 같다.

 

1. ViewModel 생성과 강하게 커플링됨

데이터를 가져오는 타이밍이 ViewModel 생성시에 있기 때문에, 새로고침 등 사용자 상호작용이나 기타 이벤트에 따라 데이터 로딩시점을 제어하기 어렵게 만든다. 

 

2. 테스트하기 어려움

ViewModel이 생성되자마자 데이터 로드가 시작되므로 1번의 이유로 인해 테스트하기 어려워진다. 

 

3. 리소스 낭비의 가능성

앱이나 화면에 진입하자마자 데이터를 필요로 하지 않을 경우, 자원의 비효율적인 사용으로 이어질 수 있음.

 

4. UI 응답성

init {} 블록은 최대한 가볍게 유지해야한다. 여기에서 메인 스레드를 차단하는 작업이 들어가는 경우에 UI 응답성에 영향을 미칠 수 있다. 

 

 

안티 패턴 살펴보기

# 예시 1

간단히 살펴보면 뭔가를 검색하는 화면의 ViewModel인데,  init {} 블록에서 검색가능한 Word들을 불러서 UI 상태를 초기화하고 있다.

 

# 예시 1 개선 코드

init {} 블록에서 데이터를 가져오는 부분을 제거하고 Flow 빌더를 통해 실제로 상태를 필요로하는 시점에 초기화 될 수 있도록 변경했다.

 

# 예시 2

이것은 실시간 검색을 구현한건데, 사용자가 입력한 쿼리를 Flow를 통해 debounce하고, 검색 요청결과를 UI 상태로 다시 만든다. 이 Flow는 init {} 블록에서 collect 된다. ViewModel은 Configuration Change와는 별개로 더 긴 생명주기를 가져가기 때문에, 이러한 방식은 화면의 생명주기와 동떨어져 자원 낭비로 이어지거나, 예상치 못한 버그를 만들어 낸다. 이 코루틴 블록이 취소되었을때는 기능이 전혀 동작하지 않을 수도 있다.

 

# 예시 2 개선 코드

개선된 코드 역시 init {} 블록에서 하던 작업을 없앴으며, switchMap을 이용해 LiveData로 바꾸어 화면의 생명주기가 끝났을때 불필요한 작업이 발생되지 않도록 했다.

 

*이 글은 Mastering Android ViewModels에서 발췌해온 것입니다.