Skip to content

로그인 API 연결#30

Merged
yoouyeon merged 29 commits intodevelopfrom
feat/MD-25
Apr 19, 2026
Merged

로그인 API 연결#30
yoouyeon merged 29 commits intodevelopfrom
feat/MD-25

Conversation

@yoouyeon
Copy link
Copy Markdown
Contributor

@yoouyeon yoouyeon commented Apr 11, 2026

💻 작업 내용

기존 mock API에서 실제 로그인 API를 연결했습니다!

실제 API 연동 (mock 제거)

  • 인증 체크: /user/auth/check → /auth/check
  • 게스트 토큰 발급: 쿠키 기반으로 전환, localStorage 저장 로직 제거
  • 로그아웃: /user/logout → /logout
  • 서비스 탈퇴: /users/me → /unlink
  • 사용자 정보 조회: /user/info → /user, User 타입을 API 응답에 맞게 수정

인증 흐름 개선 (연동 과정에서 함께 수정)

  • 카카오 로그인: OAuth state 파라미터로 로그인 완료 후 원래 페이지 복귀
  • 로그인 페이지 진입 시 이미 인증된 상태면 redirectTo 또는 홈으로 redirect하는 loader 추가
  • 401 응답 시 액세스 토큰 재발급 후 원래 요청 재시도, 실패 시 redirectTo 포함해 로그인 페이지로 이동
  • Supabase 관련 코드 제거
  • auth loader를 FSD에 맞게 features/auth/lib으로 이동
  • (4/14 추가) 토큰 재발급 실패 시 401만 로그인으로 redirect, 5xx/네트워크 오류는 error boundary로 전파

개발 환경 설정 - 쿠키 차단 문제 우회를 위해

  • localhost↔api.moddo.kr cross-origin 쿠키 차단 문제 우회를 위해 Vite proxy 추가
  • 개발 환경에서는 /api/v1 상대경로로 요청해서 Vite proxy 경유, 프로덕션에서는 VITE_SERVER_URL로 직접 요청

✅ 테스트 리스트

  • 카카오 로그인 (백엔드의 state 수정 작업 이후 테스트)
  • 액세스 토큰 재발급 (백엔드의 refresh token 수정 작업 이후 테스트)
  • 로그아웃 (게스트 유저 로그아웃 가능 여부 확인 후 테스트)
  • 서비스 탈퇴 (게스트 유저 탈퇴 가능 여부 확인 후 테스트)
  • 사용자 정보 조회 (현재는 토큰을 전달했음에도 토큰이 없다는 응답(401)이 와서 백엔드에 확인 요청중입니다... (게스트 유저 이슈일 가능성이 높아보여요))
  • 게스트 로그인
  • 인증 체크

👻 리뷰 요구사항

  • state 파라미터로 로그인 완료 후 원래 페이지 복귀
  • refreshToken의 HttpOnly 쿠키 전환

이 두가지는 현재 백엔드쪽에 요청해둔 상태이고, 지금 코드는 해당 변경을 가정하고 작성한 상태입니다.
백엔드쪽 변경사항에 따라 추가 수정이 필요할 수 있습니다!

Summary by CodeRabbit

릴리스 노트

  • Bug Fixes

    • 토큰 갱신 메커니즘을 개선하여 로그인 세션 유지 안정성 강화
  • Refactor

    • 인증 시스템 구조를 개선하고 API 엔드포인트를 정리
    • 보안 리다이렉트 경로 검증 로직을 추가하여 안전한 페이지 이동 지원
    • 로그인 후 리다이렉트 동작을 개선하여 사용자 경험 향상

yoouyeon added 12 commits April 11, 2026 16:50
- checkAuth: 인증 실패 시 redirectTo 쿼리파라미터로 원래 경로 전달
- LoginPage: redirectTo 파라미터를 읽어 kakaoLogin에 전달
- kakaoLogin: state에 완전한 URL(origin + pathname) 담아 전송
  (백엔드가 로그인 후 해당 URL로 직접 redirect)
