Skip to content

[Feature/#56] 커스텀 토스트 메시지 구현#61

Merged
wjdrjs00 merged 5 commits intodevelopfrom
feature/#56-custom-toast
Jul 30, 2025
Merged

[Feature/#56] 커스텀 토스트 메시지 구현#61
wjdrjs00 merged 5 commits intodevelopfrom
feature/#56-custom-toast

Conversation

@wjdrjs00
Copy link
Copy Markdown
Member

@wjdrjs00 wjdrjs00 commented Jul 30, 2025

[ PR Content ]

앱 전역에서 사용 가능한 커스텀 토스트 메시지를 구현했습니다.

Related issue

Screenshot 📸

default.mp4

Work Description

  • 커스텀 토스트메시지 컴포넌트 구현
  • 뒤로가기 시 앱 종료 알림 토스트 메시지 구현
  • 감정구슬 등록완료 알림 토스트 메시지 구현
  • 루틴 토글 실패 알림 토스트 메시지 구현

To Reviewers 📢

  • 추천루틴에서 사용되는 토스트 메시지의 경우 "추천 루틴"화면에서 감정등록 화면에서 감정등록을 한 뒤 "변경통신에 성공한 경우" 성공에 대한 값을 넘겨받아야 띄울수 있을거 같다고 판단을 해서 구현을 진행하지 못했습니다..! 혹시나 제가 잘못 이해한것이라면 의견 남겨주시면 감사하겠습니다요!
  • 구현 과정에서 토스트가 표시 중일 때 다른 메시지를 호출하면 기존 타이머가 계속 진행되어 새 메시지가 짧게 표시되는 문제를 발견했습니다요..
    이 문제를 BitnagilToastState의 toastId 증가 방식과 LaunchedEffect(state.toastId)를 통해 해결하여 새로운 메시지 표시 시마다 타이머가 2초로 정확히 리셋되도록 하는 방식으로 해결했습니다.
  • 이외 궁금하신 내용이 있다면 리뷰 남겨주세요!

Summary by CodeRabbit

  • 신규 기능

    • 전역 토스트 알림 시스템이 앱에 도입되어, 주요 화면에서 사용자에게 안내 메시지 및 경고를 표시할 수 있습니다.
    • 홈 화면에서 특정 이벤트(예: 루틴 완료 실패, 감정 등록 등) 발생 시 토스트 알림이 표시됩니다.
  • 버그 수정

    • 홈 화면의 플로팅 액션 메뉴 여백(padding) 처리가 개선되었습니다.
  • 디자인/스타일

    • 신규 경고 아이콘(ic_modal_warning)이 추가되고, 기존 경고 아이콘(ic_warning)이 더 간결하게 리디자인되었습니다.
    • 설정 화면의 확인 다이얼로그에 새로운 경고 아이콘이 적용되었습니다.
  • 리팩터링

    • 홈 화면의 네비게이션 및 토스트 표시 로직이 ViewModel의 사이드 이펙트 흐름으로 통합되어 코드 구조가 개선되었습니다.

wjdrjs00 added 5 commits July 30, 2025 19:33
- 기존 모달용 에셋 -> ic_modal_warning으로 수정
- 전역에서 사용할 수 있는 BitnagilToast 를 관리하는 GlobalBitnagilToast 싱글톤 객체 추가
- MainActivity에 BitnagilToastContainer 추가
- 루틴 완료/미완료 처리 실패 시 토스트 메시지 표시
- 감정 구슬 중복 등록 시 토스트 메시지 표시
@wjdrjs00 wjdrjs00 requested a review from l5x5l July 30, 2025 11:08
@wjdrjs00 wjdrjs00 self-assigned this Jul 30, 2025
@wjdrjs00 wjdrjs00 added ✨ Feature 새로운 기능 구현 🧤 대현 labels Jul 30, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jul 30, 2025

Walkthrough

앱 전체에서 사용할 수 있는 커스텀 토스트 메시지 시스템이 도입되었습니다. 새로운 디자인의 토스트 컴포넌트와 상태 관리, 글로벌 토스트 싱글턴, 그리고 각 화면 및 ViewModel에서 토스트 호출 로직이 추가 및 통합되었습니다. 기존 경고 아이콘 리소스도 개선 및 교체되었습니다.

Changes

Cohort / File(s) Change Summary
메인 UI 및 글로벌 토스트 통합
app/src/main/java/com/threegap/bitnagil/MainActivity.kt, presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt
메인 액티비티에 글로벌 토스트 상태 및 컨테이너 추가, 글로벌 토스트 싱글턴 객체 및 초기화 구현, 글로벌 토스트 메시지 호출 방식 도입
홈 네비게이션 및 홈 화면 토스트 연동
app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt, presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt, presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt
홈 화면에서 토스트 및 네비게이션 사이드이펙트 처리, intent 및 side effect 구조 확장, 뒤로가기 경고 토스트 표시 등 토스트 연동
토스트 컴포넌트 및 상태 관리
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt
커스텀 토스트 메시지 컴포넌트, 상태 관리 클래스, 애니메이션 처리, 중복 방지 로직, 프리뷰 추가
토스트/경고 아이콘 리소스
core/designsystem/src/main/res/drawable/ic_modal_warning.xml, core/designsystem/src/main/res/drawable/ic_warning.xml, presentation/src/main/java/com/threegap/bitnagil/presentation/setting/component/block/ConfirmDialog.kt
신규 경고 아이콘 리소스 추가, 기존 경고 아이콘 단순화 및 리소스 교체, 다이얼로그에서 신규 아이콘 사용
홈 인텐트 및 사이드이펙트 확장
presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt, presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeSideEffect.kt
홈 인텐트 및 사이드이펙트 sealed class 확장: 토스트, 네비게이션 등 다양한 액션 추가 및 기존 구조 개선

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant MainScreen
    participant HomeViewModel
    participant GlobalBitnagilToast
    participant BitnagilToastContainer

    User->>MainScreen: 버튼 클릭/액션 발생
    MainScreen->>HomeViewModel: HomeIntent 전달
    HomeViewModel->>HomeViewModel: 상태/사이드이펙트 처리
    HomeViewModel-->>MainScreen: HomeSideEffect(ShowToast 등)
    MainScreen->>GlobalBitnagilToast: show()/showWarning()
    GlobalBitnagilToast->>BitnagilToastContainer: 상태 업데이트
    BitnagilToastContainer-->>User: 토스트 메시지 애니메이션 표시
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
토스트 메시지 컴포넌트 구현 (#56)
토스트 메시지 기능 구현 (#56)

Poem

🐰
토스트가 번쩍! 경고가 뿅!
이제 어디서든 메시지 띄워요,
귀여운 아이콘, 애니메이션도 척척,
비트나길 앱이 더욱 반짝!
개발자 토끼도 깡총깡총 춤춰요~

( ˘▽˘)っ🥕

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/#56-custom-toast

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@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: 0

🧹 Nitpick comments (6)
core/designsystem/src/main/res/drawable/ic_modal_warning.xml (1)

9-16: 하드코딩된 색상 값 검토 필요

색상 값이 하드코딩되어 있습니다 (#C2C4C8, #ffffff). 다크 모드나 테마 변경을 고려하여 BitnagilTheme.colors의 색상을 사용하는 것을 권장합니다.

다음과 같이 색상 리소스를 정의하여 사용하는 것을 고려해보세요:

<path
    android:fillColor="?attr/modalWarningBackground"
    android:pathData="..." />
<path
    android:fillColor="?attr/modalWarningForeground"
    android:pathData="..." />
core/designsystem/src/main/res/drawable/ic_warning.xml (1)

1-12: 경고 아이콘 단순화 및 크기 조정 적절

아이콘을 55dp에서 24dp로 축소하고 디자인을 단순화한 것이 좋은 개선입니다. 표준적인 아이콘 크기를 사용하고 더 범용적인 디자인이 되었습니다.

하드코딩된 색상(#FF6868) 대신 테마 색상 사용을 고려해보세요:

android:fillColor="?attr/warningColor"
presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeSideEffect.kt (1)

6-7: 토스트 메시지 구현이 명확하고 적절합니다.

두 개의 토스트 side effect가 잘 구분되어 있습니다. 향후 확장성을 고려한다면 아이콘을 옵셔널 파라미터로 하는 단일 클래스도 고려해볼 수 있지만, 현재 구현은 명확하고 MVI 패턴에 잘 부합합니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt (1)

14-16: WeakReference null 처리에 대한 로깅 고려.

현재 _toastStateRef?.get()이 null을 반환하면 조용히 무시되는데, 디버깅을 위해 로그를 추가하는 것을 고려해보세요.

 fun show(text: String, icon: Int? = null) {
-    _toastStateRef?.get()?.show(text, icon)
+    _toastStateRef?.get()?.show(text, icon) 
+        ?: Log.w("GlobalBitnagilToast", "ToastState is not initialized or has been garbage collected")
 }
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt (2)

77-83: LaunchedEffect에서 중복 조건 체크를 제거하세요.

Line 77에서 state.isVisible을 이미 체크했는데 Line 79에서 다시 체크하는 것은 불필요합니다.

 LaunchedEffect(state.toastId) {
-    if (state.isVisible) {
-        delay(duration)
-        state.hide()
-    }
+    delay(duration)
+    state.hide()
 }

55-55: 아이콘 색상이 하드코딩되어 있습니다.

경고 아이콘에 BitnagilTheme.colors.error 색상이 하드코딩되어 있는데, 아이콘 타입에 따라 다른 색상을 사용할 수 있도록 개선하는 것을 고려해보세요.

 BitnagilIcon(
     id = id,
-    tint = BitnagilTheme.colors.error,
+    tint = when (id) {
+        R.drawable.ic_warning -> BitnagilTheme.colors.error
+        R.drawable.ic_check -> BitnagilTheme.colors.success
+        else -> BitnagilTheme.colors.white
+    },
     modifier = Modifier
         .padding(end = 4.dp)
         .size(24.dp),
 )
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 997a706 and 9287a72.

📒 Files selected for processing (11)
  • app/src/main/java/com/threegap/bitnagil/MainActivity.kt (2 hunks)
  • app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt (3 hunks)
  • core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt (1 hunks)
  • core/designsystem/src/main/res/drawable/ic_modal_warning.xml (1 hunks)
  • core/designsystem/src/main/res/drawable/ic_warning.xml (1 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt (1 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt (5 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt (2 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt (1 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeSideEffect.kt (1 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/setting/component/block/ConfirmDialog.kt (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt (1)

Learnt from: l5x5l
PR: #38
File: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt:30-35
Timestamp: 2025-07-21T10:38:49.104Z
Learning: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt의 TextButton 컴포넌트는 임시로 구현된 컴포넌트로, 디자인 시스템 구현시 대체 예정입니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt (1)

Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like LoadMyPageSuccess are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.

presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt (2)

Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like LoadMyPageSuccess are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.

Learnt from: l5x5l
PR: #38
File: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt:30-35
Timestamp: 2025-07-21T10:38:49.104Z
Learning: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt의 TextButton 컴포넌트는 임시로 구현된 컴포넌트로, 디자인 시스템 구현시 대체 예정입니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt (1)

Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like LoadMyPageSuccess are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.

app/src/main/java/com/threegap/bitnagil/MainActivity.kt (1)

Learnt from: l5x5l
PR: #38
File: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt:30-35
Timestamp: 2025-07-21T10:38:49.104Z
Learning: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt의 TextButton 컴포넌트는 임시로 구현된 컴포넌트로, 디자인 시스템 구현시 대체 예정입니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeSideEffect.kt (1)

Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like LoadMyPageSuccess are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.

core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt (1)

Learnt from: l5x5l
PR: #38
File: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt:30-35
Timestamp: 2025-07-21T10:38:49.104Z
Learning: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt의 TextButton 컴포넌트는 임시로 구현된 컴포넌트로, 디자인 시스템 구현시 대체 예정입니다.

🧬 Code Graph Analysis (3)
presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt (2)
  • sendSideEffect (23-23)
  • sendIntent (30-37)
app/src/main/java/com/threegap/bitnagil/MainActivity.kt (2)
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt (2)
  • rememberBitnagilToast (136-137)
  • BitnagilToastContainer (71-97)
app/src/main/java/com/threegap/bitnagil/MainScreen.kt (1)
  • MainScreen (9-22)
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt (1)
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilIcon.kt (1)
  • BitnagilIcon (21-33)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (31)
core/designsystem/src/main/res/drawable/ic_modal_warning.xml (1)

2-5: 아이콘 크기 적절성 확인

55dp는 일반적인 아이콘 크기보다 큽니다. 모달 다이얼로그용 특수 아이콘이라면 적절하지만, 다른 UI 컨텍스트에서 재사용성을 고려하여 크기가 적절한지 확인해주세요.

presentation/src/main/java/com/threegap/bitnagil/presentation/setting/component/block/ConfirmDialog.kt (1)

56-56: LGTM! 모달 전용 경고 아이콘으로 적절한 업데이트

새로 추가된 ic_modal_warning 리소스로의 변경이 적절합니다. 모달 다이얼로그 컨텍스트에 맞는 더 상세한 아이콘을 사용하게 되었습니다.

app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt (3)

28-28: LGTM! 글로벌 토스트 시스템 통합

GlobalBitnagilToast 임포트가 적절하게 추가되었습니다.


118-118: 패딩 모디파이어 통합으로 코드 정리

여러 개의 .padding() 호출을 하나로 통합한 것이 좋은 개선입니다.


134-134: 사용자 경험 개선을 위한 토스트 메시지 추가

뒤로가기 버튼 두 번 누르기 패턴에 토스트 메시지를 추가하여 사용자에게 명확한 피드백을 제공하는 것이 좋은 UX 개선입니다.

app/src/main/java/com/threegap/bitnagil/MainActivity.kt (2)

26-30: 글로벌 토스트 상태 초기화 구현 적절

rememberBitnagilToast()로 상태를 생성하고 LaunchedEffectGlobalBitnagilToast를 초기화하는 패턴이 Compose 모범 사례를 따르고 있습니다.


32-43: 토스트 컨테이너 레이아웃 구성 검토

Box 레이아웃으로 토스트 컨테이너를 오버레이하는 구조가 적절합니다. 하단 100dp 패딩은 bottom navigation과의 충돌을 방지하기에 적절한 값으로 보입니다.

토스트 메시지가 다른 UI 요소(예: 플로팅 액션 버튼)와 겹치지 않는지 확인해주세요.

presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt (2)

7-21: 잘 설계된 글로벌 토스트 싱글턴입니다.

WeakReference를 사용하여 메모리 누수를 방지하고, null-safe 접근 패턴을 적용한 것이 좋습니다. 편의 메서드들도 API를 깔끔하게 만들어 줍니다.


7-21: 전역 토스트 시스템 구현이 우수합니다.

WeakReference를 사용하여 메모리 누수를 방지하고, 편의 메서드들을 제공하는 설계가 좋습니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt (6)

29-30: 적절한 import 추가입니다.

새로운 기능에 필요한 import들이 올바르게 추가되었습니다.

Also applies to: 39-39


54-76: MVI 아키텍처를 잘 따른 사이드 이펙트 처리입니다.

각 사이드 이펙트 타입에 따라 적절한 액션을 수행하고, 글로벌 토스트 시스템을 올바르게 활용하고 있습니다.


95-95: 네비게이션 로직의 중앙집중화가 잘 되었습니다.

직접적인 네비게이션 콜백 호출을 Intent 전송으로 변경하여 관심사 분리가 개선되었습니다. MVI 아키텍처에 잘 부합합니다.

Also applies to: 147-152


29-30: 필요한 임포트가 정확히 추가되었습니다.

새로운 토스트 시스템과 사이드 이펙트 처리를 위한 임포트가 적절합니다.


54-76: MVI 패턴을 잘 적용한 사이드 이펙트 처리입니다.

UI에서 직접 네비게이션을 호출하지 않고 ViewModel의 사이드 이펙트를 통해 처리하는 방식이 관심사 분리 원칙에 잘 맞습니다. 토스트 표시도 전역 시스템을 통해 일관되게 처리되고 있습니다.


147-152: 직접 네비게이션 호출을 인텐트 전송으로 개선했습니다.

기존에 콜백을 직접 호출하던 방식에서 ViewModel로 인텐트를 전송하는 방식으로 변경하여 MVI 아키텍처를 더 잘 따르게 되었습니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt (2)

23-26: 새로운 Intent들이 잘 설계되었습니다.

네이밍 컨벤션이 일관성 있고, 데이터가 필요한 경우 data class, 단순한 액션의 경우 data object를 적절히 사용했습니다. MVI 아키텍처에 잘 부합합니다.


23-26: 새로운 인텐트들이 적절하게 정의되었습니다.

네비게이션과 실패 케이스를 위한 인텐트들이 MVI 패턴에 맞게 잘 정의되었습니다. 특히 RoutineToggleCompletionFailure처럼 실패 상황을 명시적으로 처리하는 것이 좋습니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt (6)

204-226: 새로운 Intent 처리 로직이 잘 구현되었습니다.

OnRegisterEmotionClick의 조건부 로직이 적절하고, 모든 사이드 이펙트 발생이 올바르게 구현되었습니다. 상태 변경이 없는 경우 null을 반환하는 것도 적절합니다.


477-477: 에러 처리가 개선되었습니다.

루틴 동기화 실패 시 사용자에게 피드백을 제공하는 Intent를 추가하여 사용자 경험이 향상되었습니다.


204-211: 감정 등록 클릭 처리 로직이 우수합니다.

이미 감정이 등록된 경우와 아닌 경우를 구분하여 처리하는 조건부 로직이 잘 구현되었습니다. 사용자 경험을 고려한 좋은 설계입니다.


213-216: 루틴 등록 네비게이션이 올바르게 구현되었습니다.

사이드 이펙트를 통한 네비게이션 처리가 MVI 패턴에 맞게 잘 구현되었습니다.


218-221: 실패 케이스 처리가 개선되었습니다.

루틴 토글 실패 시 사용자에게 명확한 피드백을 제공하는 것이 좋습니다.


477-477: 실패 처리에 토스트 알림이 추가되었습니다.

동기화 실패 시 사용자에게 피드백을 제공하여 UX가 개선되었습니다.

core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt (6)

34-69: 토스트 메시지 컴포넌트가 잘 설계되었습니다.

디자인 시스템을 일관성 있게 사용하고, 옵셔널 아이콘 지원이 깔끔하게 구현되었습니다.


71-97: 토스트 컨테이너 구현이 훌륭합니다.

애니메이션과 자동 숨기기 기능이 잘 구현되었고, toastId를 키로 사용하여 재구성을 적절히 트리거합니다.


99-134: 상태 관리가 잘 구현되었습니다.

적절한 캡슐화와 Compose 반응성을 위한 mutableStateOf 사용이 올바릅니다. toastId를 통한 재구성 트리거링도 적절합니다.


122-125: 중복 방지 로직이 잘 구현되었습니다.

500ms 윈도우와 텍스트/아이콘 비교를 통한 중복 방지가 적절합니다. 다만 빠른 연속 호출 시나리오에서의 동작을 고려해보세요.


34-69: 토스트 UI 컴포넌트가 잘 설계되었습니다.

아이콘과 텍스트를 함께 표시할 수 있는 유연한 구조와 적절한 스타일링이 적용되었습니다.


99-134: 토스트 상태 관리가 잘 구현되었습니다.

중복 토스트 방지 로직과 상태 관리가 깔끔하게 구현되었습니다. toastId를 사용한 리컴포지션 트리거링도 좋은 접근입니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeSideEffect.kt (2)

8-10: 네비게이션 side effect 구조가 일관되고 적절합니다.

파라미터가 필요한 네비게이션은 data class로, 단순 네비게이션은 data object로 구현하여 일관된 패턴을 유지하고 있습니다. "NavigateTo" 접두사를 사용한 명명 규칙도 명확합니다.


5-11: MVI 아키텍처 패턴을 잘 따르는 구조입니다.

sealed interface를 사용하여 타입 안전성을 보장하고, MviSideEffect를 확장하여 기존 아키텍처와 일관성을 유지합니다. 토스트 메시지와 네비게이션 기능을 명확히 분리한 설계가 우수합니다.

Copy link
Copy Markdown
Contributor

@l5x5l l5x5l left a comment

Choose a reason for hiding this comment

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

고생하셨습니다!

@wjdrjs00 wjdrjs00 merged commit 1a6e9f5 into develop Jul 30, 2025
2 checks passed
@wjdrjs00 wjdrjs00 deleted the feature/#56-custom-toast branch July 30, 2025 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능 구현 🧤 대현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] 커스텀 토스트 메시지 구현

2 participants