J
[SwiftUI] Source of Truth 본문
"Source of Truth"는 데이터의 유일하고 신뢰할 수 있는 저장 위치를 의미.
SwiftUI와 같은 선언적 UI 프레임워크에서 특히 중요한 개념.
애플리케이션이 데이터 상태를 관리하고 UI와 동기화하는 방식을 결정하는 핵심 요소.
1. Source of Truth란?
정의
- Source of Truth는 애플리케이션 내에서 특정 데이터의 상태를 관리하는 유일한 위치.
- 다른 모든 데이터 뷰나 컴포넌트는 이 Source of Truth를 기반으로 데이터를 읽거나 수정.
- 데이터의 일관성과 동기화를 보장.
예시
@State, @Binding, @StateObject, @ObservedObject 등을 사용 시, Source of Truth는 데이터 상태가 실제로 저장된 위치.
2. SwiftUI에서 Source of Truth
SwiftUI는 선언적 UI 프레임워크로, 데이터 상태와 UI가 동기화되어야 함.
Source of Truth는 이 동기화를 효과적으로 관리하는 데 사용 됨.
주요 프로퍼티 래퍼와 Source of Truth
SwiftUI에서 상태 관리를 위한 여러 도구들은 Source of Truth의 역할을 명확히 구분
프로퍼티 래퍼 | 역할 | Source of Truth 여부 |
@State | 개별 뷰의 상태를 관리. 해당 뷰에서만 데이터 상태를 소유. |
Yes |
@Binding | 다른 뷰에서 전달받은 상태에 대한 참조를 제공. 실제 Source of Truth는 전달받은 뷰에서 관리. |
No |
@StateObject | ObservableObject를 생성하고 해당 객체를 뷰 계층에서 Source of Truth로 사용. | Yes |
@ObservedObject | 상위 뷰에서 전달받은 ObservableObject를 관찰. 실제 Source of Truth는 상위 뷰에서 관리. |
No |
@Environment | 앱 환경 설정이나 공통적으로 사용하는 상태를 관리. 전달받은 환경 값은 Source of Truth가 아님. |
No |
3. Source of Truth의 원칙
1. 단일 책임
- 데이터를 관리하는 Source of Truth는 하나의 책임만 가짐.
- 여러 Source of Truth가 동일 데이터를 관리하면 데이터 불일치 문제가 발생할 수 있음.
2. 데이터 소유자
- 데이터의 소유자는 특정 데이터의 생성 및 수정을 책임.
- SwiftUI에서 데이터의 소유자는 @State나 @StateObject를 사용하는 뷰.
3. 데이터 전달
- 하위 뷰는 Source of Truth를 직접 소유하지 않고, @Binding이나 @ObservedObject를 통해 데이터를 참조.
- 이를 통해 데이터는 단일 Source of Truth에서 관리되며, 데이터 흐름이 명확해짐.
4. 예제
기본 예제: @State와 @Binding
struct ParentView: View {
@State private var counter: Int = 0 // Source of Truth
var body: some View {
VStack {
Text("Counter: \\(counter)")
ChildView(counter: $counter) // Binding을 통해 참조 전달
}
}
}
struct ChildView: View {
@Binding var counter: Int // Source of Truth를 참조
var body: some View {
Button("Increment") {
counter += 1 // Source of Truth에 반영
}
}
}
- ParentView
- counter는 Source of Truth이며, @State로 관리.
- ChildView에 Binding으로 counter를 전달.
- ChildView
- @Binding으로 전달받은 상태를 참조.
- 버튼 클릭 시 counter를 증가시키고, Source of Truth에서 데이터가 업데이트됨.
- SwiftUI의 자동 업데이트
- counter 값이 변경되면 SwiftUI가 자동으로 UI를 다시 렌더링.
복합 예제: @StateObject와 @ObservedObject
class CounterViewModel: ObservableObject {
@Published var count = 0 // Source of Truth
}
struct ParentView: View {
@StateObject private var viewModel = CounterViewModel() // Source of Truth
var body: some View {
VStack {
Text("Count: \\(viewModel.count)")
ChildView(viewModel: viewModel)
}
}
}
struct ChildView: View {
@ObservedObject var viewModel: CounterViewModel // Source of Truth를 참조
var body: some View {
Button("Increment") {
viewModel.count += 1 // Source of Truth에 반영
}
}
}
- ParentView
- @StateObject로 CounterViewModel을 초기화.
- CounterViewModel은 count 상태를 관리하는 Source of Truth.
- ChildView
- @ObservedObject로 CounterViewModel을 참조.
- viewModel.count를 수정하면, Source of Truth에 반영됨.
- 자동 업데이트
- count가 변경되면, SwiftUI가 ParentView와 ChildView의 UI를 다시 렌더링.
5. Source of Truth를 선택하는 가이드
요구사항 | 적합한 프로퍼티 래퍼 |
데이터가 단일 뷰에서만 사용됨 | @State |
데이터가 하위 뷰로 전달되어야 함 | @Binding |
여러 뷰에서 동일한 상태를 관찰해야 함 | @StateObject, @ObservedObject |
앱 전역에서 데이터를 공유해야 함 | @EnvironmentObject, @Environment |
6. Source of Truth를 명확히 유지하는 이유
- 데이터 일관성 보장
- 단일 위치에서 데이터가 관리되므로, 불일치가 발생할 가능성 감소.
- 코드 가독성 향상
- 데이터 흐름이 명확해져, 상태 변경 및 UI 업데이트의 원인을 쉽게 추적할 수 있음.
- 디버깅 용이성
- 데이터 변경의 출처가 명확하므로 디버깅이 쉬움.
'SwiftUI' 카테고리의 다른 글
[SwiftUI] NavigationView vs NavigationStack (0) | 2024.05.09 |
---|---|
[SwiftUI] SwiftUI의 View Rendering (0) | 2024.05.08 |
[SwiftUI] ViewModifier, modifier(_:) (0) | 2024.05.03 |
[SwiftUI] @State와 @Binding의 projectedValue ($) (0) | 2024.04.29 |
[SwiftUI] @State, @Binding (0) | 2024.04.29 |