checkAuth를 entities/auth/lib에서 features/auth/lib로 이동하고 import 경로를 수정합니다.
이미 인증된 경우 redirectTo 또는 홈으로 redirect하는 checkAlreadyAuthLoader를 추가하고 /login 라우트에 연결합니다.
401 응답 시 현재 경로를 redirectTo 쿼리 파라미터에 담아 로그인 페이지로 이동하도록 수정합니다.
또한 localStorage 기반 Authorization 헤더를 제거합니다 (쿠키 기반 인증으로 전환).

ref: #28 (comment)
캐싱이 불필요한 단순 액션이므로 useQuery 대신 직접 API 호출 방식으로 변경합니다.
@yoouyeon yoouyeon self-assigned this Apr 11, 2026
@yoouyeon yoouyeon added the ✨ Feature 신규 기능 추가 label Apr 11, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 11, 2026

📝 관련 이슈

MD-25

@github-actions github-actions bot requested a review from ongheong April 11, 2026 13:09
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

인증 시스템을 재구성하여 API 엔드포인트를 단순화하고, 모의 플래그를 제거하며, 새로운 검증 로더를 도입하고, 토큰 갱신 로직을 추가하고, 안전한 리다이렉트 경로 검증을 구현했습니다.

Changes

Cohort / File(s) Summary
Auth API 엔드포인트 변경
src/entities/auth/api/auth.ts, src/features/auth/api/authApi.ts
getAuthGET /auth/check 호출 및 Promise<AuthCheckResponse> 반환, getUserInfoGET /user 호출, logoutPOST /logout, unregisterDELETE /unlink로 변경. 모든 함수에서 useMock 옵션 제거.
Auth 모델 및 타입
src/entities/auth/model/user.type.ts
User 인터페이스에서 id 제거 및 profileImageUrlprofile 변경. 새로운 AuthCheckResponse 인터페이스 추가 (authenticated 필드 포함).
Auth 로더 및 가드
src/features/auth/lib/checkAuth.ts, src/features/auth/lib/checkAlreadyAuthLoader.ts
보호된 라우트용 checkAuth 로더와 로그인 경로용 checkAlreadyAuthLoader 로더 신규 추가. 인증 상태 확인 및 리다이렉트 로직 포함.
HTTP 클라이언트 및 리다이렉트 경로 안전성
src/shared/api/axios.ts, src/shared/lib/getSafeRedirectPath.ts, src/shared/types/axios.d.ts, vite.config.ts
axiosInstanceBASE_URL 설정, 인증서 포함(withCredentials: true), 401 응답 시 토큰 갱신 로직 추가. refreshClient 인스턴스 신규 생성. getSafeRedirectPath 유틸리티 추가로 동일 출처 리다이렉트만 허용. Vite에 /api/v1 프록시 설정.
Auth 관련 유틸리티 및 훅 변경
src/entities/auth/api/useGetGuestToken.ts, src/entities/auth/lib/kakaoLogin.ts
useGetGuestToken 훅 제거. kakaoLoginurl 대신 redirectPathAfterLogin 경로 파라미터 수용.
페이지 및 컴포넌트 업데이트
src/pages/login/LoginPage.tsx, src/pages/expenseDetail/loader.ts, src/pages/join/loader.ts, src/features/user-profile/ui/MyProfile/index.tsx
LoginPage는 게스트 토큰 로직 중앙화 및 kakaoLoginredirectTo 파라미터 전달. 페이지 로더들은 getUserInfogetAuth 호출로 변경. MyProfileprofileuser 변수 이름 변경 및 null 가드 추가.
Mock 핸들러 업데이트
src/mocks/handlers/auth.ts
GET /api/v1/user 모의 응답에서 id 필드 제거.
라우팅 설정
src/app/Router.tsx
checkAuth import 경로 변경. ROUTE.logincheckAlreadyAuthLoader 로더 추가.

Possibly related PRs

Poem

🐰 인증의 길을 새롭게 고쳐,
안전한 리다이렉트로 사용자 보호하고,
토큰 갱신으로 세션 유지하며,
API는 더욱 깔끔해졌네.
모의 데이터는 그만두고,
실제 서버와 춤을 춘다! ✨

🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/MD-25

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 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/entities/auth/lib/kakaoLogin.ts`:
- Around line 14-18: 현재 stateUrl을 redirectPathAfterLogin을 검증 없이 결합해 공격자가
"///evil.com" 같은 값을 넣어 복귀 URL을 변조할 수 있습니다; 수정하려면 redirectPathAfterLogin 값을 받아
검증하는 로직을 추가해(예: 변수명 redirectPathAfterLogin 검사) 입력이 문자열이고 반드시 '/'로 시작하며 '//'로
시작하지 않는 same-origin 경로인지 확인하고, 유효하지 않으면 '/'로 폴백한 뒤 그 검증된 값을 사용해 stateUrl을 구성하고
기존 window.location.href 생성(현재의 KAKAO_REDIRECT_URI, KAKAO_CLIENT_ID 부분)에서 해당 검증된
경로를 넣도록 변경하세요.

In `@src/features/auth/lib/checkAlreadyAuthLoader.ts`:
- Around line 20-22: The code trusts redirectTo from request.url and can cause
an open redirect; in the loader (checkAlreadyAuthLoader) validate redirectTo
before calling redirect: parse the search param then only allow it if it starts
with a single '/' (e.g., redirectTo.startsWith('/') &&
!redirectTo.startsWith('//')) and reject any absolute URLs or protocol-relative
URLs (those starting with 'http', 'https', or '//'); otherwise fall back to
ROUTE.home. Update the block that reads new
URL(request.url).searchParams.get('redirectTo') and the redirect(...) call to
perform this whitelist check and use ROUTE.home when the value is unsafe or
missing.

In `@src/features/auth/lib/checkAuth.ts`:
- Around line 24-26: The catch in checkAuth.ts currently swallows all errors and
redirects to ROUTE.login, masking real failures and losing query/hash; update
the catch to accept the caught error (e.g., err), determine if it represents an
unauthenticated/401 condition and only then return redirect to
`${ROUTE.login}?redirectTo=${encodeURIComponent(new URL(request.url).pathname +
new URL(request.url).search + new URL(request.url).hash)}` (or otherwise
preserve full request URL), otherwise rethrow the original error so
RouteErrorBoundary can handle server/network failures; reference the catch block
in checkAuth.ts, the redirect call, and the request.url handling when making
changes.

In `@src/features/user-profile/ui/MyProfile/index.tsx`:
- Around line 18-27: Initial render can crash because user (from useGetUserInfo)
may be undefined; guard accesses to user.name and user.email in this component
(around MemberProfileImage, Text rendering) by checking user presence or using
safe fallbacks. Update the render logic in MyProfile (referencing user,
MemberProfileImage, and the two Text usages) to either early-return a
loading/placeholder UI when user is falsy or use optional chaining/default
values (e.g., user?.name / user?.email or '—') so the component never reads
properties off undefined.

In `@src/shared/api/axios.ts`:
- Around line 45-50: The response interceptor causes a retry loop because the
token reissue call (axiosInstance.put('/user/reissue/token')) is also
intercepted; update the logic in the interceptor to skip reissue calls by either
1) adding a guard that checks originalRequest.url !== '/user/reissue/token' (or
originalRequest.headers flag) before attempting reissue and only set
originalRequest.isRetry for the original request, or 2) perform the reissue
using a separate axios client without the interceptor (e.g.,
authAxios.put('/user/reissue/token')) so the reissue request does not trigger
the same interceptor; apply the fix around axiosInstance, originalRequest, and
the '/user/reissue/token' call.
- Around line 52-55: The interceptor currently uses window.location.href with
only window.location.pathname, which bypasses React Router loaders and drops
search/hash; replace this with React Router's redirect() (import from
'react-router-dom' or reuse the pattern in src/features/auth/lib/checkAuth.ts)
in the token-refresh-failure branch, and build redirectTo as the full location
(window.location.pathname + window.location.search + window.location.hash)
encoded via encodeURIComponent before passing it to
redirect(`${ROUTE.login}?redirectTo=${redirectTo}`) so the router handles
navigation and preserves query/hash.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1f119f70-7a49-413e-b0e3-146f460f95ae

📥 Commits

Reviewing files that changed from the base of the PR and between b58628b and d4eb76c.

📒 Files selected for processing (13)
  • src/app/Router.tsx
  • src/entities/auth/api/auth.ts
  • src/entities/auth/api/useGetGuestToken.ts
  • src/entities/auth/lib/kakaoLogin.ts
  • src/entities/auth/model/user.type.ts
  • src/features/auth/api/authApi.ts
  • src/features/auth/lib/checkAlreadyAuthLoader.ts
  • src/features/auth/lib/checkAuth.ts
  • src/features/user-profile/ui/MyProfile/index.tsx
  • src/mocks/handlers/auth.ts
  • src/pages/login/LoginPage.tsx
  • src/shared/api/axios.ts
  • src/shared/types/axios.d.ts
💤 Files with no reviewable changes (2)
  • src/mocks/handlers/auth.ts
  • src/entities/auth/api/useGetGuestToken.ts

Comment thread src/entities/auth/lib/kakaoLogin.ts Outdated
Comment thread src/features/auth/lib/checkAlreadyAuthLoader.ts Outdated
Comment thread src/features/auth/lib/checkAuth.ts Outdated
Comment thread src/features/user-profile/ui/MyProfile/index.tsx Outdated
Comment thread src/shared/api/axios.ts
Comment thread src/shared/api/axios.ts Outdated
인증 실패 시에만 로그인으로 redirect하고, 5xx/네트워크 오류는 RouteErrorElement에서 처리되도록 불필요한 try/catch를 제거합니다.
또한 redirectTo에 pathname만 포함하던 것을 search, hash까지 포함하도록 수정합니다.

ref: #30 (comment)
재발급 요청을 axiosInstance 대신 interceptor가 없는 refreshClient로 호출합니다.
재발급 API가 401을 반환해도 interceptor를 타지 않으며, isRetry 플래그는 재시도한 원래 요청이 다시 401을 반환하는 루프를 방지합니다.

ref: #30 (comment)
@cloudflare-workers-and-pages

This comment was marked as off-topic.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
src/shared/api/axios.ts (1)

64-67: ⚠️ Potential issue | 🟠 Major

redirectTo가 query/hash를 잃어서 로그인 후 원래 위치 복귀가 깨집니다.

Line 66은 pathname만 인코딩하고 있어서, src/pages/login/LoginPage.tsx:23-24가 넘기는 redirectTo에도 검색 조건과 hash가 포함되지 않습니다. 401 이후 로그인 플로우에서 원래 URL 전체를 복원하려면 pathname + search + hash를 넘겨야 합니다.

🔧 최소 수정안
-        const redirectTo = encodeURIComponent(window.location.pathname);
+        const redirectTo = encodeURIComponent(
+          window.location.pathname +
+            window.location.search +
+            window.location.hash
+        );

Based on learnings redirectTo should be built from window.location.pathname + window.location.search + window.location.hash to avoid losing query/hash on redirect.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/shared/api/axios.ts` around lines 64 - 67, The redirect currently builds
redirectTo from window.location.pathname only, losing search and hash; update
the logic where redirectTo is computed (used before setting window.location.href
with ROUTE.login) to concatenate window.location.pathname +
window.location.search + window.location.hash, then encodeURIComponent that full
string so the login redirect preserves query params and fragment when returning
to the original page.
🤖 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/shared/api/axios.ts`:
- Around line 64-67: The redirect currently builds redirectTo from
window.location.pathname only, losing search and hash; update the logic where
redirectTo is computed (used before setting window.location.href with
ROUTE.login) to concatenate window.location.pathname + window.location.search +
window.location.hash, then encodeURIComponent that full string so the login
redirect preserves query params and fragment when returning to the original
page.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 23b05294-390e-43ef-9a5b-c2e30cd6aa61

📥 Commits

Reviewing files that changed from the base of the PR and between d4eb76c and 384fdc3.

📒 Files selected for processing (5)
  • src/entities/auth/lib/kakaoLogin.ts
  • src/features/auth/lib/checkAlreadyAuthLoader.ts
  • src/features/auth/lib/checkAuth.ts
  • src/features/user-profile/ui/MyProfile/index.tsx
  • src/shared/api/axios.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/features/auth/lib/checkAuth.ts
  • src/entities/auth/lib/kakaoLogin.ts
  • src/features/user-profile/ui/MyProfile/index.tsx
  • src/features/auth/lib/checkAlreadyAuthLoader.ts

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/shared/api/axios.ts (1)

67-70: ⚠️ Potential issue | 🟠 Major

redirectTo에 query/hash가 빠져 원래 위치가 보존되지 않습니다.

Line 69에서 pathname만 encode 해서 /foo?tab=bar#section/foo로 잘립니다. 특히 이미 /login?redirectTo=...에 있는 경우에는 원래 목적지가 /login으로 덮어써질 수 있습니다. navigation 방식을 바꾸지 않아도 이 문자열은 pathname + search + hash 전체로 바로 보정할 수 있습니다.

🔁 제안 코드
-        const redirectTo = encodeURIComponent(window.location.pathname);
+        const redirectTo = encodeURIComponent(
+          window.location.pathname +
+            window.location.search +
+            window.location.hash
+        );
         window.location.href = `${ROUTE.login}?redirectTo=${redirectTo}`;

Based on learnings: redirectTo should be built from window.location.pathname + window.location.search + window.location.hash (not just pathname) to avoid losing query/hash on redirect.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/shared/api/axios.ts` around lines 67 - 70, The code currently builds
redirectTo from window.location.pathname only, losing query/hash and potentially
overwriting an existing login redirect; change to build the full current
location using window.location.pathname + window.location.search +
window.location.hash and encodeURIComponent that value for redirectTo (use the
redirectTo variable already present), then set window.location.href =
`${ROUTE.login}?redirectTo=${redirectTo}`; additionally, guard against
clobbering an existing login redirect by checking if window.location.pathname
=== ROUTE.login and new
URLSearchParams(window.location.search).has('redirectTo') and, if so, skip
performing the redirect.
🤖 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/shared/api/axios.ts`:
- Around line 62-71: The catch block in the refresh token flow (inside the
refreshClient.put('/user/reissue/token') handling) treats all errors as
authentication failures and redirects to ROUTE.login, hiding server/network
errors; change the catch to inspect the error (from refreshClient.put) and only
perform the redirect when the response indicates an actual auth failure (e.g.,
401/403 or a specific API error code), otherwise rethrow or return a rejected
promise so the caller (e.g., checkAuth.ts) can surface server/network errors;
locate the token refresh logic around refreshClient, originalRequest and
axiosInstance to implement this conditional error handling and preserve non-auth
errors by rejecting them instead of redirecting.
- Around line 19-23: The axios.create call that constructs refreshClient has
baseURL declared twice (first as BASE_URL, then overwritten by the
import.meta.env.VITE_SERVER_URL conditional), so BASE_URL is ignored and causes
errors; fix by computing a single baseUrl value (e.g., const baseUrl =
import.meta.env.VITE_SERVER_URL ? `${import.meta.env.VITE_SERVER_URL}/api/v1` :
BASE_URL) and use that single variable in axios.create for refreshClient (update
any other client creations to reference the same baseUrl) so refreshClient,
BASE_URL usage, and the import.meta.env.VITE_SERVER_URL conditional are unified
and not duplicated.

---

Duplicate comments:
In `@src/shared/api/axios.ts`:
- Around line 67-70: The code currently builds redirectTo from
window.location.pathname only, losing query/hash and potentially overwriting an
existing login redirect; change to build the full current location using
window.location.pathname + window.location.search + window.location.hash and
encodeURIComponent that value for redirectTo (use the redirectTo variable
already present), then set window.location.href =
`${ROUTE.login}?redirectTo=${redirectTo}`; additionally, guard against
clobbering an existing login redirect by checking if window.location.pathname
=== ROUTE.login and new
URLSearchParams(window.location.search).has('redirectTo') and, if so, skip
performing the redirect.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 36cfda6b-cd4a-4d7e-b42e-e536d9732e33

📥 Commits

Reviewing files that changed from the base of the PR and between 384fdc3 and 7848c84.

📒 Files selected for processing (1)
  • src/shared/api/axios.ts

Comment thread src/shared/api/axios.ts Outdated
Comment thread src/shared/api/axios.ts
- 게스트 토큰 발급 후 ['auth', 'user'] 캐시를 removeQueries로 제거
- ensureQueryData가 캐시를 재사용하지 않고 반드시 재요청하도록 함
- Vite proxy 추가: /api/v1 요청을 VITE_SERVER_URL로 포워딩
- cookieDomainRewrite로 쿠키 domain을 localhost로 재작성
- 개발 환경에서 Vite proxy 경유하도록 수정
- Storybook MSW 핸들러 URL을 /api/v1 prefix 포함하도록 수정
- isAxiosError + status 401 체크로 실제 인증 실패만 구분
- 그 외 에러는 reject해서 error boundary에서 처리하도록 함

ref:
#30
proxy 설정을 VITE_SERVER_URL이 있을 때만 적용하도록 변경
@github-actions
Copy link
Copy Markdown

@yoouyeon
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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/pages/login/LoginPage.tsx`:
- Around line 26-30: The getGuestToken() call lacks error handling; wrap the
await getGuestToken() inside a try/catch in the LoginPage component (surround
the call where queryClient.removeQueries and navigate(ROUTE.selectGroup) are
currently invoked), on success keep the existing behavior, on failure log the
error and surface user feedback (e.g., set an error state or call the app's
toast/notification helper) and do not call queryClient.removeQueries or
navigate; ensure you reference getGuestToken, queryClient.removeQueries,
navigate, and ROUTE.selectGroup when making the change.

