Skip to content

Conversation

@oungsi2000
Copy link
Contributor

@oungsi2000 oungsi2000 commented Jan 28, 2026

#️⃣ 이슈 번호

#34


🛠️ 작업 내용

  • Scaffold에 SnackbarHost 추가 및 Compose Snackbar로 마이그레이션 하였습니다.
  • MainActivity에 아직 레거시 스낵바 호출 코드가 남아있습니다. 이 부분은 해당 이슈
    를 진행함과 동시에 마이그레이션 하는 것이 좋을 것 같습니다.

🙇🏻 중점 리뷰 요청

  • 각 메인 탭의 최상단 UiState가 Error 상태일 때만 스낵바를 띄웁니다.
    각자 작업하신 화면에서 스낵바 호출이 누락된 부분이 있다면 코멘트 부탁드립니다 !

📸 이미지 첨부 (Optional)

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능
    • 에러 발생 시 사용자에게 스낵바 알림으로 메시지 표시
    • 앱 전체 화면에서 일관된 에러 처리 및 사용자 피드백 개선
    • 뒤로가기 동작 및 다양한 상황에서 알림 메시지 제공

✏️ Tip: You can customize this high-level summary in your review settings.

기존에 `Toast`로 처리되거나 주석 처리되어 있던 사용자 알림 기능을 `Snackbar` 기반으로 통합하고, 이를 중앙에서 관리할 수 있는 `SnackbarManager`를 도입했습니다. 이로 인해 앱 전체에서 일관된 스타일의 알림을 제공하고, 에러 처리 로직을 개선했습니다.

- **`common/component/SnackBar.kt` 추가:**
    - `FestabookSnackbar` 컴포저블을 추가하여 앱의 디자인 시스템에 맞는 스낵바를 구현했습니다.
    - `SnackbarManager` 클래스를 도입하여 스낵바 메시지 표시(`show`) 및 에러 메시지 처리(`showError`) 로직을 중앙에서 관리하도록 했습니다.
    - `rememberAppSnackbarManager` 함수를 추가하여 `SnackbarManager`를 Compose 환경에서 쉽게 생성하고 재사용할 수 있도록 했습니다.

- **`main/component/MainScreen.kt` 수정:**
    - `Scaffold`에 `SnackbarHost`를 추가하고, `FestabookSnackbar`를 사용하도록 설정했습니다.
    - `rememberAppSnackbarManager`를 이용해 `SnackbarManager` 인스턴스를 생성했습니다.
    - 기존 `Toast` 알림(뒤로가기 종료 알림)과 주석 처리되었던 알림(알림 설정 성공)을 `snackbarManager.show()` 호출로 대체했습니다.
    - `homeNavGraph`에 `snackbarManager`를 전달하여 하위 화면(Home, Setting 등)에서 스낵바를 사용할 수 있도록 `onShowSnackBar`와 `onShowErrorSnackBar` 콜백을 구현했습니다.
장소 상세 정보를 불러오는 데 실패했을 때 사용자에게 스낵바를 통해 에러를 알려주는 기능을 추가했습니다.

- **`PlaceDetailScreen.kt` 수정:**
    - `PlaceDetailRoute`와 `PlaceDetailScreen`에 `onShowErrorSnackbar` 콜백 파라미터를 추가했습니다.
    - `LaunchedEffect`를 사용하여 `placeDetailUiState`가 `Error` 상태일 때, `onShowErrorSnackbar` 콜백을 호출하도록 구현했습니다.

- **`PlaceMapNavigation.kt` 및 `MainScreen.kt` 수정:**
    - `placeMapNavGraph`를 통해 `MainScreen`의 `snackbarManager::showError` 함수를 `PlaceDetailRoute`까지 전달하여 스낵바가 표시되도록 연결했습니다.
각 화면(`Home`, `Schedule`, `News`)의 ViewModel에서 발생하는 `Error` 상태를 감지하여 스낵바로 사용자에게 에러 메시지를 표시하는 기능을 추가했습니다. `MainScreen`에서 스낵바 표시 로직을 중앙에서 관리하고, 각 화면에는 에러 발생 시 호출할 콜백(`onShowErrorSnackbar`)을 전달하는 방식으로 구현했습니다.

