-
Notifications
You must be signed in to change notification settings - Fork 2
[Feature] FCM 연결 및 모달 생성, API 연결 #88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
✨ 변경사항
✏️ 작업 내용
😅 미완성 작업
📢 논의 사항 및 참고 사항
-