Conversation
Walkthrough클라이언트에 Firebase 의존성 및 Vite 기반 Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as 사용자
participant MC as MainCard (Onboarding)
participant FB as Firebase App
participant MSG as Firebase Messaging
participant API as 백엔드 API
U->>MC: 온보딩 진행
MC->>FB: initializeApp(firebaseConfig)
MC->>MSG: getMessaging(FB)
alt Step 3: 알림 권한 요청
MC->>U: Notification 권한 요청
alt 허용
MC->>MSG: getToken(VAPID 키)
MSG-->>MC: FCM 토큰 반환
MC->>MC: fcmToken 상태에 저장
MC->>U: 다음 단계로 진행
else 거부/실패
MC->>U: 오류/안내 표시
end
end
alt Step 5: 최종 제출
MC->>API: signUp(payload with fcmToken|null)
API-->>MC: 응답
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ 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 |
|
✅ Storybook chromatic 배포 확인: |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx (1)
125-133: setState 직후 값 사용 버그: 잘못된 remindDefault 전송 가능성
setRemindTime직후remindTime을 사용하면 이전 값이 전송됩니다. 로컬 변수로 계산한 값을 즉시 사용하세요.- const raw = AlarmsType[alarmSelected - 1].time; - setRemindTime(normalizeTime(raw)); + const raw = AlarmsType[alarmSelected - 1].time; + const normalized = normalizeTime(raw); + setRemindTime(normalized); postSignData({ - "email": "tesdfdfsst@gmail.com", // TODO : 익스텐션에게서 메일 받기 - "remindDefault": remindTime, - "fcmToken": fcmToken, + email: "tesdfdfsst@gmail.com", // TODO : 익스텐션에게서 메일 받기 + remindDefault: normalized, + fcmToken: fcmToken, },
🧹 Nitpick comments (5)
apps/client/src/shared/apis/axios.ts (1)
27-27: 서버 스키마 확인: null 전송 vs 필드 생략
fcmToken: string | null로 변경은 합리적이지만, 서버가null을 명시적으로 기대하는지(또는 필드 자체 생략을 선호하는지) 확인이 필요합니다. 만약 생략을 허용한다면 optional 필드가 더 깔끔합니다.가능 시 인터페이스를 아래처럼 단순화하세요:
-export interface postSignUpRequest { +export interface postSignUpRequest { email: string, remindDefault: string, - fcmToken: string | null + fcmToken?: string }그리고 호출부에서는
fcmToken ?? undefined로 넘기거나,null이면 키 자체를 제거하세요.apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx (4)
108-121: 권한/토큰 실패 시 UX 폴백권한 거부/토큰 실패 시 다음 단계로 진행을 막고 Alert만 노출합니다. 알림 미동의 사용자도 온보딩을 계속할 수 있도록 폴백 UX(건너뛰기/나중에 설정)를 고려해 주세요.
129-129: 하드코딩된 이메일 제거 필요실서비스에 머지되면 즉시 장애로 이어질 수 있습니다. 온보딩 소스에서 실제 이메일을 주입하거나, 최소한 PR 머지 전에 해당 값이 절대 하드코딩되지 않도록 가드(빌드타임 체크)를 추가하세요.
원하시면 이메일 주입 경로 확정 전까지 임시 가드를 넣는 패치도 제공하겠습니다.
66-71: 민감/준민감 데이터 콘솔 출력 지양FCM 토큰 콘솔 로그는 제거를 권장합니다. 토큰은 식별자 성격을 가지며 서드파티 확장/공유 디바이스에서 노출될 수 있습니다.
- console.log('FCM 토큰 발급 성공:', forFcmtoken);
193-193: 비활성화 조건 확인
isDisabled={step === 6}은 현재 플로우에서 도달 불가로 보입니다. 불필요하면 제거하거나 올바른 경계값으로 수정하세요.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (4)
apps/client/package.json(1 hunks)apps/client/src/firebase-config.ts(1 hunks)apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx(4 hunks)apps/client/src/shared/apis/axios.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx (1)
apps/client/src/firebase-config.ts (1)
firebaseConfig(1-9)
| "@tanstack/react-query": "^5.85.3", | ||
| "axios": "^1.11.0", | ||
| "class-variance-authority": "^0.7.1", | ||
| "firebase": "^12.2.1", |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
FCM 동작을 위해 서비스 워커와 환경변수 점검 필요
firebase 의존성 추가만으로는 웹 FCM이 동작하지 않습니다. public/firebase-messaging-sw.js 존재 여부와 VAPID/프로젝트 env 설정을 꼭 확인해 주세요.
다음 스크립트로 빠르게 점검 가능합니다:
🏁 Script executed:
#!/bin/bash
# 1) 서비스 워커 파일 존재 확인
fd -a 'firebase-messaging-sw.*' apps/client || true
# 2) FCM 관련 ENV 키 존재 여부(로컬 env가 레포에 없으면 스킵될 수 있음)
rg -nP 'VITE_FIREBASE_(API_KEY|AUTH_DOMAIN|PROJECT_ID|STORAGE_BUCKET|MESSAGING_SENDER_ID|APP_ID|MEASUREMENT_ID|VAPID_KEY)' apps/client || trueLength of output: 790
public/firebase-messaging-sw.js 없음 — 서비스 워커 추가/등록 필요
- 검증: FCM 관련 env 참조는 존재함 — apps/client/src/firebase-config.ts (VITE_FIREBASE_API_KEY, VITE_FIREBASE_AUTH_DOMAIN, VITE_FIREBASE_PROJECT_ID, VITE_FIREBASE_STORAGE_BUCKET, VITE_FIREBASE_MESSAGING_SENDER_ID, VITE_FIREBASE_APP_ID, VITE_FIREBASE_MEASUREMENT_ID) 및 apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx (VITE_FIREBASE_VAPID_KEY).
- 조치: public/firebase-messaging-sw.js를 루트(public/)에 추가하고 클라이언트에서 '/firebase-messaging-sw.js'로 서비스워커가 등록되도록 하세요 (navigator.serviceWorker.register('/firebase-messaging-sw.js')).
- 추가: 배포 환경에 VAPID 키 및 위 ENV 값들이 실제로 설정되어 있는지 확인하세요.
🤖 Prompt for AI Agents
In apps/client/package.json around line 16: the project depends on firebase but
lacks the Firebase Cloud Messaging service worker; add a file
public/firebase-messaging-sw.js at the repository's public root (containing the
FCM service worker setup) and ensure the client registers it via
navigator.serviceWorker.register('/firebase-messaging-sw.js') from app startup
(e.g., in your main client bootstrap or useEffect in a top-level component);
also verify the VAPID key and the VITE_FIREBASE_* env vars are set in deployment
and that the new file is included in the built/public assets so the registration
path resolves in production.
| export const firebaseConfig = { | ||
| apiKey: import.meta.env.VITE_FIREBASE_API_KEY, | ||
| authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN, | ||
| projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID, | ||
| storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET, | ||
| messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID, | ||
| appId: import.meta.env.VITE_FIREBASE_APP_ID, | ||
| measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID, | ||
| }; No newline at end of file |
There was a problem hiding this comment.
🛠️ Refactor suggestion
타이핑 및 런타임 검증 추가로 환경오염/미설정 조기 탐지
현재 값이 string | undefined일 수 있어, 빌드/런타임에서 문제를 늦게 발견할 수 있습니다. FirebaseOptions 타이핑과 간단한 런타임 검증을 권장합니다.
+import type { FirebaseOptions } from 'firebase/app';
-export const firebaseConfig = {
+export const firebaseConfig: FirebaseOptions = {
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
appId: import.meta.env.VITE_FIREBASE_APP_ID,
measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,
};
+
+// 선택: 필수 키 누락 시 조기 실패
+const missing = Object.entries(firebaseConfig)
+ .filter(([, v]) => !v)
+ .map(([k]) => k);
+if (missing.length) {
+ // eslint-disable-next-line no-console
+ console.error('Missing Firebase env keys:', missing);
+ throw new Error('Firebase env is not configured properly');
+}📝 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.
| export const firebaseConfig = { | |
| apiKey: import.meta.env.VITE_FIREBASE_API_KEY, | |
| authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN, | |
| projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID, | |
| storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET, | |
| messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID, | |
| appId: import.meta.env.VITE_FIREBASE_APP_ID, | |
| measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID, | |
| }; | |
| import type { FirebaseOptions } from 'firebase/app'; | |
| export const firebaseConfig: FirebaseOptions = { | |
| apiKey: import.meta.env.VITE_FIREBASE_API_KEY, | |
| authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN, | |
| projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID, | |
| storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET, | |
| messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID, | |
| appId: import.meta.env.VITE_FIREBASE_APP_ID, | |
| measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID, | |
| }; | |
| // 선택: 필수 키 누락 시 조기 실패 | |
| const missing = Object.entries(firebaseConfig) | |
| .filter(([, v]) => !v) | |
| .map(([k]) => k); | |
| if (missing.length) { | |
| // eslint-disable-next-line no-console | |
| console.error('Missing Firebase env keys:', missing); | |
| throw new Error('Firebase env is not configured properly'); | |
| } |
🤖 Prompt for AI Agents
In apps/client/src/firebase-config.ts lines 1-9, the exported config uses raw
import.meta.env values which are typed as string | undefined; update to use the
FirebaseOptions type and add a small runtime validation that each required env
var is present and a string, throwing a clear Error during startup if any are
missing. Construct the firebaseConfig as a properly typed FirebaseOptions object
(import type FirebaseOptions from 'firebase/app' or appropriate module),
validate keys like VITE_FIREBASE_API_KEY, VITE_FIREBASE_AUTH_DOMAIN,
VITE_FIREBASE_PROJECT_ID, VITE_FIREBASE_STORAGE_BUCKET,
VITE_FIREBASE_MESSAGING_SENDER_ID, VITE_FIREBASE_APP_ID (and optional
VITE_FIREBASE_MEASUREMENT_ID) before returning, and provide a helpful error
message listing any missing variables so misconfiguration is detected early.
| import { firebaseConfig } from '../../../../firebase-config'; | ||
| import { initializeApp } from 'firebase/app'; | ||
| import { getMessaging, getToken } from 'firebase/messaging'; | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Firebase import 정비 및 상대경로 개선
initializeApp만 가져오면 렌더마다 재초기화 리스크가 있습니다.getApps/getApp을 함께 임포트해 단일 인스턴스를 보장하세요.isSupported도입으로 비지원 브라우저 가드 필요.firebase-config상대경로는 취약합니다. 기존 alias(@pages,@shared)와 동일하게 alias를 부여해 주세요.
-import { firebaseConfig } from '../../../../firebase-config';
-import { initializeApp } from 'firebase/app';
-import { getMessaging, getToken } from 'firebase/messaging';
+import { firebaseConfig } from '@/firebase-config'; // 또는 적절한 alias
+import { initializeApp, getApps, getApp } from 'firebase/app';
+import { getMessaging, getToken, isSupported } from 'firebase/messaging';추가로, 상단 react 임포트에 useMemo가 필요해질 수 있습니다.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx around lines
13 to 16, replace the current firebase imports and relative config path: import
getApps/getApp alongside initializeApp and use a single-instance pattern (if
getApps().length === 0 then initializeApp(config) else getApp()), import
isSupported from 'firebase/messaging' and guard messaging code with await
isSupported() before calling getMessaging/getToken, change the
'../../../../firebase-config' relative import to the project alias (e.g.
'@shared/firebase-config' or the correct alias used in the repo), and add
useMemo to the React import at the top since it may be needed for memoized
initialization; update code paths accordingly to avoid reinitialization and to
skip messaging on unsupported browsers.
| const app = initializeApp(firebaseConfig); | ||
| const messaging = getMessaging(app); | ||
|
|
There was a problem hiding this comment.
중복 초기화 버그: 렌더마다 initializeApp 호출
컴포넌트 본문에서 initializeApp을 호출하면 재렌더 시 [DEFAULT] already exists 예외가 발생할 수 있습니다. 단일 인스턴스를 보장하도록 변경하세요.
- const app = initializeApp(firebaseConfig);
- const messaging = getMessaging(app);
+ const app = (getApps().length ? getApp() : initializeApp(firebaseConfig));
+ const messaging = getMessaging(app);추가로 안정성을 위해 모듈 스코프로 올리는 것도 고려해 주세요:
// (컴포넌트 밖 상단)
const app = (getApps().length ? getApp() : initializeApp(firebaseConfig));
const messaging = getMessaging(app);🤖 Prompt for AI Agents
In apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx around lines
51-53, the code calls initializeApp inside the component causing "[DEFAULT]
already exists" on re-render; change it to ensure a single Firebase app instance
(use getApps().length ? getApp() : initializeApp(firebaseConfig) or try getApp()
with fallback to initializeApp) and obtain messaging from that instance, and
move these calls to module scope (top of the file, outside the component) so
they run once per module load.
| const requestFCMToken = async (): Promise<string | null> => { | ||
| try { | ||
| const permission = await Notification.requestPermission(); | ||
| if (permission !== 'granted') { | ||
| alert('알림 권한 허용이 필요합니다!'); | ||
| return null; | ||
| } | ||
|
|
||
| const forFcmtoken = await getToken(messaging, { | ||
| vapidKey: import.meta.env.VITE_FIREBASE_VAPID_KEY, | ||
| }); | ||
|
|
||
| if (forFcmtoken) { | ||
| console.log('FCM 토큰 발급 성공:', forFcmtoken); | ||
| return forFcmtoken; | ||
| } else { | ||
| alert('토큰 생성 실패. 다시 시도해주세요.'); | ||
| return null; | ||
| } | ||
| } catch (error) { | ||
| console.error('FCM 토큰 받는 도중 오류:', error); | ||
| alert('알림 설정 중 오류가 발생했습니다. 다시 시도해주세요.'); | ||
| return null; | ||
| } | ||
| }; |
There was a problem hiding this comment.
웹 FCM 필수 가드 누락: 브라우저 지원 체크 + 서비스워커 미등록 상태에서 getToken 호출
isSupported()체크 없이 호출 시 일부 브라우저/환경에서 런타임 에러.firebase-messaging-sw.js를 등록하지 않으면 토큰 발급/백그라운드 수신 실패가 잦습니다.getToken에serviceWorkerRegistration을 전달하세요.
const requestFCMToken = async (): Promise<string | null> => {
try {
+ // 0) 브라우저 지원 확인
+ if (!(await isSupported())) {
+ alert('현재 브라우저는 푸시 알림을 지원하지 않습니다.');
+ return null;
+ }
+
+ // 1) 서비스워커 등록
+ const swReg = await navigator.serviceWorker.register('/firebase-messaging-sw.js');
+
const permission = await Notification.requestPermission();
if (permission !== 'granted') {
alert('알림 권한 허용이 필요합니다!');
return null;
}
- const forFcmtoken = await getToken(messaging, {
- vapidKey: import.meta.env.VITE_FIREBASE_VAPID_KEY,
- });
+ const newToken = await getToken(messaging, {
+ vapidKey: import.meta.env.VITE_FIREBASE_VAPID_KEY,
+ serviceWorkerRegistration: swReg,
+ });
- if (forFcmtoken) {
- console.log('FCM 토큰 발급 성공:', forFcmtoken);
- return forFcmtoken;
+ if (newToken) {
+ // console.log는 민감정보 노출 우려. 필요 시 debug 플래그 뒤에서만 출력하세요.
+ return newToken;
} else {
alert('토큰 생성 실패. 다시 시도해주세요.');
return null;
}운영 팁:
apps/client/public/firebase-messaging-sw.js를 추가하고 배포 루트(/{scope})와 경로가 일치하도록 호스팅 설정을 확인하세요.- 로컬 개발은
https://혹은http://localhost에서만 동작합니다.
📝 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 requestFCMToken = async (): Promise<string | null> => { | |
| try { | |
| const permission = await Notification.requestPermission(); | |
| if (permission !== 'granted') { | |
| alert('알림 권한 허용이 필요합니다!'); | |
| return null; | |
| } | |
| const forFcmtoken = await getToken(messaging, { | |
| vapidKey: import.meta.env.VITE_FIREBASE_VAPID_KEY, | |
| }); | |
| if (forFcmtoken) { | |
| console.log('FCM 토큰 발급 성공:', forFcmtoken); | |
| return forFcmtoken; | |
| } else { | |
| alert('토큰 생성 실패. 다시 시도해주세요.'); | |
| return null; | |
| } | |
| } catch (error) { | |
| console.error('FCM 토큰 받는 도중 오류:', error); | |
| alert('알림 설정 중 오류가 발생했습니다. 다시 시도해주세요.'); | |
| return null; | |
| } | |
| }; | |
| const requestFCMToken = async (): Promise<string | null> => { | |
| try { | |
| // 0) 브라우저 지원 확인 | |
| if (!(await isSupported())) { | |
| alert('현재 브라우저는 푸시 알림을 지원하지 않습니다.'); | |
| return null; | |
| } | |
| // 1) 서비스워커 등록 | |
| const swReg = await navigator.serviceWorker.register('/firebase-messaging-sw.js'); | |
| const permission = await Notification.requestPermission(); | |
| if (permission !== 'granted') { | |
| alert('알림 권한 허용이 필요합니다!'); | |
| return null; | |
| } | |
| const newToken = await getToken(messaging, { | |
| vapidKey: import.meta.env.VITE_FIREBASE_VAPID_KEY, | |
| serviceWorkerRegistration: swReg, | |
| }); | |
| if (newToken) { | |
| // console.log는 민감정보 노출 우려. 필요 시 debug 플래그 뒤에서만 출력하세요. | |
| return newToken; | |
| } else { | |
| alert('토큰 생성 실패. 다시 시도해주세요.'); | |
| return null; | |
| } | |
| } catch (error) { | |
| console.error('FCM 토큰 받는 도중 오류:', error); | |
| alert('알림 설정 중 오류가 발생했습니다. 다시 시도해주세요.'); | |
| return null; | |
| } | |
| }; |
🤖 Prompt for AI Agents
In apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx around lines
54 to 78, the FCM token flow calls getToken without checking web messaging
support and without supplying a serviceWorkerRegistration; add an isSupported()
guard before requesting permission and early-return if unsupported, attempt to
register or locate the firebase messaging service worker
(public/firebase-messaging-sw.js) and pass the obtained
serviceWorkerRegistration into getToken via the serviceWorkerRegistration
option, and handle the case where service worker registration fails by showing
the existing alert/console error and returning null.
constantly-dev
left a comment
There was a problem hiding this comment.
FCM 토큰 관련 로직이 이전보다 훨씬 간소화되고 깔끔해졌네요!
message 관련된 로직은 추가가 되어야 하는거죠??
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/client/src/shared/apis/axios.ts (1)
25-27: acorns 요청: 중복 쿼리스트링 버그 수정 필요경로에
?now=를 하드코딩한 상태에서params: { now }를 추가해 동일 파라미터가 중복됩니다. 서버에 따라 예기치 않은 값이 전달될 수 있습니다. 아래처럼 URL의 쿼리 문자열을 제거하세요.- const { data } = await apiRequest.get('/api/v1/users/acorns?now=', { - params: { now }, - }); + const { data } = await apiRequest.get('/api/v1/users/acorns', { + params: { now }, + });
🧹 Nitpick comments (3)
apps/client/src/shared/apis/axios.ts (3)
31-31: 타입명 PascalCase로 정렬코드베이스 컨벤션에 맞춰 인터페이스명을 PascalCase로 맞추면 가독성이 좋아집니다. 사용처 타입도 함께 변경하세요.
-export interface postSignUpRequest { +export interface PostSignUpRequest { ... } -export const postSignUp = async (responsedata: postSignUpRequest) => { +export const postSignUp = async (responsedata: PostSignUpRequest) => {Also applies to: 37-37
9-14: API 반환값 형식 통일일부 함수는
response전체를, 일부는data혹은data.data를 반환합니다. 호출부 혼란과 버그의 원인이 되므로 일관된 계약으로 정리하세요(예: 항상response.data반환).예시 수정:
-export const postCategory = async (categoryName: string) => { - const response = await apiRequest.post('/api/v1/categories', { - categoryName, - }); - return response; -}; +export const postCategory = async (categoryName: string) => { + const { data } = await apiRequest.post('/api/v1/categories', { categoryName }); + return data; +}; -export const deleteCategory = async (id: number) => { - const response = await apiRequest.delete(`/api/v1/categories/${id}`); - return response; -}; +export const deleteCategory = async (id: number) => { + const { data } = await apiRequest.delete(`/api/v1/categories/${id}`); + return data; +};또한
data.data를 기대하는 엔드포인트는 서버 응답 스키마와 합의해 한 단계로 평탄화하는 것도 고려해 주세요.Also applies to: 16-21, 37-40, 49-52
33-33: remindDefault 타입을 리터럴 유니온으로 한정가능한 값이 정해져 있다면
string대신 리터럴 유니온(예:'immediate' | 'daily' | 'weekly')으로 좁혀 타입 안전성을 높이세요. 백엔드 스키마(예: OpenAPI/DTO)와 허용값을 먼저 확인 바랍니다.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/client/src/shared/apis/axios.ts(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: storybook
| export interface postSignUpRequest { | ||
| email: string; | ||
| remindDefault: string; | ||
| fcmToken: string; | ||
| email: string, | ||
| remindDefault: string, | ||
| fcmToken: string | null | ||
| } |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
fcmToken: null 전송 대신 “필드 생략(옵셔널)” 권장 — 백엔드 계약 확인 필요
string | null로 두면 실제 전송 바디에 "fcmToken": null이 포함됩니다. 백엔드 DTO가 null을 허용하지 않으면 400이 날 수 있습니다. 토큰이 없을 때는 필드를 아예 생략하는 쪽이 안전합니다.
-export interface postSignUpRequest {
+export interface postSignUpRequest {
email: string,
remindDefault: string,
- fcmToken: string | null
+ fcmToken?: string
}추가 권장: 실제 전송 직전에 undefined인 필드는 제거되도록 직렬화(예: 스프레드로 조건부 포함)되어 있는지 확인해 주세요.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "PWD: $(pwd)"
echo
echo "=== Show file apps/client/src/shared/apis/axios.ts (if exists) ==="
if [ -f apps/client/src/shared/apis/axios.ts ]; then
sed -n '1,240p' apps/client/src/shared/apis/axios.ts || true
else
echo "NOT FOUND: apps/client/src/shared/apis/axios.ts"
fi
echo
echo "=== rg: postSignUpRequest ==="
rg -n --hidden -S "postSignUpRequest" -g '!.git' -g '!**/node_modules/**' -C3 || true
echo
echo "=== rg: fcmToken ==="
rg -n --hidden -S "fcmToken" -g '!.git' -g '!**/node_modules/**' -C3 || true
echo
echo "=== rg: signup/register endpoints / function names ==="
rg -n --hidden -S "signup|signUp|register/step|registerUser|register" -g '!.git' -g '!**/node_modules/**' -C3 || true
echo
echo "=== rg: axios.post / axios.create usage ==="
rg -n --hidden -S "axios\.post|axios\.create|axios\(" -g '!.git' -g '!**/node_modules/**' -C3 || true
echo
echo "=== rg: JSON.stringify / transformRequest / replacer ==="
rg -n --hidden -S "JSON.stringify|transformRequest|replacer|serialize" -g '!.git' -g '!**/node_modules/**' -C3 || true
echo
echo "=== rg: possible backend DTOs mentioning fcmToken or signup DTOs ==="
rg -n --hidden -S "fcmToken|FCM|SignUpDto|SignUpDTO|SignupRequest|SignUpRequest|SignUpDto" -g '!.git' -g '!**/node_modules/**' -C3 || trueLength of output: 2722
추가 확인을 위해 아래 스크립트를 실행하겠습니다.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "PWD: $(pwd)"
echo
echo "=== apps/client/src/shared/apis/axios.ts (existing) ==="
if [ -f apps/client/src/shared/apis/axios.ts ]; then
sed -n '1,240p' apps/client/src/shared/apis/axios.ts || true
else
echo "NOT FOUND: apps/client/src/shared/apis/axios.ts"
fi
echo
echo "=== Find any axiosInstance files ==="
find . -type f \( -iname "*axiosinstance*.ts" -o -iname "*axiosinstance*.js" -o -iname "*axiosinstance*.tsx" -o -iname "*axiosinstance*.jsx" \) -print || true
echo
echo "=== Show first axiosInstance file content (if found) ==="
file=$(find . -type f \( -iname "*axiosinstance*.ts" -o -iname "*axiosinstance*.js" -o -iname "*axiosinstance*.tsx" -o -iname "*axiosinstance*.jsx" \) | head -n1 || true)
if [ -n "$file" ]; then
echo "FOUND: $file"
sed -n '1,240p' "$file" || true
else
echo "No axiosInstance file found"
fi
echo
echo "=== Search for postSignUp call sites ==="
rg -n --hidden -S "postSignUp\\(" || true
echo
echo "=== Search for direct '/api/v1/auth/signup' usages ==="
rg -n --hidden -S "/api/v1/auth/signup" || true
echo
echo "=== Search for fcmToken usages across repo ==="
rg -n --hidden -S "fcmToken" || true
echo
echo "=== Search for where signup payload / types are referenced ==="
rg -n --hidden -S "postSignUpRequest|responsedata" || true
echo
echo "=== Show package.json files (root and apps/client) ==="
if [ -f package.json ]; then
echo "--- root package.json ---"
sed -n '1,240p' package.json || true
fi
if [ -f apps/client/package.json ]; then
echo "--- apps/client/package.json ---"
sed -n '1,240p' apps/client/package.json || true
fiLength of output: 8589
fcmToken을 null로 전송하지 말고 필드를 생략하세요 — 백엔드 DTO(가입 API) 허용 여부 확인 필요
현재 postSignUp에 전달되는 객체가 fcmToken === null이면 요청 바디에 "fcmToken": null이 포함됩니다. 백엔드가 null을 허용하지 않으면 400을 일으킬 수 있으므로 인터페이스를 옵셔널로 변경하고 전송 시 null인 경우 필드를 제외하세요.
위치: apps/client/src/shared/apis/axios.ts (postSignUpRequest), apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx (fcmToken 상태 및 전송)
-export interface postSignUpRequest {
+export interface postSignUpRequest {
email: string,
remindDefault: string,
- fcmToken: string | null
+ fcmToken?: string
}전송 구현 힌트: payload 생성 시 ...(fcmToken ? { fcmToken } : {}) 처럼 조건부 포함하거나 fcmToken을 undefined로 두고 JSON.stringify가 undefined 필드를 제거하는지 확인하세요.
📝 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.
| export interface postSignUpRequest { | |
| email: string; | |
| remindDefault: string; | |
| fcmToken: string; | |
| email: string, | |
| remindDefault: string, | |
| fcmToken: string | null | |
| } | |
| export interface postSignUpRequest { | |
| email: string, | |
| remindDefault: string, | |
| fcmToken?: string | |
| } |
📌 Related Issues
📄 Tasks
⭐ PR Point (To Reviewer)
FCM 키랑 계정정보 env 세팅 반드시 해주세요!
📷 Screenshot
Summary by CodeRabbit
신규 기능
버그 수정
작업