달력

4

« 2024/4 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

1. Intro

: 예전에 MVC의 원문을 읽고 요약했던 것에 이어서, 이번에는 MVP의 원문을 읽고 요약해보았다. MVC가 제안된 후로, 시간이 꽤 지나면서 Application의 요구사항이 복잡해지다보니... MVC의 Component를 좀 더 세분화 시킨 것이 눈에 띈다. MVP가 등장하던 시기에는 Unit Test의 중요성이 부각되진 않았는지 Testability의 장점에 대해선 언급되어 있지 않았다. Kent Beck의 XP 책이 1999년도에 등장했으니 그럴수도 있을 것 같다.

 

 MVP의 원문에서 이야기하는 핵심 내용을 잘 전달하려고 노력했지만, 개인 판단상 필요없다고 생각한 부분은 빼기도 했다. 맨 하단에 원문의 Link를 남겨두었으니, 부족한 부분이 있다면 찾아볼 수 있을 것이다.

 

 IBM의 자회사인 Taligent는 C++ & Java 언어로 개발하기 위한 차세대 Programming Model을 만들었는데, 그것에 MVP(Model View Presenter)이다. MVP는 Smalltalk의 고전적인 MVC Programming Model을 일반화한 것에 베이스를 둔다.

 MVP는 다양한 Application, Component 개발을 위한 강력하고, 이해하기 쉬운 설계(Design) 방법론을 제공한다. 또 MVP는, Multiple client / server 나 Multi-tier application architecture에도 적용할 수 있다. MVP는 주요 객체지향 언어 환경에서, 활용가능한 통합된 개념적 Programming model을 제공해줄 것이다.

 

 

 

2. Taligent에서 새로 제안한 Programming Model

2-1. Smalltalk Programming Model

: 1970년대, Smalltalk의 MVC model이 제안되었다. MVC는 Smalltalk에서 GUI 개발하기 위한 Fundamental design pattern으로 시작해서, 지금까지 다양한 Library들과 Application에서 재사용되고 채택되어 왔다.

 

 Smalltalk로 개발하던 개발자들은, Model, View, Controller를 추상화하기 위한 Base class(Smalltalk Class Library에서 제공함)들을 Customizing하거나 상속하여... GUI Object들을 만들었다. 개발자들은 GUI object에 있는, MVC에서 정의한 Model, View, Controller간 타이트한 결합을 이어받아, 개발할 때 편의를 누릴 수 있었다. 좀 복잡한 GUI object는 여러 GUI object들을 조합하여 구성할 수 있다. 궁극적으로는 모든 Graphical application은 MVC를 이용하여 구성할 수 있는 것이다.

 

 

2-2. Building the Taligent / Open Class Progamming model

: IBM을 위한 Open Class Library에서 Taligent는 다양한 Application의 전반적인 구조를 나타내기 위해, MVC Programming Model을 채택하고 일반화했다.

 

 Taligent는 전반적으로 기본적인 MVC Concept을 더 세분화한다. 우선, Model이랑 View와 Controller를 분리하고, View와 Controller를 합쳐서 Presentation이라 부른다. 이것은 Programming Problem을 Data Management와 User Interface라는 두 Fundamental Contept으로 분리하는 것이다.

 

그림 1. Model과 View, Controller를 분리

 

 

 

3. Model

3-1. Model Enable Encapsulation

: Model Concept을 일반화하면 몇몇 이점이 있는데... 우선 Model과 Presentation이 깨끗하게 분리될 수 있다. 예를 들어, 전화번호 목록 Component를 구현한다고 가정해보자. Model은 이름과 전화번호에 대한 Data를 캡슐화(Encapsulate)한다. 그리고 Model에서, Data에 대해 Query하거나 Data를 수정하기 위한 Method를 제공한다. Presentation은 전화번호 목록을 표현하는 전화번호부가 될 수 있다.

 

 깨끗하게 분리하고 캡슐화함으로써 이점을 얻을 수 있다. Model이 Data Structure를 바꾸는 것처럼 크게 수정하더라도, Presentation은 아무런 수정없이 재사용할 수 있다. 비슷하게, UI 변경과 같이 Presentation을 크게 수정하더라도, Model은 아무런 수정없이 재사용할 수 있다.

 

 

