![article thumbnail image](https://blog.kakaocdn.net/dn/La2J1/btrIy92nOdT/5T1Pqf7Ar8XPbp8VQHzcR1/img.png)
왜 아키택처를 사용해야 할까?
아주 단순히 버튼을 누르면 숫자를 업카운팅해주는 기능을 하는 화면을 구현한다고 한다면 하나의 Class에 View와 Data 처리를 한다고 해도 쉽게 구조를 파악할 수 있다. 하지만 여러 사용자가 이용하는 피드 게시판을 구현한다고 하면 어떠한가? 화면에 그려지는 뷰 수도 늘어나고, 데이터들을 외부로 가져와야 하며, 이를 각각 가공해서 뷰에 뿌려줘야 한다. 아마 하나의 클래스에서 이 모든 역할을 수행한다고 하면 생각만 해도 끔찍한 스파게티 코드의 향연이 눈 앞에 펼쳐질 것이다. 이처럼 점점 프로그래밍이 복잡해짐에 따라 각각 관심사 별로 구분이 필요해졌고 이에 따라 여러 아키택처 패턴이 출현하게 되었다.
MVC (Model-View-Controller)
MVP (Model-View-Presenter)
MVVM (Model-View-ViewModel)
MVI (Model -View-Intent)
이름을 보면 M(Model)과 View(View)를 공통적으로 가지고 있다. 프로그램의 Presentation Logic과 Business Logic들을 구현함에 있어 데이터와 UI는 필수이기 때문에 M과 V의 의존성은 필연적이다. 이 패턴들의 공통적인 특징은 다음과 같다
화면에 보여주는 로직(Presentation Logic)과 실제 데이터가 처리되는 로직(Business Logic) 분리
MVC
Model: 프로그램에 사용되는 실제 데이터 및 데이터 처리(추가, 업데이트, 삭제 등) 로직
View(UI): 사용자에게 보여지는 UI
Controller: 사용자의 입력을 받고, 해당 처리를 Model에게 요청한 결과를 통해 View를 정의
모든 입력은 컨트롤러에게 전달되고 컨트롤러는 입력에 해당하는 모델에 업데이트 한다. 모델의 업데이트 결과에 따라 뷰를 선택하여 업데이트 한다. 이처럼 MVC는 M과 V간에 강한 의존성을 가지고 있고, 안드로이드에서는 View와 Controller가 Activity에 포함되어 있기 때문에 Activity에 코드가 몰리는 현상이 발생된다.
MVP
Model: MVC의 Model과 동일
View: 이벤트가 발생할 경우 Presenter로 알리고 처리 결과를 받아 업데이트
Presenter: View에서 전달받은 이벤트에 따라 데이터를 모델에 요청하고, 결과를 가공하여 View로 반환
1. View로 사용자 입력 이벤트를 받는다
2. View는 Presenter에게 이벤트를 전달한다.
3. Presenter는 이벤트에 따라 필요한 데이터를 Model에 요청한다.
4. Model은 Presenter에 필요한 데이터를 응답한다.
5. Presenter는 해당 데이터를 필요에 맞게 가공해서 View로 전달한다.
6. View는 Presenter로부터 받은 데이터로 화면을 갱신한다.
프리젠터는 뷰와 모델의 인스턴스를 가지고, 모델과 뷰 사이에 매개체 역할을 한다. 따라서 M-V 사이에는 의존성이 존재하지 않는다. 하지만 View와 Presenter는 1:1 관계이기 때문에 앱이 복잡해질수록 의존성이 점점 강해지는 문제점이 발생한다.
MVVM
View: 사용자에게 보여지는 UI. 유저에게 입력 이벤트를 받을 시 ViewModel에게 명령을 내림
ViewModel: View에 필요한 데이터들을 구독하고 있다가, 해당 데이터가 변경될 때 DataBinding된 UI 업데이트를 진행함
Model: 실질적 데이터, 비즈니스 로직, 서비스 클라이언트 등으로 구성
1. View로 사용자 입력 이벤트를 받는다
2. ViewModel은 View로 부터 명령을 받는다
3. ViewModel은 이벤트에 따라 필요한 데이터를 Model에게 요청한다
4. Model은 ViewModel에게 요청한 데이터를 응답한다.
5. ViewModel은 응답 받은 데이터를 가공해서 저장한다.
6. View는 ViewModel과 Data Binding으로 인해 자동으로 갱신된다.
MVVM은 View와 Model이 서로 알지 못하기 때문에 독립성을 유지할 수 있고 효율적인 유닛테스트가 가능하다. View와 ViewModel을 바인딩하기 때문에 코드의 양이 줄어든다.
MVVM의 문제점
부수효과: 원래 목적과 다르게 다른 효과 또는 부작용이 나는 상태. 안드로이드에서 서버 호출, 데이터 호출을 통해 성공적으로 데이터가 불러올 것을 예상했지만 네트워크 에러, 서버 에러 등등의 부수효과로 상태 변경에 어려움이 있을 수 있다.
상태 문제: 개발을 하면서 무수한 상태를 만들지만 제어가 제대로 이뤄지지 않는다면 아래와 같은 상황이 발생할 수 있다. 원하는 데이터가 API 응답을 성공적으로 마치고 출력 완료 되었지만 로딩중이 프로그래스 바가 돌고 있는 걸 볼 수 있는데 이를 상태 문제가 발생한다고 부른다.
MVI
MVI 패턴은 의도(Intent)와 상태(State)라는 두 가지 새로운 개념이 도입되었다. MVI는 사용자 또는 시스템의 상호 작용을 기반으로, 사용자가 앱의 상태를 변화시키고자 하는 의도를 나타낸다고 규정하고 이를 Intent라고 부른다. 이 인텐트의 결과로 Model이 업데이트 되고 Model에서 방출된 상태를 기반으로 View가 업데이트 되는 반응형 아키텍처 패턴이다.
State
어느 시점이건 앱에는 현재의 시점을 표현하는 하나의 상태만 존재하고 그것을 바꿀 수 있는 유일한 트리거는 새로운 State를 만드는 Intent이다. 즉 UI의 변화는 곧 Intent 실행의 결과가 된다.
Intent
인텐트는 Android의 인텐트가 아니다. 여기서 말하는 인텐트는 앱의 상태를 바꾸려는 의도이다. 인텐트는 유저의 버튼 클릭 혹은 화면에 출력하고 싶은 API 호출 결과로 발생할 수 있다. 모든 UI의 변화는 인텐트의 결과로 동작한다. 인텐트는 모델에 처리해야 하는 동작(Intented action)을 제공한다.
Model
모델은 Intent로부터 동작을 가져온다. 모델은 데이터를 가지고 있으며 또한 UI의 상태를 나타낸다. 예를 들어 Data Loading, Loaded Success, Error 등 다양한 상태를 가질 수 있다. 즉 모델은 상태에 대해 뷰가 어떤 것을 화면에 렌더링 해야 하는 지 말해주는 응답이다.
View
모델을 구독하고 있다가 새로운 State를 받아 UI에 업데이트 한다.
* MVI는 MVP나 MVVM과는 다르게 I가 실제 컴포넌트를 지칭하지 않는다. 데이터와 상태의 흐름을 어떻게 다룰 것이냐에 대한 패러다임에 가깝다고 볼 수 있다.
* MVI에서 상태는 불변한다. VIew를 업데이트하기 위한 유일한 방법은 Intent()를 사용해 이벤트를 발생시켜서 그에 따라 새로운 State를 생성해서 적용하는 것이다.
* 불변성을 가지고 있다는 의미는 Model을 수정할 수 없기 때문에 내부 property는 바꾸지 못하고 Model 자체를 copy() 메소드를 통해 새로 생성하는 방법을 사용해야 한다.
* MVI는 단방향 데이터 흐름과 상태의 불변성으로 인해 예측 가능한 상태가 만들어지기 때문에 유지보수가 용이하다는 장점을 지닌다.
참고
https://proandroiddev.com/mvi-a-new-member-of-the-mv-band-6f7f0d23bc8a
'안드로이드 > 아키텍처' 카테고리의 다른 글
Assisted Injection (0) | 2022.07.21 |
---|