Conversation
📝 WalkthroughWalkthrough사용자 정보 조회 API(getMyInfo) 추가, 인증 토큰 초기화 플래그(isTokenInitialized) 도입 및 토큰 재발급 흐름 보강, 회원가입 단계에서 패스워드 전달 방식 변경, 라우터 인증 가드에 실제 인증 검사 로직을 적용했습니다. 일부 UI 컴포넌트 스타일/속성(입력 비활성화 처리, 레이아웃 너비)도 변경되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Browser as Browser
participant Router as Router/AuthGuard
participant Hook as useTokenRefresh<br/>(Hook)
participant AuthStore as useAuthStore
participant API as Auth API
Browser->>Router: 앱 마운트
Router->>AuthStore: isTokenInitialized?
alt 미초기화
Router->>Hook: 토큰 초기화 시작
Hook->>AuthStore: hasSession 확인
alt 세션 없음
AuthStore-->>Hook: hasSession=false
Hook->>AuthStore: setTokenInitialized()
else 세션 있음
Hook->>API: reissueToken 요청
alt 성공
API-->>Hook: 새 토큰
Hook->>AuthStore: setAccessToken(...)
else 실패
API-->>Hook: 에러
Hook->>AuthStore: resetAuth()
end
Hook->>AuthStore: setTokenInitialized()
end
Hook-->>Router: 초기화 완료
Router-->>Router: null (대기)
else 초기화됨
AuthStore-->>Router: true
Router->>AuthStore: isLoggedIn?
alt 로그인됨
Router->>Browser: 보호된 컴포넌트 렌더
else 미로그인
Router->>Browser: navigate("/login")
end
end
sequenceDiagram
participant User as User
participant Signup as Signup.tsx
participant PassStep as PasswordSetupStep
participant Profile as ProfileSetupStep
participant API as Auth API
User->>Signup: 회원가입 시작
Signup->>PassStep: 렌더(Step 2)
User->>PassStep: 비밀번호 입력 및 제출
PassStep->>Signup: onNext(password)
Signup->>Signup: password 상태 저장
Signup->>Profile: 렌더(provided password)
User->>Profile: 프로필 입력 및 제출
Profile->>API: 회원가입 요청 (email, password, profile)
API-->>Profile: 성공
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
세부 리뷰(요약·권장 개선)
버그/안정성 우선 체크리스트
필요하면 해당 파일들 중심으로 더 자세한 라인별 리뷰 제공할게. 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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: 4
🧹 Nitpick comments (4)
src/routes/Router.tsx (1)
13-26: 인증 가드 로직이 올바르게 구현되었습니다.토큰 초기화 전에
null을 반환하여 인증되지 않은 상태에서 보호된 콘텐츠가 잠깐 보이는 문제(flash)를 방지했습니다. selector 패턴 사용도 불필요한 리렌더링 방지에 좋습니다.다만, 초기화 중 빈 화면이 표시되는 시간이 길어질 경우 사용자 경험을 위해 로딩 인디케이터 추가를 고려해볼 수 있습니다.
💡 선택적: 로딩 상태 표시
if (!isTokenInitialized) { - return null; + return ( + <div className="flex h-screen items-center justify-center"> + <LoadingSpinner /> + </div> + ); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/Router.tsx` around lines 13 - 26, AuthGuard currently returns null while isTokenInitialized is false, which can cause a prolonged blank screen; update AuthGuard to render a loading indicator instead of null during token initialization by replacing the null return in the isTokenInitialized check with a lightweight loader component or spinner (e.g., render a <Loader /> or simple "Loading..." element), keeping the rest of the logic (useAuthStore selectors and the Navigate redirect when !isLoggedIn) unchanged so protected content and redirects behave the same.src/types/auth/auth.ts (1)
77-85: 타입 정의가 잘 되어 있습니다.한 가지 확인이 필요합니다:
profileImageUrl이 사용자가 프로필 이미지를 설정하지 않은 경우 서버에서null이나 빈 문자열을 반환할 수 있는지 확인해 주세요. 만약 그렇다면 타입을string | null로 변경하는 것이 안전합니다.💡 선택적 수정 제안
export interface IMyPageInfoResponse { userId: number; email: string; name: string; - profileImageUrl: string; + profileImageUrl: string | null; phoneNumber: string; isEmailVerified: boolean; providerType: TLoginProvider; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/types/auth/auth.ts` around lines 77 - 85, The IMyPageInfoResponse.profileImageUrl currently typed as string may actually be null or empty when a user hasn't set an image; update the IMyPageInfoResponse interface to make profileImageUrl nullable (e.g., string | null) and audit usages of IMyPageInfoResponse (calls that read profileImageUrl, components rendering profile images, and any serialization logic) to handle null/empty values safely (fallback image or conditional rendering).src/layout/main/MainLayout.tsx (1)
10-10: 쿼리 결과 활용 및 에러 처리 검토가 필요합니다.
useCoreQuery를 호출하고 있지만 결과를 사용하지 않고 있습니다. 현재 의도가 무엇인지에 따라 다음을 고려해 주세요:
데이터 프리페칭 목적이라면: 에러 발생 시 사용자에게 피드백이 없습니다. API 실패 시 토스트나 에러 바운더리를 통한 처리가 필요할 수 있습니다.
실제 데이터 사용 목적이라면: 쿼리 결과를 destructuring하여
isLoading,isError,data를 활용해야 합니다.♻️ 에러 처리 추가 예시
export default function MainLayout() { - useCoreQuery(["myInfo"], getMyInfo); + const { isError } = useCoreQuery(["myInfo"], getMyInfo); + + // 필요시 에러 처리 로직 추가 + // if (isError) { ... } + return (🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/layout/main/MainLayout.tsx` at line 10, The call to useCoreQuery(["myInfo"], getMyInfo) in MainLayout currently ignores the returned query result; update it to capture and handle the query tuple (e.g., const { data, isLoading, isError, error } = useCoreQuery(...)) and then use those flags to either prefetch only (silently) or surface failures—if prefetching, swallow failures but log them; if using data, render loading state when isLoading, show a user-facing error (toast or error boundary) when isError using the error object, and use data where needed; reference useCoreQuery and getMyInfo to locate and modify the call and add the appropriate UI/error handling paths.src/components/auth/flows/signup/ProfileSetupStep.tsx (1)
31-35: 리다이렉트 전 일시적 렌더링 방지 고려현재
useEffect에서 리다이렉트가 발생하기 전에 폼이 잠깐 렌더링될 수 있습니다. 사용자 경험 개선을 위해 조건이 맞지 않을 때 early return으로 로딩 상태나 null을 반환하는 것을 고려해 주세요.♻️ 제안하는 개선 방법
useEffect(() => { if (!email || !password) { navigate("/signup", { replace: true }); } }, [email, password, navigate]); + if (!email || !password) { + return null; + } + const { register,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/auth/flows/signup/ProfileSetupStep.tsx` around lines 31 - 35, In ProfileSetupStep, avoid briefly rendering the form before the useEffect redirect by adding an early return when email or password are missing: inside the ProfileSetupStep component (before JSX return), check the email and password props/state and return null or a loading placeholder instead of rendering the form, so navigation(navigate) still occurs in the existing useEffect but no UI flashes; ensure you reference the same email, password and navigate identifiers used in the current useEffect.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/common/input/Input.tsx`:
- Around line 56-62: In Input.tsx fix the typo in the success branch of the
className ternary (the conditional that checks the success prop) where "rubg-2"
is used; replace it with "ring-2" so the success state applies the intended ring
styling (update the class string in the success branch of the disabled ? ... :
error ? ... : success ? ... : ... expression).
In `@src/store/useAuthStore.ts`:
- Line 8: The stored state property socialId is declared as number | null but
the setter setSocialId only accepts number; update setSocialId's parameter type
to accept number | null (or alternatively change socialId to number if null
isn't allowed) so types are consistent—locate the socialId declaration and the
setSocialId action in useAuthStore and make their types match.
- Line 47: The resetAuth setter only clears email and should also clear socialId
to match logout's behavior; update the resetAuth implementation in useAuthStore
so it calls set with both email: "" and socialId: null (i.e., resetAuth: () =>
set({ email: "", socialId: null })) so temporary social login state is fully
cleared and consistent with logout; ensure you reference the existing resetAuth
and logout methods and the socialId state key when making the change.
- Around line 30-37: The logout implementation (logout) fails to reset
isTokenInitialized, causing state mismatch; update logout to also reset
isTokenInitialized to false (call the existing setter or set the field in set)
so token initialization flow restarts on next login, or alternatively change
setTokenInitialized to accept a boolean (setTokenInitialized(value: boolean))
and use it here to set false—locate logout and setTokenInitialized in
useAuthStore and apply one of these fixes.
---
Nitpick comments:
In `@src/components/auth/flows/signup/ProfileSetupStep.tsx`:
- Around line 31-35: In ProfileSetupStep, avoid briefly rendering the form
before the useEffect redirect by adding an early return when email or password
are missing: inside the ProfileSetupStep component (before JSX return), check
the email and password props/state and return null or a loading placeholder
instead of rendering the form, so navigation(navigate) still occurs in the
existing useEffect but no UI flashes; ensure you reference the same email,
password and navigate identifiers used in the current useEffect.
In `@src/layout/main/MainLayout.tsx`:
- Line 10: The call to useCoreQuery(["myInfo"], getMyInfo) in MainLayout
currently ignores the returned query result; update it to capture and handle the
query tuple (e.g., const { data, isLoading, isError, error } =
useCoreQuery(...)) and then use those flags to either prefetch only (silently)
or surface failures—if prefetching, swallow failures but log them; if using
data, render loading state when isLoading, show a user-facing error (toast or
error boundary) when isError using the error object, and use data where needed;
reference useCoreQuery and getMyInfo to locate and modify the call and add the
appropriate UI/error handling paths.
In `@src/routes/Router.tsx`:
- Around line 13-26: AuthGuard currently returns null while isTokenInitialized
is false, which can cause a prolonged blank screen; update AuthGuard to render a
loading indicator instead of null during token initialization by replacing the
null return in the isTokenInitialized check with a lightweight loader component
or spinner (e.g., render a <Loader /> or simple "Loading..." element), keeping
the rest of the logic (useAuthStore selectors and the Navigate redirect when
!isLoggedIn) unchanged so protected content and redirects behave the same.
In `@src/types/auth/auth.ts`:
- Around line 77-85: The IMyPageInfoResponse.profileImageUrl currently typed as
string may actually be null or empty when a user hasn't set an image; update the
IMyPageInfoResponse interface to make profileImageUrl nullable (e.g., string |
null) and audit usages of IMyPageInfoResponse (calls that read profileImageUrl,
components rendering profile images, and any serialization logic) to handle
null/empty values safely (fallback image or conditional rendering).
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
src/api/auth/auth.tssrc/components/Sidebar/Sidebar.tsxsrc/components/auth/common/InputActions.tsxsrc/components/auth/flows/signup/PasswordSetupStep.tsxsrc/components/auth/flows/signup/ProfileSetupStep.tsxsrc/components/common/input/Input.tsxsrc/hooks/auth/useTokenRefresh.tssrc/layout/main/MainLayout.tsxsrc/pages/auth/Signup.tsxsrc/routes/Router.tsxsrc/store/useAuthStore.tssrc/types/auth/auth.ts
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/store/useAuthStore.ts (1)
13-13:⚠️ Potential issue | 🟠 Major
isTokenInitialized가 로그아웃에서 리셋되지 않아 인증 상태가 꼬일 수 있어요Line 30의
logout에서isTokenInitialized를 초기화하지 않고, Line 44의setTokenInitialized가true만 설정 가능해서 상태 복원이 막혀 있습니다. 다음 로그인/토큰 초기화 사이클에서 가드 분기가 잘못될 가능성이 있습니다.수정 제안
interface IAuthState { isLoggedIn: boolean; isTokenInitialized: boolean; @@ - setTokenInitialized: () => void; + setTokenInitialized: (value: boolean) => void; @@ logout: () => { localStorage.removeItem("hasSession"); set({ isLoggedIn: false, + isTokenInitialized: false, accessToken: null, email: "", socialId: null, }); }, @@ - setTokenInitialized: () => set({ isTokenInitialized: true }), + setTokenInitialized: (value) => set({ isTokenInitialized: value }),Also applies to: 30-38, 44-44
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/store/useAuthStore.ts` at line 13, The store's token-initialized flag isn't reset on logout and the setter only allows true, causing stale auth state; update the logout implementation (logout) to reset isTokenInitialized to false and change setTokenInitialized to accept a boolean (or add a clearTokenInitialized method) so callers can set it to false during logout or reinitialize flows; update usages to call setTokenInitialized(false) (or the new clear) where appropriate to ensure the guard branching uses the correct state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/store/useAuthStore.ts`:
- Line 13: The store's token-initialized flag isn't reset on logout and the
setter only allows true, causing stale auth state; update the logout
implementation (logout) to reset isTokenInitialized to false and change
setTokenInitialized to accept a boolean (or add a clearTokenInitialized method)
so callers can set it to false during logout or reinitialize flows; update
usages to call setTokenInitialized(false) (or the new clear) where appropriate
to ensure the guard branching uses the correct state.
|
P4: 확인했습니다 고생하셨습니다! |
🚨 관련 이슈
#61
✨ 변경사항
✏️ 작업 내용
1.
Router.tsx2. 마이페이지 API 연동
IMyPageInfoResponse타입 추가getMyInfo()API 함수 추가3. 기타
😅 미완성 작업
N/A
📢 논의 사항 및 참고 사항
N/A
Summary by CodeRabbit
릴리스 노트
New Features
Refactor
Style