MVVM 디자인 패턴 in iOS

유재우·2022년 5월 25일
0

iOS Developer의 길!

목록 보기
2/15

MVVM

MVVM은 그래픽 사용자 인터페이스(뷰)의 개발을 비즈니스 로직 또는 백-엔드 로직(모델)로부터 분리시켜서 뷰가 어느 특정한 모델 플랫폼에 종속되지 않도록 해주는 패턴이다.

MVVM의 구성요소

  • 모델(Model)
- 데이터, 네트워크 로직, 비즈니스 로직등을 담으며 데이터를 캡슐화하는 역할을 맡고 있다.
- View, ViewModel에 대한 신경은 쓰지 않는다. 
- 데이터를 어떻게 가지고 있을지만 걱정하며, 데이터가 어떻게 보여질 것인지에 대해서는 고려하지 않는다.
→ MVC의 Model과 크게 다르지 않다.
  • 뷰(View)
- 사용자가 화면에서 보는 것들에 대한 구조, 배치, 그리고 외관에 해당하는 내용을 다룬다.
- Model을 직접 알고 있어서는 안된다.
- View는 ViewModel로부터 데이터를 가져와서 표현한다.
- 사용자와 View의 상호 작용을 수신하고 이에 대한 처리를 ViewModel에 부탁한다.
-> MVVM의 View는 보이는 부분에 대한 설정을 스스로 직접 한다.
  • 뷰 모델(ViewModel)
- View로부터 전달받는 요청을 처리할 로직을 담고 있으며 Model에 변화가 생기면
  View에 notification을 보낸다. 
  (데이터의 변화를 View가 알아챌 수 있도록 한다고 생각하면 된다)
- ViewModel은 View와 Model 사이의 중개자 역할을 하며 
  Presentation Logic을 처리하는 역할을 한다.

여기서 말하는 Presentation Logic이란?

일반적으로 ViewModel은 Model 클래스의 메서드를 호출하여 Model과 상호 작용한다. 
그런 다음 ViewModel은 Model의 데이터를 가져오고, 
View가 쉽게 사용할 수 있는 형태로 가공하여 제공한다.
ex) View가 데이터를 더 쉽게 처리할 수 있도록(보여줄 수 있도록)
데이터 형식을 다시 지정 (formatting)

동작의 흐름

  • View에 들어온 Event를 View Model에게 알려주면 View Model은 Model을 업데이트 시킨다.
  • Model이 변화하면 이는 View Model에 알려지고, View Model과 바인딩되어있는 View가 업데이트 된다.

MVC와의 차이점

  1. MVC: 기본적으로 View와 Model은 다른 구성요소들을 알지 못하며, Controller는 View와 Model을 모두 알고있는 형태로 구현되어야 했다.
    (여기서 '기본적'이라고 말한 이유는 꼭 그래야 하는 것은 아니기 때문이다.
    -전통적 MVC에서는 Model이 View를 알고 있도록 구현되기도 했었음)
  • MVVM: View는 ViewModel을 알고 있으며, 소유한다. 그리고 ViewModel은 Model만을 알고 있도록 구현된다. Model은 다른 구성요소들을 알지 못하도록 만들어져야 한다. (Model만이 MVC와 크게 달라지지 않았다)

  1. MVC: View가 데이터를 보여주는 방식은 크게 두 가지로 나뉘었었다.
    -Model에 View를 Observer로 등록하여 데이터를 설정하는 방식
    (Model이 View를 알고 있는 형태, 전통적 방식, apple이 문제를 제기했던 방식)
    -ViewController가 Model의 변경을 알아차리고 직접 View에 데이터를 설정해주는 방식(apple's MVC)
  • MVVM: View는 ViewModel과의 데이터 바인딩을 통해 스스로 데이터를 보여준다. (데이터를 View에 보이게 하기 위한 설정 책임을 View 스스로가 가진다)

  1. MVC(iOS): 사용자 상호작용에 대해 View가 Controller에게 처리를 부탁하는 것은 Delegate Pattern, Target-Action등을 썼었다.
  • MVVM: View가 ViewModel을 알고 있으므로 필요할 때 ViewModel의 메서드를 호출하는 방식으로 구현이 가능하다.

  • Apple의 MVC에서는 ViewController가 View에 대한 설정 뿐만 아니라 life cycle관리까지 하는 등 View와 밀접한 관계를 지니고 있었다.
  • 하지만 MVVM에서의 ViewModel은 View를 알지 못하며 View를 설정하는 코드가 전혀 안들어간다.
    (데이터 변경에 대해 뷰를 업데이트하는 것은 온전히 뷰의 책임이 되었다)

MVVM for UIKit / SwiftUI


UIKit

  • ViewController는 View로써 취급된다.
  • ViewController는 UIView의 life-cycle을 관리하면서 ViewModel을 소유한다.
  • 'MVVM View와 ViewModel간의 데이터 바인딩'은 ViewController와 ViewModel간의 바인딩으로 구현된다.
  • 사용자 상호작용에 대한 처리는 ViewController에서 ViewModel의 특정 메서드를 호출하는 방식으로 구현 가능하다.

SwiftUI

  • SwiftUI에서의 MVVM View는 View 프로토콜을 채택한 Struct가 맡는다.
  • View 프로토콜을 채택한 Struct들은 ViewModel을 소유한다.
  • View와 ViewModel간의 데이터 바인딩은 Property Wrapper들을 통해 구현할 수 있다.
  • 사용자 상호작용에 대한 처리는 View에서 ViewModel의 특정 메서드를 호출하는 방식으로 구현 가능하다.

데이터 바인딩

  • View → ViewModel 데이터 바인딩: View에서의 값 변화도 하나의 이벤트처럼 판단하고 위에서 말한 이벤트 처리 방식을 써볼 수 있다. SwiftUI를 쓰는 경우에는 Published 프로퍼티에 대한 $ 사용을 고려해볼 수 있다.
  • View ← ViewModel 데이터 바인딩: 방법이 정말 많다. Delegate Pattern, Closure(콜백),KVO, NotificationCenter 등을 써볼 수 있으며 이것들을 Property Observer와 조합하여 사용해볼 수도 있다. (물론 Reactive 라이브러리 / 프레임워크도 사용해 볼 수 있다)

Binding in SwiftUI

View - ViewModel바인딩은 ObservableObject 프로토콜 및 Published같은 Property Wrapper를 주로 이용.

  • ViewModel은 ObservableObject를 채택하여 만들게 되며 이 ViewModel은 View가 ObservedObject로 소유하게 된다.(경우에 따라 EnvironmentObject, StateObject 등으로 소유하기도 한다) 이렇게 만들면 ViewModel은 View에 의해 Observed 되며 ViewModel의 @Published 프로퍼티에 변화가 생기면 해당 데이터 변화에 영향을 받는 View들이 다시 그려진다.

MVVM 요약


인용한 블로그 링크

profile
끝없이 탐구하는 iOS 개발자 유재우입니다!

0개의 댓글