In `@vite.config.ts`:
- Around line 106-113: The proxy's cookieDomainRewrite currently uses new
URL(env.VITE_SERVER_URL).hostname which will throw on invalid URLs and does
exact-match rewrites that miss variants like '.moddo.kr' vs 'moddo.kr'; update
the proxy config that builds cookieDomainRewrite (the object under proxy ->
'/api/v1' using env.VITE_SERVER_URL) to first validate/parses
env.VITE_SERVER_URL safely (wrap new URL(...) in a try/catch or use a small
validator) and, instead of mapping only the parsed hostname, use a wildcard key
'*' mapping to 'localhost' so all backend cookie domains are rewritten to
localhost; if env.VITE_SERVER_URL is missing/invalid, skip hostname parsing and
still set cookieDomainRewrite: { '*': 'localhost' } or omit gracefully.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b4eaa505-6e6d-4a39-a785-f713b80af27d

📥 Commits

Reviewing files that changed from the base of the PR and between 7848c84 and 68cdded.

📒 Files selected for processing (4)
  • src/pages/expenseDetail/ui/ExpenseTimeHeader/index.stories.tsx
  • src/pages/login/LoginPage.tsx
  • src/shared/api/axios.ts
  • vite.config.ts
✅ Files skipped from review due to trivial changes (1)
  • src/pages/expenseDetail/ui/ExpenseTimeHeader/index.stories.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/shared/api/axios.ts

