Conversation
- MainNavigator.kt: RouteStack을 사용하여 현재 및 이전 경로 관리 - MainScreen.kt: 현재 경로 대신 RouteStack 사용 - NavigatorProvider.kt: 이전 경로 반환 타입을 String에서 Route로 변경 - PermissionScreen.kt: 이전 경로 체크 로직 수정
- LocalNavigatorProvider 제거 및 clearBackStack 인자 사용 - MainNavigator.kt: 내비게이션 메서드 수정으로 코드 간결화
- HomeNavEntry.kt: 홈 화면 네비게이션 엔트리 추가 - InquiryNavEntry.kt: 문의 화면 네비게이션 엔트리 추가 - LegalNavEntry.kt: 법적 정보 화면 네비게이션 엔트리 추가 - LoginNavEntry.kt: 로그인 화면 네비게이션 엔트리 추가 - NicknameNavEntry.kt: 닉네임 화면 네비게이션 엔트리 추가 - OnboardingNavEntry.kt: 온보딩 화면 네비게이션 엔트리 추가 - OpinionNavEntry.kt: 의견 화면 네비게이션 엔트리 추가 - PermissionNavEntry.kt: 권한 화면 네비게이션 엔트리 추가 - RegistryNavEntry.kt: 등록 화면 네비게이션 엔트리 추가 - ReportNavEntry.kt: 보고서 화면 네비게이션 엔트리 추가 - SettingNavEntry.kt: 설정 화면 네비게이션 엔트리 추가 - SignupNavEntry.kt: 회원가입 화면 네비게이션 엔트리 추가
- MainActivity.kt: RouteStack을 통한 스택 관리 로직 추가 - MainViewModel.kt: 네비게이션 관련 상태 관리 메서드 추가 - MainScreen.kt: RouteStack을 활용한 UI 업데이트
- CompleteScreen.kt, GuideScreen.kt, HomeScreen.kt, LoginScreen.kt, NicknameScreen.kt, PermissionScreen.kt, PrivacyScreen.kt, ReportScreen.kt, SettingScreen.kt, SignupScreen.kt, TermsScreen.kt: Hilt ViewModel 임포트 경로를 변경하여 최신 라이브러리와 호환성 확보 - build.gradle.kts: androidx.lifecycle.viewmodel.navigation3 라이브러리 추가
- AndroidManifest.xml: 메인 액티비티의 테마를 투명 시스템 바 스타일로 변경 - themes.xml: 투명 시스템 바 스타일 정의 추가
- RegistryNavEntry.kt: hiltViewModel을 사용하여 ViewModel 주입 방식 수정
- CompleteScreen.kt: 네비게이션 시 LaunchMode.CLEAR_ALL 적용 - MainViewModel.kt: 모든 navigateTo 함수에 LaunchMode 파라미터 추가 - NavigatorAction.kt: navigateTo 함수 시그니처 변경 - PermissionScreen.kt, SettingScreen.kt: 네비게이션 호출 시 LaunchMode 적용
There was a problem hiding this comment.
Pull request overview
This PR migrates the navigation system from Navigation Compose to Navigation3, introducing a custom backstack management system with LaunchMode support. The migration modernizes the navigation architecture while providing more explicit control over navigation behavior through the introduction of LaunchMode enum values (STANDARD, SINGLE_TOP, CLEAR_TOP, CLEAR_ALL).
Changes:
- Migrated from Navigation Compose to Navigation3 with NavDisplay and entryProvider pattern
- Implemented custom RouteStack data class for managing navigation backstack independently
- Introduced LaunchMode enum for explicit backstack management behavior
- Updated RegistryViewModel to use
@AssistedInjectfor route parameter injection
Reviewed changes
Copilot reviewed 54 out of 54 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| core/navigation/build.gradle.kts | Updated dependencies from navigation-compose to navigation3-runtime and navigation3-ui |
| core/navigation/src/main/java/com/teambrake/brake/core/navigation/route/Route.kt | Changed Route to extend NavKey interface for Navigation3 compatibility |
| core/navigation/src/main/java/com/teambrake/brake/core/navigation/route/RouteStack.kt | Implemented custom RouteStack for backstack state management |
| core/navigation/src/main/java/com/teambrake/brake/core/navigation/route/LaunchMode.kt | Added LaunchMode enum for navigation behavior control |
| core/navigation/src/main/java/com/teambrake/brake/core/navigation/action/NavigatorAction.kt | Updated all navigation methods to use LaunchMode instead of NavOptions |
| core/navigation/src/main/java/com/teambrake/brake/core/navigation/provider/NavigatorProvider.kt | Simplified interface to return Route instead of String |
| presentation/main/src/main/java/com/teambrake/brake/presentation/main/MainViewModel.kt | Centralized navigation logic with custom RouteStack management |
| presentation/main/src/main/java/com/teambrake/brake/presentation/main/MainActivity.kt | Restructured initialization flow to work with Navigation3 |
| presentation/main/src/main/java/com/teambrake/brake/presentation/main/MainScreen.kt | Updated to use RouteStack instead of Navigator |
| presentation/main/src/main/java/com/teambrake/brake/presentation/main/navigation/MainNavHost.kt | Replaced NavHost with NavDisplay and entryProvider pattern |
| presentation/main/src/main/java/com/teambrake/brake/presentation/main/navigation/MainNavigator.kt | Removed old MainNavigator class (logic moved to MainViewModel) |
| presentation//navigation/.kt | Removed all old navigation files using NavGraphBuilder |
| presentation//navEntry/.kt | Added new navEntry files using EntryProviderScope |
| presentation/*/Screen.kt | Updated hiltViewModel imports to androidx.hilt.lifecycle.viewmodel.compose |
| presentation/home/src/main/java/com/teambrake/brake/presentation/registry/RegistryViewModel.kt | Converted to use @AssistedInject with Factory pattern |
| presentation/main/src/main/AndroidManifest.xml | Added transparent system bar theme |
| presentation/main/src/main/res/values/themes.xml | Created TransparentSystemBar theme |
| gradle/libs.versions.toml | Added Navigation3 dependencies and updated targetSdk to 36 |
| build-logic/src/main/kotlin/brake.android.feature.gradle.kts | Removed navigation-compose dependencies |
| .github/git-commit-instructions.md | Added commit message guidelines (unrelated to navigation migration) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| compileSdk = "36" | ||
| minSdk = "28" | ||
| targetSdk = "35" | ||
| targetSdk = "36" |
There was a problem hiding this comment.
The targetSdk has been updated from 35 to 36. Android 15 (API 36) includes significant behavior changes and new restrictions. Ensure that the app has been tested against API 36 requirements, including new runtime permissions, foreground service restrictions, and other breaking changes documented in the Android 15 behavior changes guide. This change could introduce runtime issues if not properly validated.
| targetSdk = "36" | |
| targetSdk = "35" |
| ## 프로젝트 컨텍스트 | ||
|
|
||
| - **기술 스택**: Kotlin, Jetpack Compose, MVVM/MVI 아키텍처, Multi-module | ||
| - **모듈 구조**: | ||
| - `feature/*`: 기능별 모듈 (home, cargo-detail, myinfo 등) | ||
| - `core/*`: 공통 모듈 (designsystem, data, domain, network 등) | ||
|
|
||
| ## 커밋 메시지 형식 | ||
|
|
||
| ``` | ||
| 타입: 간단한 제목 (한국어, 50자 이내) | ||
|
|
||
| - 변경 사항 1 (구체적으로) | ||
| - 변경 사항 2 (파일명 포함 권장) | ||
| - 변경 사항 3 (왜 변경했는지 포함) | ||
| ``` | ||
|
|
||
| ## 타입 정의 | ||
|
|
||
| 변경사항을 분석하여 가장 적합한 타입 하나를 선택하세요: | ||
|
|
||
| - **feat**: 새로운 기능 추가 | ||
| - 예: 새로운 화면, 새로운 컴포넌트, 새로운 API 연동 | ||
|
|
||
| - **fix**: 버그 수정 | ||
| - 예: 크래시 수정, 잘못된 로직 수정, UI 버그 수정 | ||
|
|
||
| - **refactor**: 코드 리팩토링 (기능 변경 없음) | ||
| - 예: 함수 분리, 변수명 변경, 구조 개선 | ||
|
|
||
| - **style**: UI/디자인 변경 (코드 스타일 X) | ||
| - 예: 색상 변경, 간격 조정, 폰트 수정 | ||
|
|
||
| - **test**: 테스트 코드 추가/수정 | ||
| - 예: 단위 테스트, UI 테스트, Integration 테스트 | ||
|
|
||
| - **chore**: 빌드, 설정, 의존성 관련 | ||
| - 예: Gradle 업데이트, 라이브러리 추가, CI/CD 설정 | ||
|
|
||
| ## 작성 규칙 | ||
|
|
||
| ### 1. 제목 작성 | ||
| - 한국어로 작성 | ||
| - 50자 이내로 간결하게 | ||
| - 마침표 없이 명령형으로 작성 | ||
| - 무엇을 했는지 명확하게 | ||
|
|
||
| ### 2. 본문 작성 | ||
| - 각 항목은 `-`로 시작 | ||
| - 구체적인 파일명이나 컴포넌트명 포함 | ||
| - 변경 이유나 맥락 포함 (필요시) | ||
| - 모듈 경로 명시 (`feature/home`, `core/designsystem` 등) | ||
|
|
||
| ✅ 좋은 예: | ||
| ``` | ||
| - HomeScreenRedesign.kt: 사용자 정보 카드 컴포넌트 추가 | ||
| - CargoItemCard.kt: 화물 상태별 색상 구분 로직 구현 | ||
| - Figma 디자인(node-id: 1942-56177) 기반 레이아웃 적용 | ||
| - Material 3 디자인 시스템 적용 | ||
| ``` | ||
|
|
||
| ❌ 나쁜 예: | ||
| ``` | ||
| - 코드 수정 | ||
| - 파일 추가 | ||
| - 작업 완료 | ||
| ``` | ||
|
|
||
| ## 변경사항 분석 체크리스트 | ||
|
|
||
| 커밋 메시지를 작성하기 전에 다음을 확인하세요: | ||
|
|
||
| 1. **어떤 파일이 변경되었는가?** | ||
| - 파일명과 경로 확인 | ||
|
|
||
| 2. **무엇이 추가/수정/삭제되었는가?** | ||
| - 새로운 함수/클래스/컴포넌트 | ||
| - 수정된 로직 | ||
| - 삭제된 코드 | ||
|
|
||
| 3. **왜 이 변경이 필요했는가?** | ||
| - 버그 수정 | ||
| - 기능 추가 | ||
| - 성능 개선 | ||
| - 디자인 반영 | ||
|
|
||
| 4. **이 변경의 영향 범위는?** | ||
| - 다른 모듈에 영향 | ||
| - Breaking Change 여부 | ||
| - 테스트 필요 여부 | ||
|
|
||
| ## 실제 예시 | ||
|
|
||
| ### 예시 1: 새 화면 추가 | ||
| ``` | ||
| feat: 화물 상세 화면 추가 | ||
|
|
||
| - CargoDetailScreen.kt: 새 화면 구현 | ||
| - CargoDetailViewModel.kt: 상태 관리 | ||
| - CargoDetailUiState.kt: UI 상태 정의 | ||
| - 화물 정보, 차주 정보, 경로 정보 표시 | ||
| - 전화/문자 버튼 기능 구현 | ||
| - Navigation 연결 완료 | ||
| ``` | ||
|
|
||
| ### 예시 2: 버그 수정 | ||
| ``` | ||
| fix: 화물 등록 시 날짜 선택 오류 수정 | ||
|
|
||
| - DatePicker.kt: 시간대 처리 로직 수정 | ||
| - LocalDateTime을 ZonedDateTime으로 변경 | ||
| - 서버와 시간대 불일치로 발생한 오류 해결 | ||
| - 테스트 케이스 추가: DatePickerTest.kt | ||
| ``` | ||
|
|
||
| ### 예시 3: 리팩토링 | ||
| ``` | ||
| refactor: Repository 레이어 분리 및 정리 | ||
|
|
||
| - CargoRepository.kt: Local/Remote 분리 | ||
| - CargoLocalDataSource.kt: 로컬 데이터 소스 | ||
| - CargoRemoteDataSource.kt: 리모트 데이터 소스 | ||
| - 단일 책임 원칙 적용 | ||
| - 테스트 용이성 개선 | ||
| ``` | ||
|
|
||
| ### 예시 4: UI 스타일 변경 | ||
| ``` | ||
| style: 메인 홈 카드 디자인 수정 | ||
|
|
||
| - CargoItemCard.kt: 카드 스타일 조정 | ||
| - elevation 2dp → 4dp 변경 | ||
| - 모서리 반경 6dp → 8dp 변경 | ||
| - 그림자 색상 조정 (#000000 → #0000001A) | ||
| - Figma 디자인과 일치하도록 수정 | ||
| ``` | ||
|
|
||
| ### 예시 5: 여러 타입의 변경 | ||
| 가장 중요한 변경사항의 타입을 사용하세요: | ||
|
|
||
| ``` | ||
| feat: 로그인 화면 개선 | ||
|
|
||
| - LoginScreen.kt: UI 리디자인 (Figma 기반) | ||
| - LoginViewModel.kt: 자동 로그인 기능 추가 | ||
| - PreferencesManager.kt: 로그인 상태 저장 로직 | ||
| - 버그 수정: 비밀번호 입력 시 키보드 숨김 처리 | ||
| ``` | ||
|
|
||
| ## 주의사항 | ||
|
|
||
| 1. **하나의 커밋에는 하나의 논리적 변경만** | ||
| - 여러 기능을 한 커밋에 섞지 말 것 | ||
| - 필요시 커밋을 분리 | ||
|
|
||
| 2. **WIP(Work In Progress) 커밋 지양** | ||
| - 완전하지 않은 작업은 커밋하지 말 것 | ||
| - 부득이한 경우 `[WIP]` 태그 사용 | ||
|
|
||
| 3. **파일 경로는 프로젝트 이름 기준** | ||
| - ✅ `HomeScreen.kt` | ||
|
|
||
| 4. **민감 정보 포함 금지** | ||
| - API 키, 비밀번호, 개인정보 제외 | ||
| - 환경 설정은 .env 파일 활용 | ||
|
|
||
| ## 마지막 체크 | ||
|
|
||
| 커밋하기 전 확인: | ||
| - [ ] 타입이 명확한가? | ||
| - [ ] 제목이 50자 이내인가? | ||
| - [ ] 본문에 구체적인 내용이 있는가? | ||
| - [ ] 파일명이나 컴포넌트명이 포함되었는가? | ||
| - [ ] 변경 이유가 명확한가? | ||
| - [ ] Breaking Change가 있다면 명시했는가? | ||
|
|
||
| --- | ||
|
|
||
| 이 가이드를 따라 일관성 있고 명확한 커밋 메시지를 작성하세요. | ||
|
|
There was a problem hiding this comment.
This file appears to be unrelated to the Navigation3 migration described in the PR. It's a commit message guideline document. Consider whether this should be included in this PR or moved to a separate documentation update PR to keep changes focused and easier to review.
| data class RouteStack( | ||
| val backStack: List<Route> = emptyList(), | ||
| ) { | ||
| val current: Route? = backStack.lastOrNull() | ||
|
|
||
| val previous: Route? = backStack.dropLast(1).lastOrNull() | ||
|
|
||
| constructor(startDestination: Route) : this(backStack = listOf(startDestination)) |
There was a problem hiding this comment.
The RouteStack constructor that takes a single Route parameter wraps it in a list. However, the primary constructor initializes backStack with an empty list by default. While this works correctly, consider adding validation to prevent creating a RouteStack with an empty backStack after initialization, as an empty backStack could lead to null current and previous values, which might cause unexpected behavior in navigation logic.
| LaunchMode.CLEAR_TOP -> { | ||
| if (route in current.backStack) { | ||
| current.copy( | ||
| backStack = current.backStack.takeWhile { it != route } + route, | ||
| ) | ||
| } else { | ||
| current.copy(backStack = current.backStack + route) | ||
| } |
There was a problem hiding this comment.
The CLEAR_TOP implementation may have an issue with route equality. Since SubRoute.Registry is a data class with a nullable groupId parameter, two Registry instances with different groupId values will not be equal (e.g., Registry(groupId=1) != Registry(groupId=2)). This means CLEAR_TOP won't work as expected when navigating to a Registry route that already exists in the backstack with a different groupId. Consider whether this is the intended behavior, or if you need custom equality logic for routes with parameters.
- AndroidManifest.xml: 테마를 Theme.Brake.Activity로 변경 - themes.xml: 새로운 테마 Theme.Brake.Activity 추가 및 스플래시 배경 설정 - colors.xml: 스플래시 배경 색상 정의 - splash_background.xml: 스플래시 화면 배경 및 로고 설정
- Nav3 백스택의 destination 상태가 유지됨에 따라, 화면 이동 시 이전 화면의 상태를 처리하는 로직 추가
fcd4792 to
52836c0
Compare
TaewoongR
left a comment
There was a problem hiding this comment.
Nav3 적용 후 발생한 문제
- 스플래시 화면이 Application 단위가 아닌 Activity 구성에서 실행됨
- 네비게이션 백스택 초기화 후 로그인 화면으로 이동 시, 이전의 로딩 상태가 유지되어 로딩 중 화면이 나타남
해결 방법
- Activity 스플래시 화면 구성 적용
- 로그인 화면에서 다음 화면으로 이동하기 직전에 해당 화면 상태 초기화
Theme.BrakeActivity에 parent 속성을 명시하여 의도치 않은 암시적 상속(Implicit Inheritance) 문제 해결 존재하지 않는 'Theme'을 부모로 찾으려다 발생하는 AAPT 빌드 에러 방지
0e3d971 to
f2f6405
Compare
📋 개요
📑 세부 사항
1. Navigation3 마이그레이션 ✅
NavDisplay와entryProvider를 사용한 선언적 네비게이션 구현2. 커스텀 RouteStack 구현 ✅
current,previous프로퍼티로 현재/이전 화면 정보 제공3. LaunchMode 도입 ✅
clearBackStack파라미터 제거로 API 단순화4. AssistedInject 지원 ✅