3-2. Model enable Persistence

: Model내에 Data가 저장되기도 하지만, Model이 Data를 저장하지 않고 Persistent Data Store에 접근해서 저장된 Data를 사용하기도 한다. Model은 접근 제어나 인증 관련 Logic을 구현할 수도 있고, 회계 또는 과금 Logic을 구현할 수도 있고, 성능 향상을 위해 Cache를 구현할 수도 있다.

 

 

3-3. Model Enable Sharing

: Model을 추상화하면, 여러 사용자 간의 Data 사용을 유연하게 할 수 있다. 다른 Program의 Model이 동일한 Remote Data를 캡슐화하는 것은, 여러 사용자가 Data를 공유할 수 있게 해준다. 아래의 그림을 참고하면, 이해가 쉬울 것이다.

 

그림 2. 다른 Program의 Model이 Data를 공유해서 쓰고 있음

 

3-4. Three Data Management Questions

: Taligent는 Data Management와 UI를 분리하는 다양한 개발 경험을 바탕으로, Data Management의 문제를 정리했다. 그들은, 아래의 그림처럼 Data Management의 문제를 3개의 질문을 바탕으로 3 부분으로 나누었다.

 

그림 3. Data Management 문제

 

1) What is my data?

: 위의 그림에서 Model에 해당하며, 우리가 알고있는 기존의 Model과 비슷하고 Data를 캡슐화하고 읽고, 쓸 수 있는 Method를 제공한다.

 

2) How do I specify my data?

: Model의 Data에서, 다른 부분집합들을 명시하기 위한 추상화. 위의 사진에서 Selections에 해당한다.

 

3) How do I change my data?

: Selections에서 수행될 수 있는 연산들을 표현하기 위한 추상화. 위의 사진에서 Commands에 해당한다.

 

 

 Model, Selections, Commands에 대한 이해를 돕기 위해, 예시를 들어 설명해보겠다. 아래의 그림을 보자. Model은 2차원 Integer Array라고 가정한다. View는 막대 그래프이다. Selections은 막대 그래프에 표시된 Data의 부분을 명시(또는 구분)할 수 있는 수단을 제공한다. Commands는 Data로 할 수 있는 동작들이다.

 

그림 4. Model, Selections, Commands, View 각각의 예시

 

 

 

4. Presentation

4-1. Three User Interface Questions

: Application에서 UI를 어떻게 설계할 수 있을까? Taligent는 Data Management를 나눴던 것과 비슷하게, 3개의 질문을 바탕으로 3 부분으로 나누었다. 아래의 그림을 보자.

 

그림 5. UI 설계를 위한 질문들

 

1) How do I display my data?

: 위의 그림에서 View에 해당한다. View는, 여러 개의 다른 View들로 구성될 수 있고 각 View들은 꼭 시각적으로 표시되지 않아도 된다.

 

2) How do events map into changes in my data?

: 위의 그림에서 Interactor에 해당한다.

 

3) How do I put it all together?

: 위의 그림에서 Presenter에 해당한다. Presenter는 MVC의 Controller와 유사하지만... 좀 더 높은, 추상화된 Application Level에 위치하고 Command와 Interactor랑 상호작용한다. 이 Presenter의 약자를 따서, Taligent가 제안한 Programming Model을 MVP(Model View Presenter)라고 이름을 지었다.

 Presenter의 역할을 좀 더 직관적으로 요약하면, Event를 받아서 적절한 Command에 연결해주는 것이라고 볼 수 있다(본 MVP를 소개하는 원문에서는, 이것을 Business Logic을 제공한다고 표현했다).

 

 

 이해를 돕기 위해 예시를 들어 설명해보겠다. 아래의 그림에서, Interactor에게 'Mouse Cursor의 이동'이나 'Menu의 선택'과 같은 행위를 적절한 Event로 정의할 수 있다. Interactor가 행위에 대한 Event를 전달하면, Presenter는 전통적인 Application의 'Main' 또는 'Event Loop'처럼 동작하여... 적절한 Model, Selection, Command, View, Interactor를 만들거나 상호작용한다(그림 5에는 방향성이 있는 것처럼 그려져 있으나, MVP의 원문에는 단방향성을 지켜야 한다같은 제약은 없었다).

 

