WooKoo Blog

물과 같이

개발/개발

[iOS] - MVVM 아키텍처 개선해보기

WooKoo 2022. 6. 29. 23:13

 

요즘 너무 바빠서 글 정리를 자주 못올렸네요

 

오늘은 포카마켓 iOS 팀에서 사용하고 있는 아키텍쳐 개선에 대해서 정리해보려고합니다.

 

우선 저희 iOS 팀은 아키텍쳐로 MVVM과 일부 ReactorKit을 사용하고 있습니다.

 

MVVM은 회사마다 모두 조금씩은 다르게 사용하고 있는 것으로 알고 있고

 

MVVM 예제들을 많이 찾아봐도 조금씩은 다르게 사용하고 있었습니다.

(모든 아키텍쳐가 조금씩은 회사마다 다르겠지만요 :] )

 

저희는 ViewModel을 설계 할 때 흔이 알고 계시는 input output 프로토콜을과 ViewModelType 프로토콜을 사용해서

 

ViewModel을 설계했었습니다.

 

많이들 이렇게 사용하는 것으로 알고있는데 예제로 한번 보시죠

 

protocol FirstViewModelType {
	var input: FirstViewModelInput { get }
    var output: FirstViewModelOut { get }
}
protocol FristViewModelInput {

}
protocol FirstViewModelOut {

}
final class FirstViewModel: FirstViewModelIntput, FirstViewModelOutput {

}
extension FirstViewModel: FirstViewModelType {
    var input: FristViewModelInput { self }
    var output: FristViewModelOutput { self }
}

 

즐겨쓰는 방법입니다.

 

ViewController와 ViewModel 간에 어떠한 이벤트를 주고 받을 때 input과 output의 변수로

단방향적인 흐름으로 개발을 할 수 있어서 즐겨 사용했습니다.

 

사용하다보니 불편했던 점들이 있어서 정리해보며 개선한 뷰모델을 설명해드리겠습니다.

 

문제점

1. input, output 의 명칭

뷰모델에서 어떠한 액션이 일어났을 때 input이라는 의미가 명확하게 맞을까요??

어떤 뷰모델의 값이 변경되었을 때 우리는 viewmodel.output.xxxx 를 구독하는데요 정말로 output의 의미가 맞을까요??

 

2. ViewModelType 이라는 프로토콜의 명칭

저희는 뷰모델을 추상화한 프로토콜을 사용하려고하는데 ViewModelType이 맞을까요??

 

3. 위 구조를 작성하면서에 대한 불편함

너무 많은 프로토콜을 만들어주어야하고 채택해주어야했고 코드가 길었습니다.

 

 

위 같은 문제점들을 느끼고 새로운 방식의 ViewModel을 만들어보았습니다.

(답은 리액터킷과 비슷한 구조로 ViewModel을 설계하는 것 이었습니다.)

 

protocol FirstViewModelProtocol {
	// Action
  func handleAction(_ action: FirstViewModelAction)
 	// State
  var state: FirstViewModelState { get }
}
enum FirstViewModelAction {

}

struct FirstViewModelState {

}

final class FirstViewModel: FirstViewModelProtocol {

  func handleAction(_ action: FirstViewModelAction) {
    
    switch action {
    }
    
  }

  var state = FirstViewModelState()
  
}

리액터킷과 비슷한 구조로 설계해서 리액터킷과 뭐가 다르냐고 생각하실 수 도 있습니다만

리액터킷은 Action과 State가 많아질 경우 확장하기가 조금 까다로웠습니다.

 

문제점 개선

1. input, output 의 명칭

input은 handleAction의 Enum으로 output은 State로 변경하여 좀 더 명확하게 이름을 수정해서 사용할 수 있었습니다.

어떤 이벤트가 발생해서 viewModel에게 요청 시 Action을 핸들링한다는 느낌의 이름과 State라는 이름의 변수들을 구독하여

좀 더 바인딩해서 사용하는 느낌이 확 와닿도록 말이죠

 

2. ViewModelType 이라는 프로토콜의 명칭

보통 프로토콜의 이름은 xxxxProtocol로 짓기 마련입니다.

xxxxType의 프로토콜의 경우는 클래스 자체가 타입이 되는 경우?에 많이 사용한다고 하네요.

그래서 왠만하면 프로토콜의 명칭은 프로토콜로 사용하는게 좋아보여서 수정했습니다.

 

3. 위 구조를 작성하면서에 대한 불편함

기존에는 인풋, 아웃풋, 타입, 채택하기위한 extension 까지 총 4가지를 만들어줬었는데

이렇게 MVVM을 설계하면 비슷하지만 좀 더 짧게 작성할 수 있다는 점이 편했던 것 같습니다.

또한 구현체인 ViewModel 클래스에서 Switch 문을 통해 정리된 느낌도 받을 수 있었구요.

 

ReactorKit에서 영감을 많이 받아서 수정해보았는데

ReactorKit은 뭔가 Reactor 안에서 갖혀서 개발한다는 느낌을 받았던 반면

이렇게 뷰모델을 설계하니 좀 더 개방되고 정돈된 느낌으로 뷰모델을 작성할 수 있었던 것 같아서

좋은 경험이었던 것 같습니다.