SwiftUI - TCA MultiStore

CodeCat·2024년 9월 12일

IOS SwiftUI TCA

목록 보기
19/20
post-thumbnail

안녕하세요 !

이번에는 TCA MultiStore 라는 주제로 포스팅해보겠습니다

MultiStore 패턴의 개념, 구현 방법, 그리고 실제 사용 사례를 통해 이 패턴이 어떻게 앱의 구조를 개선하고 유지보수성을 높이는지 알아보도록해요~~~

MultiStore 패턴?

MultiStore 패턴은 TCA에서 여러 개의 독립적인 스토어를 사용하여 앱의 상태를 관리하는 방식이고 이 패턴은 큰 규모의 앱에서 특히 유용하며, 코드의 모듈화와 재사용성을 높이는 데 도움이 됩니다

MultiStore의 장점

  1. 모듈화: 각 기능을 독립적인 스토어로 분리하여 관리할 수 있음
  2. 성능 향상: 필요한 부분만 업데이트되므로 전체 앱의 성능이 개선
  3. 테스트 용이성: 각 스토어를 독립적으로 테스트할 수 있음
  4. 유지보수성: 코드의 구조가 명확해져 유지보수가 쉬움

MultiStore 구현하기

예시 - 사용자 프로필과 설정을 관리하는 두 개의 스토어를 만들어 볼게요

struct ProfileState: Equatable {
    var name: String = ""
    var age: Int = 0
}

enum ProfileAction {
    case setName(String)
    case setAge(Int)
}

let profileReducer = Reducer<ProfileState, ProfileAction, Void> { state, action, _ in
    switch action {
    case let .setName(name):
        state.name = name
        return .none
    case let .setAge(age):
        state.age = age
        return .none
    }
}

struct SettingsState: Equatable {
    var isDarkMode: Bool = false
    var notificationsEnabled: Bool = true
}

enum SettingsAction {
    case toggleDarkMode
    case toggleNotifications
}

let settingsReducer = Reducer<SettingsState, SettingsAction, Void> { state, action, _ in
    switch action {
    case .toggleDarkMode:
        state.isDarkMode.toggle()
        return .none
    case .toggleNotifications:
        state.notificationsEnabled.toggle()
        return .none
    }
}

이제 이 두 스토어를 결합하여 앱의 전체 상태를 관리하는 AppState를 만들어 보겠습니다

struct AppState: Equatable {
    var profile: ProfileState
    var settings: SettingsState
}

enum AppAction {
    case profile(ProfileAction)
    case settings(SettingsAction)
}

let appReducer = Reducer<AppState, AppAction, Void>.combine(
    profileReducer.pullback(
        state: \.profile,
        action: /AppAction.profile,
        environment: { _ in () }
    ),
    settingsReducer.pullback(
        state: \.settings,
        action: /AppAction.settings,
        environment: { _ in () }
    )
)

이렇게 구성된 MultiStore 패턴을 사용하면, 각 기능별로 독립적인 상태 관리가 가능해집니다

예를 들어, 프로필 화면에서는 ProfileState만 사용하고, 설정 화면에서는 SettingsState만 사용할 수 있습니다

예시

실제 뷰에서 사용하는 방법

struct ProfileView: View {
    let store: Store<ProfileState, ProfileAction>

    var body: some View {
        WithViewStore(self.store) { viewStore in
            VStack {
                TextField("Name", text: viewStore.binding(
                    get: \.name,
                    send: ProfileAction.setName
                ))
                Stepper("Age: \(viewStore.age)", value: viewStore.binding(
                    get: \.age,
                    send: ProfileAction.setAge
                ))
            }
        }
    }
}

struct SettingsView: View {
    let store: Store<SettingsState, SettingsAction>

    var body: some View {
        WithViewStore(self.store) { viewStore in
            Form {
                Toggle("Dark Mode", isOn: viewStore.binding(
                    get: \.isDarkMode,
                    send: SettingsAction.toggleDarkMode
                ))
                Toggle("Notifications", isOn: viewStore.binding(
                    get: \.notificationsEnabled,
                    send: SettingsAction.toggleNotifications
                ))
            }
        }
    }
}

다음 포스팅에서는 다른 예시들을 보면서 좀 더 자세히 알아보겠습니다

이상으로 포스팅 마무리 하겠습니다.

.
.
.

감사합니다.

profile
코드와 고양이의 만남

0개의 댓글