그림 6. UI 구성요소를 설명하기 위한 예시

 

 

 

5. Programming Model Frameworks

: Taligent에서 MVP Programming Model을 고안했을때, 그들은 Object-Oriented Frameworks로 설계 및 구현했고... 개발자들이 자신의 Application에 Customizing할 수 있게 했다(이후, Taligent에서 몇번의 Release를 거쳐 Framework를 제공했었고, Update 내역에 대해 적혀있었는데, 중요한 내용이 아니라고 생각하여 생략했다).

 

그림 7. Taligent가 제공했던 Framework의 구조

 

 

 

6. Programming Model Classes

: 아래 그림은 MVP Programming Model에 대한 Class Diagram으로, 앞서 이야기했던 Concept이나 Structure들을 잘 나타내고 있다.

 

그림 8. MVP Programming Model에 대한 Class Diagram

 

 IModel, IView, ISelection, ICommand, IInteractor, IPresenter와 같은 MVP의 기본적인 Class들이 있다. 개발자들은 이 기본적인 Class들의 Subclass를 만들어서, 개발하면 된다(옛날에는 Interface 역할을 하는 Type의 이름 앞에 I를 붙였었다고 하고, 이 원문이 쓰여진지는 20년도 더 지났다. 당연히, 사용하는 언어의 Spec에 따라, Protocol이나 Interface 같은 것을 써도 상관없다).

 

 이 당시, 어지간한 Application들은 Interactor를 직접 구현할 필요가 없었다. IMenuInteractor, IButtonInteractor 같은 많이들 쓸법한 Interactor들이 이미 구현된 Open Class Library가 있었기 때문이었다.

 

 

 

7. Building An Application - Client / Server

: MVP Programming Model로, Client / Server Application을 구현하면 어떤 형태일까? MVP의 각 구성요소들이, Client와 Server중에 어디에 구현되어야 할지 결정해야 할 것이다. 보통, 전통적인 Client와 Server는 Presenter에 따라 나눌 수 있다. Model, Selection, Command는 Server에 속할 것이다. View, Interactor는 Client에 속할 것이다. 그러면, Presenter는 Client와 Server를 연결하는 역할이 될 것이다. 즉, Client와 Server 모두를 위한, 하나의 개념적인 Presenter가 존재하게 된다. 하지만 Presenter는 하나이므로 Presenter에 Client 관련 Code가 Server 관련 Code보다 많아지거나, 그 반대의 상황이 생길 수 있다. 

 

 Client, Server 각각을 MVP로 구현해보면 아래의 그림과 같은 형태가 될 것이다. Client에서 Model은 Server에서 가져와서 사용하는 Surrogate 또는 Proxy 형태가 될 수 있다. Server는 따로 View가 없고, Client에 있는 View를 갱신하는 형태가 될 수 있다. 여기서의 핵심은, Client / Server 모두를 MVP Programming Model로 구현할 수 있다는 것이다.

 

 

 

그림 9. Both Side MVP

 

 

 

8. Benefits of Abstractions

: 원문이 쓰여지던 당시, 다양한 Application을 개발하는 데에 MVP Programming Model을 활용할 수 있었다. MVP Programming Model의 구성요소대로, Logic들을 구분하고 나누는 것은 어떤 이점이 있는 걸까?

 

 Model과 View를 구분하는 것은, View의 독립시킬 수 있다는 이점이 있다. 간단한 예를 들면... 서로 다른 계산기의 UI가 있더라도, 동일한 계산기 핵심 Logic을 사용할 수 있는 상황을 생각해볼 수 있다.

 

 Selection과 Model을 구분하는 것은, Model을 독립시킬 수 있다는 이점이 있다. Model을 독립하면... Data의 구조나 File Format을 변경하더라도, Application의 나머지 부분에서 Data를 어떻게 보여주고 다룰 것인지를 변경하지 않아도 된다.

 

 언급한 2가지 이점들은 역할을 잘 구분하여 얻을 수 있는 일반적인 장점들이다. 이 2가지 이점 외에도 MVP Programming Model에 있는 구성요소들 중, 인접한 구성요소들간에는 구분하여 얻을 수 있는 장점들이 더 있다.

 

 궁극적으로는 MVP Programming Model로 추상화하여 구현하면... Platform이나 표준이 다르더라도 많은 Code들을 추가적인 수정없이 사용할 수 있는, 호환성(Portability)을 높일 수 있다는 장점이 있을 것이다.

 

 

 

