#What
MVC / MVP / MVVM
널리쓰이는 아키텍처를
안드로이드 관점에서 알아보도록 하겠습니다.
*아키텍처 패턴
아키텍처 패턴은 주어진 문맥 안에서 소프트웨어 아키텍처의 공통적인 발생 문제에 대한 일반적인, 재사용 가능한 해결책을 의미한다. 아키텍처 패턴은 소프트웨어 디자인 패턴과 비슷하지만 더 넓은 범위에 속한다
#Preview - 이해하기 전에
MVC = Model View Controller
MVP = Model View Presenter
MVVM = Model View ViewModel
Android 아키텍쳐의 목표
-> 거대해지는 프로젝트를 'UI + 비즈로직+ 데이터 처리' 역할 분리를 통해 '유지보수, 테스트, 재사용' 을 쉽게 하기
Model, View는 동일하나, Controller - Presenter - ViewModel로 변화해 왔음을 볼 수 있다
-> 즉 'Controller -Presenter -ViewModel' 에 문제를 느껴 새로운 패턴을 만들었다는 사실
xxxModel.java, xxxPresenter.java 처럼 파일명 뒤에 역할명이 붙는다고 생각하지 말 것
-> 구분 위한 카테고리 일 뿐
# MVC
1) 모델 : 앱의 '데이터 + 상태 + 비즈로직'을 담당 == 데이터 처리
- 통신/DB 처리를 담당하는 '데이터 관리' 의 핵심
- UI 외적인 부분이므로 View와는 완전 분리 필요(뷰에 데이터가 어떻게 보여질지 모델은 모름)
2) 뷰 : 데이터가 보여질 화면/뷰/레이아웃 ex) xml 파일, 'android.view'
- 어떤 데이터가 어느 로직을 거쳐 뷰에 보여질지 뷰는 모름
3) 컨트롤러 : '뷰'와 '모델'간 중재자/컨트롤러 ex) Activity, Fragment
- 앱이 어떻게 동작 할 지 모르는 '모델'과 '뷰'를 이어 준다
- '뷰'로 부터 이벤트가 들어오면 어떤 동작을 취할 지 '모델'의 수행을 결정
- 반대로 '모델'의 수행 결과를 뷰에 표시 역할도 담당
[요약]
- '모델'과 '뷰 '분리는 확실
- '모델' 유닛 테스트도 가능(분리가 확실하니)
- 상대적 간단하고 구현이 쉬움
[고려할 점]
Android에서는 그닥 적합하지 않은 이유
- 컨트롤러와 뷰의 결합도가 높음
- Controller(Activity,Fragment)와 View(.xml) 의 완벽한 분리가 불가하기 때문이다.
- 뷰 변경에 따라 컨트롤러도 변경해야 하는 경우 발생도 잦음
- 컨트롤러가 역할 부담을 많이 지며 비대해지기 쉬움
- 어찌됐든 저찌됐든 UI 관련 로직은 Activity, Fragment에서 처리해야 하니까.
- => Controller 비대 => 유지보수가 힘들어지고 가독성, 코드 재사용, 확장성 등이 떨어질 수 밖에 없음
- 컨트롤러 유닛 테스트가 어려움
- Controller(Activitiy, Fragmen)는 안드로이드 API이며 대부분 Context를 필요로 하므로
# MVP
1) 모델 : MVC와 동일
2) 뷰 : 데이터가 보여질 화면/뷰/레이아웃(MVC와 동일내용) (+ Activity/Fragment)
- Activity/Fragment는 View 역할도 하면서 최소한의 Controller역할도 한다
- 프리젠터에게 interface를 전달 해, 프리젠터로 하여금 전달된 인터페이스로 뷰를 제어하게끔 동작
3) 프리젠터 : 컨트롤러와 비슷해 보이지만 인터페이스를 통해 뷰와 상호작용한다는 점에서 다름(뷰의 기능을 인터페이스 호출을 통해 사용)
[요약]
- '모델'과 '뷰 '분리 보다 더 확실(Activity와 모델 사이에 프리젠터 개념이 추가 됐으므로)
- '모델' 유닛 테스트가 용이(분리가 확실하니)
- '프리젠터'가 Android API에 연결 되지 않아서 유닛테스트 가능(인터페이스를 이용해 Mock 뷰 객체 생성 가능) New
[고려할 점]
- 프리젠터 역시 컨트롤러처럼 역할 부담을 많이 지며 비대해지기 쉬움
- View는 어찌됐든 presenter를 참조 할 수 밖에 없음
- Configuration 변경 시 등의 UI 데이터 보존을 위한 처리를 고려 해야 한다는 점 등의 문제가남아 있음
# MVVM
1) 모델 : MVC와 동일
2) 뷰 : 데이터가 보여질 화면/뷰/레이아웃 + Activity/Fragment (MVP와 동일내용) + Observe Data
- ViewModel의 데이터를 관찰해서 UI를 갱신. MVC/MVP와 달리 '뷰'가 능동적으로 바뀜. ('뷰'가 뷰모델이 가진 데이터를 observe 하고 있을 테니 변경하려면 변경해!!)
- 관찰 방식으로는 LiveData,Observable, Flow 등이 있다
3) 뷰모델 : UI에 표시할 데이터를 가지고 있다 (뷰가 observe 할 데이터를)
[요약]
- View에 표시할 데이터니 UI 상태값 등은 ViewModel이 관리하고, View는 그것을 관찰한다
- View가 관찰하면서 알아서 UI 업데이트를 하니, ViewModel은 View에 데이터 셋을 신경 안써도 되므로 부담이 줄어듦(ViewModel 입장에서는 어떤 View가 데이터 가져다 쓰는지 전혀 모르는 상태)
- 다시 말해, View는 관찰 및 UI 업데이트에만 집중하며 UI 상태값이나 데이터 정보는 관리하지 않는다
- => So, 극단 적인 예로는 잘 만든 ViewModel 하나로 휴대폰과 네비게이션 화면에서 동일 데이터를 다른 View로 보여주기가 가능해지는 것
- 앞서 모델을 '데이터 관리' 의 핵심이라고 했던 것 처럼, ViewModel 의 이름의 뜻을' View에 대한 데이터 관리' 라고 생각하면 좋을 듯 하다
- View와의 결합도가 낮으므로 ViewModel 재사용성 UP!
[고려할 점]
- 설계가 상대적으로 어려움
- 기본적으로 LiveData나 Coroutine-StateFlow와 같은 개념 학습이 필요
- ViewModel이 커질 위험성 고려
# 번외 - MVVM에서의 ViewModel vs AAC의 ViewModel
Q : 두 ViewModel은 같은 ViewModel일까?
AAC-ViewModel은 화면회전, 글자 크기 변경 처럼 Configuration 변경에 따른 Activity 재생성 시 ViewModel은 영향을 받지 않기 때문에(생명 주기가 다름) 가지고 있던 데이터를 재생성된 Activity에게 다시 제공해줄 수 있다.
그리고 무엇보다 AAC-ViewModel은 androidx.lifecycle.ViewModel API를 상속 받아야 함(Context 필요 시 AndroidViewModel)
A : 결론은 다른 의미의 ViewModel이지만, AAC-ViewModel을 MVVM-ViewModel 패턴에 적용해서 쓰기 적절하니까
구글에서도 이렇게 쓰라고 동일하게 작명하지 않았을까...
# 기타
- 각각의 패턴의 범위에 대한 개발자들의 생각은 다양하며, 암묵적으로 합의를 만들어가는 과정 인 듯
- 패턴 각각의 장단점을 파악해 필요한 부분을 적용해야 할 듯
참고 사이트 - https://academy.realm.io/kr/posts/eric-maxwell-mvc-mvp-and-mvvm-on-android/
문제 있을시 알려 주세요.
좋은 하루 되세요!
'Architecture, Pattern' 카테고리의 다른 글
[Android] MVVM - ViewModels AntiPatterns (0) | 2022.08.02 |
---|---|
[Pattern] 책임 연쇄 패턴 (Chain-of-responsibility pattern) (0) | 2021.11.10 |