- **`MainScreen.kt` 수정:**
    - `homeNavGraph`, `scheduleNavGraph`, `newsNavGraph`에 `snackbarManager::showError`를 `onShowErrorSnackbar` 콜백으로 전달하여 에러 처리를 위임했습니다.

- **`HomeScreen.kt`, `ScheduleScreen.kt`, `NewsScreen.kt` 수정:**
    - `onShowErrorSnackbar: (Throwable) -> Unit` 파라미터를 추가했습니다.
    - `LaunchedEffect`를 사용하여 각 ViewModel의 UI 상태(`festivalUiState`, `scheduleUiState`, `noticeUiState` 등)가 `Error`일 경우, `onShowErrorSnackbar` 콜백을 호출하도록 구현했습니다.
    - `rememberUpdatedState`를 사용하여 항상 최신의 콜백을 참조하도록 하여 안정성을 높였습니다.

- **관련 `NavGraph` 파일들 수정:**
    - `homeNavGraph`, `scheduleNavGraph`, `newsNavGraph` 함수에 `onShowErrorSnackbar` 파라미터를 추가하고, 이를 각 화면 컴포저블로 전달하도록 수정했습니다.
기존 스낵바가 표시된 상태에서 새로운 스낵바가 호출될 경우, 이전 스낵바를 즉시 닫고 새로운 스낵바가 표시되도록 `show` 함수의 동작을 수정했습니다. 또한, 불필요한 `Dismiss` 버튼을 제거하여 UI를 간소화했습니다.

- **`SnackBar.kt` 수정:**
    - `show` 함수 호출 시, `hostState.currentSnackbarData?.dismiss()`를 먼저 실행하여 현재 표시 중인 스낵바를 닫는 로직을 추가했습니다.
    - `showSnackbar`의 `withDismissAction` 파라미터를 제거하여, 스낵바에 별도의 '닫기' 버튼이 나타나지 않도록 변경했습니다.

- **`MainScreen.kt` 수정:**
    - 설정 화면에서 알림 활성화 성공 시 스낵바를 표시하던 `ObserveAsEvents` 로직을 제거했습니다. 이는 새로운 정책에 따라 더 이상 필요하지 않은 기능입니다.
`PlaceMapRoute`에서 발생하는 오류를 상위 컴포저블(`MainScreen`)로 전달하여 스낵바를 통해 사용자에게 표시할 수 있도록 구조를 개선했습니다.

- **`PlaceMapScreen.kt` 수정:**
    - `PlaceMapRoute` 컴포저블에 `onShowErrorSnackBar: (Throwable) -> Unit` 콜백 파라미터를 추가했습니다.
    - `PlaceMapSideEffectHandler` 내에서 `ShowErrorSnackBar` 이펙트가 발생했을 때, `onShowErrorSnackBar` 콜백을 호출하여 `Throwable`을 전달하도록 수정했습니다.

- **`MainScreen.kt` 수정:**
    - `PlaceMapRoute`를 호출할 때 `onShowErrorSnackBar` 파라미터에 `snackbarManager::showError`를 전달하여, 지도 화면에서 오류가 발생하면 `MainScreen`의 스낵바 매니저가 오류 메시지를 표시하도록 연결했습니다.
@oungsi2000 oungsi2000 self-assigned this Jan 28, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 28, 2026

📝 Walkthrough

순서 정보

이 PR은 안드로이드 Compose 앱 전체에 걸쳐 중앙 집중식 스낵바 시스템을 추가합니다. 새로운 SnackbarManager를 도입하고 여러 화면 및 네비게이션 그래프를 업데이트하여 오류 상태를 스낵바 시스템으로 라우팅하는 onShowErrorSnackbar 콜백을 수락하도록 합니다.

변경 사항