9. 읽은 후 생각 정리

: MVC 대비, Model은 Data와 Data Management로 나누어 졌다. View와 Controller(MVP에선 Presenter) 사이에, Event를 전달 및 변환과 관련된 역할을 하는 Interactor가 추가되었다. Model과 Controller 사이에도 Selection과 Command가 추가되었다.

 

 하지만 원문의 내용과 달리, 지금도 iOS MVP Architecture로 검색해보면... 구현하려는 기능, 해결하려는 문제를 오직 Model, View, Presenter 세개의 Component에 맞추어서 설명하는 글들이 많다. Selection, Command, Interactor에 대해서는 언급이 없다. 심지어 MVC Architecture에서는 View에 UIView만 속했는데, MVP Architecture에서는 View에 UIView, UIViewController 모두 속하는 것이 차이라고 설명하는 글들도 있다. 당연히 잘못된 내용이다.

 

 바로 위의 문단(8. Benefits of Abstractions)에 Platform간의 호환성 이야기가 나오는데, 이걸 MVC에도 적용해보면... Controller에선 View가 어떤 형태인지 함부로 가정하거나 제한을 두지 않아야 한다. View는 UIKit에 속하는 Class로 구현할 수도 있고, AppKit에 속하는 Class로 구현할 수도 있다. 심지어 Metal로 구현할 수도 있다. 그렇다면 당연히, Controller는 UIKit, AppKit 같은 것에 의존적이지 않는 것이 바람직하다. 구현 편의상 UIViewController에 Controller의 역할을 부여하는 것은 이해가 되고 그것을 비판할 생각은 없지만, 그건 이상적인 Code가 아니라고 말하고 싶다.

 

 MVC의 이야기를 하며 글을 마무리 짓게 되었다. 빠른 시일내에, MVVM에 대해서도 정리해서 올려야지...

 

 

 

10. Reference

1) Mike Potel: MVP: Model-View-Presenter The Taligent Programming Model for C++ and Java, Taligent Inc, 1996

 

'Software Engineering > Architecture' 카테고리의 다른 글

The original MVC Reports 요약  (0) 2020.08.31
VIP를 읽어보고 고민한 것들  (0) 2019.09.08
:
Posted by syjdev

1. Intro

: iOS 관련 개발 블로그나 세미나/행사에서 Architecture 주제를 다룰 때, 종종 하는 이야기가 있다. MVC의 C가 비대해져서 MVVM을 도입해보고, VM이 비대해져서 VIP를 도입했다는 것. 예전에는 이런 이야기를 의심없이 받아들였으나, 개발을 할수록 의문이 쌓여갔다. C가 비대해서 도입한 MVVM에서, VM이 비대해졌다면... MVC로 개발하면서 발생한 문제를 잘못 짚은게 아닐까.

 

 개발을 하다보면 Model을 단순한 Data Structure로 작성한 코드를 많이 보았다. 그런 코드에서 Business Logic은 Controller나 ViewModel에 작성되어 있었다. 그러니까, Controller나 ViewModel에서 HTTP 통신을 하고, UserDefault나 내부 DB에서 Data를 가져오거나 저장하는 것이다. 당연히 Controller나 ViewModel은 비대해질 수 밖에 없어보이는데, 이상하지 않은가?

 

 마틴(Robert C Martin)은, 여러 공학에서 Model을 만들어서 검증하는 사례를 이야기하며 Model은 '추상화한 것'이라고 이야기한다(UML 책 참고). 나는 이 이야기에 크게 공감하며, ViewModel은 View를 추상화해야 하고 Model은 Business를 추상화해야 한다고 생각한다. 그래서 Business Logic은 Controller나 ViewModel에 작성하는 것이 잘못됬다고 생각한다. 

 

 Model을 단순한 Data Structure로 작성할 수도 있다. 문제는 왜 Business Logic을 Controller나 ViewModel에 작성하냐는 것이다. 이런 고민을 하면서, MVC나 MVVM을 처음 이야기한 사람은 어떻게 생각했는지 궁금해졌다. 그래서 이번 포스트에서는 MVC를 처음 고안한 사람의 Report를 읽은 후 요약해보고, 향후 다른 포스트에서는 다른 Architecture에 대해서도 정리해보고자 한다.

 

 

 

