요즘 채용 공고를 보면 MVC, MVP, MVVM에 관한 지식 보유자를 우대하는 공고를 많이 볼 수 있습니다. 저 또한 면접에서도 이런 MVVM이 뭔지? MVP와의 차이점에 대해서 많은 질문을 받곤 했습니다. 사실 저도 공부하는 단계지만 간략하게 정리해 보려고 합니다.
일단 MVC, MVP, MVVM은 소프트웨어에서 자주 사용되는 인기있는 디자인 패턴입니다. 이러한 디자인 패턴은 각각의 책임을 분리해주어 결합도를 낮추고, 확장, 테스트, 유지 보수에 용이하다는 장점이 있습니다. 따라서 각각의 패턴이 어떤 특징과 장단점이 있는지 알아보고 효율적인 디자인 패턴에 대해 알아보겠습니다.
MVC 디자인 패턴은 하나의 애플리케이션을 Model, View, Controller로 이루어진 3개의 측면으로 분리하여 개발하는 디자인 패턴입니다.
Model은 View에 표시되기 위해 필요한 데이터입니다. Model은 비즈니스 로직을 설명하는 클래스의 집합으로 구성됩니다. Model은 어떻게 데이터가 변경되고 조작될 수 있는지에 관한 규칙을 정의합니다.
View는 Android의 XML, 프론트엔드의 HTML과 같은 UI 구성요소를 나타냅니다. View는 Controller로 부터 받은 UI 데이터를 표시하는 역할을 합니다. MVC 패턴에서의 View는 옵저버 패턴을 이용하여 Model을 관찰하게 되는데요, 이는 데이터의 상태 변화를 업데이트 하기 위함입니다.
Controller는 다가오는 사용자의 요청을 처리하는 역할을 담당하고 있습니다. Controller는 Model을 통해 받은 데이터를 처리하거나, 결과 값을 View에 반환하는 역할을 합니다. 일반적으로 View와 Model사이를 중재하는 역할로 보시면 되겠습니다.
- 사용자의 요청이 Controller에 들어옵니다.
- Controller는 요청에 맞게 Model을 업데이트합니다.
- Controller에서 업데이트된 Model을 나타내줄 View를 선택합니다.
- View는 업데이트된 Model을 사용자에게 보여주기 위해 UI 데이터를 업데이트 합니다.
가장 단순한 패턴으로 여러 개발 분야에서 보편적으로 사용되는 디자인 패턴입니다.
View와 Model사이의 의존성이 높습니다. 이는 앱이 커질수록 유지보수가 어려워집니다.
MVP 패턴은 MVC와 유사한 디자인 패턴입니다. 이는 MVC 패턴에서 파생되었기 때문인데요, 기존 Controller의 역할을 Presenter가 한다고 보시면 됩니다.
MVC와 같은 컨셉으로 사용됩니다.
Presenter는 View를 통한 사용자의 입력을 받습니다. 그 다음 Model에 도움을 받아 사용자의 데이터를 처리하고 결과를 View로 다시 전달합니다. Presenter는 interface를 통하여 View와 상호작용합니다. interface는 필요한 데이터를 전달하는 presenter 클래스에서 정의됩니다. 액티비티나 프래그먼트와 같은 view 구성요소는 이 인터페이스를 구현하고 원하는 방식으로 데이터를 랜더링합니다.
MVP 패턴에서 Presenter는 Model을 조작할 뿐만 아니라 View를 업데이트합니다. Presenter와 View는 서로 완전히 분리되어 인터페이스를 통해 통신합니다. 이 방식은 MVC보다 단위테스트가 훨씬 쉬워집니다.
- 사용자의 Action은 View를 통해 들어오게 됩니다.
- View는 데이터를 Presenter에 요청합니다.
- Presenter는 Model에게 데이터를 요청합니다.
- Model은 Presenter에게 요청받은 데이터를 응답합니다.
- Presenter가 데이터를 가공하고 다시 View에게 응답합니다.
- View는 Presenter로 부터 데이터를 응답받고 UI 데이터를 갱신합니다.
앞서 말했듯이 MVP패턴은 인터페이스를 통해 통신하기 때문에 MVC의 단점으로 지적되었던 View와 Model사이의 의존성이 없습니다.
View와 Presenter사이의 의존성이 높고, 앱이 커질수록 이 의존성은 더 강해집니다.
MVVM 패턴은 양방향 데이터 바인딩을 지원합니다. 이에 따라 뷰 모델 안에 있는 데이터의 변화를 View에 전파합니다. 일반적으로 옵저버 패턴을 활용하여 View Model의 변경사항을 Model에게 알립니다.
MVC, MVP와 같은 컨셉으로 사용됩니다.
ViewModel는 View 상태를 유지 및 변화시키고, View에 대한 작업의 결과로 Model을 조작하고, View에서 발생되는 이벤트를 트리거하는데 도움이 되는 메서드, 명령, 또는 다른 속성들을 노출하는 역할을 합니다.
View는 ViewModel에 관한 참조를 가지고 있지만, ViewModel은 View에 관한 정보를 모릅니다. 이는 View와 ViewModel사이의 n:1의 의존관계가 생기며 다수의 View는 하나의 ViewModel에 매핑될 수 있습니다. 이로서 ViewModel은 다수의 View에 대해 완전히 독립적입니다.
안드로이드에서 단방향 혹은 양방향 데이터 바인딩을 사용한다면 ViewModel의 속성들과 View와 동기화를 보장할 수 있습니다.
간혹 Android AAC의 ViewModel과 MVVM의 ViewModel을 착각하시는 분들도 계십니다. (제가 그랬습니다..ㅠㅠ) MVVM에서 ViewModel을 물어보는 질문에 AAC ViewModel의 특징을 언급하시면 안됩니다. AAC ViewModel은 수명 주기를 인식하여 UI 관련 데이터를 보관해주는 추상클래스로, MVVM의 ViewModel의 역할과 다릅니다. 그러나 MVVM ViewModel의 역할을 알고 있다면 AAC ViewModel를 활용하여 MVVM 패턴을 구현할 수 있습니다.
자세한 내용은 https://wooooooak.github.io/android/2019/05/07/aac_viewmodel/
에서 확인해보실 수 있습니다.
- 사용자의 Action들은 View를 통해 들어옵니다.
- View에 Action이 들어오면 ViewModel에 Action을 전달합니다.
- ViewModel은 Model에게 데이터를 요청합니다.
- Model은 ViewModel에게 요청받은 데이터를 응답합니다.
- ViewModel은 응답 받은 데이터를 가공하여 저장합니다.
- View는 Data Binding을 이용해 UI를 갱신시킵니다.
언뜻 보기에는 MVP와 비슷한 부분이 많습니다. 그러나 MVP는 View와 Presenter 사이의 의존관계가 1:1로 형성되어있다면, MVVM은 View와 ViewModel사이의 관계가 1대n으로 되어있습니다. 또한 데이터 바인딩을 이용한다면 View와 ViewModel 사이의 의존성을 없앨 수 있습니다.
테스트 및 확장 용이성이 증가하고, 데이터 바인딩을 사용한다면 View와 ViewModel사이의 의존성 또한 없어집니다.
ViewModel의 설계가 쉽지 않습니다.