Design Pattern

Eli·2021년 2월 8일
3

Design Pattern

목록 보기
1/2

디자인 패턴은 개발에 있어서 일반적으로 발생하는 문제를 재사용 가능한 코드로 해결하는 솔루션들이다.
뭐 넓은 의미에서 있어서는 이런 의미를 지니겠고 어떤 수준에서 보느냐에 따라 많은 디자인 패턴이 존재한다.

iOS 아키텍처에 있어서는 일반적으로 View, Model, Business Logic들을 어떤 관계를 어디에 두면서 맺어줄지에 대해서 고민하는 것이다.

앞으로 다룰 대표적으로 많이 사용되고 지지를 받아오는 Pattern들이 있다.
이 밖에도 수 많은 디자인 패턴들이 있음을 잊지 말아야 하며, 정답도 없는 내용들이다.
어떤 제품에선 적합한 패턴들이 있을 수 있고 그렇지 않을 수도 있다.
그러므로 우리가 만들어가는 제품에 가장 적합한 패턴을 도입해야하며, 어쩌면 새로운 패턴을 만들어 낼 수도 있다.
또 이런저런 패턴을 섞어가면서 쓸 수도 있음을 인지해야한다.

MVC (Model - View - Controller or Massive View Controller)

일단 iOS 의 기본적인 패턴은 MVC 패턴을 염두에 두고 설계가 되어있고 많은 부분들이 mvc로 구현이 되어있다.

여러 코드들을 예시로 쉽게 볼 수 있지만 위의 요소로 볼 수 있다.
Model: 비즈니스 로직들을 담고 있으며, 데이터들을 주로 다룬다.
View: 화면 요소를 들고 있으며, UIView로 구성이 되어 있다. (Interface Builder를 사용하는 유저라면 Stroyboard가 되겠다)
Controller: Model과 View를 제어해 적당한 시점에 모델에서 데이터를 불러와 View에 반영해주는 방식이다.

각각 요소들이 소통하는 방식에 제한이 어느정도 있는데, 간단히만 정리를 한다.

View ↔ Controller

  1. Controller > View를 직접 들고 있어 곧바로 전달을 하게 되어 직접 제어를 한다.
  2. View > Controller 는 IBOutlet or IBAction 등으로 소통을 하는 방식이 된다.

Model ↔ Controller

  1. Model > Controller 기본적으로 모델은 컨트롤러에게 직접적으로 접근할 수 없는게 룰이며, Notification이나 Delegate Pattern을 이용해 대화를 한다.
  2. Controller > Model는 직접 들고있어 곧장 호출하거나 접근 할 수 있어 특이한게 없다.

매우 간단한 구조이며, 어느정도의 룰이 있긴 하나 위에서 읽어봐서 간단하게 느낄 수 있겠지만 Controller의 역할이 막중하다. 정말 Controller가 다 한다.

그렇기에 너무 많은 코드들이 Controller에 위치해 Massive ViewController라는 말이 생겨났다는....

아마 애플에서도 초기 설계시점에 앱의 생태계나 구현되는 UI들이 이리 복잡해질 줄은 몰랐겠지...

이 문제 역시도 애플에서 인지하고 Swift UI + Combine 결합이 생기면서 어느정도 해결을 하려고 했던 것 같다.

MVP (Model - View - Presenter)

아마 MVC의 비대함과 길어지는 코드들을 해결하기 위해서 고안된 파생 구조인 것 같다.

View: View + Controller로 생각을 하면 된다.

Presenter: 비즈니스 로직과 보여지는 값들을 관리 한다.

Model: 기존의 모델과 동일

MVP의 목적은 굉장히 간단해 보인다.

기존에 우리가 MVC라는 녀석을 많이 사용하면서 문제로 지적되어 왔던 거대한 Controller의 무게를 Presenter를 만들어 나누자는 취지 같아 보인다.

간단한 예로는 아래정도의 코드로 정리할 수 있을 것 같다.

Simple MVP Design Pattern in Swift

보면 위의 MVC에 비해 한결 간결해진 모습을 가질 수 있는 것 같다.
모든 책임을 Presenter로 넘겨버려 View의 역할이 굉장히 작아진다.
Massive View Controller를 탈출한다는 얘기.

단점이라면 Presenter와 View의 관계를 맺어주는 과정에 있어서 많은 코드가 필요하다 정도 인 것 같다.

MVVM ( Model - View - ViewModel)

디자인 패턴을 고민하는 많은 iOS 개발자들에게 선택받는 디자인패턴이 아닐 까 싶다.
그러나 다른 MVx 패턴과는 조금 다르게 Rx를 함께 해야 제대로된 구현이 가능하다.
그래서 러닝커브가 다른 아키텍처를 도입할 때 보다 높다고 볼 수 있다.

그렇지만 그만큼 코드를 나누고 유지보수 가능한 데에 있어서 상당한 이점이 있는 것으로 보여진다.

이제 내용을 보자.

크게 구성요소는 다른 MVx와 비슷하게 3가지 요소로 구성이 된다.

Model: 기존 MVx과 같은 역할을 하게 된다.

View: UIView와 UIViewController 가 이에 해당을 하는데 뷰 구성들을 모두 들고 있다. 또 ViewModel을 소유하며 바인딩 코드를 통해 View에 반영해준다.