2. The original MVC reports - Trygve Reenskaug

 

2.1. Intro

: 옛날 1978-79년에, Tregve Reenskaug는 Xerox Palo Alto Research Laboratory (PARC)에서 연구원으로 재직하던 때에, MVC reports를 작성하고 구현했었다. MVC는, 여러 관점에서 사용자들이 Data를 통제할 수 있게 하는 일반적인 문제에 대한 솔루션으로 만들어졌었다. MVC에서 가장 어려웠던 문제 중 하나는, Architecture를 구성하는 Component들의 이름을 정하는 것이다. 처음에는 Thing-Model-View-Editor라고 이름을 지었었다(1979년 5월 12일). 하지만 긴 논의 끝에, Model-View-Controller로 이름을 바꾸게 되었다(1979년 12월 10일).

 

 

2.2 Thing-Model-View-Editor (1979년 5월 12일)

=> Thing-Model-View-Editor는 중요한 부분이 아니라고 생각해서, 아주 간략하게 각 컴포넌트의 정의부분만 정리하고자 한다.

 

- Thing

: 사용자가 관심을 가질만한 것.

 

- Model

: Computing System에서, Model은 Data의 형태로 추상화의 표현. Data를 다루는 방법도 함께 제공되는 Collection으로 보자.

 

- View

: View는 Model을 표시하는 역할을 한다. Thing-Model-View-Editor를 고안해낸 당시, 저자는 Model을 하나 이상의 View에 부착(Attach)시키고 싶었던 것 같다.

 

- Editor

: 사용자와 View간 인터페이스 역할을 한다.

 

 

2.3 Model-View-Controller (1979년 12월 10일)

- Model

: Model은 지식(Knowledge)을 나타낸다. Model은 단일 객체일 수 있고, 객체들의 구조체일 수 있다. Model의 Node는 문제에서 식별가능한 부분으로 나타날 수 있어야 한다. => 말이 좀 어려운데, '문제'가 의미하는 것은 개발로서 해결해야 하는 것으로 생각하면 될 것 같다.

 Model의 Node는 모두 같은 문제 레벨에 있어야 한다. => 이것도 역시 말이 어렵다. 나는, 개발할려는 시스템 또는 시스템의 부분을 여러 Layer로 나눈다고 가정할 때 'Model들은 같은 Layer에 있어야 한다'정도로 이해했다(Robert C Martin의 Clean Archtecture의 Entity Layer에 대한 설명을 보고, 이렇게 생각하게 됬다).

 

- View

: Model의 시각적 표현. View는 View의 Model에 부착(Attach)되고, Model을 표현하기 위해 Model로부터 Data를 얻는다.

 

- Controller

: Controller는 사용자와 System을 잇는 역할을 한다. 사용자에게 출력할 것을 적절한 Message로 바꾸어서 하나 이상의 View에 전달한다던지, 화면에 View들을 적절하게 배치하여 사용자에게 입력을 위한 수단을 제공한다던지 해서, Controller는 사용자에게 필요한 입출력 인터페이스를 제공한다.

 Controller는 View를 보완하지 않는 것이 좋다(원 글에선, Controller가 서로 다른 View 끼리 연결을 하지 말라고 하였음). 그리고 View는 사용자의 입력(마우스 동작, 키보드 입력)을 몰라야 한다. 이를 위해, Message를 View로 보내는 Method는 Controller에 구현한다.

 

- Editor

: Controller는 모든 View에 연결되어 있다. 어떤 View는 Editor라는 특별한 Controller를 제공하는데, Editor는 View에 표시된 정보를 사용자가 수정할 수 있게 한다.

 

 

 

3. 읽은 후, 생각 정리