Comment thread src/pages/login/LoginPage.tsx
Comment thread vite.config.ts Outdated
- VITE_SERVER_URL 파싱을 상단에서 try/catch로 처리해서 잘못된 URL 형식에도 안전하게 동작하도록 함
- cookieDomainRewrite를 { '*': 'localhost' }로 변경해 .moddo.kr 등 모든 도메인 변형을
  모두 커버하도록 함

ref:
#30 (comment)
@github-actions
Copy link
Copy Markdown

@yoouyeon
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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/pages/login/LoginPage.tsx`:
- Around line 22-37: handleLoginButtonClick currently allows concurrent
getGuestToken() calls when loginType === 'GUEST'; add an in-flight guard (e.g.,
isGuestLoginInFlight ref or state) checked at the top of handleLoginButtonClick
to return early if true, set it to true immediately before awaiting
getGuestToken(), and ensure it is cleared in a finally block (or both catch and
success paths) so subsequent clicks are allowed; keep existing logic
(queryClient.removeQueries, navigate, showToast) but make sure the guard is
reset on both success and failure to avoid deadlocking the button.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 06e69a02-f7d1-4a85-9a12-621d1369e400

📥 Commits

Reviewing files that changed from the base of the PR and between 68cdded and 767f196.

📒 Files selected for processing (2)
  • src/pages/login/LoginPage.tsx
  • vite.config.ts

Comment thread src/pages/login/LoginPage.tsx
Copy link
Copy Markdown
Contributor

@ongheong ongheong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드 모두 확인했습니다! 게스트 유저 이슈도 모두 확인되면 이제 "비회원으로 진행" 버튼도 로그인 화면에서 제거해도 되겠네요.
코멘트 두개 남겨두었는데 확인해주시면 감사하겠습니다~!

Comment thread src/features/auth/lib/checkAlreadyAuthLoader.ts Outdated
Comment thread vite.config.ts Outdated
@github-actions
Copy link
Copy Markdown

@yoouyeon
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 19, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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/shared/lib/getSafeRedirectPath.ts`:
- Line 11: getSafeRedirectPath currently allows paths like "/\evil.com" because
it only checks startsWith('/') and not backslashes; update the guard in
getSafeRedirectPath to also reject any path containing backslashes (e.g., add a
check like !path.includes('\\')) or explicitly disallow "/\\" (e.g.,
!path.startsWith('/\\')), and otherwise return the fallback; alternatively,
validate by resolving new URL(path, origin) and ensure the result's origin
matches the app origin before returning path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cdcceb2a-cb39-45e7-8cb9-ccd73fa74cfe

