Fix: 401 전역 처리에서 user 정보 api 제외#187
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded@seueooo has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 3 minutes and 27 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (3)
WalkthroughuserInfo 쿼리의 에러 처리 책임이 일부 이동했습니다: HTTP 클라이언트의 beforeError 훅은 USER_INFO 요청을 글로벌 상태 기반 리다이렉트에서 제외하고, 설정 페이지는 userInfo 쿼리의 onError로 로그인 경로로 리다이렉트하도록 추가했습니다. 네비게이션 바에 홈 버튼과 스타일명 변경이 추가되었으며, 한 파일은 포맷만 변경되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as User
participant Page as Page (setting / other)
participant Query as userInfo Query
participant HTTP as http.beforeError
participant Router as Router
U->>Page: 페이지 진입 또는 액션
Page->>Query: userInfo() 호출 (with optional onError)
Query->>HTTP: HTTP 요청 발생 / beforeError 훅
alt 요청이 USER_INFO
HTTP-->>Query: 에러 반환 (전역 리다이렉트 생략)
Query-->>Page: 에러 전파
alt Page에 onError 있음
Page->>Router: onError -> router.replace(PATH.LOGIN)
else
Page-->>U: 에러 응답 (전역 리다이렉트 없음)
end
else 다른 엔드포인트
HTTP->>HTTP: 상태별 처리 (401/404 등) -> 전역 리다이렉트 실행
HTTP-->>Query: 에러 반환 (이미 사이드이펙트 발생)
Query-->>Page: 에러 전파
end
Estimated code review effort🎯 3 (중간) | ⏱️ ~20 minutes ✨ 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. 🪧 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/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
|
This pull request (commit
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/(sub)/capsule-detail/[invite-code]/[id]/page.tsx (1)
43-47: React Query retry 비활성화 및 상태 노출 적용 권장다음 사항들을 반영하면 401 에러 시 불필요한 재시도/리다이렉트 호출을 방지하고, 인증 확인 흐름을 명확히 제어할 수 있습니다.
useQuery기본 재시도(3회) →retry: false명시isFetching와refetch구조분해로 인증 확인 상태 제어- (선택)
userQueryOptions.userInfo옵션 타입을 확장해 재사용성 향상- const { data: user } = useQuery( - userQueryOptions.userInfo({ - enabled: shouldCheckUser - }) - ); + const { + data: user, + isFetching: isUserFetching, + refetch: refetchUser, + } = useQuery( + userQueryOptions.userInfo({ + enabled: shouldCheckUser, + retry: false, // 401 반복 호출 방지 + }), + );추가로,
shared/api/queries/user.ts(또는 유사 파일)에서userInfo시그니처를 아래처럼 확장하면 다양한 옵션을 손쉽게 주입할 수 있어 좋습니다.export const userQueryOptions = { - userInfo: (options?: { enabled?: boolean }) => + userInfo: ( + options?: Omit<Parameters<typeof queryOptions>[0], "queryKey" | "queryFn">, + ) => queryOptions({ queryKey: userQueryKeys.userInfo(), queryFn: () => apiClient.get<UserInfo>(ENDPOINTS.USER_INFO), ...options, }), };현재 코드베이스에서는 글로벌 401 인터셉터나 중복된
router.push(PATH.LOGIN)처리가 발견되지 않았으니, 이 페이지의 수동 리다이렉트와 충돌 우려는 없습니다.
향후 전역 처리 로직이 추가될 때는 중복 리다이렉트를 방지하도록 정책을 통일해 주세요.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
app/(sub)/capsule-detail/[invite-code]/[id]/page.tsx(3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
app/(sub)/capsule-detail/[invite-code]/[id]/page.tsx (1)
shared/api/queries/user.ts (1)
userQueryOptions(11-20)
⏰ 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). (2)
- GitHub Check: deploy
- GitHub Check: test
🔇 Additional comments (2)
app/(sub)/capsule-detail/[invite-code]/[id]/page.tsx (2)
32-32: useState import 추가 적절지연 실행 플래그 도입을 위한 import 추가 적절합니다. 다른 변경과의 종속성 문제 없습니다.
41-41: 지연 실행 플래그(shouldCheckUser) 도입 합리적초기 진입 시 불필요한 인증 API 호출을 막는 방향이 문제의 핵심을 잘 해결합니다. 다만 이 플래그가 true로 바뀐 이후에는 포커스/재진입 시 불필요한 재호출이 발생하지 않도록 후속 로직에서 상태를 재설정할 필요가 있는지 한번만 점검해 주세요(현 요구사항상 필수는 아님).
|
This pull request (commit
|
🚀 Storybook 배포📖 Storybook: https://683d91ab23651aa0b399e435-onppfmdxhq.chromatic.com/ |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
app/(main)/setting/page.tsx (1)
20-24: onError에서 모든 에러에 대해 로그인으로 리다이렉트 → 401일 때만 리다이렉트하도록 가드 권장네트워크 단절/일시 오류(5xx 등)에서도 로그인으로 보내는 것은 UX 측면에서 과도합니다. ky의 HTTPError와 상태코드를 확인해 401(또는 필요 시 403)일 때만 이동하도록 가드를 넣어주세요.
추가로, React Query 기본 retry(기본 3회)로 onError가 여러 번 호출될 수 있어 중복 replace가 발생할 수 있습니다. userInfo 쿼리에서 retry를 꺼두는 것을 함께 권장합니다(아래 user.ts 코멘트 참고).적용 diff(현재 범위 내):
- const { data: userInfo } = useQuery(userQueryOptions.userInfo({ - onError: (_error) => { - router.replace(PATH.LOGIN); - }, - })); + const { data: userInfo } = useQuery(userQueryOptions.userInfo({ + onError: (error) => { + if (error instanceof HTTPError && error.response.status === HTTP_STATUS_CODE.UNAUTHORIZED) { + router.replace(PATH.LOGIN); + } + }, + }));변경에 필요한 추가 임포트(범위 밖):
import { HTTP_STATUS_CODE } from "@/shared/constants/api"; import { HTTPError } from "ky";shared/api/api-client.ts (1)
25-30: USER_INFO 예외 처리 조건을 보다 엄격하게 매칭해주세요substring includes는 유사 경로가 생길 때 오탐 소지가 있습니다. pathname 기준 endsWith 매칭으로 좁히면 안전합니다. (querystring이 붙지 않는 엔드포인트라면 endsWith만으로 충분)
- const url = error.request.url; - - if (url.includes(ENDPOINTS.USER_INFO)) { - return error; - } + const pathname = new URL(error.request.url).pathname; + if (pathname.endsWith(ENDPOINTS.USER_INFO)) { + return error; + }shared/api/queries/user.ts (1)
21-23: 중복 속성 제거 및 인증 시나리오에 맞게 retry 비활성화 권장
- 현재 onError를 명시 지정하면서 동시에 ...options로 다시 전달하고 있어 중복입니다. 하나만 유지해도 동작 동일합니다.
- 인증 실패(401)는 재시도해도 성공 가능성이 낮고, onError가 여러 번 호출될 수 있어 UX 저하가 발생합니다. userInfo는 기본적으로 retry를 끄는 것을 권장합니다.
queryOptions({ queryKey: userQueryKeys.userInfo(), queryFn: () => { return apiClient.get<UserInfo>(ENDPOINTS.USER_INFO); }, - onError: options?.onError, - ...options, + retry: false, + ...options, // onError는 options를 통해 그대로 전달됩니다. }),
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
app/(main)/setting/page.tsx(1 hunks)app/(sub)/capsule-detail/[invite-code]/[id]/page.tsx(1 hunks)shared/api/api-client.ts(2 hunks)shared/api/queries/user.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- app/(sub)/capsule-detail/[invite-code]/[id]/page.tsx
🧰 Additional context used
🧬 Code Graph Analysis (3)
shared/api/api-client.ts (1)
shared/constants/endpoints.ts (1)
ENDPOINTS(3-41)
app/(main)/setting/page.tsx (3)
app/(auth)/_api/auth.queries.ts (1)
useLogout(16-24)shared/api/queries/user.ts (1)
userQueryOptions(11-24)shared/constants/path.ts (1)
PATH(1-13)
shared/api/queries/user.ts (3)
shared/api/api-client.ts (1)
apiClient(52-67)shared/types/api/user.ts (1)
UserInfo(1-7)shared/constants/endpoints.ts (1)
ENDPOINTS(3-41)
⏰ 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). (3)
- GitHub Check: test
- GitHub Check: deploy
- GitHub Check: storybook-deploy
🔇 Additional comments (2)
app/(main)/setting/page.tsx (1)
13-13: PATH 의존성 추가는 타당합니다설정 페이지에서 인증 실패 시 라우팅이 필요하므로 PATH 임포트 추가는 방향이 맞습니다.
shared/api/queries/user.ts (1)
12-15: userInfo 옵션에 onError 노출은 방향이 맞습니다API 클라이언트의 USER_INFO 전역 우회를 감안하면, 컴포넌트 단에서 onError를 받아 처리하도록 공개하는 설계가 적절합니다.
|
This pull request (commit
|
|
This pull request (commit
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (5)
shared/ui/navbar/navbar-detail/navbar-detail.css.ts (1)
18-23: 아이콘 간격은 margin-right 대신 wrapper gap으로 관리 + 포커스/아이콘 컬러 상속 보완 제안
- 버튼 자체에
marginRight를 두면 마지막 아이콘에도 여백이 생겨 좌측 그룹과 우측 영역 사이 간격이 의도치 않게 벌어질 수 있습니다(이번처럼 아이콘이 2개일 때 더 두드러짐). 간격은 래퍼(div)에서gap으로 관리하는 편이 안정적입니다.- 접근성도 함께 보완하면 좋겠습니다: 키보드 포커스 표시(
:focus-visible) 추가, SVG가currentColor를 상속받도록 보장.아래처럼 수정을 제안합니다.
export const iconButton = style({ width: "4.4rem", height: "4.4rem", - marginRight: "1rem", color: themeVars.color.white[40], + display: "inline-flex", + alignItems: "center", + justifyContent: "center", + selectors: { + "&:focus-visible": { + outline: "0.2rem solid currentColor", + outlineOffset: "0.2rem", + }, + "& svg": { + fill: "currentColor", + stroke: "currentColor", + }, + }, });그리고 아래와 같이 좌측 버튼 래퍼 스타일을 신설해
gap으로 간격을 관리하는 것을 권장합니다.// navbar-detail.css.ts (추가) export const leftGroup = style({ display: "flex", alignItems: "center", gap: "1rem", });shared/ui/navbar/navbar-detail/index.tsx (4)
28-31: 홈 이동 네비게이션: push vs replace 고려
router.push(PATH.HOME)은 히스토리에 홈이 쌓입니다. 사용자가 홈에서 뒤로가기를 누르면 직전 페이지로 돌아가길 원하지 않는 UX라면replace가 더 적합할 수 있습니다. 현재 동작도 문제는 없으니 의도에 따라 선택하세요.예시:
- router.push(PATH.HOME); + router.replace(PATH.HOME);
34-34: 간격은 래퍼에서gap으로 관리아이콘 간 간격을 버튼 스타일의
margin-right로 두기보다 래퍼에gap을 적용하면 마지막 요소 여백 문제를 피하고 유지보수성이 좋아집니다. CSS에leftGroup를 추가한 뒤 아래처럼 적용을 권장합니다.- <div> + <div className={styles.leftGroup}>
38-41: 아이콘 버튼 접근성: 라벨 추가 및 아이콘 숨김현재 아이콘만 있는 버튼이라 스크린리더에 이름이 없습니다.
aria-label(또는title)을 추가하고, 아이콘은 장식용이므로aria-hidden을 권장합니다.- <button - type="button" - onClick={handleBack} - className={styles.iconButton} - > - <BackIcon /> + <button + type="button" + onClick={handleBack} + className={styles.iconButton} + aria-label="뒤로 가기" + title="뒤로 가기" + > + <BackIcon aria-hidden /> </button>
42-45: Home 버튼도 동일한 접근성 보완 적용Home 버튼에도 라벨을 부여하고 아이콘을 스크린리더에서 숨겨주세요.
- <button type="button" onClick={handleHome} className={styles.iconButton}> - <HomeIcon /> + <button + type="button" + onClick={handleHome} + className={styles.iconButton} + aria-label="홈으로 이동" + title="홈으로 이동" + > + <HomeIcon aria-hidden /> </button>
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
shared/assets/icon/home.svgis excluded by!**/*.svg
📒 Files selected for processing (2)
shared/ui/navbar/navbar-detail/index.tsx(2 hunks)shared/ui/navbar/navbar-detail/navbar-detail.css.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-20T15:06:20.286Z
Learnt from: seung365
PR: YAPP-Github/26th-Web-Team-3-FE#185
File: app/(sub)/search/_components/card-container/index.tsx:1-4
Timestamp: 2025-08-20T15:06:20.286Z
Learning: Next.js App Router에서 상위 컴포넌트에 "use client" 지시어가 있어도, 하위 컴포넌트에서 클라이언트 훅(useRouter, useState 등)을 사용하는 경우 해당 컴포넌트 파일에도 "use client"를 명시해야 합니다. 클라이언트 컴포넌트 경계는 각 파일별로 독립적으로 설정됩니다.
Applied to files:
shared/ui/navbar/navbar-detail/index.tsx
🧬 Code Graph Analysis (1)
shared/ui/navbar/navbar-detail/index.tsx (1)
shared/constants/path.ts (1)
PATH(1-13)
⏰ 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). (2)
- GitHub Check: deploy
- GitHub Check: test
🔇 Additional comments (2)
shared/ui/navbar/navbar-detail/navbar-detail.css.ts (1)
18-18: 네이밍 개선 👍 (‘backButton’ → ‘iconButton’)특정 의미(뒤로가기)에 종속된 이름에서 재사용 가능한
iconButton으로 확장한 점 좋습니다. 컴포넌트 전반에서 일관된 스타일을 공유하기 용이합니다.shared/ui/navbar/navbar-detail/index.tsx (1)
4-4: 확인 완료: SVG 아이콘 currentColor 사용 및 backButton 참조 없음
- shared/assets/icon/home.svg, shared/assets/icon/left.svg 양쪽 모두
<path fill="currentColor">으로 설정되어 있어 버튼에 적용된color: themeVars.color.white[40]가 정상 반영됩니다.backButton스타일 이름도 프로젝트 전반에 더 이상 참조되지 않음을 확인했습니다.추가 조치 없이 머지 진행하시면 됩니다.
seung365
left a comment
There was a problem hiding this comment.
저는 이렇게 예외로 뺴는거 괜찮아보여요! 나중에 더 좋은 방법 나오면 그때 수정하시죠👍
📌 Summary
해당 PR에 대한 작업 내용을 요약하여 작성해주세요.
📚 Tasks
👀 To Reviewer
401에러 전역처리하니까 캡슐 상세에서 user쿼리 호출해서 로그인 여부 판별하고있었어서,, 캡슐 상세에서 바로 로그인페이지로 가버리더라구요ㅜ
user쿼리는 전역처리에서 제외시키고, 필요한 부분에 직접 리다이렉트 로직 추가하도롥 수정했습니다!(더 좋은 방법이 있을까요..)
Summary by CodeRabbit
Refactor
Bug Fixes / Behavior Changes
New Features