: The Original은 1979년대에 Trygve Reenskaug가 Xerox에서 사용자를 위한 시스템을 개발할 때, 작성된 글이다. 그래서 The Original MVC에서 제안하는 내용 중 일부는 공감되지 않을 수 있는데, 지금과 그 당시의 시대적 차이를 고려해보자(지금 개발중인 앱과, 당시에 개발중인 시스템의 복잡도는...).

 

 View와 Model이 부착(Attach)된다고 표현한 것이 조금 아쉬웠다. 요즘은, View가 Model의 존재를 몰라야 한다는 것이 일반적으로 받아들여지기 때문이다.

 

 Thing-Model-View-Editor에서의 Model과 Model-View-Controller에서 Model에 대한 역할이나 설명이 크게 달라지지 않았는데, 문서에서 설명한 것처럼 Model에서 Data를 다루는 방법도 제공한다면, 이 당시의 Controller는 역할이 방대하지 않았을 것으로 추측된다.

 

 여담이지만, 일하다보면 ViewController(많은 iOS 개발자들이 MVC의 Controller 역할을 부여함)에서 Network나 Local Database를 통해 Data를 가져오는 코드를 많이 보게 된다. 하지만 The Original MVC에 설명된 내용에 따르면 Data를 다루는 Model의 역할을 Controller에게 넘긴 것으로, Controller의 역할 분배를 잘못한 것으로 볼 수 있지 않을까? 바람직하지 않은 것 같다.

 

 

 

4. Reference

1)Trygve Reenskaug: The original MVC Reports, Oslo, February 12, 2007

:
Posted by syjdev

Intro

 최근에, 동료와 함께 Demo App을 개편하는 일을 하게 되었다. Demo App의 주 목적은, 우리가 개발 및 배포하는 SDK에 대한 가이드와 간단한 동작을 보여주는 것이다. 그 외에 다른 복잡한 비즈니스적 요구사항이 없었고 시간상 여유가 있어서, 새로운 Architecture로 개발하기로 했다. 

 

 선택한 Architecture는 VIP인데, VIP를 설명하는 글에 따르면 Uncle Bob의 Clean Architecture를 참고해서 iOS 개발에 적합한 Component들로 구성한 Architecture라고 한다. 나는 VIP Architecture에 맞게 개발하기 위해 관련 글들(친절하게도, Sample Project도 공개되어 있다)을 읽었고, 생각한 것들을 여기에 정리해보고자 한다.

 

 

Vip의 Components 훑어보기

Clean Swift (VIP) Flow Diagram - 출처 https://hackernoon.com/introducing-clean-swift-architecture-vip-770a639ad7bf

 위의 Flow Diagram은, VIP를 구성하는 Component들을 보여주고, 어떻게 상호작용하는지를 보여준다. 역할이 애매하여 ViewController에 많은 코드를 넣는 실수를 줄이고자 Interactor와 Presenter를 두었고, Interactor에서도 Data를 가져오는 역할을 Worker가 담당하도록 하였다.

 

 Interactor는 View단의 요청을 받아서 자신의 역할을 수행하고, Presenter는 View단을 위한 Presentation Logic 처리를 담당한다. Router는 ViewController간 Transition 처리를 담당한다. Worker는 여러가지 Business Logic에 따라 다양한 처리를 하게 된다.

 

 

 

고민되는 것들

 

1) Router는 ViewController와 의존관계를 맺어야 하는가?

 Transition을 하기위해, 다음 화면을 노출하기 위한 정보가 필요할 수 있다. 예를들어, 쇼핑몰의 상품 목록에서 상품 상세화면으로 넘어가는 시나리오가 있다면 상세하게 보여줄 상품에 대한 ID가 필요할 것이다. Router의 역할중에 Transition시 Data를 전달하는 것도 있는데, Sample Project에서는 이를 위해 Router가 DataStore(Protocol)라는 것을 갖고 Interactor가 이 Protocol을 구현한다. 여기서 어색하다는 느낌이 들었는데, VIP Flow상 Router와 소통하는 Component는 ViewController 뿐이다. Sample Project는 VIP Flow와 맞지 않다.

 

 코드를 수정하여 ViewController에서 Transition에 필요한 정보가 있는 Model을 Router로 넘겨주게끔 수정하면 어떨까? VIP에서 ViewController에 Model을 넘겨주는 Component는 없다. 그리고 View가 Model을 직접 보는 것은, 일반적으로 좋지 않다.

 

 그렇다면 Presenter에서 'Transition에 필요한 추상화된 정보'를 ViewController로 넘겨주고, ViewController는 그 정보를 Router로 넘겨주면 어떨까. 그리고 ViewController는 'Transition에 필요한 추상화된 정보'를 그대로 Router로 넘기는 것이다. 그럴꺼면 애초에 Router가 ViewController가 아니라 Presenter와 상호작용 하는게 어떨까?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protocol Presenter {
    func presentSampleDetail(data: Data?)
}
 
