😊 읽기 전, 숙지하고 있으면 좋은 포스팅들
MVVM의 개념적 원리는 마틴 파울러(Martin Fowler)가 2004년에 발표한 프레젠테이션 모델(PM) 을 통해 처음 언급되었다. 프레젠테이션 모델은 뷰의 상태와 행동을 담는 공간인데, 이 개념이 당시에는 꽤 이목을 끌었던 소재였다.
이윽고 2005년에 WPF와 실버라이트의 설계자인 존 고스맨(John Gossman)이 데이터바인딩을 활용해 UI , 비즈니스 로직, 프레젠테이션 로직의 분리를 최우선 목적으로 삼는 MVVM 패턴을 블로그에 공개하였다. 여기서 PM의 개념과 상당히 유사한, 뷰의 상태와 행동을 담는 뷰모델(ViewModel)을 정의하였다.
MVVM 패턴은 초기엔 WPF에서 주로 사용되어 인지도가 낮았으나 시간이 흐르며 iOS, 안드로이드와 같은 모바일 환경에서 앱 구조가 복잡해짐에 따라 주요 디자인 패턴으로 채택하며 이용률이 꾸준히 올라 가고 있는 추세이다.
MVVM 패턴에는 Model
, View
, ViewModel
이라는 세 가지 핵심 컴포넌트가 있고, 각각의 컴포넌트 특성에 대해 알아보기에 앞서 컴포넌트 간의 관계를 먼저 파악할 필요가 있다.
View -> ViewModel -> Model
View
는 ViewModel
을 알지만, ViewModel
은 View
를 알지 못한다.ViewModel
은 Model
을 알지만, Model
은 ViewModel
을 알지 못한다.이런 구조를 통해 ViewModel
과 Model
이 View
로부터 독립적인 형태가 완성되고, UI로부터 비즈니스 로직과 프레젠테이션 로직을 분리할 수 있게 되어 MVVM의 근본적 목적을 달성할 수 있게 된다.
이 관계를 잘 기억하면서 각 컴포넌트의 특성을 알아보자.
View
는 유저가 보는 화면의 구조, 레이아웃을 나타낸다.
View
는 자신의 레이아웃에 맞는 ViewModel
을 참조할 수 있게 되며 보통 View
와 ViewModel
의 관계는 N:1
로 형성된다. View
에 표현할 데이터가 필요할 때는 주로 데이터바인딩(Data Binding)을 통해 ViewModel
에서 가져온다. 이 과정에서 View
는 ViewModel
을 알지만 ViewModel
은 View
를 알 수 없는 관계가 형성되고, 이로 인해 View
가 DB에 직접 접근하는 것이 아니라 UI 업데이트에만 집중하게 되어 데이터 변화에 능동적으로 대응할 수 있게 된다. 이 부분이 우리가 흔히 아는 MVC 패턴과 가장 큰 차이라고 할 수 있다.
ViewModel
에서 데이터 변경이 일어나면 View
의 화면도 이에 맞춰 변경이 일어나는 것이라고 보면 이해가 쉽다.ViewModel
은 View
가 사용할 메소드와 필드를 구현하고, 데이터를 Model
에 요청하는 역할을 수행한다. 이 과정에서 상태 변화를 감지하면 이를 View
에게 알리고, 그 변화에 맞춰 화면을 변화시킬 것인지는 View
에서 결정한다. 대체적으로 MVC의 Controller
와 유사한 역할을 맡고 있으나 역시 가장 큰 차이점은 View
에 대해 전혀 모르고 있다는 점이다.
데이터에 대해 접근하고 검증하는 로직, 즉 비즈니스 로직이 포함되어 있다. MVVM에서는 ViewModel
이 요청한 데이터를 반환하는 역할을 주로 수행하고 있으며 MVC의 Model
과 거의 유사하다.
View
를 통해 요구 사항을 요청한다.ViewModel
에게 요청을 전달한다.ViewModel
은 요청에 따라 필요 데이터를 Model
에게 요청한다.Model
은 요청에 맞춰 데이터를 응답한다.ViewModel
이 응답받은 데이터를 가져오고 이를 가공하여 저장한다.View
는 데이터바인딩을 통해 ViewModel
의 데이터를 즉시 전달받고 이를 화면에 나타낸다.장점
(디자이너로부터 디자인을 받지 못한 시점에서도 다른 컴포넌트를 개발할 수 있음)
(왜? 로직을 꼼꼼하게 분리해놓았으니까!)
단점
View
의 변화를 나타내고, 이 과정에서 간단한 로직을 만들 때도 많은 코드와 클래스의 작성을 요구로 한다.안드로이드 개발을 진행할 때 MVC 패턴을 따라가게 되면 보통 액티비티가 View
, Controller
의 역할을 모두 수행하기 때문에 상당한 양의 코드로 구성된 경우가 많다. 동작에 있어 문제가 발생하지는 않지만 동작이 늘어날 수록 액티비티가 점점 무거워지고 이 후 수정이나 유지보수에 어려움을 겪는 경우가 많아진다. 이를 보통 스파게티 코드라고 하는데, 안드로이드 측에서는 개발자들의 이런 어려움을 조금이나마 해소시키기 위해 MVVM 패턴 구현에 용이한 AAC
(Android Architecture Component)를 제공하고 있다.
MVVM에 맞춰 역할을 나누면 위에서부터 View
- ViewModel
- Repository
- Model
순으로 흐름 이 진행된다. 자료 속에 있는 구성 요소를 하나씩 살펴보도록 한다.
UI를 담당하는 액티비티나 프래그먼트를 의미하며 화면에 무엇을 그릴지 결정하고 사용자와 상호 작용한다. 데이터의 변화를 감지하기 위해 Observer
를 가지고 있다.
UI를 위한 데이터를 가지고 있으며 View와 분리되어 있기 때문에 화면 변화에도 데이터가 사라지지 않는다. 주의할 점으로, 위의 ViewModel
부분을 읽었다면 알겠지만 AAC ViewModel
은 MVVM의 ViewModel
과 비교했을 때 개념 자체가 다르다.
위에서 이야기한 데이터바인딩을 구현하기 위해 사용되는 핵심적인 구성 요소이다. View
에서 ViewModel
의 LiveData
를 관찰하게 되면 데이터가 변경될 때 자동적으로 View
에게 변경 사항을 알려준다. 액티비티 및 프래그먼트의 생명주기를 인지하고 있으므로 액티비티가 유저의 화면에 활성화되고 있을 때만 데이터의 변경 사항을 View
에게 알려 메모리 누수를 방지한다.
ViewModel
과 데이터를 주고받기 위해 데이터 API를 포함하고 있는 클래스이다. 실제 앱에 필요한 데이터를 가져오는 역할을 수행하며 이로 인해 ViewModel
은 Model
에 직접적으로 접근하지 않게 되고, 전체적으로 앱 구조의 결합도가 느슨해지게 된다.
서울열린데이터광장의 오픈 API를 이용하여 실제 적용 사례를 살펴볼 것이며, 위의 자료와 동일 한 과정으로 진행된다. 적용 후 화면에 보여질 것은 서울 지하철역 리스트이다.
자료에서 보는 것과 같이 액티비티에서 핵심적인 부분은 데이터 변화를 감지하기 위해 옵저빙을 하고 있다는 점이다. ViewModel
에서 데이터 변화가 일어나면 이에 맞게 UI를 변경한다.
위의 자료와 같이 ViewModel
에서는 직접 데이터에 접근하지 않고 Repository
를 이용해 데이터를 받아온다. 그리고 이를 LiveData
로 설정하여 데이터에 변화가 생기면 이를 지켜보고 있는 구독자, 즉 View
에게 알림이 가도록 설정한다.
실제 데이터에 접근하여 필요한 데이터를 요청하고 받아오는 임무를 수행한다. 전체적인 결합도를 낮춰 유지보수 비용을 완화하기 위해 사용한다.
비즈니스 로직을 처리하고 이에 따른 결과 데이터를 저장하는 공간이다.
MVVM 패턴은 위의 적용 예시와 같이 ViewModel
혹은 Repository
같이 낯선 클래스를 새롭게 생성해야 하기 때문에 처음 접하는 사람들에겐 어렵고 복잡하게 보일 수 있다. 또한 개념을 이해한 사람도 기존 MVC 패턴에서 MVVM 패턴으로 마이그레이션을 진행하려 하면 비용이 상당히 많이 소비될 것이다.
그럼에도 불구하고, MVVM 패턴 적용으로 인해 코드 재사용성이 상당히 올라가며 프로젝트 구조가 깔끔해지는 것을 피부로 느낄 수 있었고, 이 과정에서 모바일 시장에서 대부분의 디자인 패턴이 MVVM으로 구성되어 있는 이유를 확실히 알 수 있었다. 물론 모든 상황에 MVVM을 적용하는 것은 옳지 않으나, MVVM의 철학을 이해하고 실제 적용해야 하는 프로젝트가 무엇인지 생각하는 과정을 적절하게 거친다면 MVVM을 보다 더 잘 활용할 수 있게 될 것이다.
참고 및 출처
MVVM & 안드로이드 아키텍쳐 컴포넌트 시작하기
[Prism 4.1] MVVM 패턴 구현하기
MVVM 패턴이란? UIKit의 MVC와의 비교
깔쌈하게 MVVM 패턴과 AAC 알아보기
아하 감사합니다!