Conversation
Summary by CodeRabbit
WalkthroughFirebase Cloud Messaging과 알림 기능이 새롭게 도입되었습니다. 서비스워커, FCM 연동, 알림 API, 타입, 커스텀 훅, 모달 컴포넌트 등이 추가되었고, 기존 Header 및 MobileMenu에서 알림 모달을 띄우도록 변경되었습니다. 관련 패키지와 ESLint, tsconfig, queryKey 설정도 함께 수정되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Browser
participant ServiceWorker
participant Firebase
participant Server
User->>Browser: 첫 클릭 발생
Browser->>Firebase: 서비스워커 등록, FCM 토큰 발급
Firebase-->>Browser: FCM 토큰 반환
Browser->>Server: 디바이스 토큰 전송
Server-->>Browser: 등록 결과 응답
Firebase->>ServiceWorker: Push 메시지 전달
ServiceWorker->>Browser: 알림 표시
User->>Browser: 알림 클릭
Browser->>ServiceWorker: notificationclick 이벤트
ServiceWorker->>Browser: 지정 URL 새 창 오픈
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20분 📜 Recent review detailsConfiguration used: .coderabbit.yaml ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
🧰 Additional context used🪛 Biome (2.1.2)src/components/layout/MobileMenu.tsx[error] 55-59: Provide an explicit type prop for the button element. The default type of a button is submit, which causes the submission of a form when placed inside a (lint/a11y/useButtonType) 🔇 Additional comments (1)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 14
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock,!**/*.lock
📒 Files selected for processing (17)
eslint.config.mjs(1 hunks)package.json(2 hunks)public/firebase-messaging-sw.js(1 hunks)src/api/alarm/alarm.ts(1 hunks)src/components/alarmModal/alarm.tsx(1 hunks)src/components/common/graySvgButton.tsx(1 hunks)src/components/common/modalProvider.tsx(2 hunks)src/components/layout/Header.tsx(3 hunks)src/components/layout/MobileMenu.tsx(2 hunks)src/components/modal/alarmModal.tsx(1 hunks)src/firebase/firebase.ts(1 hunks)src/hooks/alarm/useDeviceToken.ts(1 hunks)src/hooks/alarm/useGetAlarm.ts(1 hunks)src/pages/home/HomePage.tsx(2 hunks)src/queryKey/queryKey.ts(1 hunks)src/types/alarm/alarm.ts(1 hunks)tsconfig.app.json(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (6)
src/components/alarmModal/alarm.tsx (1)
src/types/alarm/alarm.ts (1)
TAlarm(17-22)
src/components/layout/Header.tsx (2)
src/components/common/modalProvider.tsx (1)
MODAL_TYPES(13-18)src/components/layout/MobileMenu.tsx (1)
MobileMenu(15-75)
src/types/alarm/alarm.ts (1)
src/types/common/common.ts (1)
TCommonResponse(4-9)
src/api/alarm/alarm.ts (2)
src/types/alarm/alarm.ts (4)
TRequestGetAlarm(3-6)TResponseGetAlarm(7-12)TRequestPostDeviceToken(13-15)TResponsePOstDeviceToken(16-16)src/api/axiosInstance.ts (1)
axiosInstance(11-14)
src/firebase/firebase.ts (1)
public/firebase-messaging-sw.js (1)
messaging(17-17)
src/components/modal/alarmModal.tsx (2)
src/hooks/alarm/useGetAlarm.ts (1)
useGetAlarm(8-15)src/components/common/modal.tsx (1)
Modal(15-43)
🪛 Gitleaks (8.27.2)
public/firebase-messaging-sw.js
8-8: Uncovered a GCP API key, which could lead to unauthorized access to Google Cloud services and data breaches.
(gcp-api-key)
🪛 Biome (2.1.2)
src/components/layout/MobileMenu.tsx
[error] 55-59: Provide an explicit type prop for the button element.
The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset
(lint/a11y/useButtonType)
src/components/layout/Header.tsx
[error] 61-61: Provide an explicit type prop for the button element.
The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset
(lint/a11y/useButtonType)
🔇 Additional comments (19)
package.json (1)
25-25: 새 의존성 버전은 최신 안정 버전으로 확인되었습니다
firebasev12.0.0react-intersection-observerv9.16.0react-spinnersv0.17.0모두 npm 레지스트리에서 최신 버전임을 확인했으나, 취약점 검사를 위해서는 lockfile(package-lock.json 또는 yarn.lock)이 필요합니다.
lockfile을 생성한 뒤 아래 명령어로 취약점 검사를 진행해 주세요:# package-lock.json만 생성 npm i --package-lock-only # 취약점 검사 npm audit # 또는 yarn 사용 시 yarn audit검토 위치:
- package.json: 25번 줄(firebase), 34번 줄(react-intersection-observer), 36번 줄(react-spinners)
eslint.config.mjs (1)
13-13: 서비스 워커 ESLint 제외 설정이 적절합니다.Firebase 메시징 서비스 워커를 ESLint 검사에서 제외하는 것은 합리적입니다. 서비스 워커는 일반적인 애플리케이션 코드와 다른 패턴을 사용하기 때문입니다.
tsconfig.app.json (1)
29-29: 서비스 워커 TypeScript 컴파일 설정이 올바릅니다.Firebase 메시징 서비스 워커를 TypeScript 컴파일 대상에 포함시킨 것은 타입 검사와 일관성을 위해 필요한 변경사항입니다.
src/pages/home/HomePage.tsx (1)
1-1: useDeviceToken 훅 동작 확인 완료 — 변경 사항 승인합니다.useEffect 내부에 빈 배열을 두어 마운트 시 한 번만 실행되고, 클릭 이벤트를 통해 FCM 서비스 워커 등록↔토큰 생성·전송 로직이 정상적으로 동작합니다.
TRequestPostDeviceToken타입도 올바르게 정의되어 있어 추가적인 수정이 필요 없습니다.src/components/common/graySvgButton.tsx (1)
1-1: 타입 안전성 개선이 잘 되었습니다.
React.ReactNode로 변경하여 더 유연한 자식 요소를 지원할 수 있게 되었고, 전체 React 네임스페이스 import로 일관성이 향상되었습니다.Also applies to: 7-7
src/components/common/modalProvider.tsx (1)
4-4: 모달 시스템 통합이 올바르게 구현되었습니다.기존 모달 패턴을 잘 따라 AlarmModal을 중앙 집중식 모달 관리 시스템에 정확히 통합했습니다.
Also applies to: 17-17, 24-24
src/components/alarmModal/alarm.tsx (1)
8-9: 반응형 디자인과 텍스트 처리가 잘 구현되었습니다.모바일과 데스크톱에 대한 적절한 너비 설정과 텍스트 오버플로우 처리가 잘 되어 있습니다.
src/hooks/alarm/useDeviceToken.ts (2)
10-14: FCM 브라우저 지원 확인이 잘 구현되었습니다.Firebase 메시징 지원 여부를 확인하여 안전하게 처리하고 있습니다.
28-37: 이벤트 리스너 관리와 클린업이 올바르게 구현되었습니다.첫 번째 클릭 시에만 FCM 설정을 실행하고 이벤트 리스너를 정리하는 패턴이 적절합니다.
src/firebase/firebase.ts (1)
25-33: 서비스 워커 등록이 적절하게 구현되었습니다.브라우저 지원 확인과 에러 처리가 잘 되어 있습니다. 서비스 워커 경로가 public 폴더의 파일과 일치하는 것도 확인되었습니다.
src/components/modal/alarmModal.tsx (1)
20-26: 무한 스크롤 로직이 잘 구현되었습니다!useInView와 useEffect를 사용한 무한 스크롤 구현이 적절하며, 불필요한 API 호출을 방지하는 조건 검사도 잘 되어 있습니다.
src/hooks/alarm/useGetAlarm.ts (1)
8-15: 무한 쿼리 구현이 훌륭합니다!useInfiniteQuery를 사용한 페이지네이션 로직이 적절하게 구현되어 있고, 타입 안전성도 잘 보장되어 있습니다. getNextPageParam에서 커서를 올바르게 추출하는 로직도 정확합니다.
src/api/alarm/alarm.ts (1)
15-18: 디바이스 토큰 API 구현이 적절합니다!POST 요청 구조와 타입 정의가 명확하고 간결합니다.
src/components/layout/Header.tsx (3)
5-5: 모달 관리를 위한 import가 적절히 추가되었습니다.중앙집중식 모달 관리로의 리팩토링을 위해 필요한 import들이 올바르게 추가되었습니다.
Also applies to: 12-12
20-20: 중앙집중식 모달 관리로의 전환이 적절합니다.로컬 상태에서 useModalStore를 사용한 중앙집중식 관리로 변경하여 일관성과 유지보수성이 향상되었습니다.
87-87: 모바일 메뉴에서도 일관된 모달 관리 방식을 사용합니다.데스크톱과 모바일에서 동일한 모달 시스템을 사용하여 일관성이 확보되었습니다.
src/types/alarm/alarm.ts (3)
1-1: 공통 타입 import가 적절합니다.type-only import를 사용하여 TypeScript 모범 사례를 따르고 있습니다.
3-12: 페이지네이션을 지원하는 알림 조회 타입이 잘 정의되었습니다.요청 타입의 선택적 매개변수와 응답 타입의 페이지네이션 구조가 무한 스크롤 기능을 적절히 지원합니다.
17-22: 알림 엔티티 타입이 적절히 정의되었습니다.알림 시스템에 필요한 필드들이 올바른 타입으로 잘 정의되어 있습니다.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (4)
src/components/alarmModal/alarm.tsx (1)
5-5: props 사용 패턴을 재검토해 주세요.TAlarm 객체 전체를 받지만 title만 사용하고 있습니다. 다른 필드들(id, isRead 등)도 활용할 계획이 있다면 현재 구조를 유지하고, 그렇지 않다면 필요한 props만 받는 것을 고려해 보세요.
src/firebase/firebase.ts (1)
5-13: 환경 변수 유효성 검증을 추가해 주세요.Firebase 설정에 필요한 환경 변수들이 누락될 경우 런타임 오류가 발생할 수 있습니다. 애플리케이션 시작 시 필수 환경 변수들을 미리 검증하는 로직을 추가해 주세요.
+// 필수 환경 변수 검증 +const requiredEnvVars = [ + 'VITE_FIREBASE_API_KEY', + 'VITE_FIREBASE_AUTH_DOMAIN', + 'VITE_PROJECT_ID', + 'VITE_STORAGE_BUCKET', + 'VITE_MESSAGE_SENDER_ID', + 'VITE_APP_ID', + 'VITE_MEASUREMENT_ID', + 'VITE_FIREBASE_VAPID_KEY', +]; + +requiredEnvVars.forEach((key) => { + if (!import.meta.env[key]) { + throw new Error(`환경 변수 ${key}가 설정되지 않았습니다.`); + } +}); + const firebaseConfig = {public/firebase-messaging-sw.js (1)
7-15: Firebase 클라이언트 API 키 노출에 대한 설명을 추가해 주세요.정적 분석 도구가 보안 이슈로 플래그했지만, Firebase 클라이언트 API 키는 공개적으로 노출되도록 설계되었습니다. 하지만 코드 리뷰어들을 위해 주석으로 이를 명시해 주세요.
+// Firebase 클라이언트 설정 - 이 키들은 공개용이며 클라이언트에서 안전하게 사용할 수 있습니다 firebase.initializeApp({ apiKey: 'AIzaSyAjZqK2lhCOeX_P2Sf-_2IGEFlORchcO5w',src/components/modal/alarmModal.tsx (1)
17-17: 페이지 크기를 props로 받는 것을 고려해 주세요.현재 하드코딩된
size: 5를 props로 받아 재사용성을 높일 수 있습니다.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (9)
public/firebase-messaging-sw.js(1 hunks)src/api/alarm/alarm.ts(1 hunks)src/components/alarmModal/alarm.tsx(1 hunks)src/components/layout/Header.tsx(3 hunks)src/components/modal/alarmModal.tsx(1 hunks)src/firebase/firebase.ts(1 hunks)src/hooks/alarm/useGetAlarm.ts(1 hunks)src/queryKey/queryKey.ts(1 hunks)src/types/alarm/alarm.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
src/firebase/firebase.ts (1)
public/firebase-messaging-sw.js (1)
messaging(17-17)
src/components/alarmModal/alarm.tsx (1)
src/types/alarm/alarm.ts (1)
TAlarm(17-22)
src/hooks/alarm/useGetAlarm.ts (3)
src/types/alarm/alarm.ts (1)
TRequestGetAlarm(3-6)src/queryKey/queryKey.ts (1)
alarmKeys(7-9)src/api/alarm/alarm.ts (1)
getAlarm(5-13)
src/types/alarm/alarm.ts (1)
src/types/common/common.ts (1)
TCommonResponse(4-9)
src/components/layout/Header.tsx (2)
src/components/common/modalProvider.tsx (1)
MODAL_TYPES(13-18)src/components/layout/MobileMenu.tsx (1)
MobileMenu(15-75)
src/api/alarm/alarm.ts (2)
src/types/alarm/alarm.ts (4)
TRequestGetAlarm(3-6)TResponseGetAlarm(7-12)TRequestPostDeviceToken(13-15)TResponsePostDeviceToken(16-16)src/api/axiosInstance.ts (1)
axiosInstance(11-14)
src/components/modal/alarmModal.tsx (3)
src/hooks/alarm/useGetAlarm.ts (1)
useGetAlarm(8-15)src/pages/common/Error.tsx (1)
Error(1-3)src/components/common/modal.tsx (1)
Modal(15-43)
🪛 Gitleaks (8.27.2)
public/firebase-messaging-sw.js
8-8: Uncovered a GCP API key, which could lead to unauthorized access to Google Cloud services and data breaches.
(gcp-api-key)
🪛 Biome (2.1.2)
src/components/modal/alarmModal.tsx
[error] 10-10: Do not shadow the global "Error" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
🔇 Additional comments (9)
src/queryKey/queryKey.ts (1)
7-9: cursor 타입 스펙 일치 확인
TRequestGetAlarm및getAlarm구현 모두cursor?: number로 정의되어 있어, API 스펙과 일치함을 확인했습니다. 추가 수정은 필요 없습니다.src/firebase/firebase.ts (1)
18-31: 토큰 생성 함수의 에러 처리가 개선되었습니다.적절한 try-catch 블록과 로깅이 추가되어 디버깅과 사용자 경험이 향상되었습니다.
public/firebase-messaging-sw.js (1)
36-42: 알림 클릭 에러 처리가 적절히 구현되었습니다.
clients.openWindow에 대한 에러 처리가 추가되어 잘못된 URL이나 네트워크 오류 시에도 안정적으로 동작할 것입니다.src/components/layout/Header.tsx (2)
60-66: 모달 통합과 버튼 타입 명시가 적절히 구현되었습니다.중앙화된 모달 관리 시스템 사용과
type="button"속성 추가로 코드 품질이 향상되었습니다. 로컬 상태 관리를 제거하고useModalStore를 활용한 것도 좋은 개선입니다.
87-87: MobileMenu props 전달이 일관성 있게 구현되었습니다.
onOpenSettings콜백을 통해 모달 관리가 일관되게 처리되고 있어 좋습니다. 모바일과 데스크톱 환경에서 동일한 모달 시스템을 사용하는 것이 사용자 경험 통일성에 도움이 됩니다.src/api/alarm/alarm.ts (1)
5-18: API 함수 구현이 잘 되어 있습니다.타입 안전성과 구조가 깔끔하게 구현되어 있고, 단축 속성 문법도 적절히 사용되고 있습니다. 에러 처리는 상위 레벨에서 처리되는 것으로 보입니다.
src/components/modal/alarmModal.tsx (2)
30-32: 에러 처리가 잘 구현되어 있습니다.이전 리뷰에서 언급된 에러 상태 처리가 적절히 추가되었습니다.
37-39: 빈 상태 처리가 잘 구현되어 있습니다.알림이 없는 경우에 대한 사용자 친화적인 메시지가 적절히 구현되어 있습니다.
src/types/alarm/alarm.ts (1)
3-22: 타입 정의가 잘 구현되어 있습니다.알림 관련 모든 타입이 일관된 네이밍 컨벤션을 따르고 있으며, 이전 리뷰에서 언급된 오타도 수정되었습니다. nullable 타입과 선택적 속성들이 적절히 사용되어 있습니다.
🚨 관련 이슈
#87
✨ 변경사항
✏️ 작업 내용
😅 미완성 작업
📢 논의 사항 및 참고 사항
-