디자인패턴

MVVM 패턴

SniKuz 2024. 6. 20. 17:15

목차

 

개요

Presentation Model(PM)은 2004년 Martin Fowler가 기재한 패턴입니다. 이 패턴은 View의 행동과 상태를 분리한다는 점에서 MVP와 유사하지만, Presentation Model이라 부르는 View의 추상화를 생성한다는 점에서 차이점이 있습니다.
https://martinfowler.com/eaaDev/PresentationModel.html

 

마이크로소프트의 WPF, Silverlight 개발자인 John Gossman은 2005년 자신의 블로그에 Model-View-ViewModel 패턴을 공개했습니다. MVVM 패턴은 View의 상태와 행동을 포함하는 View의 추상화를 쓴다는 점에서 Presentation Model과 동일합니다. 차이점이 있다면 Martin Fowler가 PM을 View의 UI 플랫폼 독립적인 추상화를 만드는 방법으로 사용했다면, John Gossman은 MVVM을 UI 생성을 단순화하기 위해 WPF의 핵심 기능을 활용하는 표준화된 방법으로 사용했습니다.
이런면에서 MVVM은 WPF 플랫폼을 위해 특별하게 만든 보편적인 PM 패턴으로 생각합니다.
MSDN Magazine Issues( By Josh Smith | February 2009 )

 

 

Presentation Model (also known as Application Model)

Presentation Model은 View의 상태와 행동을 Presenation의 일부인 model class(PM)로 끌어냅니다. PM은 domain layer(model)에 위치하며 View에게 최소화된 인터페이스를 제공합니다. View는 PM의 모든 상태를 저장하거나 동기화합니다.

여러 View가 같은 Presentation을 이용할 수 있지만, 각 View는 오직 하나의 PM만 상호작용해야 합니다. 또한 구성에 관하여 PM은 하나 이상의 자식 PM 인스턴스를 포함하지만 각각의 자식들은 또 자신의 PM만 조작합니다.

 

- 예시상황

Sequence Diagram

누군가 클래식 체크박스를 누른다면 체크박스는 자신의 상태를 바꾼 후 View 내에 적절한 이벤트 핸들러는 부를것입니다.
이벤트 핸들러는 View의 상태를 PM에 저장한 다음  PM에서 자체적으로 업데이트 합니다.(이 시점에서 *거친 동기화(coarse-grained synchronization)를 진행합니다) 

PM은 체크박스가 체크되어 있을 때만 composer필드가 활성화 된다는 로직이 포함되어 있어, View가 PM에서 자체 업데이트되면 작곡가 필드 컨트롤이 활성화 상태로 변경됩니다.

이 예시는 PM 아이디어의 본질을 보여줍니다. Presntation display에 필요한 모든 의사 결정은 PM에 의해 완전히 단순하게 이루어집니다.

PM에 가장 짜증나는 부분은 PM과 View 간의 동기화일 것입니다. 간단히 작성할 수 있는 코드이지만, 항상 이런 지루한 반복 코드를 최소화하고 싶습니다. 이상적으로는 어떤 프레임워크가 이 를 해결할 수 있을 것이며, 언젠가 .NET의 데이터 바인딩과 같은 기술로 이루어지길 바랍니다.

동기화는 종종 원하는 테스트 범위 수준과 선택 항목에 따라 결정됩니다. View에 동기화를 넣는다면 PM의 테스트에서 동기화를 테스트할 수 없습니다. PM에 동기화를 넣으면 PM의 View에 종속성이 추가되어 커플링이 더 많이 발생합니다. 결정할 때 생각해볼 점은 둘다 오류가 발생한다면 일반적으로 동기화 코드에서 발견하고 수정하는 것이 쉽다는 점입니다.( * fine-grained synchronization를 사용하지않는 한에는) 

추가로 PM에서 View가 PM에 참조를 가질지, PM이 View에 참조를 가질지에 대한 부분은 찬반이 나뉩니다. 
일반적으로 PM이 View를 참조할 경우 PM이 동기화 코드를 관리합니다. View가 PM을 참조할 경우에도 View가 동기화 코드를 관리합니다.

*coarse-grained synchronization(거친 동기화): 큰 범위의 데이터, 작업에 대해 단일 잠금(lock) 또는 동기화 메커니즘. 반대로 fine-grained synchronization(세밀한 동기화)는 더 작은 범위의 데이터에 대해 많은 동기화 객체를 사용해 수행해 더 높은 병렬처리 능력 제공하지만 복잡성, 오버헤드 증가. 

- 언제 쓸까?

PM은 View에서 Presentation 동작을 꺼낸 패턴이기에 Supervising Controller, Passive View의 대안입니다. UI 없이 테스트할 수 있고, 어떤 형태의 멀티뷰를 지원하며, UI를 더 쉽게 개발할 수 있도록 관심사를 분리한 것입니다. (*비즈니스 로직과 *프레젠테이션 로직을 UI에서 분리)

Supervising Controller, Passive View와 비교할 때 PM을 사용하면 display를 위한 View의 로직과 완전히 독립적으로 로직을 작성할 수 있고, 상태를 저장하기 위해 View에 의존할 필요도 없습니다. 단점은 PM과 View 사이 동기화 메커니즘이 필요하다는 점입니다.Passive View의 경우 동기화가 전혀 필요하지 않다는 점이 있습니다.

* 비즈니스 로직 (도메인 로직) : 데이터의 생성, 저장, 변경 등 방법을 결정하는 실제 비즈니스 규칙 인코딩하는 프로그램의 일부
* 프레젠테이션 로직 : 비즈니스 객체가 소프트웨어 사용자에게 표시되는 방법.

 

 

Model - View - ViewModel 

