Android MVC, MVP, MVVM, MVI
안드로이드 앱을 개발할 때, 이용할 수 있는 여러 아키텍처 패턴들이 있습니다.
MVC (Model-View-Controller)
MVP (Model-View-Presenter)
MVVM (Model-View-ViewModel)
MVI (Model-View-Intent)
기타
이름을 보면 M(Model)과 V(View)를 공통적으로 가지고 있습니다.
Model : 데이터 or 데이터를 생성하거나 업데이트
View : UI or 화면을 표시
프로그램의 Presentation Logic과 Business Logic들을 구현함에 있어 데이터와 UI는 필수이기 때문에, M-V 사이의 의존성이 당연히 생길 수밖에 없습니다.
Presentation Logic : 실제 눈에 보이는 GUI(Graphic User Interface) 화면을 구성하는 코드를 뜻함.
Businees Logic : 데이터를 보여주기 위해서 데이터베이스를 검색하는 코드 및 GUI(Graphic User Interface) 화면에서 새롭게 발생된 데이터를 데이터베이스에 저장하는 코드 등 실제적인 작업을 하는 코드를 뜻함.
[출처] Presentation Logic과 Businees Logic
Logic들이 커지고 복잡해짐에 따라 의존성은 더 강해지고, 결국 앱을 유지 보수하기가 점점 더 어려워지게 됩니다.
이러한 문제들을 해결하기 위해 여러 패턴들이 나왔는데, 결국 M-V 사이의 관계를 어떻게 처리하느냐에 따라 패턴들을 구분 지을 수 있습니다.
앱 아키텍처 패턴들(MVC, MVP, MVVM, MVI)에 대해 간략히 알아보겠습니다.
프로그램을 각각의 역할에 따라 Model, View, Controller로
나누어 설계한 아키텍처 패턴
1. 모든 입력(Input)들은 Controller로 전달됩니다.
2. Controller는 입력에 해당하는 Model을 업데이트합니다.
3. 업데이트 결과에 따라 View를 선택합니다.
(하나의 Contoller는 View를 선택할 수 있기 때문에 1:n 관계로, 여러 개의 View를 관리할 수 있습니다.)
4. Controller는 View를 선택만 할 뿐, 직접 업데이트하지는 않습니다.
(View는 Controller를 알지 못합니다.)
5. View를 업데이트하기 위해서는 아래와 같은 방법들이 있습니다.
View가 Model을 직접 이용하여 업데이트
Model에서 View에서 Notify 하여 업데이트
View가 Polling 하여 Model의 변화를 감지해서 업데이트
View를 업데이트하기 위해서는 결국 M-V 사이에 의존성이 존재하게 됩니다.
게다가 안드로이드는 Activity(or Fragment)가 Controller와 View 모두 처리하기 때문에, 한 클래스에서 M-V-C 모두 처리하게 되는 문제점이 발생합니다.
장점
가장 단순한 패턴
단점
Model과 View 사이의 의존성 발생 > 앱이 커지고 복잡해질수록 유지보수가 어려움
MVC에서 파생된, Model과 View 간의 의존성이 없는 아키텍처 패턴
1. 모든 입력(Input)들은 View로 전달됩니다.
2. Presenter는 입력에 해당하는 Model을 업데이트합니다.
3. Model 업데이트 결과를 기반으로 View를 업데이트합니다.
4. Presenter는 해당 View를 참조하고 있습니다.
(View와 Presenter는 1:1 관계입니다.)
5. Presenter는 View와 Model 인스턴스를 가지고, Model과 View 사이의 매개체 역할을 합니다.
Presenter가 M-V 사이에서 관리를 해주기 때문에, MVC 패턴과는 달리 M-V 사이의 의존성이 없습니다.
하지만 앱이 커지거나 복잡해질수록 V-P 간 의존성이 강해지는 문제점이 발생합니다.
장점
Model과 View 사이의 의존성이 없음
단점
View와 Presenter가 1:1 관계이기 때문에 서로 간 의존성이 커짐
필요한 클래스 개수가 많음
좀 더 자세한 구현법은 아래 링크를 참고해 주시기 바랍니다.
MVC에서 파생된, Model과 View 간의 의존성뿐만 아니라
Controller와 View 간의 의존성도 고려하여
각 구성 요소가 독립적으로 작성되고
테스트될 수 있도록 설계된 아키텍처 패턴
1. 모든 입력(Input)들은 View로 전달됩니다.
2. ViewModel은 입력에 해당하는 Presentation Logic을 처리하여 View에 데이터를 전달합니다.
4. ViewModel은 View를 참조하지 않기 때문에 독립적입니다.
(ViewModel과 View는 1:n 관계입니다.)
4. 따라서 View는 자신이 이용할 ViewModel을 선택해 바인딩하여 업데이트를 받게 됩니다.
(Command 패턴이나 Data Binding을 이용하여 V-VM 간 의존성을 없앨 수 있습니다.)
5. Model이 변경되면 해당하는 ViewModel을 이용하는 View가 자동으로 업데이트됩니다.
6. ViewModel은 View를 나타내 주기 위한 Model이자, View의 Presentation Logic을 처리합니다
MVP와 마찬가지로 M-V 사이의 의존성이 없고, MVP처럼 V-VM이 1:1 관계가 아닌 독립적이기 때문에 이 둘 사이의 의존성도 없습니다.
장점
Model과 View 사이의 의존성이 없음
ViewModel과 View 사이의 의존성이 없음
중복되는 코드를 모듈화 할 수 있음
단점
ViewModel 설계가 쉽지 않음
자바스크립트 생태계에서 탄생했으며
MVC에서 파생된, 능동적인 Controller 대신
Intent라고 불리는 Reactive 요소를 이용한 아키텍처 패턴
MVC에서 Controller가 직접 Model을 업데이트하고 View를 선택하는 능동적인 구조가 아닌,
MVI는 Intent가 User를 관찰하고, Model이 Intent를 관찰하고, View가 Model을 관찰하고, User가 View를 관찰하는 Reactive 요소로 이루어져 있습니다.
따라서 안드로이드에서는 RxJava 같은 라이브러리가 필수적입니다.
1. Intent로 User로부터 입력을 가져옵니다.
(Android의 Intent와 서로 다른 개념입니다.)
2. Intent는 Model에서 처리해야 하는 동작(Intended action)을 제공합니다.
3. Model은 Intent로부터 동작을 가져옵니다.
(MVI의 Model은 단순 데이터뿐만 아니라, Application 상태(State)와 Business Logic을 관리합니다.)
4. Model은 View에 표시할 새로운 모델을 생성합니다.
(Immutability 한 모델을 생성합니다.)
5. View는 Model로부터 새로운 모델을 가져와 표시합니다.
Android에서 발생할 수 있는 여러 이슈들(화면 회전, BackStack, Process death 등)로 인해 코드들이 복잡해지기 쉬운데, MVI는 단방향(Uni-directional) 데이터 흐름과 불변성(Immutability)으로 인해 예측 가능한 상태가 만들어지기 때문에 유지보수가 좀 더 용이해지는 장점이 있습니다.
장점
단방향, 불변성 데이터를 이용해 예측 가능한 상태
서로 간 의존성 없음
단점
RxJava와 같은 Observable 한 외부 라이브러리를 이용해야 함
Realm과 함께 하는 Android의 단방향 아키텍처 살펴보기
academy.realm.io
http://hannesdorfmann.com/android/mosby3-mvi-2
http://blog.javarouka.me/2013/06/understanding-mvc-mvp-and-mvvm.html
지금도 수 많은 디자인 패턴이 생겼다가 사라져 갔고 앞으로도 계속 그럴 것이지만 가장 많이 언급되는 이 ...
blog.naver.com
아키텍처 패턴에 대해 자료를 찾아보고 공부하고 글도 작성했는데, 많은 안드로이드 개발자들이 느꼈듯이 어떤 패턴을 써야 하는지에 대한 정답은 없는 거 같습니다.
같은 패턴이라도 어떤 라이브러리(RxJava, Dagger, Data binding 등)를 썼는지에 따라 구현법이 다 다르고, 장단점들도 달라지게 됩니다.
MVW(Model-View-Whatever) 패턴이 있듯이 각자의 개발 상황이나 환경에 따라 적절하게 이용하는 게 좋을 거 같습니다.