📥 Commits

Reviewing files that changed from the base of the PR and between 68cdded and eb9f106.

📒 Files selected for processing (5)
  • src/entities/auth/lib/kakaoLogin.ts
  • src/features/auth/lib/checkAlreadyAuthLoader.ts
  • src/pages/login/LoginPage.tsx
  • src/shared/lib/getSafeRedirectPath.ts
  • vite.config.ts
✅ Files skipped from review due to trivial changes (1)
  • vite.config.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/entities/auth/lib/kakaoLogin.ts
  • src/features/auth/lib/checkAlreadyAuthLoader.ts
  • src/pages/login/LoginPage.tsx

Comment thread src/shared/lib/getSafeRedirectPath.ts Outdated
new URL을 이용해서 origin을 명시적으로 확인하는 방식 적용

ref:
#30 (comment)
/user API에 id 필드가 없어 loader에서 user.id 비교가 불가능한 문제 수정.
@yoouyeon
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 19, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
src/pages/expenseDetail/loader.ts (1)

47-60: ⚠️ Potential issue | 🟡 Minor

401 캐치 분기 제거 또는 상태 코드 검토 필요

axiosInstance 응답 인터셉터가 401 에러를 전역적으로 처리하고 로그인으로 리다이렉트하므로, 50-55번 줄의 BoundaryError 분기는 도달할 수 없는 데드 코드입니다.

