진행했던 UIkit 프로젝트에서의 환경은MVVM(Input/Output, Action) + RxSwift + Clean Architecture
를 적용했다.
SwiftUI 프로젝트에서도 동일하게MVVM(Input/Output, Action) + Combine + Clean Architecture
를 적용하면서
프로퍼티 관리에 대한 고민이 정말 많았다.
UIKit을 사용했을 땐 ViewController 내에서는 Component 와 ViewModel, DisposeBag
외엔 사용할 프로퍼티가 없었다.
그 이유는 ViewController에서 어떤 Event가 발생한 경우 ViewModel에 Input Action을
전달하여 로직이 작동하고 해당 로직을 통해 데이터의 변동이 일어날 경우 ViewController로
Output에 대한 Action을 전달하면 ViewController에서 해당 Action을 감지하여
컴포넌트 프로퍼티에 접근해 View를 업데이트 해주었기 때문이다.
나는 SwiftUI에서도 모든 프로퍼티를 ViewModel
의 Output
에서 관리해줘야겠다 라는
생각으로 옮기다가 View가 아닌 ObservableObject
를 채택한 Class 내에서 @Binding
혹은 @FocusState
등과 같은 프로퍼티 래퍼
를 관리할 수 없다 라는 것을 깨달았다.
그래서 뷰에서 일어나는 Action
과 데이터에 관련해서 바인딩
해야 하는 Action에 대해 일관성
을
유지하기 위해 아래 ViewType
이라는 Protocol
을 정의해서 View에 적용해본 결과 이 경우도
실패라는 판단이 내려졌다. 그 이유 또한 구조체로 사용될 ViewOutput
이 View 프로토콜을
채택하고 있지 않아 위와 동일하게 @Binding
혹은 @FocusState
등과 같은 프로퍼티 래퍼
를
관리해줄 수 없기 때문이었다.
protocol ViewType where Self: View {
associatedtype ViewInput
associatedtype ViewOutput
associatedtype ViewAction
var viewInput: ViewInput { get }
var viewOutput: ViewOutput { get }
var cancellable: Set<AnyCancellable> { get }
func transform()
func viewAction(_ action: ViewAction)
}
이런식으로 이 프로퍼티들을 어떻게 관리해주는 것이 좋을까? 라는 고민을 계속 하다보니
문득, 나는 왜 계속 이 ViewModel
에 끼워맞추며 고집하고있는거지?
라는 생각이 들기 시작했다.
물론 코드의 양이 많아질수록 모듈화는 피할 수 없지만 굳이 ViewModel을 사용하면서까지
억지로 끼워맞출 필요는 없지 않을까 라는 생각과 동시에 좀 더 효율적으로 프로퍼티와 바인딩을
관리할 수 있는 구조가 뭐가 있을까 라는 고민이 생겼다.