개요
지난 1편에서는 클린아키텍처에 대한 내 생각과 고민점 그리고 리팩토링 하는 과정을 적어봤었다.
이번에는 MVVM 패턴에 대한 내 생각에 대해서 적어보고자 한다.
레거시였던 MVC
MVC는 예전에 아주 많이 사용하였던 전통적인 Android의 디자인 패턴이다.
Model-View-Controller로 구성되어 있으며 각각은 아래와 같은 역할을 한다.
Model
- 도메인 논리(실제 비즈니스 규칙)를 처리
- 데이터베이스 및 네트워크 계층과의 통신 담당
View
- 화면에 보이는 컴포넌트를 담고 있는 UI Layer
- Model에 저장된 데이터의 시작화
- 사용자와의 상호 작용 제공
- 일반적으로 XML이 해당 역할을 수행(컴포즈 이전)
Controller
- 뷰와 모델간의 관계를 설정
- 애플리케이션 핵심 로직 포함
- 사용자의 행동에 대한 정보를 얻고 필요에 따라 모델을 업데이트
- 일반적으로 Activity/Fragment가 이 역할을 수행
- 때로는 Controller와 View를 Activity/Fragment에서 모두 수행하기도 함
이렇게 역할이 나뉘어져있고 모듈식 디자인을 제공함에도 불구하고 코드 레이어는 서로에게 의존한다.
이 패턴에서는 특히 View와 Controller는 모두 모델에 의존하게 되고 View와 Controller는 모두 비대해져 간다.
즉, 역할이 제대로 분리되지 않는다는 것이다.
대체제, MVVM
MVC를 대체하기 위해 MVP, MVVM, MVI등의 패턴이 나왔지만 우리는 가장 대중적인 MVVM을 채택했다.
MVVM에서 View는 오롯이 View의 역할만을 하고(Activity/Fragment) UI 로직은 ViewModel에서 수행한다.
직접적으로 View에서 UI를 컨트롤 하지 않고 ViewModel에서 상태를 핸들링한다.
ViewModel의 상태는 Layout XML에서 Observing하고 데이터가 변경됨에 따라 UI를 Update한다.
그렇기에 Android에서는 Databinding을 추천하고 있다.
Databinding 사용하지 않는다면 View에서 Observing 코드가 반복적으로 들어가고 좀 더 UI의 비즈니스 로직이 View에 종속되어야 하는 문제들이 생겨난다.
그러므로 가히 필수적이라고는 생각이 들긴 하지만 우리팀에서는 사용을 지양하였다.
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/imgFreeShipping"
style="@style/ItemTag"
visible="@{item.property.hasDeliveryFee}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="@string/free_delivery"
tools:text="무료배송" />
MVVM에 대한 우리의 컨벤션
위에서 MVVM에 대한 내 생각은 Databinding이 가히 필수적이라고 생각한다고 했지만 우리는 사용하지 않았다.
이에 대한 우리만의 타당한 이유는 있었고 나도 그에 공감이 갔다.
코드의 혼란으로 인한 유지보수 비용
Databinding은 분명히 편리한 도구이자 MVVM에 필요한 요소이다.(MVVM을 완성본으로 만들어주는 것이랄까...?)
하지만 코드 흐름의 전개를 파악하기가 상당히 난해하고, XML에서 Code 처리가 되고있는 부분이 좀 더 어렵게 만들어가는 느낌이 들었다. 결국에는 해결할 수 없는 상태변화는 BindingAdapter를 활용해서 해결해야 한다.
Databinding을 활용해도 결국에는 View에서 처리해야 하는 비즈니스 로직이 존재한다..
이를 코드베이스로 레이아웃을 작성하고 재사용성을 높이며 가독성을 좋게하여 해결한 Compose 👍
ViewModel에 대한 나의 고민
ViewModel은 View와 1:N 관계를 성립하고 재사용 또한 가능하다. 그런데 제대로 된 1:N 관계를 설계하려면 상태 관리에 대해 ViewModel을 더욱 작게 쪼개야 성립할 수 있을 것 같다.
하지만 개발을 하다보면 ViewModel이 복잡해지는 경험이 몇번씩 생겼고 팀원들 또한 같은 생각이었다.
사실 뷰모델이 복잡해지는 것은 역할 파악이 제대로 안 되었다고도 볼 수 있다.
뷰모델은 그저 리포지터리에서 데이터를 가져와 뷰상태를 생성하는 것이 역할인데 다른 비즈니스 로직이 들어가거나 그 외의 역할을 하기 때문이다.
이것은 설계된 클린아키텍처를 제대로 활용하지 못하고 있거나 Databinding을 사용하지 않는 것도 지분을 차지하고 있다고 본다.
이를 위해서는 함께 고민할 시간을 가지며 우리의 컨벤션을 다시 정립해봐야 할 필요가 있다고 생각한다.
'안드로이드' 카테고리의 다른 글
🔥 Android SDUI 도입기(with. GraphQL, Apollo) (2) | 2024.02.12 |
---|---|
💡 UI Layer을 위한 새로운 코딩 컨벤션을 구축했던 이유 (0) | 2024.02.06 |
MVC-> 클린아키텍처 + MVVM 리팩토링을 했던 나의 생각 - 1 (1) | 2024.01.25 |
중첩 RecyclerView에서 상태 변화에 따른 스크롤 유지 (0) | 2024.01.07 |
RecyclerView Adapter에서의 이벤트 처리 방식 개선 (1) | 2024.01.06 |