feat: 앱 아이콘 뱃지 동기화 및 알림 실시간 갱신 구현 - #280
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No description provided. |
|
Warning Review limit reached
More reviews will be available in 39 minutes and 47 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (13)
📝 WalkthroughWalkthrough웹 알림 읽음 처리 후 WebBridge를 통해 앱 아이콘 뱃지 수를 동기화하는 기능을 추가했습니다. Changes앱 아이콘 뱃지 동기화 (WebBridge WEB_REQ_SET_BADGE)
Sequence Diagram(s)sequenceDiagram
rect rgba(100, 150, 255, 0.5)
Note over Web,NativeApp: 경로 1 — 읽음 처리 후 즉각 뱃지 반영
participant Web as Web (알림 읽음 처리)
participant WebBridge as WebBridge
participant NativeApp as NativeApp (index.tsx)
participant pushNotification as pushNotification.ts
participant Notifications as expo-notifications
Web->>Web: onSuccess → invalidateQueries
Web->>WebBridge: postMessage(WEB_REQ_SET_BADGE, { count })
WebBridge->>NativeApp: 메시지 전달
NativeApp->>pushNotification: setAppBadgeCount(count)
pushNotification->>Notifications: setBadgeCountAsync(count)
end
rect rgba(100, 200, 150, 0.5)
Note over FCM,Notifications: 경로 2 — FCM 포그라운드 수신 시 뱃지 자동 갱신
participant FCM as FCM (포그라운드)
FCM->>pushNotification: onMessage(remoteMessage)
pushNotification->>pushNotification: unreadCount 추출 및 변환
pushNotification->>Notifications: setBadgeCountAsync(unreadCount)
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/app/utils/pushNotification.ts`:
- Around line 127-130: The code in the unreadCount handling block has two
issues: the comparison using !== undefined violates ESLint's no-undefined rule,
and the Number(unreadCount) conversion can produce NaN which gets passed to
setAppBadgeCount without validation. Replace the !== undefined check with an
ESLint-compliant approach (such as using typeof comparison or checking for a
truthy string representation), and add a validation step to ensure the converted
number is not NaN using Number.isNaN() before calling setAppBadgeCount to
prevent invalid badge values from being set.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 73ba91a6-a4bd-4f9c-bfc2-78a74fc6ca92
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (9)
apps/app/app.jsonapps/app/app/index.tsxapps/app/package.jsonapps/app/utils/pushNotification.tsapps/web/src/app/notification/_hooks/usePostNotificationsRead.tspackages/core/src/consts/webBridge.tspackages/core/src/index.tspackages/core/src/types/pushNotification.tspackages/core/src/types/webBridge.ts
| const unreadCount = remoteMessage.data?.unreadCount; | ||
| if (unreadCount !== undefined) { | ||
| await setAppBadgeCount(Number(unreadCount)); | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
FCM unreadCount 처리에서 lint 에러와 비정상 배지 값 전파 가능성이 있습니다.
Line 128의 !== undefined는 현재 ESLint(no-undefined) 에러를 유발하고, Line 129는 숫자 검증 없이
Number(unreadCount)를 사용해 NaN이 배지 API로 전달될 수 있습니다.
수정 예시
- const unreadCount = remoteMessage.data?.unreadCount;
- if (unreadCount !== undefined) {
- await setAppBadgeCount(Number(unreadCount));
- }
+ const unreadCount = remoteMessage.data?.unreadCount;
+ if (unreadCount != null) {
+ const nextBadgeCount = Number(unreadCount);
+ if (Number.isFinite(nextBadgeCount) && nextBadgeCount >= 0) {
+ await setAppBadgeCount(Math.trunc(nextBadgeCount));
+ }
+ }📝 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.
| const unreadCount = remoteMessage.data?.unreadCount; | |
| if (unreadCount !== undefined) { | |
| await setAppBadgeCount(Number(unreadCount)); | |
| } | |
| const unreadCount = remoteMessage.data?.unreadCount; | |
| if (unreadCount != null) { | |
| const nextBadgeCount = Number(unreadCount); | |
| if (Number.isFinite(nextBadgeCount) && nextBadgeCount >= 0) { | |
| await setAppBadgeCount(Math.trunc(nextBadgeCount)); | |
| } | |
| } |
🧰 Tools
🪛 ESLint
[error] 128-128: Unexpected use of undefined.
(no-undefined)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/app/utils/pushNotification.ts` around lines 127 - 130, The code in the
unreadCount handling block has two issues: the comparison using !== undefined
violates ESLint's no-undefined rule, and the Number(unreadCount) conversion can
produce NaN which gets passed to setAppBadgeCount without validation. Replace
the !== undefined check with an ESLint-compliant approach (such as using typeof
comparison or checking for a truthy string representation), and add a validation
step to ensure the converted number is not NaN using Number.isNaN() before
calling setAppBadgeCount to prevent invalid badge values from being set.
Source: Linters/SAST tools
c31ebbe to
cdb05d6
Compare
cdb05d6 to
a4e8432
Compare
a7d4b13 to
a4e8432
Compare
a4e8432 to
b1b0895
Compare
* chore: expo-notifications 설치 * feat: WebBridge 타입 추가 * feat: pushNotification 타입 추가 * feat: WebBridgeMessageT 유니온에 추가 * feat: usePostNotificationsRead에서 unreadCount를 WebBridge로 전송 * feat: WEB_REQ_SET_BADGE 처리 + silent push 수신 시 뱃지 업데이트 * feat: WEB_REQ_SET_BADGE 메시지 처리 * chore: expo-notifications 플러그인 app.json에 추가 * chore: expo-notifications SDK 54 호환 버전으로 교체 및 iOS 최소 버전 16.4 상향 * feat: SSE silent-sync 이벤트 처리 및 알림 뱃지 동기화 * feat: 알림 목록 갱신 시 앱 뱃지 카운트 동기화 * feat: expo-notifications 포그라운드 뱃지 처리 및 FCM silent push 뱃지 동기화
작업 요약
배경
서버는 읽음 처리 API 응답에 갱신된
unreadCount를 내려주고 silent push도 발송하고 있었으나, FE에서 OS 레벨 뱃지 업데이트를 하지 않아 뱃지 숫자가 줄어들지 않는 문제가 있었음백엔드에서 SSE 이벤트
tournament-item-parsed→silent-sync(type 분기) 변경 및UNREAD_COUNT_CHANGEDsilent-sync 이벤트가 추가됨에 따라 클라이언트 대응동작 흐름
뱃지 DOWN (읽음 처리)
즉각 반영
전 기기 동기화 (SSE)
전 기기 동기화 (FCM)
뱃지 UP (새 알림 도착)
알림 목록 실시간 갱신
작업 내용
WebBridge 메시지 타입 추가 (
packages/core)WEB_REQ_SET_BADGE메시지 타입 추가WebReqSetBadgeMessageT타입 정의 및WebBridgeMessageT유니온에 추가웹 → 앱 뱃지 동기화 (
apps/web)usePostNotificationsReadonSuccess에서unreadCount를WEB_REQ_SET_BADGE로 WebBridge 전송 (단건/전체 읽음 동일)useGetNotifications에서unreadCount변경 시 WebBridge로 뱃지 동기화 (알림 페이지 진입 시 즉시 반영)silent-sync이벤트 처리:TOURNAMENT_ITEM_PARSED/UNREAD_COUNT_CHANGEDtype 분기notification이벤트 수신 시 알림 목록 즉시 갱신 + 뱃지 증가SilentSyncSsePayloadT타입 추가,NotificationTypeT에 누락 타입 추가앱 SSE 버그 수정
Next.js rewrite 경유 시 SSE 버퍼링 문제로 앱 WebView에서 이벤트 미수신되던 문제 수정.
→ Route Handler(
/api/notifications/subscribe) 경유로 통일,X-Client-Type헤더 forwarding 추가앱 뱃지 설정 (
apps/app)setAppBadgeCount(count)함수 추가 (expo-notifications.setBadgeCountAsync활용)WEB_REQ_SET_BADGE메시지 수신 시 OS 레벨 뱃지 즉시 업데이트setNotificationHandler추가 — 포그라운드에서 APNsaps.badge처리 허용 (expo-notificationsdelegate 충돌 해결)onMessage)data.unreadCount로 뱃지 동기화data.unreadCount로 뱃지 동기화빌드 환경 (
apps/app)expo-notifications@^0.32.17설치 (SDK 54 호환 버전)app.json에 expo-notifications 플러그인 추가useFrameworks: static조합 빌드 에러 수정$RNFirebaseAsStaticFramework = true추가RNFBAnalytics CLANG_ENABLE_MODULES = NO설정관련 이슈
closes #279
closes #287