View Model: 데이터를 보여주기 위한 로직과 데이터를 가지고 있다. 특징이란 것이 데이터의 state를 가진다는 것이다.

뭐 위처럼 설명을 했지만 가장 큰 점은 값의 상태변화에 따른 바인딩이 가장 큰 컨셉으로 보여질 수 있다.

이를 통해 비슷한 화면의 ViewModel이라면 View에 따라 매번 ViewModel을 생성하는 게 아니라 다른 화면에서도 재사용을 할 수 있을 것이다.

또한 View 바인딩이라는 적당한 책임을 부여해주는 것 역시 한 몫을 한다고 본다.

위의 바인딩이라는 과정에서 RxSwift의 필요성이 굉장히 커지는데, 기본 iOS에서 사용하려면 Notification 또는 KVO 같은 내용을 사용해야 한다. (그럴바엔 MVVM 안쓰고 만다)

크게 특징을 나누어 본다면

  1. 적당한 요소간 책임 분리
  2. View Model의 재사용 가능성
  3. 더 적은 코드
  4. 로직과 뷰의 분할로 테스트 용이성 상승

위의 정도로 보며, 많은 개발자들이 선택하는 이유가 되는 것 같다.

좀 단점이 있다면 Massive를 탈출하기 위함이었지만 View Model이 비대해질 수 있다는...

Viper

우리가 기존에 봐 왔었던 MVx 패턴들을 대체하기 위해서 구현된 디자인 패턴으로 조금 더 많은 책임 분산으로 나뉘어져 있다.

크게 5개의 요소들로 나뉘어져 있으며, 구조는 아래와 같다.

그림이 이전의 MVx들과 비교해 굉장히 많이 쪼개져 있다.

View: MVP 와 동일한 정말 View만을 담당한다.

Interactor: Use case에 따라 데이터를 조작

Presenter: Interactor에서 데이터를 가져오고, 뷰로부터의 사용자 입력 처리, 뷰에서 보여줄 내용을 정리

Entities: 단순 프로퍼티를 정의하는 모델

Router: 화면을 넘어가는 Navigation 영역을 담당한다.

아무래도 MVx 패턴과 조금 찢어지다 보니 예시 코드들을 보아가면서 해야 이해가 가능할 듯 하다.

VIPER-Architecture for iOS project with simple demo example.

위에 코드들을 보면 알겠지만 분리로서 MVVM에 View Model에 해당 하는 내용이 상당부분이 더 나뉘었으며, Router를 통해서 어디에 둘지 모르는 segue 관리까지 할 수 있다.

Viper에 대해서 느낀점이라면 더 세분화된 책임으로 책임에 따른 코드 나눔이 명확하다는 것이다.

또한 영역별로 기능별로 Test가 든다는 점.

단점은 역시 보다시피 한 화면 기능을 만드는데 5개나 되는 파일을 만들어야 한다는 점....

이것을 관리하고 유지시키는데 또 처음 구축할 때 역시도 기능에 따라 오버헤드가 발생하는 느낌을 받게 될 예정이다.

뭐 아래와 같이 어느정도 기능에 따라 템플릿화 시켜서 생성해주는 도움을 받아 수고를 더는 방법도 있긴하다.

strongself/Generamba

그래도 일반적인 단순한 리스트나 뷰가 위주인 서비스에 적합하기 보단 서비스 복잡도가 높아 이렇게 관리하지 않으면 안될 서비스에 적합해 보인다. (아마 필요성을 느끼는 개발자가 찾지 않을까 싶다 ...)

ReactorKit

사실 ReactorKit의 내용은 디자인 패턴이라기 보단 프레임워크이다.

프레임 워크로 Reactor라는 프로토콜을 따라 일련된 패턴들을 적용시키기에 적합하다.

RxSwift를 기반에 두어 Rx를 시작하는데에도 조금은 쉽게 쓸 수 있는 예시들을 제공한다.

기존 MVVM과 RxSwift의 조합은 상태 관리가 쉽지 않다. 초기화 값을 위해 꼭 BehaviorSubject를 엄청 사용하게되는데 이게 맞나 싶기도 하고, Binding 시점에 이게 View에 있어야 할 코드인가? View Model에 있어야하는 코드인가? 하는 문제 점도 있었는데 구현해야하는 함수를 프로토콜로 강제하면서 이런 문제를 해결해주는 듯 한다.

가장 큰 컨셉은 반응형 단방향 앱을 구현하는 것 입니다.

가장 좋은 문서는 저자의 글을 조회하는게 가장 좋을 것 같다.

국내 개발자가 개발을 해, 한국어 자료가 많고 국내 기업에서도 많이 도입되어 있다는 점도 장점으로 꼽을 수 있을 것 같다.

ReactorKit 시작하기

기본적인 컨셉으로

View는 Action을 Reactor로 전달을 하고

Reactor 내의 mutate()에서 비즈니스 로직을 처리
Reactor 내의 reduce()에서 보여질 수 있는 데이터로 처리

후에 State를 업데이트 하는 일관성 있는 단방향 처리가 가능해 굉장히 심플하게 구현이 가능하다는게 큰 장점으로 보인다.

아마 이번 테스트 모앱은 Reactor Kit으로 작업을 해보지 싶어 모앱 모델링이나 설계부분에서 더 자세히 다뤄보려고 한다.

profile
애플을 좋아한다. 그래서 iOS 개발을 한다. @Kurly

0개의 댓글