iOS) MVC Pattern

Publishing Date:2020-09-29

배경지식

MVC 패턴은 iOS 뿐만 아니라 소프트웨어를 만들 때 고려하는 디자인 패턴 중 하나이다. 디자인 패턴이란, 프로그래머가 소프트웨어를 만들 때 발생하는 공통적인 문제들을 해결하기 위해 만들어놓은 일종의 솔루션 템플릿이라고 할 수 있다. 싱글턴도 공통 인스턴스를 리턴하는 디자인 패턴이다.

MVC 패턴

MVC는 세 가지 컴포넌트의 약자이다.

M: Model V: View C: Controller

MVC 패턴을 적용한 애플리케이션에서 각 객체들은 위 세 가지 컴포넌트중 하나의 역할을 수행한다. 즉, 위 컴포넌트들은 애플리케이션에서 객체가 맡고 있는 역할이라고 생각할 수 있다. 이 역할들은 동시에 애플리케이션에서 객체가 어떻게 통신하는지 를 정의할 수 있다.

역할

Model은 UI와 관계 없이 애플리케이션에 관한 데이터를 담고 있다. UI와 관계가 없으나 자체의 데이터를 가지고 조작하고 처리하는 논리 연산을 모델에서 처리한다. 모델 객체는 데이터를 직접적으로 사용자에게 제공할 수 없다.

View는 쉽게 말해서 사용자에게 보여지는 객체이다. 버튼, 이미지, 텍스트뷰를 포함해 사용자가 보고 상호작용할 수 있으며 뷰들의 집합이 곧 애플리케이션의 UI를 이룬다. 주의해야 할 점은, 뷰에서 모델이 가진 데이터를 보여줄 수는 있지만 모델 객체와의 직접적인 링크는 없다는 사실이다. 뷰는 모델과 직접 소통하거나 데이터를 가져올 수 없으며, 그저 Controller에게 데이터를 받아 보여주고, 사용자가 편집할 수 있도록 사용자와 상호작용한다.

Controller는 애플리케이션을 관리하는 객체이다. 사용자가 보는 뷰들과 모델간 일종의 동기화를 시켜준다. 즉, iOS에서 사용자가 텍스트 필드를 수정했을 때, 뷰에게서 사용자 액션을 받아 응답하고 수정된 데이터를 모델에 전달하는 등 뷰와 모델이 직접적으로 컨택할 수 없으므로 중간에서 중개자 역할을 해 준다.
iOS의 Cocoa Touch 프레임워크코디네이팅 컨트롤러뷰 컨트롤러 두 가지 기본 타입을 제공한다.

  • 코디네이팅 컨트롤러: 애플리케이션 전체 혹은 일부 기능을 감독하고 관리한다. Delegation, notirication, Action 등의 기능이 수행된다.
  • 뷰 컨트롤러: 화면에 표시하는 뷰를 관리하며, 해당 뷰에 대한 참조를 유지하고, 프레젠테이션 및 후속 뷰로의 전환 등 사용자에게 보여지는 화면을 책임진다. 모달 뷰나 기기의 방향 전환 등도 뷰 컨트롤러에서 담당한다. 이 때 뷰 컨트롤러는 여러 가지 프레임워크 객체에 대한 델리게이트 혹은 데이터 소스 객체인 경우가 많다!
    iOS에서는 뷰 컨트롤러가 코디네이팅 컨트롤러의 역할을 겸하는 경우가 많다.

통신

그렇다면 각 객체는 어떻게 통신하는걸까? 역할에서 알 수 있었다시피, 모델과 뷰 사이에서는 직접적인 커뮤니케이션이 허용되지 않는다. 대신 모델과 뷰는 각각 컨트롤러와 통신함으로써 필요한 내용을 전달한다. 이를 그림으로 나타내면 대략 다음과 같다.
MVC

  1. User Action
    먼저 뷰가 사용자의 입력을 받으면 미리 정해진 target-action 구조로 입력을 컨트롤러에 전달한다. 예를 들어 어떠한 뷰가 사용자의 입력을 받았을 때 뷰는 다른 객체의 메소드를 호출하는데 이 때 객체를 타겟(target), 메소드를 액션(action)이라고 한다. iOS에서 타겟은 주로 뷰컨트롤러의 인스턴스를 의미한다.
  2. Update Model
    뷰의 변화를 전달받은 컨트롤러는 해당 액션을 바탕으로 모델을 업데이트한다. 이 때 컨트롤러는 모델에 자유롭게 접근할 수 있다.
  3. Model Notification
    모델은 자체 연산을 처리하고, 뷰에 업데이트 될만한 데이터를 컨트롤러에게 전달한다. 이 때 모델은 직접적으로 컨트롤러에 말을 걸 수는 없고, Notification을 사용한다. 이 때 사용하는 Notification이 KVO이다.
  4. Update View
    컨트롤러는 모델에게서 받아온 데이터를 뷰에 업데이트해준다.

