Skip to content

온보딩 과정 마케팅 알림 동의 플로우 추가#116

Merged
chanho0908 merged 6 commits intodevelopfrom
feat/#114-onboarding-marketing
Feb 26, 2026
Merged

온보딩 과정 마케팅 알림 동의 플로우 추가#116
chanho0908 merged 6 commits intodevelopfrom
feat/#114-onboarding-marketing

Conversation

@chanho0908
Copy link
Member

@chanho0908 chanho0908 commented Feb 26, 2026

이슈 번호

#114

작업내용

  • 온보딩 푸시/마케팅/야간 마케팅 동의 요청 기능 구현 완료

결과물

리뷰어에게 추가로 요구하는 사항 (선택)

온보딩 갈 수 있는 계정이 카카오 계정뿐인데 계속 테스트하다가 차단당함...
몇 번 테스트해서 기능 구현은 다된거 같은데 디테일하게 못해가지구 확인 부탁해 ㅠㅠ
스크린샷 2026-02-26 오후 11 39 06

@chanho0908 chanho0908 self-assigned this Feb 26, 2026
@chanho0908 chanho0908 added the Feature Extra attention is needed label Feb 26, 2026
@chanho0908 chanho0908 linked an issue Feb 26, 2026 that may be closed by this pull request
1 task
@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

Warning

Rate limit exceeded

@chanho0908 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 16 minutes and 26 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between fe4e586 and 751921b.

📒 Files selected for processing (8)
  • core/design-system/src/main/java/com/twix/designsystem/components/dialog/MarketingDialog.kt
  • feature/onboarding/src/main/java/com/twix/onboarding/OnBoardingViewModel.kt
  • feature/onboarding/src/main/java/com/twix/onboarding/couple/CoupleConnectRoute.kt
  • feature/onboarding/src/main/java/com/twix/onboarding/dday/DdayRoute.kt
  • feature/onboarding/src/main/java/com/twix/onboarding/di/OnBoardingModule.kt
  • feature/onboarding/src/main/java/com/twix/onboarding/invite/InviteCodeScreen.kt
  • feature/onboarding/src/main/java/com/twix/onboarding/navigation/OnboardingNavGraph.kt
  • feature/onboarding/src/main/java/com/twix/onboarding/profile/ProfileScreen.kt
📝 Walkthrough

Walkthrough

온보딩 흐름에 마케팅 정보 수신 동의를 처리하는 새로운 기능이 추가되었습니다. 디자인 시스템에 MarketingDialog 컴포넌트와 관련 UI 리소스(벡터 드로어블, 문자열)가 추가되었으며, CoupleConnectRoute에 다이얼로그 표시 및 알림 권한 확인 로직이 통합되었습니다. OnBoardingIntent에 SubmitMarketingConsent 인텐트가 추가되었고, OnBoardingViewModel의 initNotificationSettings 메서드가 사용자 선택값을 받아 처리하도록 수정되었습니다.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes


주요 검토 사항

MarketingDialog 컴포넌트 설계

마케팅 다이얼로그 구현이 명확하고 재사용 가능한 구조로 설계된 점이 좋습니다. 다만 다음을 확인해주세요:

질문: 사용자가 다이얼로그를 명시적으로 거절하는 경우 (다이얼로그를 닫기)의 처리 방식은 어떻게 되나요? 현재 구현에서는 onConfirm 콜백만 있어 보이는데, 취소 시나리오에 대한 처리가 필요할 수 있습니다.

권한 처리 로직 검증

CoupleConnectRoute에서 isNotificationPermissionGranted() 함수로 알림 권한을 확인하는 구현이 포함되어 있습니다:

확인 포인트:

  • rememberUpdatedState로 context를 관리한 점은 좋습니다 (재컴포지션 안정성)
  • TIRAMISU+ 버전 체크가 적절히 처리되었는지 검증 필요
  • 권한이 없는 경우 isPushEnabledfalse로 전달하는 로직이 명확히 구현되어 있으신가요?

상태 관리 흐름의 일관성

Intent 기반의 단방향 데이터 흐름 구조가 명확합니다:

제안: SubmitMarketingConsent 인텐트에서 세 개의 Boolean 파라미터를 받고 있는데, 파라미터 이름이 매우 유사합니다. 각 파라미터의 의미를 명확히 하는 것을 권장합니다:

  • isPushEnabled - 푸시 알림 활성화 여부
  • isMarketingEnabled - 마케팅 정보 알림 활성화 여부
  • isNightMarketingEnabled - 야간 마케팅 정보 알림 활성화 여부

이러한 의미가 코드에 충분히 반영되어 있는지 확인해 주세요.

문자열 리소스 검토

한국어 문자열들이 일관되게 추가되었습니다. 다이얼로그 설명 문자열 "* 언제든지 설정 > 알림 설정에서 변경 가능해요"에서 참조하는 실제 설정 화면이 존재하는지 확인이 필요합니다.

CoupleConnectScreenPreview 가시성 변경

프리뷰 함수를 private으로 변경한 점이 좋습니다. 이는 프리뷰의 범위를 명확히 제한합니다.

🚥 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
Title check ✅ Passed PR 제목이 변경사항의 주요 내용을 명확하게 설명합니다. 마케팅 알림 동의 플로우 추가라는 핵심 기능이 잘 드러나 있습니다.
Description check ✅ Passed PR 설명이 변경 사항과 관련이 있으며, 이슈 번호(#114)와 작업 내용(온보딩 푸시/마케팅/야간 마케팅 동의 요청 기능)을 명확히 기술하고 있습니다.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#114-onboarding-marketing

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.

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

🧹 Nitpick comments (4)
feature/onboarding/src/main/java/com/twix/onboarding/couple/CoupleConnectRoute.kt (1)

63-64: 사용되지 않는 currentContext 변수

currentContextrememberUpdatedState로 생성되었지만, Line 100에서 context가 직접 사용되고 있습니다. rememberUpdatedState는 콜백 내에서 최신 값을 참조하기 위해 사용되는데, 여기서는 일관성을 위해 currentContext를 사용하거나, 불필요하다면 제거하는 것이 좋겠습니다.

♻️ 수정 제안
     val context = LocalContext.current
-    val currentContext by rememberUpdatedState(context)
     
     // ... 
     
     MarketingDialog(
         visible = showMarketingDialog,
         onConfirm = { marketing, nightMarketing ->
             showMarketingDialog = false
             val isPushEnabled = isNotificationPermissionGranted(context)

또는 콜백 내에서 최신 context가 필요하다면:

     MarketingDialog(
         visible = showMarketingDialog,
         onConfirm = { marketing, nightMarketing ->
             showMarketingDialog = false
-            val isPushEnabled = isNotificationPermissionGranted(context)
+            val isPushEnabled = isNotificationPermissionGranted(currentContext)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/onboarding/src/main/java/com/twix/onboarding/couple/CoupleConnectRoute.kt`
around lines 63 - 64, The variable currentContext created with
rememberUpdatedState(LocalContext.current) is unused while the code continues to
reference context directly; either replace uses of context inside any callbacks
(e.g., lambdas that may run later) with currentContext.value to ensure the
latest Context is read, or remove the rememberUpdatedState call and the
currentContext declaration if you don't need a stable reference for callbacks;
update references to LocalContext.current, currentContext, rememberUpdatedState
and any callback/lambda that currently uses context accordingly.
core/design-system/src/main/java/com/twix/designsystem/components/dialog/MarketingDialog.kt (1)

114-134: 클릭 영역 확장 고려

현재 클릭 영역이 아이콘(24dp)에만 적용되어 있습니다. UX 개선을 위해 텍스트를 포함한 전체 Row를 클릭 가능하게 만드는 것을 고려해 보시는 것은 어떨까요?

💡 클릭 영역 확장 제안
     Row(
         verticalAlignment = Alignment.CenterVertically,
-        modifier = Modifier.fillMaxWidth(),
+        modifier = Modifier
+            .fillMaxWidth()
+            .noRippleClickable(onClick = onClick),
     ) {
         Image(
             painter = painterResource(icon),
             contentDescription = "$text $checkboxDescription",
-            modifier =
-                Modifier
-                    .size(24.dp)
-                    .noRippleClickable(onClick = onClick),
+            modifier = Modifier.size(24.dp),
         )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@core/design-system/src/main/java/com/twix/designsystem/components/dialog/MarketingDialog.kt`
around lines 114 - 134, The Row's click handling is currently applied only to
the Image via .noRippleClickable(onClick) so expand the tappable area by moving
or adding the click handler to the Row (e.g., apply
Modifier.noRippleClickable(onClick) on the Row's modifier or wrap the Row with a
clickable container) so that the entire Row including AppText responds to
onClick; keep the Image size and spacing as-is and ensure you remove the
duplicate .noRippleClickable from Image to avoid overlapping handlers.
feature/onboarding/src/main/java/com/twix/onboarding/vm/OnBoardingViewModel.kt (1)

152-161: 에러 처리 누락 확인 필요

initNotificationSettings 호출에서 onSuccess가 빈 람다이고 onError 핸들러가 정의되어 있지 않습니다. 알림 설정 초기화가 실패할 경우, 사용자에게 피드백이 전달되지 않아 마케팅 동의가 실제로 저장되었는지 알 수 없습니다.

의도적인 fire-and-forget 패턴이라면 괜찮지만, 사용자 경험을 위해 실패 시 토스트 메시지나 재시도 로직을 고려해 보시는 것은 어떨까요?

💡 에러 처리 추가 제안
     private fun initNotificationSettings(
         isPushEnabled: Boolean,
         isMarketingEnabled: Boolean,
         isNightMarketingEnabled: Boolean,
     ) {
         launchResult(
             block = {
                 notificationRepository.initNotificationSettings(
                     isPushEnabled,
                     isMarketingEnabled,
                     isNightMarketingEnabled,
                 )
             },
             onSuccess = {},
+            onError = {
+                // 필요시 에러 처리 로직 추가
+                // emitSideEffect(OnBoardingSideEffect.Marketing.ShowSettingsFailToast)
+            },
         )
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/onboarding/src/main/java/com/twix/onboarding/vm/OnBoardingViewModel.kt`
around lines 152 - 161, The current call to launchResult uses
notificationRepository.initNotificationSettings with an empty onSuccess and no
onError, so failures are silent; update the launchResult invocation that wraps
notificationRepository.initNotificationSettings to provide a non-empty onSuccess
(e.g., confirm UI state or show success toast) and add an onError lambda that
handles failures (show a toast/error dialog and optionally trigger a retry or
revert local state). Specifically modify the launchResult call site (the block
invoking initNotificationSettings) to supply onSuccess and onError handlers that
call your ViewModel methods or UI event dispatcher to surface errors to the
user.
core/design-system/src/main/res/drawable/ic_empty_check.xml (1)

1-18: 하드코딩된 색상 및 다크 모드 미지원 확인 필요

현재 색상이 drawable 내에 직접 하드코딩되어 있습니다 (#ffffff, #C6C6C6). 디자인 시스템 가이드라인에 따르면, 색상은 테마에서 참조하는 것이 권장됩니다. 또한 체크마크 stroke 색상이 #ffffff로 배경 fill 색상과 동일하여 체크마크가 보이지 않을 수 있는데, 이것이 "빈 체크박스" 상태를 의도한 것인지 확인 부탁드립니다.

다크 모드 지원을 위해 res/drawable-night/ 폴더에 별도의 리소스를 추가하거나, 테마 색상을 참조하는 방식을 고려해 주세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/design-system/src/main/res/drawable/ic_empty_check.xml` around lines 1 -
18, The drawable currently hardcodes colors in the vector paths (first path's
android:fillColor and android:strokeColor using `#ffffff` and `#C6C6C6`, and the
check path's android:strokeColor using `#ffffff`) which breaks theming and can
make the check invisible; update both path elements to reference theme
attributes (e.g., use ?attr/colorSurface / ?attr/colorOnSurface or a custom
color attribute like ?attr/dsCheckboxBorderColor and ?attr/dsCheckboxCheckColor)
instead of hex literals, and ensure the check stroke color differs from the fill
so an “empty” vs “checked” state is visually correct; also provide a dark-mode
variant (or ensure the theme attrs adapt in night mode) so colors render
correctly in dark theme.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@core/design-system/src/main/java/com/twix/designsystem/components/dialog/MarketingDialog.kt`:
- Around line 118-125: The Image composable currently sets contentDescription =
null which prevents screen readers from announcing the checkbox state; update
the Image in MarketingDialog.kt (the Image using painterResource(icon) and
noRippleClickable(onClick)) to supply a meaningful description that reflects the
current checked state (e.g., use an existing state variable like isChecked or
checkedState to choose between "checked" / "unchecked" or better, use
stringResource(R.string.xxx_checked) and stringResource(R.string.xxx_unchecked)
for localization), so accessibility tools can convey the checkbox status.

---

Nitpick comments:
In
`@core/design-system/src/main/java/com/twix/designsystem/components/dialog/MarketingDialog.kt`:
- Around line 114-134: The Row's click handling is currently applied only to the
Image via .noRippleClickable(onClick) so expand the tappable area by moving or
adding the click handler to the Row (e.g., apply
Modifier.noRippleClickable(onClick) on the Row's modifier or wrap the Row with a
clickable container) so that the entire Row including AppText responds to
onClick; keep the Image size and spacing as-is and ensure you remove the
duplicate .noRippleClickable from Image to avoid overlapping handlers.

In `@core/design-system/src/main/res/drawable/ic_empty_check.xml`:
- Around line 1-18: The drawable currently hardcodes colors in the vector paths
(first path's android:fillColor and android:strokeColor using `#ffffff` and
`#C6C6C6`, and the check path's android:strokeColor using `#ffffff`) which breaks
theming and can make the check invisible; update both path elements to reference
theme attributes (e.g., use ?attr/colorSurface / ?attr/colorOnSurface or a
custom color attribute like ?attr/dsCheckboxBorderColor and
?attr/dsCheckboxCheckColor) instead of hex literals, and ensure the check stroke
color differs from the fill so an “empty” vs “checked” state is visually
correct; also provide a dark-mode variant (or ensure the theme attrs adapt in
night mode) so colors render correctly in dark theme.

In
`@feature/onboarding/src/main/java/com/twix/onboarding/couple/CoupleConnectRoute.kt`:
- Around line 63-64: The variable currentContext created with
rememberUpdatedState(LocalContext.current) is unused while the code continues to
reference context directly; either replace uses of context inside any callbacks
(e.g., lambdas that may run later) with currentContext.value to ensure the
latest Context is read, or remove the rememberUpdatedState call and the
currentContext declaration if you don't need a stable reference for callbacks;
update references to LocalContext.current, currentContext, rememberUpdatedState
and any callback/lambda that currently uses context accordingly.

In
`@feature/onboarding/src/main/java/com/twix/onboarding/vm/OnBoardingViewModel.kt`:
- Around line 152-161: The current call to launchResult uses
notificationRepository.initNotificationSettings with an empty onSuccess and no
onError, so failures are silent; update the launchResult invocation that wraps
notificationRepository.initNotificationSettings to provide a non-empty onSuccess
(e.g., confirm UI state or show success toast) and add an onError lambda that
handles failures (show a toast/error dialog and optionally trigger a retry or
revert local state). Specifically modify the launchResult call site (the block
invoking initNotificationSettings) to supply onSuccess and onError handlers that
call your ViewModel methods or UI event dispatcher to surface errors to the
user.

ℹ️ Review info

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dde8b28 and fe4e586.

📒 Files selected for processing (6)
  • core/design-system/src/main/java/com/twix/designsystem/components/dialog/MarketingDialog.kt
  • core/design-system/src/main/res/drawable/ic_empty_check.xml
  • core/design-system/src/main/res/values/strings.xml
  • feature/onboarding/src/main/java/com/twix/onboarding/couple/CoupleConnectRoute.kt
  • feature/onboarding/src/main/java/com/twix/onboarding/model/OnBoardingIntent.kt
  • feature/onboarding/src/main/java/com/twix/onboarding/vm/OnBoardingViewModel.kt

Copy link
Member

@dogmania dogmania left a comment

Choose a reason for hiding this comment

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

고생하셨슴당 테스트해보니까 잘 되네요

modifier =
Modifier
.size(24.dp)
.noRippleClickable(onClick = onClick),
Copy link
Member

Choose a reason for hiding this comment

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

클릭 영역을 텍스트를 클릭해도 가능하도록 Row 전체로 잡아도 좋을 것 같아요!

@chanho0908 chanho0908 merged commit d471b69 into develop Feb 26, 2026
1 check passed
@chanho0908 chanho0908 deleted the feat/#114-onboarding-marketing branch February 26, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature Extra attention is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

온보딩 마케팅 알림 동의 플로우 추가

2 participants