Conversation
앱 실행 시 스플래시 화면을 표시하고, 앱 버전 확인 및 강제 업데이트를 처리하는 로직을 구현했습니다. 이를 위해 `SplashScreen` 컴포저블과 관련 탐색 로직을 추가하고, 앱의 시작점을 스플래시 화면으로 변경했습니다.
- **스플래시 화면 구현 (`SplashScreen.kt`)**:
- 앱 실행 시 버전 체크(`appVersionManager`)를 수행하고, 결과에 따라 `SplashViewModel`의 상태를 업데이트합니다.
- `UiState` 변화에 따라 업데이트 다이얼로그(`UpdateDialog`)나 네트워크 오류 다이얼로그(`NetworkErrorDialog`)를 표시합니다.
- 버전 확인 후, 등록된 축제가 없으면 탐색 화면(`Explore`)으로, 있으면 메인 화면(`Main`)으로 이동시킵니다.
- **내비게이션 설정 (`SplashNavigation.kt`, `MainScreen.kt`)**:
- `splashNavGraph`를 추가하여 스플래시 화면의 내비게이션 경로를 정의했습니다.
- `MainScreen`의 `NavHost`에 `splashNavGraph`를 통합하고, 화면 이동 및 앱 종료 콜백을 설정했습니다.
- **시작 화면 변경 (`FestabookNavigator.kt`)**:
- 앱의 시작 라우트를 기존 `MainTabRoute.Home`에서 `FestabookRoute.Splash`로 변경했습니다.
기존 `ExploreActivity`로 분리되어 있던 둘러보기 화면을 `MainActivity`의 `NavGraph`에 통합했습니다. 이로써 `Activity` 전환 없이 `Compose Navigation`을 통해 화면을 전환할 수 있게 되어 사용자 경험과 코드 일관성이 개선되었습니다. - **`exploreNavGraph` 추가**: `MainActivity`의 `NavHost`에 통합될 `exploreNavGraph`를 새로 정의했습니다. - **`MainActivity` 수정**: `MainScreen`에 `ExploreViewModel`을 추가하고, `NavHost`에 `exploreNavGraph`를 포함시켰습니다. - **`AndroidManifest.xml` 정리**: 둘러보기 화면이 `MainActivity`로 통합됨에 따라, 더 이상 사용되지 않는 `ExploreActivity`의 `LAUNCHER` 인텐트 필터를 제거하고 `SplashActivity`를 시작점으로 변경했다가, 최종적으로 `MainActivity`를 시작점으로 설정했습니다.
앱의 전체 네비게이션 흐름을 관리하는 `FestabookScreen`을 새로 도입하고, 기존 `MainActivity`와 `MainScreen`의 역할을 분리하여 구조를 개선했습니다.
- **`FestabookScreen.kt` 추가:**
- 스플래시(`splash`), 둘러보기(`explore`), 메인(`main`) 화면 간의 최상위 네비게이션을 담당하는 `NavHost`를 생성했습니다.
- `FestabookNavigator`를 통해 앱의 전반적인 화면 전환을 제어하도록 구현했습니다.
- **`mainNavGraph` 분리:**
- 기존 `MainScreen`에 포함되어 있던 메인 화면 관련 네비게이션 로직을 `mainNavGraph`로 분리하여 재사용성을 높였습니다.
- **`FestabookNavigator` 수정:**
- 시작 라우트(`startRoute`)를 생성자에서 설정할 수 있도록 변경하여 네비게이션 유연성을 확보했습니다.
- **`MainActivity` 및 `MainScreen` 역할 변경:**
- `MainActivity`는 이제 `FestabookScreen`을 호출하는 역할만 담당합니다.
- `MainScreen`에서는 스플래시와 둘러보기 관련 네비게이션 로직을 제거하고, 하위 탭(홈, 지도 등) 간의 네비게이션만 처리하도록 역할을 축소했습니다.
`SettingViewModel`의 인스턴스가 `MainScreen`의 생명주기에 종속되지 않고, `MainActivity`의 생명주기를 따르도록 수정했습니다. 이를 통해 화면 전환 시에도 ViewModel의 상태가 유지되도록 개선했습니다.
- **`FestabookScreen.kt` 수정:**
- `FestabookScreen`에서 `SettingViewModel`을 생성하고 `mainNavGraph`로 전달하도록 변경했습니다.
- **`MainNavigation.kt` 수정:**
- `mainNavGraph`에서 `SettingViewModel`을 직접 생성하는 대신, 상위 컴포저블로부터 전달받도록 수정했습니다.
- **`MainActivity.kt` 수정:**
- 불필요한 `// TODO SnackBarHost로 변경` 주석을 제거했습니다.
`FestabookScreen`에서 `MainViewModel`과 `NewsViewModel`을 생성하여 하위 `mainNavGraph`로 전달하도록 의존성 주입 구조를 변경했습니다. 이를 통해 `MainScreen`에서 ViewModel을 직접 생성하지 않고 상위 컴포저블로부터 주입받게 되어 생명주기 관리가 개선되었습니다.
- **`FestabookScreen.kt` 수정:**
- `MainViewModel`과 `NewsViewModel`을 `viewModel()`로 직접 생성하고 `mainNavGraph`에 파라미터로 전달했습니다.
- **`MainNavigation.kt` 수정:**
- `mainNavGraph` 함수가 `MainViewModel`과 `NewsViewModel`을 파라미터로 받도록 수정했습니다.
- `MainScreen`에 전달되는 ViewModel을 기존 `viewModel(mainBackEntry)` 방식 대신, 상위로부터 주입받은 인스턴스를 사용하도록 변경했습니다.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
etama123
left a comment
There was a problem hiding this comment.
고생하셨습니다,,
더 좋은 구조가 생각나면 차차 개선해봅시다 !!
| LaunchedEffect(Unit) { | ||
| // 앱 실행 시 즉시 앱 버전 업데이트의 필요 유무 확인 | ||
| val result = appVersionManager.getIsAppUpdateAvailable() | ||
| viewModel.handleVersionCheckResult(result) | ||
| } | ||
|
|
||
| LaunchedEffect(uiState) { | ||
| when (val state = uiState) { | ||
| is SplashUiState.NavigateToExplore -> { | ||
| currentOnNavigateToExplore() | ||
| } | ||
|
|
||
| is SplashUiState.NavigateToMain -> { | ||
| currentOnNavigateToMain(state.festivalId) | ||
| } | ||
|
|
||
| else -> {} | ||
| } | ||
| } |
There was a problem hiding this comment.
나중에 이 부분도 uiState와 effect로 분리할 수 있을 것 같아요 ~!
There was a problem hiding this comment.
혹시 예제를 좀 남겨주실 수 있으실까요? 처음 한 번만 실행되는 로직이라 effect로 따로 빼야할까 싶습니다
etama123
left a comment
There was a problem hiding this comment.
앱 첫 진입시에 팝업되는 알림 받기 다이얼로그에서 알림 받기 버튼을 클릭하면, 다음 동작으로 이동하지 않는 오류가 있습니다! 확인부탁드립니다
| import com.daedan.festabook.presentation.main.FestabookRoute | ||
|
|
||
| fun NavGraphBuilder.exploreNavGraph( | ||
| viewModel: ExploreViewModel, |
There was a problem hiding this comment.
홈에서 탐색화면으로 이동할 때, 검색창에 첫 진입 시 입력한 내용이 남아있습니다.
- 기존에 어디서 탐색화면으로 접근하는 지에 따라, 초기진입 용 탐색화면과 후 진입용 탐색화면으로 나누었었는데요. 지금은 초기 진입용 탐색화면만 뜨는 것 같습니다.
혹시 이 부분은 어떻게 처리하는 게 좋을까요?
There was a problem hiding this comment.
홈화면에서 탐색화면에서 새로운 축제로 접근했을 때, 첫 방문 알림 설정 다이얼로그가 뜨지 않습니다.
#️⃣ 이슈 번호
🛠️ 작업 내용
🙇🏻 중점 리뷰 요청
기존에는 SplashActivity, ExploreActivity로 인해 자연스럽게 ViewModel의 생명주기가 해결되었습니다.
하지만 이제는 MainActivity 하나만 남게 되었습니다.
이는 MainActivity가 ExploreActivity의 역할까지 수행한다는 의미입니다.
문제는 ExploreActivity는 축제 검색 전의 상태를 가집니다.
이는 구현 난이도를 급상승하는 원인이 됩니다.
문제 상황들
이런 문제로 인해 상당한 시간이 소요되었습니다.
제가 생각한 아키텍쳐는 다음과 같습니다.
다만 가장 큰 문제가 navController가 여러 개가 생길 수 있어, 복잡한 화면으로 구현 시, 관리가 매우 까다로워 질 수 있습니다. (단일 진실 공급원 위반)
다만 MainScreen과 FestabookScreen을 별개의 모듈 로 생각한다면 조금 납득 가능한 구현이라고 생각하여, 이 방식을 채택했습니다.
단일 NavHost, Screen에 가시성 추가
예를 들어 기존 MainScreen에서 수행한 초기화 로직(컴포저블 함수)을 축제 검색 완료 후의 상태일때만 수행하도록 가시성을 제한합니다. navController가 하나가 되는 장점은 있지만, 반대로 코드의 불필요한 depth가 증가하고, 가시성을 변경 하는 것이기 때문에 viewModel 생명주기의 문제가 남아있습니다.
ViewModel의 init을 public으로 만들기
만약 ViewModel이 100개가 생기면 100개의 뷰모델을 모두 로딩한 후, 데이터만 갈아끼는 방법입니다. 가장 간단하지만 메모리를 비효율적으로 쓰는 것 같으며, FIle Changes가 늘어나기에 기각했습니다
이외에도 다른 좋은 방법이 있다면 공유 부탁드립니다!!
📸 이미지 첨부 (Optional)