전통적인 MVC 패턴과의 차이점

위에서 설명한 MVC 패턴은 ViewController가 대부분의 일을 맡아서 하는 iOS의 구조 특성상 모델과 뷰 사이의 접점이 차단되어 있다. 그러나 전통적인 MVC 패턴에서는 컨트롤러가 뷰와 모델 사이에서 이벤트를 받아 전달해주는 것 외에도 모델에서 Observer로 등록된 뷰 객체에게 Notify할 수 있다.
Traditional MVC Pattern
출처: Apple Developer Docs
(iOS에서 사용하는 MVC 패턴을 먼저 알았기 때문에 설명 순서가 엉망이다.)

애플의 다른 디자인 패턴

MVC 외에 MVP, MVVM, VIPER을 사용한다고 한다. 간단하게만 정리해보았다.

MVP

Model + View + Presenter
뷰 컨트롤러 대신 프레젠터를 사용한다. 프레젠터와 뷰는 일대일 관계 이다.
모델과 뷰 간의 의존성을 완전히 해결하였지만 뷰와 프레젠터간 관계가 밀접하다.

MVVM

Model + View + View Model
뷰 컨트롤러 대신 뷰 모델을 사용한다. 뷰와 뷰 모델은 다대일 관계 이다. 뷰는 자신이 사용할 뷰 모델을 선택해 데이터를 바인딩한다.
바인더를 통해 뷰와 뷰 모델 사이에 동기화되면서 뷰와 뷰 모델 사이의 관계 의존성을 감소시켰다.

VIPER

View + Interactor + Presenter + Entities + Router

  • Entity: 모델 객체
  • Interactor: 엔티티를 조작
  • Presenter: Interactor에서 데이터를 가져와 View에 뿌려줌
    엔티티를 제외한 다른 것들과 전부 상호작용함
  • View: Presenter의 요청대로 디스플레이되고 사용자의 입력을 다시 Presenter에 전달
  • Router: 화면 전환
    Presenter가 언제 화면을 전환할지 알려주면 뷰 컨트롤러를 생성하여 Presenter과 연결함

왜 사용하는가

언급했다시피 디자인 패턴은 이미 선배 개발자들이 많은 경험을 통해 특정 상황에 맞는 구조를 미리 만들어놓은 것으로 재사용하기 좋은 구조이다. 이 중 특히 MVC 패턴은 소프트웨어를 설계할 때 객체간의 역할을 구분함으로써 각 객체가 본인의 역할만 수행하며 다른 객체와 분리되어있기 때문에 효율적일뿐 아니라 애플리케이션의 유연성을 가지며 유지보수에 유리하다.

그러나 iOS에서 MVC 패턴은 분리성에서 그다지 효율적이지 못하다. 전통적인 패턴에서 모델과 뷰를 분리하여 독립성을 확보하였지만, ViewController간 관계가 너무 밀접하여 제대로 된 분리성을 확보하지 못했다. ViewController사이의 관계가 밀접하다는 것은 곧 Controller에서 View의 생명주기와 같은 부분을 관장하고 있기 때문이다. 따라서 MVC 패턴이 아닌 MVVM 패턴을 사용하는 등 다른 디자인 패턴을 사용할 수 있다.

Reference

다음에서 발췌: Keur,Christian. ‘iOS Programming: The Big Nerd Ranch Guide (Big Nerd Ranch Guides).’ Apple Books. 네이버 iOS 부스트코스
애플 공식 문서
좋은 아키텍처에 관해서
아키텍쳐 패턴

Comments