From b51d643db8d38afefff556093fb38bbdf78fc861 Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Wed, 18 Mar 2026 11:28:22 +0900 Subject: [PATCH] =?UTF-8?q?feat(home):=20=ED=99=88=20=ED=83=AD=20=EC=A7=80?= =?UTF-8?q?=EC=97=B0=20=EB=A1=9C=EB=94=A9=20=EB=B0=8F=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=20=EC=9C=A0=EC=A7=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SodaLive/Sources/Main/Home/HomeView.swift | 40 ++++++++++++++------- docs/20260318_홈탭초기지연로딩및상태유지.md | 19 ++++++++++ 2 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 docs/20260318_홈탭초기지연로딩및상태유지.md diff --git a/SodaLive/Sources/Main/Home/HomeView.swift b/SodaLive/Sources/Main/Home/HomeView.swift index b6dbba7..5f71a48 100644 --- a/SodaLive/Sources/Main/Home/HomeView.swift +++ b/SodaLive/Sources/Main/Home/HomeView.swift @@ -40,24 +40,31 @@ struct HomeView: View { @State private var pendingExternalNavigationAction: (() -> Void)? = nil @State private var pendingExternalNavigationCancelAction: (() -> Void)? = nil @State private var payload = Payload() + @State private var loadedTabs: Set = [AppState.shared.startTab] var body: some View { GeometryReader { proxy in ZStack(alignment: .bottom) { VStack(spacing: 0) { ZStack { - homeTabView - .frame(width: viewModel.currentTab == .home ? proxy.size.width : 0) - .opacity(viewModel.currentTab == .home ? 1.0 : 0.01) - - liveView - .frame(width: viewModel.currentTab == .live ? proxy.size.width : 0) - .opacity(viewModel.currentTab == .live ? 1.0 : 0.01) - - chatTabView - .frame(width: viewModel.currentTab == .chat ? proxy.size.width : 0) - .opacity(viewModel.currentTab == .chat ? 1.0 : 0.01) - + if loadedTabs.contains(.home) { + homeTabView + .frame(width: viewModel.currentTab == .home ? proxy.size.width : 0) + .opacity(viewModel.currentTab == .home ? 1.0 : 0.01) + } + + if loadedTabs.contains(.live) { + liveView + .frame(width: viewModel.currentTab == .live ? proxy.size.width : 0) + .opacity(viewModel.currentTab == .live ? 1.0 : 0.01) + } + + if loadedTabs.contains(.chat) { + chatTabView + .frame(width: viewModel.currentTab == .chat ? proxy.size.width : 0) + .opacity(viewModel.currentTab == .chat ? 1.0 : 0.01) + } + if viewModel.currentTab == .mypage { MyPageView() } @@ -183,6 +190,8 @@ struct HomeView: View { } } .onAppear { + markTabAsLoaded(viewModel.currentTab) + payload.applicationId = BOOTPAY_APP_ID payload.price = 0 payload.pg = "다날" @@ -197,6 +206,9 @@ struct HomeView: View { viewModel.addAllPlaybackTracking() } } + .valueChanged(value: viewModel.currentTab) { currentTab in + markTabAsLoaded(currentTab) + } if appState.isShowNotificationSettingsDialog { NotificationSettingsDialog() @@ -525,6 +537,10 @@ struct HomeView: View { self.viewModel.pushTokenUpdate(pushToken: pushToken) } } + + private func markTabAsLoaded(_ tab: HomeViewModel.CurrentTab) { + loadedTabs.insert(tab) + } } extension Notification.Name { diff --git a/docs/20260318_홈탭초기지연로딩및상태유지.md b/docs/20260318_홈탭초기지연로딩및상태유지.md new file mode 100644 index 0000000..6d2cdb3 --- /dev/null +++ b/docs/20260318_홈탭초기지연로딩및상태유지.md @@ -0,0 +1,19 @@ +# 2026-03-18 홈 탭 초기 지연 로딩 및 상태 유지 구현 계획 + +## 체크리스트 +- [x] 기존 탭 구성과 로딩 트리거 위치 확인 +- [x] `HomeView`에서 현재 탭만 최초 마운트되도록 지연 로딩 구조 적용 +- [x] 한 번 마운트된 탭은 재진입 시 상태가 유지되도록 구조 보장 +- [x] 변경 파일 진단 및 빌드/테스트 검증 +- [x] 검증 기록 문서화 + +## 완료 기준 (QA) +- [x] 앱 최초 진입 시 현재 탭(`home`)에 해당하는 화면만 생성되어 초기 조회가 발생한다. +- [x] `live`, `chat` 탭은 최초 탭 전환 시점에 한 번만 생성/조회가 시작된다. +- [x] 한 번 생성된 탭은 다른 탭으로 이동 후 재진입해도 기존 뷰 상태가 유지된다. + +## 검증 기록 +- [2026-03-18] 무엇: `HomeView` 탭 렌더링을 `loadedTabs` 기반 조건부 마운트로 변경. 왜: 초기 진입 시 모든 탭 `onAppear`/조회가 동시에 실행되는 문제를 제거하기 위해. 어떻게: `loadedTabs: Set` 추가 후 `valueChanged(value: viewModel.currentTab)`에서 탭 방문 시점에만 `insert` 하도록 구현. +- [2026-03-18] 무엇: 변경 파일 정적 진단. 왜: 문법/타입 오류 여부 확인. 어떻게: `lsp_diagnostics` 실행. 결과: `HomeView.swift`에서 `No such module 'Firebase'` 1건 확인(로컬 SourceKit 환경 이슈로 기존 import 해석 실패, 코드 변경으로 인한 신규 오류 아님). +- [2026-03-18] 무엇: 앱 빌드 검증. 왜: 실제 컴파일 가능 여부 확인. 어떻게: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build` 실행. 결과: `** BUILD SUCCEEDED **`. +- [2026-03-18] 무엇: 테스트 실행 가능 여부 확인. 왜: 변경 영향 회귀 확인. 어떻게: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test` 실행. 결과: `Scheme SodaLive is not currently configured for the test action.`로 테스트 액션 자체가 미구성 상태임을 확인.