MVVM 패턴을 사용하여 애플리케이션을 사용하는 주요 이유는 다음과 같습니다.1. 관심사 분리를 제공합니다. 애플리케이션 로직과 UI를 깔끔하게 분리하면 애플리케이션을 테스트, 유지, 발전시키기 더 쉬워질 것입니다. 코드 재사용 기회를 개선하합니다.2. 개발자-디자이너 워크플로우를 가능하게 합니다. UI가 단단히 결합되어 있지 않을 때 디자이너가 더 활동하기 자유롭습니다.3. 테스트 가능성을 높입니다. 로직을 nonvisual에 몰아넣으며 단위 테스트가 훨씬 쉬워집니다. 개발자는 뷰를 사용하지 않고 뷰모델과 모델에 대한 단위 테스트를 만들 수 있습니다.

각 컴포넌트가 서로 분리, 디커플링되어 다음이 가능합니다.

  • 컴포넌트의 스왑이 가능합니다. 
  • 다른 컴포넌트에 영향을 주지 않고 내부 구현을 변경할 수 있습니다.
  • 컴포넌트들이 독립적으로 작업할 수 있습니다.
  • 격리된 단위 시험이 가능합니다.

3가지 컴포넌트의 역할을 이해하는 것 외에도 서로 어떻게 상호작용하는지 이해하는 것도 중요합니다.  뷰가 뷰모델을 알고, 뷰모델이 모델을 알지만, 그 역은 아니라는 점을 기억하고 있어야 합니다.
뷰모델은 뷰를 모델 클래스에서 분리하고 뷰와 독립적으로 모델을 진화시킬 수 있도록 합니다.

View 

  • 뷰는 사용자가 화면에서 보는 것의 구조, 레이아웃 및 외관(UI)을 정의하는 역할을 합니다. 
  • 이상적으로 뷰는 애니메이션 같은 UI 로직을 포함하지만 비즈니스 로직을 포함하지 말아야합니다.
  • 뷰는 고유 뷰모델을 가질 수도 있고 부모뷰모델을 상속할 수도 있습니다. 뷰는 뷰모델에서 바인딩 또는 호출 메서드를 통해 뷰모델에서 데이터를 가져옵니다. 런타임에 뷰는 뷰모델 속성에 변경 응답 이벤트가 오면 변경됩니다.

Model

  • 비즈니스 및 검증 로직과 함께 데이터 모델을 포함하는 애플리케이션의 도메인 모델을 구현한 

*도메인 모델 : 동작과 데이터를 모두 통합하는 도메인의 개념 모델로, 일반적으로 개념, 역할, 데이터유형, 개인 및 규칙을 공식적으로 표현한 것

View  Model

  • 뷰와 모델 사이 중개자 역할을 하며, 뷰 로직을 처리하는 역할을 담당합니다. View를 위한 Model입니다.
  • 일반적으로 뷰모델은 모델 클래스에서 메서드를 호출하여 모델과 상호작용합니다. 그 후 뷰모델은 뷰가 쉽게 사용할 수 있는 형태로 모델로부터 데이터를 제공합니다. 
  • 뷰가 사용할 메서드와 필드를 구현해 사용자가 뷰에서 개시하는 명령들의 구현들을 제공합니다. 예를 들어 UI 버튼을 클릭할 때, 그 동작은 뷰 모델에서 명령을 트리거할 수 있습니다. 하지만 실제로 UI에서 어떻게 보여줄 것인지는 View에서 결정합니다.
  • 일부 동작이 보류중이라는 표시와 같이 뷰에서 디스플레이의 일부 양상에 영향을 미치는 논리적 상태 변화를 정의하는 것을 담당할 수 있습니다.
  • 일반적으로 뷰 모델과 뷰는 1:1관계를 권장하지만, 1대다 관계를 가질 수 있습니다. 실제 개발 상황에서는 서로 다른 레이아웃이나 플랫폼을 가진 여러 View가 동일한 데이터와 명령을 공유할 때, 하나의 ViewModel을 여러 View와 연결해 사용할  수 있습니다.

 

 

정리

MVC(입력처리에 문제) , MVP(희미해진 입력처리 문제와 비대해진 View에 문제)를 거쳐 이제는 테스트에 대한 고민이 생기기 시작했고, 그 결과 Presentation Model과 MVVM 패턴까지 이르게 되었습니다. PM과 MVVM의 시기가 2004~5년대였던 것을 생각해볼때 테스트 주도 개발(Test-driven development) 기법이 재발견됐다고 말하는 시기가 2003년이란 점에서 테스트에 대한 해법을 찾던 중 PM과 MVVM으로 발전했다고 추측할 수 있습니다.

MVVM은 기존 Presenter에게 역할을 더 전담시킨 MVP에서 View를 추상화해  View를 온전히 UI로직에 집중시켰습니다. 그 결과 Model과 의존성을 완전히 없앴고 데이터바인딩을 통해 View가 ViewModel의 존재만 알고 구체적인 구현을 몰라도 되어 의존성도 최소화할 수 있었습니다. 또한 Model과 ViewModel에서 테스트를 집중할 수 있게 됐습니다.

결국 MVC, MVP, MVVM은 각 시대상황에 따라 주요 문제점을 해결하기 위한 대안으로 발전했으며, 그 중 사람들이 열광하는 패턴들의 이름으로 살아남아 발전했다고 생각합니다.
한 가지 신기한 예시로 MVVM 패턴에 시작이 된 WPF를 만든 MS의 매거진에서는 WPF를 설명할 때 View의 추상화를 ViewModel이 아니라 Presentation Model로 설명했다는 점입니다. 하지만 WPF와 Silverlight 커뮤니티에서는 ViewModel이 더 대중적이었기에 MVVM이 대표적인 이름으로 살아남았다고 생각합니다.

 

*참고출처

더보기