Repository navigation
refactor(navigation): 탭별 NavigationStack + Router/Coordinator 전환 - #112
Conversation
gomminjae
commented
Jul 11, 2026
- 전역 단일 스택 + AppRoute god-enum 제거, 탭별 독립 Route/Router 도입
- feature View에서 커스텀 @Environment(AppRouter/TabSelection/AppState/ToastCenter) 제거; 네비게이션은 클로저 주입, 세션상태/토스트는 .shared 직접 접근으로 전환
- AppCoordinator(탭 선택·크로스탭·둘러보기 pending·auth present) + AuthFlow(contextual fullScreenCover)
- AppRouter/AppRoute/TabSelection 삭제, NewDokTab enum 분리
- Interface/Builder 8쌍 시그니처 + AppContainer + 셸(NewdokApp/AppRootView/NewDokTabView) 재작성
- 전역 단일 스택 + AppRoute god-enum 제거, 탭별 독립 Route/Router 도입 - feature View에서 커스텀 @Environment(AppRouter/TabSelection/AppState/ToastCenter) 제거; 네비게이션은 클로저 주입, 세션상태/토스트는 .shared 직접 접근으로 전환 - AppCoordinator(탭 선택·크로스탭·둘러보기 pending·auth present) + AuthFlow(contextual fullScreenCover) - AppRouter/AppRoute/TabSelection 삭제, NewDokTab enum 분리 - Interface/Builder 8쌍 시그니처 + AppContainer + 셸(NewdokApp/AppRootView/NewDokTabView) 재작성
There was a problem hiding this comment.
Code Review
This pull request refactors the application's navigation architecture by replacing the global AppRouter and TabSelection with a centralized AppCoordinator and generic Router system utilizing the Observation framework. It introduces dedicated stack views for each tab, manages authentication flows via AuthFlow presented as a full-screen cover, and refactors feature views to use closure-based callbacks for navigation instead of environment objects. Feedback on these changes highlights a critical issue in AppCoordinator where tab routers' paths are not cleared upon logout, potentially exposing previous user states to newly logged-in accounts. Additionally, a minor cleanup is requested to remove a leftover crash log message from a comment in ToastCenter.swift.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| func logout(to route: AuthRoute) { | ||
| mypageRouter.popToRoot() | ||
| selectedTab = .home | ||
| authRoute = route | ||
| } |
There was a problem hiding this comment.
현재 AppCoordinator는 NewdokApp에서 @State로 관리되어 앱의 생명주기 동안 단 한 번만 생성되고 유지됩니다. 따라서 NewDokTabView가 .id(...) 변경으로 인해 재생성되더라도, AppCoordinator 내부의 각 탭 라우터(homeRouter, exploreRouter 등)의 path 상태는 초기화되지 않고 그대로 유지됩니다.
이로 인해 로그아웃 후 다른 계정으로 로그인했을 때 이전 사용자가 보던 상세 화면 스택이 그대로 노출되는 심각한 UX 및 보안 문제가 발생할 수 있습니다.
따라서 logout 메서드에서 모든 라우터의 path를 비워주도록(popToRoot()) 명시적으로 처리해야 합니다.
func logout(to route: AuthRoute) {
homeRouter.popToRoot()
exploreRouter.popToRoot()
subscribeRouter.popToRoot()
bookmarkRouter.popToRoot()
mypageRouter.popToRoot()
exploreDay = nil
exploreTab = 0
hasPendingExplore = false
selectedTab = .home
authRoute = route
}| if toast.isShown { | ||
| if ToastCenter.shared.isShown { | ||
| // DesignSystem의 ToastView는 상위 모듈에 존재하므로, 여기서는 텍스트만 렌더합니다. | ||
| // 실제 디자인 토스트를 쓰려면 이 ToastHost를 App 레이어로 옮겨 DesignSystem을 import 하세요.Thread 1: Fatal error: No ObservableObject |
There was a problem hiding this comment.
주석 끝에 디버깅 중 발생한 것으로 보이는 크래시 로그(Thread 1: Fatal error: No ObservableObject)가 실수로 남겨져 있습니다. 불필요한 텍스트를 제거하여 코드를 깔끔하게 정리해주세요.
| // 실제 디자인 토스트를 쓰려면 이 ToastHost를 App 레이어로 옮겨 DesignSystem을 import 하세요.Thread 1: Fatal error: No ObservableObject | |
| // 실제 디자인 토스트를 쓰려면 이 ToastHost를 App 레이어로 옮겨 DesignSystem을 import 하세요. |