코호트 / 파일 변경 사항 요약
스낵바 컴포넌트 및 관리자
app/src/main/java/com/daedan/festabook/presentation/common/component/SnackBar.kt
FestabookSnackbar 컴포저블, SnackbarManager 클래스(show/showError 메서드 포함), 그리고 rememberAppSnackbarManager 컴포저블 도입. ApiResultException 타입별 로컬라이즈된 오류 메시지 매핑 포함.
화면 컴포넌트 - 오류 콜백 추가
app/src/main/java/com/daedan/festabook/presentation/home/component/HomeScreen.kt, app/src/main/java/com/daedan/festabook/presentation/news/component/NewsScreen.kt, app/src/main/java/com/daedan/festabook/presentation/schedule/component/ScheduleScreen.kt, app/src/main/java/com/daedan/festabook/presentation/placeDetail/component/PlaceDetailScreen.kt, app/src/main/java/com/daedan/festabook/presentation/placeMap/component/PlaceMapScreen.kt
onShowErrorSnackbar 콜백 파라미터 추가. rememberUpdatedState와 LaunchedEffect를 사용하여 Error 상태에서 콜백 호출.
네비게이션 그래프 - 콜백 전파
app/src/main/java/com/daedan/festabook/presentation/home/navigation/HomeNavigation.kt, app/src/main/java/com/daedan/festabook/presentation/news/navigation/NewsNavigation.kt, app/src/main/java/com/daedan/festabook/presentation/schedule/navigation/ScheduleNavigation.kt, app/src/main/java/com/daedan/festabook/presentation/placeMap/navigation/PlaceMapNavigation.kt
onShowErrorSnackbar 파라미터를 함수 시그니처에 추가하고 각 화면 컴포저블로 전달.
메인 오케스트레이션
app/src/main/java/com/daedan/festabook/presentation/main/component/MainScreen.kt
SnackbarHost, SnackbarHostState, SnackbarManager 추가. FestabookNavHost에 snackbarManager 파라미터 추가. 모든 네비게이션 그래프의 오류 콜백을 snackbarManager::showError로 연결.

시퀀스 다이어그램

sequenceDiagram
    participant Screen as 화면 컴포넌트
    participant Effect as LaunchedEffect
    participant Callback as onShowErrorSnackbar
    participant Manager as SnackbarManager
    participant Host as SnackbarHost

    Screen->>Effect: UiState.Error 감지
    Effect->>Callback: throwable 전달
    Callback->>Manager: showError(throwable)
    Manager->>Manager: 오류 타입별 메시지 맵핑
    Manager->>Host: show(message)
    Host->>Host: 스낵바 표시
Loading

예상 코드 리뷰 노력

🎯 3 (Moderate) | ⏱️ ~25 minutes

관련 가능성 있는 PR

제안 검토자

  • etama123
  • parkjiminnnn

🐰 스낵바 시스템이 춤을 춘다
오류들이 메시지로 변신하고
화면 곳곳에 펼쳐지며
사용자에게 부드럽게 전달돼
앱의 경험이 더욱 윤기나네! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 PR의 주요 변경사항을 명확하게 요약하고 있습니다. SnackbarHost 설정 및 Snackbar Compose 마이그레이션이라는 핵심 작업이 PR의 대부분의 변경사항을 정확하게 반영합니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@oungsi2000
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/java/com/daedan/festabook/presentation/placeMap/component/PlaceMapScreen.kt (1)

81-98: onShowErrorSnackBar 콜백이 remember 키에서 누락됨

PlaceMapSideEffectHandlerremember 블록 안에서 생성되지만, onShowErrorSnackBar 콜백이 키에 포함되지 않았습니다. 부모 컴포저블이 다른 콜백 인스턴스로 리컴포지션되면 핸들러는 재생성되지 않아 이전(stale) 콜백이 호출될 수 있습니다.

🐛 제안: remember 키에 콜백 추가
     val placeMapSideEffectHandler =
