Conversation
WalkthroughFirebase Cloud Messaging setup adjusted: added public firebase-config, updated messaging service worker to use CDN scripts and new defaults, changed SW registration path. Introduced KST timestamp helper and applied in client modal and extension popup. Updated Vercel rewrites and extension manifest icons. Minor formatting fix in onboarding component. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client as Web App
participant SW as firebase-messaging-sw.js
participant FCM as Firebase Cloud Messaging
Client->>SW: register('/firebase-messaging-sw.js')
Note right of SW: install -> self.skipWaiting()<br/>activate -> log
FCM-->>SW: push message (payload)
alt has payload.data.title/body/icon
SW->>SW: build notificationOptions from payload.data
else missing fields
SW->>SW: use defaults (title "PINBACK", icon '/link_Thumbnail.png')
end
SW-->>Client: showNotification(title, options)
sequenceDiagram
autonumber
participant UI as Client UI / Extension
participant Util as getKSTISOString
participant API as Backend
UI->>Util: request current KST ISO
Util-->>UI: ISO string (seconds precision)
UI->>API: send payload with now/createdAt in KST
API-->>UI: response
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (5 warnings)
✨ Finishing touches
🧪 Generate unit tests
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 |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
🚨 Storybook 배포 실패 |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx (2)
13-15: 모듈 import 경로가 잘못되어 빌드가 실패합니다.
../../../../firebase-config는apps/client/public/firebase-config.js를 가리키는데, public 폴더 자산은 번들에 포함되지 않으며 ESM export도 제공하지 않습니다. 이 상태로는 번들링 시 “Module has no exported member 'firebaseConfig'” 혹은 “Cannot resolve module” 오류가 발생해 앱이 실행되지 않습니다.src내에 별도 모듈을 두고export const firebaseConfig = …형태로 내보내거나, 환경변수를 통해 설정을 주입하는 방향으로 수정해주세요.
14-66: Firebase 앱을 매 렌더마다 재초기화하고 있어 런타임이 즉시 깨집니다.
함수형 컴포넌트 본문에서initializeApp을 호출하면, 상태 업데이트로 두 번째 렌더가 일어나는 순간 “Firebase App named '[DEFAULT]' already exists” 예외가 터져 FCM 토큰 취득 흐름이 전부 멈춥니다. 렌더 사이클 밖에서 한 번만 초기화하거나getApps()체크로 기존 인스턴스를 재사용하도록 바꿔주세요. 예시 수정안은 아래와 같습니다.-import { initializeApp } from 'firebase/app'; -import { getMessaging, getToken } from 'firebase/messaging'; +import { initializeApp, getApps } from 'firebase/app'; +import { getMessaging, getToken } from 'firebase/messaging'; +import { useMemo, useState, useEffect } from 'react'; @@ - const app = initializeApp(firebaseConfig); - const messaging = getMessaging(app); + const app = useMemo( + () => (getApps().length ? getApps()[0] : initializeApp(firebaseConfig)), + [] + ); + const messaging = useMemo(() => getMessaging(app), [app]);이와 같이 수정하면 중복 초기화 예외 없이 안전하게 FCM을 사용할 수 있습니다.
🧹 Nitpick comments (1)
apps/client/public/firebase-messaging-sw.js (1)
36-39: 알림 기본값이 하드코딩되어 있습니다.알림 제목, 본문, 아이콘의 기본값이 코드에 직접 작성되어 있습니다. 향후 다국어 지원이나 커스터마이징을 고려한다면 설정 파일로 분리하는 것을 권장합니다.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
apps/extension/public/icon.pngis excluded by!**/*.png
📒 Files selected for processing (8)
apps/client/public/firebase-config.js(1 hunks)apps/client/public/firebase-messaging-sw.js(2 hunks)apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx(3 hunks)apps/client/src/pages/onBoarding/utils/registerServiceWorker.ts(1 hunks)apps/client/src/shared/components/cardEditModal/CardEditModal.tsx(2 hunks)apps/client/vercel.json(1 hunks)apps/extension/manifest.json(1 hunks)apps/extension/src/pages/MainPop.tsx(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
apps/client/public/firebase-config.js (1)
apps/client/public/firebase-messaging-sw.js (1)
firebaseConfig(4-12)
apps/client/public/firebase-messaging-sw.js (1)
apps/client/public/firebase-config.js (1)
firebaseConfig(1-9)
apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx (2)
apps/client/src/constants/alarms.ts (1)
AlarmsType(11-15)apps/client/src/pages/onBoarding/utils/formatRemindTime.ts (1)
normalizeTime(1-26)
🪛 Gitleaks (8.28.0)
apps/client/public/firebase-config.js
[high] 2-2: Uncovered a GCP API key, which could lead to unauthorized access to Google Cloud services and data breaches.
(gcp-api-key)
🔇 Additional comments (3)
apps/extension/src/pages/MainPop.tsx (2)
230-230: now 필드에 KST 타임스탬프를 사용하고 있습니다.위에서 지적한
getKSTISOString함수의 문제를 수정한 후, 업데이트 API의now필드가 KST 타임스탬프를 기대하는지 확인하세요. 서버 측에서 타임스탬프 형식과 타임존을 어떻게 처리하는지 검증이 필요합니다.
196-196: createdAt 필드의 시간대(UTC vs KST) 일관성 확인 필요
apps/extension/src/pages/MainPop.tsx에서getKSTISOString()으로 KST 타임스탬프를 전송하고 있습니다. API 타입 정의에는createdAt: string으로만 명시되어 있어 시간대가 명확하지 않으므로, 백엔드가 UTC 타임스탬프를 기대하는지 API 명세를 확인하세요.apps/client/src/shared/components/cardEditModal/CardEditModal.tsx (1)
102-102: EditArticleRequest.now는 string 타입입니다. 서버가 KST ISO 문자열을 기대하는지 API 계약과 백엔드 타임스탬프 처리 방식을 반드시 검증하세요.
| const firebaseConfig = { | ||
| apiKey: 'AIzaSyD3KM0IQ4Ro3Dd2fyAY8fnhE1bQ_NesrBc', | ||
| authDomain: 'pinback-c55de.firebaseapp.com', | ||
| projectId: 'pinback-c55de', | ||
| storageBucket: 'pinback-c55de.firebasestorage.app', | ||
| messagingSenderId: '370851215931', | ||
| appId: '1:370851215931:web:08382b5e57808d29dcba1e', | ||
| measurementId: 'G-847ZNSCC3J', | ||
| }; |
There was a problem hiding this comment.
Firebase 설정 정보가 공개 파일에 노출되어 있습니다.
서비스 워커는 public 디렉토리에 있어 웹 브라우저에서 누구나 접근할 수 있습니다. Firebase API 키와 프로젝트 정보가 코드에 직접 하드코딩되어 있어 보안 위험이 있습니다.
영향 분석:
- Firebase API 키 노출로 인한 무단 사용 가능성
- 프로젝트 설정 정보가 공개되어 공격 표면 증가
- API 키에 대한 도메인 제한이 없다면 쿼터 남용 위험
권장 사항:
- Firebase 콘솔에서 API 키에 대한 도메인/앱 제한 설정 확인
- 가능하다면 환경변수를 통한 설정 주입 고려 (빌드 시점에 주입)
- Firebase App Check를 활성화하여 무단 요청 차단
| importScripts( | ||
| 'https://www.gstatic.com/firebasejs/9.22.2/firebase-app-compat.js' | ||
| ); | ||
| importScripts( | ||
| './firebase_sdk/firebase-app-compat.js', | ||
| './firebase_sdk/firebase-messaging-compat.js', | ||
| './firebase-config.js' | ||
| 'https://www.gstatic.com/firebasejs/9.22.2/firebase-messaging-compat.js' | ||
| ); |
There was a problem hiding this comment.
🧩 Analysis chain
Firebase SDK 버전이 프로젝트 의존성과 불일치합니다.
CDN에서 Firebase v9.22.2를 사용하고 있지만, 프로젝트에는 Firebase ^12.2.1이 설치되어 있습니다. 주요 버전 차이로 인해 호환성 문제가 발생할 수 있습니다.
확인 필요 사항:
- v9와 v12 간의 API 변경사항 검토
- 서비스 워커에서 사용하는 messaging API의 호환성 확인
- 최신 버전(v12)으로 업그레이드 시 Node 20+ 요구사항 충족 여부
최신 Firebase SDK 버전과 마이그레이션 가이드를 확인하세요:
🏁 Script executed:
#!/bin/bash
# Firebase 패키지 버전 확인
cat package.json | jq '.dependencies.firebase, .devDependencies.firebase'Length of output: 9
🌐 Web query:
Firebase JavaScript SDK v9 to v12 migration guide and breaking changes
💡 Result:
Summary — how to migrate Firebase Web (JS) from v9 → v12 and breaking changes
High-level steps
- Read the official modular migration guide and codelab — migrate namespaced/compat usage to the modular API (per-product, one at a time). Use compat packages only temporarily. [1][2]
- Upgrade package.json to the target firebase version (v10/11/12) and reinstall. Run tests and fix compile errors. [2][3]
- Replace namespaced imports / firebase.compat usage with modular imports (initializeApp, getAuth, getFirestore, etc.) and update all call sites to use exported functions rather than methods on a firebase namespace/App. Test incrementally (Auth, then Firestore, etc.). [1][2]
- Update TypeScript and build tool settings if required; rebuild and measure bundle size (tree-shaking improvements expected once compat is removed). [1][2]
- Read release notes for each major version between your current and v12 and apply any per-version fixes (see links below). [3]
Key breaking changes and compatibility issues (v9 → v12)
- Modular API is the default: v9 introduced the modular API; v9→v12 assumes you move off namespaced APIs. Compat packages (firebase/compat/...) exist but disable tree-shaking and are intended as a temporary migration bridge. Migrate to modular imports to reduce bundle size and use modern APIs. [1][2]
- Import paths & API shape: stop using namespace imports (firebase.*) and app.method() calls. Instead import named functions from product entrypoints (e.g., import { initializeApp } from 'firebase/app'; import { getAuth, signInWithEmailAndPassword } from 'firebase/auth'). Many function signatures and return types changed to be modular-friendly. [1][2]
- Tree-shaking and bundling: using compat packages prevents tree-shaking for that product; full modular usage enables smaller bundles. [2]
- ESM / package entry points: releases have moved browser bundles to ESM entry points; ensure your build/tooling supports ESM imports. Older CJS patterns may require adjustments. [3]
- TypeScript / build targets: review minimal TypeScript/Node targets required by intermediate major releases; TypeScript minimums have changed in older major bumps and may be raised further (verify exact minimal version in your target release notes). [3]
- Per-version breaking changes you must check and possibly handle:
- v10/v11/v12 release notes include product-specific behavior/API changes — read each release note for services you use (Auth, Firestore, Realtime DB, Storage, Messaging, Functions, etc.). Example: some defaults and flags have changed in recent releases (e.g., automaticDataCollectionEnabled behavior was changed in a later minor release), and product APIs occasionally remove deprecated fields. Always check per-product notes. [3]
- Deprecation / maintenance windows: older major versions (v9/v10) have been deprecated/scheduled for EoM — plan upgrades rather than staying on an unsupported major. [3]
Practical checklist (minimal)
- Search your repo for "firebase/compat" and "firebase." namespace usages.
- Replace initialization and product calls with modular imports and getXxx/getXxxWithUrl forms where needed.
- Remove compat packages when all code is modular.
- Update TypeScript and bundler settings to support ESM if necessary.
- Run unit + integration tests, emulator tests, and smoke test all app flows (auth, DB reads/writes, storage uploads, messaging).
- Read release notes for intermediate major versions between your current and v12 for any service-specific migration steps. [1][2][3]
References
- Upgrade from the namespaced API (modular upgrade guide). firebase.google.com/docs/web/modular-upgrade. [1]
- "Upgrade to the modular Firebase JS SDK" codelab (step-by-step with compat usage and progressive migration). firebase.google.com/codelabs/upgrade-to-modular. [2]
- Firebase JavaScript SDK release notes / changelog (per-version breaking changes and release notes). firebase.google.com/support/release-notes/js and main releases page. [3]
If you tell me which Firebase products you use (Auth, Firestore, Realtime DB, Storage, Functions, Messaging, Analytics, etc.) and share a small snippet of your current initialization code, I’ll generate a targeted migration diff (v9 → v12) you can paste into your codebase.
다음 스크립트를 실행하여 클라이언트 앱의 package.json 파일을 찾고 Firebase 의존성을 확인하겠습니다:
🏁 Script executed:
#!/bin/bash
find . -maxdepth 4 -type f -name package.jsonLength of output: 257
다음 스크립트를 실행하여 apps/client/package.json에서 Firebase SDK 버전을 확인하겠습니다:
🏁 Script executed:
#!/bin/bash
jq '.dependencies["firebase"], .devDependencies["firebase"]' apps/client/package.jsonLength of output: 14
서비스 워커 Firebase SDK 버전을 v12.2.1로 업데이트하세요
프로젝트 앱(apps/client/package.json)에 Firebase ^12.2.1을 사용 중이나, 서비스 워커에서는 CDN에서 v9.22.2 호환 패키지를 불러와 주요 버전 불일치가 발생합니다.
- CDN importScripts를 아래와 같이 v12.2.1로 변경
importScripts('https://www.gstatic.com/firebasejs/12.2.1/firebase-app-compat.js'); importScripts('https://www.gstatic.com/firebasejs/12.2.1/firebase-messaging-compat.js');
- v9→v12 마이그레이션 가이드(https://firebase.google.com/docs/web/modular-upgrade) 참고하여 namespaced(compat) 사용 → 모듈식 API(getMessaging 등) 전환 검토
- v12 패키지의 package.json
"engines": { "node": ">=20" }확인 후 로컬/CI 환경의 Node 버전을 20 이상으로 유지해야 합니다
Location: apps/client/public/firebase-messaging-sw.js Lines 14–19
🤖 Prompt for AI Agents
In apps/client/public/firebase-messaging-sw.js around lines 14 to 19, the
service worker imports Firebase v9.22.2 via CDN causing a major-version mismatch
with the app; update the importScripts URLs to use v12.2.1 (both
firebase-app-compat.js and firebase-messaging-compat.js), then run the app and
tests, and optionally follow the Firebase v9→v12 migration guide to replace
compat (namespaced) usage with the modular API (getMessaging, etc.); also
confirm CI/local Node is >=20 to match v12 package engine requirements.
| function getKSTISOString() { | ||
| const now = new Date(); | ||
| const offset = now.getTimezoneOffset() * 60000; | ||
| const kst = new Date(now.getTime() - offset); | ||
| return kst.toISOString().slice(0, 19); | ||
| } |
There was a problem hiding this comment.
getKSTISOString 함수가 중복 정의되어 있습니다.
이 함수는 MainPop.tsx (lines 172-177)에도 동일하게 존재합니다. 동일한 로직 오류(잘못된 타임존 계산, 타임존 표시 누락)를 가지고 있습니다.
위의 MainPop.tsx 리뷰 코멘트를 참고하여 공유 유틸리티 함수로 추출하고 타임존 계산 로직을 수정하세요.
+import { getKSTISOString } from '@shared/utils/datetime';
+
- function getKSTISOString() {
- const now = new Date();
- const offset = now.getTimezoneOffset() * 60000;
- const kst = new Date(now.getTime() - offset);
- return kst.toISOString().slice(0, 19);
- }| function getKSTISOString() { | ||
| const now = new Date(); | ||
| const offset = now.getTimezoneOffset() * 60000; | ||
| const kst = new Date(now.getTime() - offset); | ||
| return kst.toISOString().slice(0, 19); | ||
| } |
There was a problem hiding this comment.
KST 타임스탬프 계산 로직에 오류가 있고 코드가 중복되어 있습니다.
문제점:
-
잘못된 타임존 계산:
getTimezoneOffset()은 사용자의 로컬 타임존 오프셋을 반환하므로, 사용자가 KST 타임존에 있지 않으면 잘못된 시간이 생성됩니다. 예를 들어 미국 사용자가 사용하면 KST가 아닌 미국 시간 기준으로 계산됩니다. -
타임존 표시 누락: ISO 문자열을 19자로 잘라서 타임존 정보('Z' 또는 '+09:00')가 제거되어, 파싱 시 로컬 시간으로 해석될 위험이 있습니다.
-
코드 중복:
CardEditModal.tsx(lines 80-85)에 동일한 함수가 존재합니다.
해결 방안:
공유 유틸리티 함수를 생성하여 명시적으로 KST(UTC+9)를 처리하도록 수정하세요:
// shared/utils/datetime.ts 또는 유사한 위치에 추가
export function getKSTISOString(): string {
const now = new Date();
const kstOffset = 9 * 60; // KST는 UTC+9
const kst = new Date(now.getTime() + kstOffset * 60 * 1000);
return kst.toISOString().replace('Z', '+09:00');
}그런 다음 두 파일에서 공통 함수를 import하여 사용하세요:
+import { getKSTISOString } from '@shared/utils/datetime';
+
- function getKSTISOString() {
- const now = new Date();
- const offset = now.getTimezoneOffset() * 60000;
- const kst = new Date(now.getTime() - offset);
- return kst.toISOString().slice(0, 19);
- }🤖 Prompt for AI Agents
In apps/extension/src/pages/MainPop.tsx around lines 172-177, the
getKSTISOString implementation incorrectly uses the user's getTimezoneOffset
(yielding wrong results for non-KST users), trims off timezone info by slicing
to 19 chars, and is duplicated in CardEditModal.tsx; replace both
implementations with a single shared utility (e.g., shared/utils/datetime.ts)
that computes KST explicitly using UTC+9 (add 9 hours to Date.now()), formats
the ISO string with the KST offset included (e.g., replace trailing 'Z' with
'+09:00' or otherwise append the explicit timezone), export that function and
import it in MainPop.tsx and CardEditModal.tsx to remove duplication and ensure
correct KST timestamps.
📌 Related Issues
📄 Tasks
⭐ PR Point (To Reviewer)
📷 Screenshot
Summary by CodeRabbit