protocol Router {
    func transition(from viewController: UIViewController, data: Data?)
}
 
protocol SampleRepresentable { }
 
class SamplePresenter: Presenter {
    var router: Router?
    var sampleRepresenter: SampleRepresentable?
    
    // data는 Interactor가 넘겨줄 것이다.
    func presentSampleDetail(data: Data?) {
        guard let viewController = sampleRepresenter as? UIViewController else { return }
        router?.transition(from: viewController, data: data)
    }
}
cs

 

 Router를 Presenter와 상호작용을 하도록, 위와같이 예제를 작성해보았다. 위의 간단한 예제를 작성하기 전에 Router와 상호작용 해야하는 Component가 Presenter 여야 할지, Interactor 여야 할지 고민이 되었다.

 

 Interactor는 이름이 온갖 역할을 다 해도 될것 같은 느낌을 준다(당연히 그러면 안된다). VIP Flow상 ViewController가 Interactor 무언가 요청하면, Interactor가 동작하고 필요에 따라 Presenter를 통해 ViewController가 갱신된다. 이때, Interactor는 presenter에 '무언가를 나타내줘'라고 요청하는 게 자연스럽다. 어떻게 보여줄지는 Interactor의 관심사가 아니다. 따라서 Presenter가 UILabel에 노출시킬 수 있는 단순한 문자열을 ViewController에 넘겨줄지, 다른 ViewController로 Transition하여 보여줄지 Interactor는 관심을 가져선 안된다고 판단했다.

 

 

2) Worker는 이해가 잘 안된다

: Worker같은 이름은 조심해서 쓸 필요가 있다고 생각한다. 'Manager라는 이름을 쓰지말자, 자제하자'와 비슷한 이유에서다. 아 그리고, hackernoon에 게시된 VIP 소개글을 읽을 때는 주의해서 읽는게 좋을 것 같다. Worker의 역할을, 마치 'Network나 내부 저장소에서 Data를 가져오는 Component'라고 오해하게끔 글을 적어놓았기 때문이다. 이건 조금만 생각해봐도 말이 안되는데, 성능상의 이유로 Network를 통해 가져온 Data를 내부 저장소에 Caching 해두는 시나리오를 생각해보자. 이때 Interactor가 Data를 요청한다면, Cached Data인지 확인해서 적절한 Worker에 요청해야 하는가? 당연히 그렇지 않을 것이다. Interactor는 Data가 필요할 뿐이지, 그게 Cached Data인지 Network로 요청해야 하는지에 대해서는 관심사가 아니기 때문이다(clean-swift에서 소개하는 VIP에서는 이렇게 적혀있지 않다).

 처음에는 Business Logic을 처리하는 Component를 Worker라고 굳이 명시해야 했는지 의문이 들었지만, VIP가 Clean Architecture를 참고하여 만든 Architecture라는 것을 떠올렸다. 아마도 VIP를 창조해낸 사람은, Interactor가 Model에 직접 의존하는 것을 가능한 막고 싶었던 것이겠지.

 

 

 

마무리하며

 VIP를 설명하는 글을 읽고, VIP는 현실의 일부 복잡한 문제들에 적용하기 어렵다는 생각이 들었다. 그냥 어떤 문제에서 잘 쓰일 수 있는 Solution인 것이다. 고민한 내용을 동료에게 공유하여, 현재 작업중인 Demo App 개편을 어떻게 할지 이야기를 나눠보아야 겠다. 아직 경력와 역량이 부족한 내가, 잘못 생각한 걸지도 모르기 때문이다.

 

 

 

Reference

- https://clean-swift.com/clean-swift-ios-architecture/

https://hackernoon.com/introducing-clean-swift-architecture-vip-770a639ad7bf

https://github.com/Clean-Swift/CleanStore

:
Posted by syjdev