-        remember(placeMapViewModel, logger, mapManagerDelegate) {
+        remember(placeMapViewModel, logger, mapManagerDelegate, onShowErrorSnackBar) {
             PlaceMapSideEffectHandler(
                 mapManagerDelegate = mapManagerDelegate,
                 bottomSheetState = bottomSheetState,
                 viewModel = placeMapViewModel,
                 logger = logger,
                 onStartPlaceDetail = onStartPlaceDetail,
                 onPreloadImages = {
                     preloadImages(
                         context = context,
                         scope = scope,
                         places = it.places,
                     )
                 },
                 onShowErrorSnackBar = { onShowErrorSnackBar(it.error.throwable) },
             )
         }

또는 onStartPlaceDetail도 동일한 문제가 있으므로 함께 키에 추가하는 것을 권장합니다.

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/daedan/festabook/presentation/main/component/MainScreen.kt`:
- Around line 63-66: The local val noticeEnabledMessage declared via
noticeEnabledMessage = stringResource(R.string.setting_notice_enabled) inside
the MainScreen composable is unused; either remove that declaration (and any
now-unneeded imports) or actually use it where intended (e.g., pass it to a
Snackbar, dialog, or UI text) — if it’s meant as a placeholder for future work,
replace the declaration with a short TODO comment referencing its intended use;
locate the val noticeEnabledMessage in MainScreen.kt to apply the change.
🧹 Nitpick comments (1)
app/src/main/java/com/daedan/festabook/presentation/common/component/SnackBar.kt (1)

66-78: errorMessages 맵의 remember 키 누락 검토 필요

errorMessages 맵이 remember {} 블록 안에서 키 없이 생성되지만, 맵의 값들(clientErrorMessage 등)은 블록 외부에서 stringResource로 가져옵니다. 앱 실행 중 로케일이 변경되면 stringResource 값은 갱신되지만 remember 블록 내부의 맵은 재생성되지 않아 이전 로케일의 메시지가 유지될 수 있습니다.

만약 런타임 로케일 변경을 지원해야 한다면 remember 키에 문자열 값들을 포함하거나, 맵 생성을 remember 외부로 이동하는 것을 고려해 주세요.

♻️ 제안: remember 키에 문자열 값 추가
     val errorMessages =
-        remember {
+        remember(clientErrorMessage, serverErrorMessage, networkErrorMessage, unknownErrorMessage) {
             mapOf(
                 ApiResultException.ClientException::class to clientErrorMessage,
                 ApiResultException.ServerException::class to serverErrorMessage,
                 ApiResultException.NetworkException::class to networkErrorMessage,
                 ApiResultException.UnknownException::class to unknownErrorMessage,
             )
         }

Comment on lines +63 to +66
val snackbarHostState = remember { SnackbarHostState() }
val snackbarManager = rememberAppSnackbarManager(snackbarHostState)
val backPressExitMessage = stringResource(R.string.back_press_exit_message)
val noticeEnabledMessage = stringResource(R.string.setting_notice_enabled)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

사용되지 않는 변수 확인 필요

noticeEnabledMessage가 선언되었지만 이 파일 내에서 사용되지 않습니다. 향후 구현을 위해 의도적으로 추가한 것인지, 아니면 제거해야 하는지 확인해 주세요.

🔧 사용하지 않는 경우 제거 제안
 val snackbarHostState = remember { SnackbarHostState() }
 val snackbarManager = rememberAppSnackbarManager(snackbarHostState)
 val backPressExitMessage = stringResource(R.string.back_press_exit_message)
-val noticeEnabledMessage = stringResource(R.string.setting_notice_enabled)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
val snackbarHostState = remember { SnackbarHostState() }
val snackbarManager = rememberAppSnackbarManager(snackbarHostState)
val backPressExitMessage = stringResource(R.string.back_press_exit_message)
val noticeEnabledMessage = stringResource(R.string.setting_notice_enabled)
val snackbarHostState = remember { SnackbarHostState() }
val snackbarManager = rememberAppSnackbarManager(snackbarHostState)
val backPressExitMessage = stringResource(R.string.back_press_exit_message)
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/daedan/festabook/presentation/main/component/MainScreen.kt`
around lines 63 - 66, The local val noticeEnabledMessage declared via
noticeEnabledMessage = stringResource(R.string.setting_notice_enabled) inside
the MainScreen composable is unused; either remove that declaration (and any
now-unneeded imports) or actually use it where intended (e.g., pass it to a
Snackbar, dialog, or UI text) — if it’s meant as a placeholder for future work,
replace the declaration with a short TODO comment referencing its intended use;
locate the val noticeEnabledMessage in MainScreen.kt to apply the change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants