목적
TCA Store를 보유한 SwiftUI View에서 Store 이외의 @State가 화면 역할과 관계없이 함께 관리되는 구조를 정리한다.
NavigationStack의 경로는 NavigationRouter가 소유하고, sheet와 push 목적지처럼 사용자 동작에 따라 표시되는 상태는 Feature의 State와 Action이 소유한다. 스크롤 측정처럼 렌더링에만 필요한 일시 상태는 View에 남긴다.
조사 범위와 기준
Application, Libraries, Widget의 운영 Swift 소스에서 StoreOf 또는 Store(initialState:)를 사용하는 View 전수 검색
- 같은 View 타입에 선언된 Store 이외의
@State만 집계
- 같은 파일의 다른 하위 View 상태는 해당 타입 기준으로 분리
- Store 자체를
@State로 보관하는 TCA Observation 패턴은 집계에서 제외
NavigationRouter를 보관하는 @State는 탐색 경로 소유 방식으로 인정
@FocusState, @Environment, @ScaledMetric은 이번 집계에서 제외
조사 결과 Store 이외의 로컬 @State는 7개 View의 10개 속성이다.
상태 소유 기준
NavigationRouter가 소유할 경로
NavigationStack(path:)에 전달하는 경로와 push, pop 조작은 View가 보유한 NavigationRouter를 통해 처리한다. 경로 배열을 Feature State로 옮기거나 새로운 TCA stack 탐색 구조를 도입하지 않는다.
Store가 소유할 표시 상태
View의 직접 대입을 Feature Action으로 바꾸고, sheet와 navigationDestination은 Store 상태에 연결한다.
GoalDetailView의 recordEditor, todoLinkSheet, recordDetail, todoDetail 연결은 Store가 presentation 상태를 소유하는 현재 기준으로 유지하며 구현 참고 대상으로 사용한다.
View에 유지할 렌더링 상태
두 상태는 스크롤 위치에 따른 헤더 배치와 추적 제어에만 사용되므로 View에 유지한다.
작업 범위 및 완료 조건
기존 이슈와의 관계
- #879부터 #884는 현재 탐색 경로 소유권을 유지하는 조건으로 View 구성 요소 분리를 다룬다.
- 이 이슈는 View 분리와 별개로
NavigationRouter, Store, View 사이의 상태 소유권을 정리한다.
- 같은 파일을 수정할 경우 #879부터 #884의 구현과 충돌하지 않도록 착수 순서를 조율한다.
- 기존 이슈 본문은 이 이슈 변경만으로 수정하지 않는다.
제외 범위
- 모든
@State의 일괄 제거
NavigationStack 경로를 Feature State로 이전
StackState, StackAction, NavigationStackStore 도입
NavigationRouter의 공개 계약이나 전체 구조 변경
HomeView.searchStore, ProfileView.settingsStore의 생명 주기 재구성
@FocusState, geometry 측정값, 애니메이션 진행값을 근거 없이 Feature로 이전
- UI 디자인과 탐색 결과 변경
- 관련 없는 View 또는 Feature 정리
검증
- 영향받는 Feature 단위 테스트
DevLog.xcworkspace의 App 스킴 build-only
- 실제 탐색 제스처와 presentation 동작 검증은 별도 실행 허용 후 수행
목적
TCA
Store를 보유한 SwiftUIView에서 Store 이외의@State가 화면 역할과 관계없이 함께 관리되는 구조를 정리한다.NavigationStack의 경로는NavigationRouter가 소유하고, sheet와 push 목적지처럼 사용자 동작에 따라 표시되는 상태는 Feature의State와Action이 소유한다. 스크롤 측정처럼 렌더링에만 필요한 일시 상태는 View에 남긴다.조사 범위와 기준
Application,Libraries,Widget의 운영 Swift 소스에서StoreOf또는Store(initialState:)를 사용하는 View 전수 검색@State만 집계@State로 보관하는 TCA Observation 패턴은 집계에서 제외NavigationRouter를 보관하는@State는 탐색 경로 소유 방식으로 인정@FocusState,@Environment,@ScaledMetric은 이번 집계에서 제외조사 결과 Store 이외의 로컬
@State는 7개 View의 10개 속성이다.상태 소유 기준
NavigationRouter가 소유할 경로
TodayView.path를NavigationRouter<TodayRoute>로 이전HomeView.path를NavigationRouter<HomeRoute>로 이전SearchView.router는 현재 기준 유지ProfileView.path를NavigationRouter<ProfileRoute>로 이전NavigationStack(path:)에 전달하는 경로와 push, pop 조작은 View가 보유한NavigationRouter를 통해 처리한다. 경로 배열을 FeatureState로 옮기거나 새로운 TCA stack 탐색 구조를 도입하지 않는다.Store가 소유할 표시 상태
HomeView.goalPresentation을HomeFeature의 presentation 상태로 이전RecordDetailView.isEditorPresented를RecordDetailFeature의 presentation 상태로 이전RecordDetailView.isHistoryPresented를RecordDetailFeature의 push 목적지 상태로 이전RecordVersionHistoryView.destination을RecordDetailFeature의 push 목적지 상태로 이전View의 직접 대입을 Feature
Action으로 바꾸고, sheet와navigationDestination은 Store 상태에 연결한다.GoalDetailView의recordEditor,todoLinkSheet,recordDetail,todoDetail연결은 Store가 presentation 상태를 소유하는 현재 기준으로 유지하며 구현 참고 대상으로 사용한다.View에 유지할 렌더링 상태
TodoListView.headerOffsetTodoListView.isScrollTrackingEnabled두 상태는 스크롤 위치에 따른 헤더 배치와 추적 제어에만 사용되므로 View에 유지한다.
작업 범위 및 완료 조건
TodayView,HomeView,ProfileView의 경로 배열을NavigationRouter로 통일SearchView의 기존NavigationRouter동작 유지Action으로 전달navigationDestinationAPI에 연결기존 이슈와의 관계
NavigationRouter, Store, View 사이의 상태 소유권을 정리한다.제외 범위
@State의 일괄 제거NavigationStack경로를 FeatureState로 이전StackState,StackAction,NavigationStackStore도입NavigationRouter의 공개 계약이나 전체 구조 변경HomeView.searchStore,ProfileView.settingsStore의 생명 주기 재구성@FocusState, geometry 측정값, 애니메이션 진행값을 근거 없이 Feature로 이전검증
DevLog.xcworkspace의App스킴 build-only