기존의 MVC패턴의 한계를 극복하고자 MVP, 그리고 MVVM 패턴이 등장하게 되었다.
MVC의 한계와 MVVM이 탄생한 이유는 여러가지가 있을 수 있겠으나, 대표적으로 다음의 이유들이 있었다.
- View와 Business logic간의 긴밀한 연관성에 의해 확장성, 유지보수에 어려움을 겪음
- 추가로 View가 Model에 영향을 줄 수 있기 때문에, 터치 이상으로 복잡한 소통을 해야 할 경우 프로토콜 등을 통해 Controller에 책임을 위임함
- ViewController의 역할이 많아지면서 Controller가 비대해지는 Massive View Controller의 문제가 발생
이 외에도 여러 이유가 있을 수 있겠지만, 어쨌든 MVVM이 등장한 가장 핵심 이유는"View와 Model의 의존성 분리"라고 생각한다.
충분히 납득할만한 이유라고 생각한다.
다만, 이 핵심 이유 외에 Controller가 비대해지는 문제를 해결하기 위함도 있었는데, 이부분은 잘 와닿지 않았다.
ViewController의 역할 중 일부가 ViewModel로 이동해서 ViewController의 비대성은 어느정도 해결됐을지 몰라도, 이렇게 되면 어쨌든 ViewModel역시 비대해질 수 있다는 것 아닌가?
이에 대해 여러 블로그도 찾아보고, 나의 생각도 풀어보면서 정리해보려고 한다.
MVC의 한계와 MVVM의 등장
애플의 MVC패턴의 동작은 Controlle는 Model이 화면에 어떻게 표현이 될 지 전달해주는 역할을 하고,
View는 사용자에게 입력을 받아 Controller를 통해 Model을 업데이트 하기도 한다.
View와 Model은 Controller라는 애를 통해서 소통을 하지만, 결국 Controller는 View와 Model에 대한 모든 정보를 알고 있으면, 항상 접근할 수 있게 된다. 또한 View가 Model에 영향을 줄 수도 있다.
또한 Cotroller가 중간에서 많은 역할을 맡게 되었다.
레이아웃, 유저의 입력, 비즈니스 로직, 화면 전환 등...
이렇게 ViewController가 비대해지는 Massive View Controller 문제가 발생하고, 이를 보완하기 위해 MVP, 그리고 MVVM 패턴이 등장하게 되었다.

MVVM의 목적은 View(UI 관련 코드)와 Model을 명확하게 분리하는 것이 목적이다.
ViewModel이라는걸 통해 비즈니스 로직을 분리하고, 이는 Model을 참조하고 있는 형태이다.
View는 Date Binding을 통해 ViewModel과 연결되고, ViewModel은 Model의 변경사항을 View에게 직접 알리지는 않고 무언가가 변경되 었다고 발표(Publish)한다는 특징이 있다.

