Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Archives
Today
Total
관리 메뉴

J

[SwiftUI] Source of Truth 본문

SwiftUI

[SwiftUI] Source of Truth

yujaehui 2024. 4. 29. 15:17

"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에 반영
        }
    }
}
  1. ParentView
    • counter는 Source of Truth이며, @State로 관리.
    • ChildView에 Binding으로 counter를 전달.
  2. ChildView
    • @Binding으로 전달받은 상태를 참조.
    • 버튼 클릭 시 counter를 증가시키고, Source of Truth에서 데이터가 업데이트됨.
  3. 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에 반영
        }
    }
}
  1. ParentView
    • @StateObject로 CounterViewModel을 초기화.
    • CounterViewModel은 count 상태를 관리하는 Source of Truth.
  2. ChildView
    • @ObservedObject로 CounterViewModel을 참조.
    • viewModel.count를 수정하면, Source of Truth에 반영됨.
  3. 자동 업데이트
    • count가 변경되면, SwiftUI가 ParentView와 ChildView의 UI를 다시 렌더링.

5. Source of Truth를 선택하는 가이드

요구사항 적합한 프로퍼티 래퍼
데이터가 단일 뷰에서만 사용됨 @State
데이터가 하위 뷰로 전달되어야 함 @Binding
여러 뷰에서 동일한 상태를 관찰해야 함 @StateObject, @ObservedObject
앱 전역에서 데이터를 공유해야 함 @EnvironmentObject, @Environment

6. Source of Truth를 명확히 유지하는 이유

  1. 데이터 일관성 보장
    • 단일 위치에서 데이터가 관리되므로, 불일치가 발생할 가능성 감소.
  2. 코드 가독성 향상
    • 데이터 흐름이 명확해져, 상태 변경 및 UI 업데이트의 원인을 쉽게 추적할 수 있음.
  3. 디버깅 용이성
    • 데이터 변경의 출처가 명확하므로 디버깅이 쉬움.