Skip to main content

Command Palette

Search for a command to run...

Mvvm 패턴의 고찰

Published
3 min read
Mvvm 패턴의 고찰

오늘은 MVVM 패턴에 대한 이해를 빠르게 가져보고 MVVM 패턴을 고찰해 보는 시간을 가져 보겠습니다.

MVVM 패턴이란?

MVVM 패턴은 모델-뷰-뷰 모델(Model-View-Viewmodel, MVVM) 아키텍처 패턴으로 마이크로소프트의 켄 쿠퍼(Ken Cooper)와 테드 피터스(Ted Peters)에 의해 만들어졌습니다. 이는 모델-뷰-바인더(model-view-binder)의 일종입니다. 다른 아키텍처 패턴으로 MVC(Model-View-Controller), MVP(Mode-View-Presenter)가 있고, 최근에 MVU(Model-View-Update) 패턴을 살펴볼 수 있습니다.

MVVM 패턴에서 뷰모델은 특이한 포지션을 가지는데, 모델에 노출하는 역할을 합니다. 모델을 어떻게 뷰에 "전달"하는가에 대한 모든 책임을 지게 됩니다.

MVVM출처:위키백과

MVVM 패턴의 구성 요소

  • 모델(Model) : 도메인 모델 또는 데이터 모델 도메인 모델은 행위과 상태를 모두 가지는 추상화 모델입니다. 일반적으로 객체지향의 객체라 이해할 수 있습니다. 데이터 모델은 데이터의 상태에 집중하는 방식으로 데이터 접근 레이어(Data Access Layer, DAL)를 통해 속성으로만 구성되는 객체입니다. 대표적인 예로 ORM의 모델이 됩니다.

  • 뷰(View) : 사용자 화면에 보여지는 구조, 배치, 외관 뷰는 곧 사용자 유저 인터페이스 입니다. 하지만 MVVM 패턴의 뷰는 어떻게 "동작"하느냐가 아니라 어떻게 "보여지느냐"만 담당합니다. 뷰의 동작은 뷰모델에서 처리됩니다.

  • 뷰모델(View Model) : 뷰의 추상화 모델(화면이 없는 뷰) 뷰모델은 "화면이 없는 뷰"입니다. 뷰모델이 뷰가 "동작"하도록 만듭니다. 뷰모델이 뷰를 동작하도록 만들기 위한 메커니즘으로 바인딩을 사용합니다. 그렇기 때문에 MVVM을 MVB(Model-View-Binder)라고도 합니다.

MVVM 고찰

MVVM 구성요소

뷰(View)

MVVM에서 뷰는 오직 어떻게 "보여지느냐"에만 집중해야 합니다. 어떻게 "동작하느냐"는 것은 모두 뷰모델에서 처리되어야 합니다. 이는 뷰는 단위테스트를 자동화 할 수 없기 때문에 중요합니다. 뷰의 동작을 뷰모델에 위임하는 방법은 바인딩입니다. 바인딩이란 뷰모델의 값이 변경되거나, 바인딩된 뷰의 컨트롤에서 해당 값을 변경했을 때 상호 작용이 일어나는 것을 말합니다. 바인딩을 통해 뷰모델의 값을 변경하는 것으로 뷰의 동작을 제어할 수 있게 됩니다.

이때 중요한 것은 뷰모델이 뷰에 대한 의존성이 없어야 하는데 있을 경우 단위테스트를 진행할 수 없게 되기 때문입니다. 또한 의존성이 발생하면 잘 구현된 뷰모델을 다른 뷰에 적용할 수 없게 됩니다.

뷰모델(View Model)

일반적으로 뷰모델을 MVC의 컨트롤러 정도로 생각하는 경향이 있는데 아닙니다. 뷰모델은 추상화된 뷰로 보이지 않는 뷰의 완전한 동작을 구현해야 합니다. 하지만 뷰모델은 보여지지 않는 상태로 구성되므로 이를 뷰의 모델(View Model)이라 합니다. 만약 뷰모델이 뷰가 어떻게 "동작하는지"를 달성했다면 뷰모델의 단위테스트를 통해 MVVM 패턴을 적용한 어플리케이션의 뷰의 동작을 단위테스트 할 수 있게 됩니다. 실제로 마이크로소프트에서 제공하는 컨트롤은 뷰모델에 해당하는 객체를 통해 단위테스트를 수행하고 있습니다.

모델(Model)

모델은 도메인 모델 및 데이터 모델이 대상이 될 수 있으며 정보를 제공하는 모든 대상이 모델이 될 수 있습니다. 일반적으로 화면과 관련 없는 비즈니스 로직이 모델이 됩니다. 화면 동작에 관련 있는 비즈니스 로직은 뷰모델에 배치될 수 있습니다. 하지만 뷰모델 또한 모델이므로 뷰모델이 뷰모델을 모델로 사용할 수 도 있습니다.

뷰-뷰모델-모델의 의존관계

뷰-뷰모델의 의존 관계

  • 뷰는 뷰모델의 속성을 바인딩하여 이용하므로 뷰모델과 의존 관계를 가집니다.
  • 뷰모델은 단지 바인딩할 수 있도록 속성을 노출할 뿐이므로 뷰와 의존 관계를 가지지 않습니다.

뷰-모델의 의존 관계

  • 뷰는 뷰모델에서 제공하는 모델을 사용하므로 모델과 의존 관계를 가집니다.
  • 모델은 어떤 뷰를 사용하는지 알지 못하므로(알 필요가 없으므로) 뷰와 의존 관계를 가지지 않습니다.

뷰모델-모델의 의존 관계

  • 뷰모델은 모델을 이용하므로 모델과 의존 관계를 가집니다.
  • 모델은 어떤 뷰모델이 모델을 사용하는지 알 필요가 없으므로 뷰모델과 의존 관계를 가지지 않습니다.

image.png

뷰모델이 뷰의 요소를 참조할 필요가 있을 경우

이런 경우를 생각해봅시다. 가령 F2 단축키를 눌렀을 때 선택된 요소에 텍스트 박스가 활성화 되어 텍스트를 입력할 수 있어야 하며 입력이 완료되면 입력된 값이 선택된 요소에 반영되어야 한다고 가정해 봅시다. 이는 뷰모델의 바인딩된 속성에 따라 뷰에서 적절히 텍스트 박스를 보이게 하고 관련처리를 진행할 수 있지만 뷰모델이 뷰의 텍스트 박스에 접근할 수만 있다면 좀 더 간단한 로직으로 로직이 구성될 수 도 있습니다. 이처럼 다양한 이유로 뷰모델이 뷰의 요소에 접근해야 하는 이유가 있습니다. 이때 의존성을 해치지 않으면서 뷰모델이 뷰의 요소에 접근하는 방법은 객체지향 설계 SOLID원칙 중 의존관계 역전 원칙을 적용 하는 것입니다. 이는 MVVM 패턴처럼 각 구성요소가 명확히 구분된 의존 관계를 역전할 수 있게 합니다.

image.png

뷰에서 제공하는 기능을 IView 인터페이스로 노출하고 뷰모델은 뷰가 아닌 IView를 참조하는 방식입니다. 뷰의 구성요소 또한 이렇게 인터페이스로 뷰 모델에 노출할 수 있고 인터페이스로 추상화 및 캡슐화 되므로 뷰모델이 뷰를 직접 참조하지 않아도 뷰의 요소에 접근할 수 있게 됩니다.

정리

간략히 MVVM 패턴에 대해 정리해 보았습니다. MVVM 뿐만 아니라 MVU등 최신 트랜드에 맞는 다양한 아키텍쳐 패턴이 있으니 두루 살펴보면 좋을 것 같습니다.

More from this blog

개발, 테스트, 운영에서의 도커 활용

핵심 원칙: "한 번 빌드하고, 어디서든 실행한다 (Build once, run anywhere)" 도커의 가장 큰 장점은 환경 일관성입니다. 동일한 도커 이미지를 사용하여 개발, 테스트, 운영 환경을 구성함으로써 "제 PC에서는 됐는데..." 하는 문제를 최소화할 수 있습니다. 1. 개발 단계 (Development) 목표: 빠른 코드 변경 반영, 쉬운 디버깅, 실제 운영 환경과 유사한 환경 구성. Docker 사용 방안: Dockerf...

May 9, 20256 min read15

[EF Core] 데이터 삭제 시 소프트 삭제 적용

DB에서 데이터를 삭제하면 일반적으로 복구할 수 없습니다. 또한 관계에 따라 영구 삭제 자체가 어려울 수도 있습니다. 그래서 데이터를 영구 삭제하는 대신 IsDeleted 속성을 true로 주고 IsDeleted 속성을 필터링해서 조회하는 방법을 사용하기도 합니다. 이를 소프트 삭제라고 합니다. 그런데 EF에서 알아서 데이터 삭제 시 소프트 삭제를 하고 쿼리시 IsDeleted 속성을 체크해서 삭제한 데이터를 제외한 데이터만 쿼리하게 하는 ...

Mar 18, 20243 min read19

[EF Core] ValueConverter를 이용해서 엔터티 속성의 도메인 관리

EF Core를 사용하면서 문자열 길이 등의 특성을 일일이 지정하는 것은 번거롭습니다. ... [MaxLength(32)] public string? 제목 { get; set; } 엔터티가 한 개일 때는 상관이 없으나 제목 유형이 여러 엔터티에 사용될 경우 유형을 지정하기 번거롭습니다. 속성 유형을 도메인으로 관리하면 참 편할텐데요, ValueConverter를 이용할 수 있습니다. 그런데 이것을 인터페이스 정적 추상를 사용해서 다음처럼 ...

Mar 16, 20242 min read8

디모이 블로그

154 posts

.NET 관련 기술을 선호하고 새로운 언어를 배우는데 관심이 있습니다.