그럼에도 존재하는 MVVM의 한계
위와 같은 이유로 MVVM 패턴이 등장함에 따라 Controller가 가진 역할들 중 비즈니스 로직을 ViewModel이 맡게 되었다.
이로써 Massive View Controller의 문제는 어느정도 해결한걸로 보인다.
그런데.. 다음과 같은 의문이 생겼다.
결국 Controller의 역할은 줄었을지 몰라도, ViewModel의 역할이 비대해지는 것 아닌가?
결론부터 말하자면 맞다.
결국 Controller의 역할이 그대로 ViewModel로 이동했을 뿐, 프로젝트의 규모가 커질수록 결국 ViewModel의 규모도 함께 커질 수 밖에 없을 것이다.
그럼 어떻게 이 문제를 해결할 수 있을까?
Massive View Model을 해결하기 위한 방법들
다음 글에서 이러한 문제를 해결하는 방법 4가지를 소개하고 있다.
그런데 그 중에 와닿는 두 가지의 방법만 나의 언어로 소개하고자 한다. (잘 이해하지 못하고 소개하면 안되니까!)
Dealing with Massive View Models using MVVM on iOS
Four practices that will help you to get rid of Massive View Models
medium.com
- 하위 뷰 모델 사용
MVP는 VC와 Presenter의 관계가 1:1의 관계라면, MVVM의 경우 1:n의 관계로 구성할 수 있다는 특징이 있다.
이는 하나의 ViewController가 여러 개의 ViewModel을 가지고 있을 수 있다는 말이 아니다.
만약 하나의 ViewController안에 TableView가 있고, 그 TableViewCell에 대한 ViewModel을 별도로 만들 수 있다는 뜻이다.
이는 객체지향 프로그래밍의 단일 책임 원칙(SRP)와도 연관이 있다.
단일 책임 원칙이란, 각 클래스는 단 하나의 책임만을 가져야 한다는 것을 말한다.
MVC가 비대해지는 이유가 ViewController라는 클래스가 여러 역할을 하기 때문이었는데, 이는 곧 단일 책임 원칙을 위반하는 거라도도 볼 수 있다.
MVVM에 이를 적용해본다면, ViewController에 대한 ViewModel이 존재하고, TableViewCell에 대한 ViewModel이 따로 존재하게 됨으로써 단일 책임 원칙을 따를 수 있다는 것이다.
이렇게 되면 자연스럽게 하나의 ViewModel이 비대해지는 문제를 자연스럽게 해결할 수 있을 것이다.
단, 그렇다고 해서 모든 클래스에 ViewModel이 따로 존재해야 한다는 것은 아니다. 이는 불필요한 개발 리소스가 들어갈 수 있기 때문이라고 생각한다. 그래서 만약 하나의 ViewModel이 너무 비대해지는 것 같을 때 분리를 하는것을 추천한다.
- Coordinator 사용
Coordinator는 navigation을 담당하는 역할로 한번 더 분리한다고 생각하면 된다.
MVVM에 Coordinator를 도입한 패턴을 MVVMC 또는 MVVM-C 패턴이라고 하는데, 사실 사용법이 딱 정해져 있는건 아니라서, 간단히 컨셉만 살펴보겠다.
MVVM에서 Model은 실제 데이터, View는 UI관련, ViewModel은 비즈니스 로직을 담당하고 있다고 하면, Coordinator는 navigation 역할을 전담한다고 보면 된다.
이렇게 되면 화면 이동에 대한 단일 책임 원칙을 따르게 되고, ViewController 등은 화면 이동에 대해 다음 화면에 어떤 화면이 와야 하는 지 등에 대한 정보를 알지 못해도 된다.
지금까지의 MVVM의 화면이동은, 사용자의 입력이 들어오면 View(Controller)는 VIewModel에게 이를 전달하고, ViewModel은 다시 View(Controller)에게 트리거만을 전달해서 결국 ViewController에서 화면전환 로직이 진행된다.
반면 MVVMC에서는 View에서 사용자의 입력을 받아서 Coordinator에 전달하게 되고, Coordinator에서 화면 전환 로직을 처리하게 된다.
물론, View -> ViewModel -> Coordinator로 전달하는게 조금 더 일반적일수도 있지만 ViewModel의 비대성을 줄이기 위해 View 에서 바로 Coordinator로 이동하도록 할 수도 있다.
더 자세한 Coordinator의 구성 방법은 아래 글에서 확인해볼 수 있다.
https://youbidan-project.tistory.com/228
[Swift] MVVMC 간단하게 알아보기
MVVMC 는 기존 MVVM 아키텍처 패턴에 Coordinator을 추가한 조합 MVVMC, MVVM-C, MVVM Coordinator 패턴이라고도 함 MVVM에서 화면 전환(navigation) 기능을 Coordinator가 맡아 처리함 MVVM 이 처음이라면 👇 2022.06.07 - [
youbidan-project.tistory.com
이 외에도 "의존성 주입", "ViewModel 외부에서 Action 다루기" 등 방법이 더 있지만, 이 부분은 조금 더 공부를 하고 정리해보려 한다.
다양한 방법에 대한 내용은 참고자료 전문을 참고하면 좋을 것 같다.
※참고자료
'iOS > Swift' 카테고리의 다른 글
| [iOS/Swift] Realm의 데이터 삭제하기 (0) | 2025.03.12 |
|---|---|
| [iOS/Swift] Typed throws - Swfit6에서의 에러처리 패턴 개선사항 (0) | 2025.02.16 |
| [iOS/Swift] ARC - Swift의 메모리 관리 기법 그런데 이제 weak을 곁들인 (0) | 2025.02.08 |
| [iOS/Swift] 커스텀 Observable와 bind메서드에 대한 고찰 (0) | 2025.02.04 |
| [iOS/Swift] WMO와 Method Dispatch - class에 final을 붙이는 진짜 이유 (0) | 2025.01.25 |