최근에 Swift UI를 입문하게 되면서 정들었던 😍UIKit과 🥺RxSwift 를 떠나
Combine을 학습하면서 고민하게된 사연입니다.
UIKit은 위와같은 MVC 구조로 되어있어서
UIViewControlelr의 역활을 줄여주기 위해
위와같은 MVVM 패턴을 도입하여
비즈니스 로직
과View
를 분리 하였었습니다.
그럼 스유는 무엇을 기반으로 하고있을까요?
WWDC 2019 KeyNote (2:07:40 초 부터 보시면 좋아요) 를 한번 봐보죠
보고 오셨나용?
해당 영상에선 슬프게도 UIKit의 단점(뷰 코드가 길어)를 보완하여 반응형으로 해줄께 라고 하고있습니다.
자. 반응형입니다.
위 말처럼 SwiftUI는 값이 변경됨을 감지하게 해주는
@State
와@Binding
이 존재합니다.
즉 정말특별한 비즈니스 로직
이 필요 없는이상 더이상뷰모델을 필요
가 없어진거죠.
Model
이 업데이트 될 때View
에다가 반영하기 위해선View
를 참조해야 하는데,
아쉽게도 SwiftUI의 View는Struct
이기 때문에 참조할 수 없습니다.
그래서 컨테이너 라는 개념이 존재하는데 다음 시간에 다루도록 하겠습니다.
자 한번 생각 해볼께요 구조체 기반인 SwiftUI의 뷰 변화를 주기위해 @State 또는 @Binding
을 사용 해본다고 해보겠습니다.
자 뷰모델에 반응 시켜야 하는 상황이라면 그때또 Binding 혹은 PassthroughSubject<> 등을 이용해서
또 반응해주어야 합니다.
이상하지 않나요? 이미 반응해주고 있는데 또 반응하는것을 두어 사용해야 하는 점이요
반응 하더라도 양방향인 MVVM ...? 과연 옳을까요,
반응 하더라도 뷰보델이 더 가벼워 질순 없는 걸까요?
Swift UI는 단항향 플로우 기반인데 양방향 플로우로 만드는게 맞을까요?
그래서 새로운 패턴인 MVI 대해서 알아 보도록 해보겠습니다.
MVVM과 비슷한 아키텍쳐 패턴으로 단방향 데이터 흐름을 가진 패턴입니다.
View -> 사람이 액션~ -> intent -> 뷰모델에서 처리 -> 상태 변경 -> View 상태 반영
앱 상태를 나타내며, 상태 관리의 중심입니다.
struct AppState {
var count: Int = 0
}
사용자 인터랙션 혹은 뷰(외부)의 이벤트를 모델로 전달하는 역할을 합니다.
enum AppIntent {
case increment
case decrement
}
Intent 의 이벤트를 처리하고 상태를 업데이트 합니다
class AppViewModel: ObservableObject {
@Published private(set) var state = AppState()
func send(_ intent: AppIntent) {
switch intent {
case .increment:
state.count += 1
case .decrement:
state.count -= 1
}
}
}
뷰에 반영시 예시 코드 입니다.
struct ContentView: View {
@StateObject
private var viewModel = AppViewModel()
var body: some View {
VStack {
Text("Count: \(viewModel.state.count)")
.font(.largeTitle)
HStack {
Button(action: {
viewModel.send(.decrement)
}) {
Text("-")
.font(.largeTitle)
.padding()
}
Button(action: {
viewModel.send(.increment)
}) {
Text("+")
.font(.largeTitle)
.padding()
}
}
}
}
}
MVVM 은 input output 패턴으로 만들었다고 하여도
양방향 플로우가 불가능 한것이 아니며, 인풋을 구성할때도 따로 바인딩 할수있게 했어야 했기에
MVI 패턴인 단방향 플로우와의 차이점은 분명하다고 생각합니다.
데이터의 흐름이 단 향이라 정흐름을 이해하고 유지보수에 도움이 됩니다.
다만 변경되는 모든것들이intent
를 통해야 함으로 아무리 간단한 뷰라도
최소한intent
와model
이 필요합니다.
https://betterprogramming.pub/mvi-architecture-for-swiftui-apps-cff44428394