또한 "접근 권한이 없어요" 메시지는 의미상 타인의 정산에 접근한 경우(403 또는 특정 권한 에러)에 해당하며, 401은 인증 만료/미로그인을 의미하므로 여기서 사용하기에 맞지 않습니다.

주석의 "실제로는 500 에러가 발생함"은 백엔드 API 동작을 확인한 후 실제 상태 코드(403 등)로 교체하거나, 이 분기를 제거하는 방안을 검토해 주세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/expenseDetail/loader.ts` around lines 47 - 60, The catch block in
loader.ts contains a dead 401 branch guarded by isAxiosError(error) that creates
a BoundaryError with a "접근 권한이 없어요" message; because axiosInstance globally
handles 401, this branch is unreachable and the message semantics fit a
403/authorization error not 401. Either remove the entire 401 branch (the if
(error.response?.status === 401) { ... } block) or change the status check to
the correct authorization code (e.g., 403) and keep BoundaryError
(BoundaryError({...})) with the same message; update/remove the comment and
ensure you reference isAxiosError, error.response?.status and BoundaryError when
making the change.
🧹 Nitpick comments (1)
src/features/user-profile/ui/MyProfile/index.tsx (1)

18-24: Null guard 이후 optional chaining 불필요

Line 18-20에서 !user early return을 추가했으니 이후 코드에서는 user가 항상 정의되어 있습니다. Line 24의 user?.profile만 optional chaining을 쓰고 Line 26/33은 user.name/user.email로 직접 접근하고 있어 스타일이 일관되지 않습니다. Line 24도 user.profile로 통일해 주시면 좋겠습니다 (profile은 optional 필드라 ProfileImagesrcundefined일 수 있는 점은 동일).

♻️ 제안 diff
-      <ProfileImage size="36" src={user?.profile} />
+      <ProfileImage size="36" src={user.profile} />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/user-profile/ui/MyProfile/index.tsx` around lines 18 - 24, After
the early return guard (if (!user) return null;) the component can assume user
is defined; replace the optional chaining usage user?.profile with user.profile
to be consistent with subsequent direct accesses like user.name and user.email
(ProfileImage can still accept undefined for src since profile is optional).
🤖 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/entities/auth/api/auth.ts`:
- Around line 19-27: The mock flow broke because the { useMock: true } request
option (which triggers the axios interceptor to set the X-Mock-Request: true
header) was removed from getAuth, getUserInfo and getGuestToken; restore mock
behavior by re-adding the { useMock: true } option to the axiosInstance.get
calls in getAuth and getUserInfo (and wherever getGuestToken is defined) so the
interceptor attaches the header, or alternatively implement a global mock-mode
branch that automatically attaches X-Mock-Request: true for all requests when
mock mode is enabled; target the functions getAuth, getUserInfo and
getGuestToken when applying the fix.

---

Outside diff comments:
In `@src/pages/expenseDetail/loader.ts`:
- Around line 47-60: The catch block in loader.ts contains a dead 401 branch
guarded by isAxiosError(error) that creates a BoundaryError with a "접근 권한이 없어요"
message; because axiosInstance globally handles 401, this branch is unreachable
and the message semantics fit a 403/authorization error not 401. Either remove
the entire 401 branch (the if (error.response?.status === 401) { ... } block) or
change the status check to the correct authorization code (e.g., 403) and keep
BoundaryError (BoundaryError({...})) with the same message; update/remove the
comment and ensure you reference isAxiosError, error.response?.status and
BoundaryError when making the change.

---

Nitpick comments:
In `@src/features/user-profile/ui/MyProfile/index.tsx`:
- Around line 18-24: After the early return guard (if (!user) return null;) the
component can assume user is defined; replace the optional chaining usage
user?.profile with user.profile to be consistent with subsequent direct accesses
like user.name and user.email (ProfileImage can still accept undefined for src
since profile is optional).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 60f9b03d-1ee1-4e1a-9253-7d24a554f930

📥 Commits

Reviewing files that changed from the base of the PR and between eb9f106 and 5f343ce.

📒 Files selected for processing (8)
  • src/app/Router.tsx
  • src/entities/auth/api/auth.ts
  • src/entities/auth/model/user.type.ts
  • src/features/user-profile/ui/MyProfile/index.tsx
  • src/mocks/handlers/auth.ts
  • src/pages/expenseDetail/loader.ts
  • src/pages/join/loader.ts
  • src/shared/lib/getSafeRedirectPath.ts
💤 Files with no reviewable changes (1)
  • src/mocks/handlers/auth.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/app/Router.tsx
  • src/entities/auth/model/user.type.ts
  • src/shared/lib/getSafeRedirectPath.ts

Comment thread src/entities/auth/api/auth.ts
@yoouyeon
Copy link
Copy Markdown
Contributor Author

@coderabbitai approve

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 19, 2026

✅ Actions performed

Comments resolved and changes approved.

@yoouyeon yoouyeon merged commit 97d3db0 into develop Apr 19, 2026
2 checks passed
@yoouyeon yoouyeon deleted the feat/MD-25 branch April 19, 2026 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 신규 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants