Skip to content

Conversation

@Chiman2937
Copy link
Member

@Chiman2937 Chiman2937 commented Dec 14, 2025

📝 변경 사항

💡 Axios 응답 인터셉터 로직 수정

  • status 처리 로직: errorResponse의 status를 참조하도록 수정
  • 401 에러 발생 시 /login redirect: 어떤 페이지에서 401에러 발생했는지 Query String에 기록하도록 수정
image

Note

Todo:

  • 로그인 페이지에서 error=unauthorized 일 경우 => toast 팝업 필요
  • path 값이 있을 경우 => 로그인 했을 때 기존 페이지로 다시 redirect 필요
    const { status } = errorResponse;
    const isServer = typeof window === 'undefined';

    if (status === 401) {
      if (isServer) {
        const { redirect } = await import('next/navigation');
        redirect('/login');
      } else {
        const currentPath = window.location.pathname + window.location.search;
        window.location.href = `/login?error=unauthorized&path=${encodeURIComponent(currentPath)}`;
      }
    }
    if (status === 404) {
      const { notFound } = await import('next/navigation');
      notFound();
    }

🔗 관련 이슈

Closes #


🧪 테스트 방법

  • 수동 테스트 검증(로컬 환경)
  • 유닛 테스트 검증
  • 통합 테스트 검증

📸 스크린샷 (선택)


📋 체크리스트

  • 관련 문서를 업데이트했습니다 (필요한 경우)
  • 테스트를 추가/수정했습니다 (필요한 경우)
  • Breaking change가 있다면 명시했습니다

💬 추가 코멘트


CodeRabbit Review는 자동으로 실행되지 않습니다.

Review를 실행하려면 comment에 아래와 같이 작성해주세요

@coderabbitai review

Summary by CodeRabbit

릴리즈 노트

  • 버그 수정
    • API 응답 오류 처리 개선으로 인증 오류 발생 시 로그인 페이지로 더 정확하게 리다이렉트됨
    • 존재하지 않는 페이지 오류에 대한 처리 최적화

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 14, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📋 변경 사항 분석

걸어보기

src/api/core/index.ts에서 정적 서버/클라이언트 네비게이션 처리를 제거하고 동적 next/navigation 임포트와 환경별 런타임 분기로 대체했습니다. 401 상태는 서버에서 /login으로 리다이렉트하고, 클라이언트에서는 쿼리 파라미터와 함께 리다이렉트합니다. 404 상태는 양쪽 모두 notFound 함수를 호출합니다.

변경사항

응집단 / 파일(들) 변경 요약
에러 처리 및 네비게이션 동적 임포트
src/api/core/index.ts
정적 네비게이션 처리 제거 및 동적 next/navigation 임포트 추가. 401/404 상태에 대한 환경별 분기 로직 구현. 401: 서버는 redirect 함수로 /login 리다이렉트, 클라이언트는 에러 및 경로 쿼리 파라미터와 함께 브라우저 리다이렉트. 404: 양쪽 모두 notFound 함수 호출.

시퀀스 다이어그램

sequenceDiagram
    participant Client as 클라이언트
    participant API as API 핸들러
    participant Env as 환경 감지
    participant Nav as next/navigation
    participant Router as 라우터/서버

    Client->>API: API 요청 (401/404 응답)
    API->>API: errorResponse 처리
    
    alt 상태 = 401
        API->>Env: 환경 확인 (서버/클라이언트)
        
        rect rgb(200, 220, 255)
        Note over Env,Router: 서버 사이드
        Env->>Nav: redirect 동적 임포트
        Nav->>Router: /login으로 리다이렉트
        end
        
        rect rgb(255, 240, 200)
        Note over Env,Client: 클라이언트 사이드
        Env->>Nav: useRouter 동적 임포트
        Nav->>Client: error & path 쿼리 파라미터<br/>함께 /login으로 리다이렉트
        end
    else 상태 = 404
        API->>Nav: notFound 동적 임포트
        Nav->>Client: 404 페이지 표시
    end
Loading

예상 코드 리뷰 노력

🎯 3 (중간 복잡도) | ⏱️ ~20분

  • 주의 필요 영역:
    • 서버/클라이언트 환경 분기 로직의 정확성 검증 필요
    • 동적 임포트 처리가 런타임에 올바르게 작동하는지 확인
    • 클라이언트 쿼리 파라미터 전달 및 /login 페이지에서의 파싱 방식 검토
    • 기존 에러 처리 경로와의 호환성 확인

제안된 검토자

  • wooktori

시🐰

동적 길을 찾아, 401과 404를 잡으니,
서버와 클라이언트 경계를 넘나드네.
쿼리 파라미터를 품고 /login으로 달려가고,
런타임 분기로 무한한 길을 열었노라! 🚀✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 axios 인터셉터의 status 처리 및 redirect 로직 수정이라는 주요 변경사항을 명확하게 요약하고 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed PR 설명이 템플릿 구조를 대부분 따르고 있으며, 변경 사항이 명확하게 설명되어 있고 수동 테스트 검증이 완료되었습니다.

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.

@github-actions github-actions bot requested a review from wooktori December 14, 2025 07:33
@Chiman2937 Chiman2937 changed the title [Fix] axios 인터셉터 401 redirect 로직 수정 [Fix] axios 인터셉터 status 처리, redirect 로직 수정 Dec 14, 2025
@github-actions
Copy link

github-actions bot commented Dec 14, 2025

🎨 Storybook Report

변경 사항이 없습니다

모든 Story가 이전 빌드와 동일합니다.

Status Storybook Build Log Updated (UTC)
✅ Unchanged View Storybook View Build 2025-12-15 00:18:59

@github-actions
Copy link

github-actions bot commented Dec 14, 2025

🎭 Playwright Report

E2E Test가 성공적으로 완료되었습니다.

Test 요약 내용을 확인해주세요.

Status Build Log Updated (UTC)
✅ Ready View Build 2025-12-15 00:18:32

📊 Test Summary

  • ✅ Passed: 9
  • ❌ Failed: 0
  • ⏱️ Duration: 44.8s

📜 Test Details

✅ Passed Tests (9)
  • profile.test.ts (9)
    • [chromium] 비로그인 상태에서 /mypage 접속 시 /login으로 redirect 되는 지 테스트
    • [chromium] 나의 프로필 페이지로 접속 시 /mypage로 /redirect 되는 지 테스트
    • [chromium] 존재하지 않는 프로필 페이지로 접속 시 404 redirect 되는 지 테스트
    • [firefox] 비로그인 상태에서 /mypage 접속 시 /login으로 redirect 되는 지 테스트
    • [firefox] 나의 프로필 페이지로 접속 시 /mypage로 /redirect 되는 지 테스트
    • [firefox] 존재하지 않는 프로필 페이지로 접속 시 404 redirect 되는 지 테스트
    • [webkit] 비로그인 상태에서 /mypage 접속 시 /login으로 redirect 되는 지 테스트
    • [webkit] 나의 프로필 페이지로 접속 시 /mypage로 /redirect 되는 지 테스트
    • [webkit] 존재하지 않는 프로필 페이지로 접속 시 404 redirect 되는 지 테스트

@github-actions
Copy link

github-actions bot commented Dec 14, 2025

📊 Coverage Report

Status Build Log Updated (UTC)
✅ Ready View Build 2025-12-15 00:17:06

➡️ #181main에 병합하면 coverage가 0.00% 유지합니다.

Coverage 요약

@@             Coverage Diff             @@
##             main     #181       +/-   ##
===========================================
  Coverage   35.57%   35.57%     0.00%     
===========================================
  Files         149      149         0     
  Lines        6144     6144         0     
  Branches      246      246         0     
===========================================
  Hits         2186     2186         0     
  Misses       3958     3958         0     

영향받은 파일

이 PR로 영향받은 파일이 없습니다

수정된 모든 파일이 현재 coverage를 유지했습니다.

@github-actions
Copy link

github-actions bot commented Dec 14, 2025

🚀 PR Preview Report

Build가 성공적으로 완료되었습니다.

Preview에서 변경사항을 확인하세요.

Status Preview Build Log Updated (UTC)
✅ Ready Visit Preview View Logs 2025-12-15 00:18:18

@Chiman2937 Chiman2937 added the Ready For Review! 리뷰 받을 준비가 되었습니다. label Dec 14, 2025
@Chiman2937
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 14, 2025

✅ 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
Contributor

@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: 3

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b8cdb47 and 1056ec3.

📒 Files selected for processing (1)
  • src/api/core/index.ts (1 hunks)

Comment on lines 47 to 49
const { status } = errorResponse;
const isServer = typeof window === 'undefined';

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

HTTP status 분기 기준이 payload(errorResponse.status)라 오동작 여지 있음
Axios의 실제 상태코드(error.response?.status)를 1순위로 쓰고, payload status는 fallback으로 두는 편이 안전합니다.

-    const { status } = errorResponse;
+    const status = error.response?.status ?? errorResponse.status;
     const isServer = typeof window === '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.

Suggested change
const { status } = errorResponse;
const isServer = typeof window === 'undefined';
const status = error.response?.status ?? errorResponse.status;
const isServer = typeof window === 'undefined';
🤖 Prompt for AI Agents
In src/api/core/index.ts around lines 47-49, the code currently uses payload
status (errorResponse.status) as the primary HTTP status which can misbehave;
change the logic to prefer Axios' actual HTTP status (error.response?.status)
first and only fall back to errorResponse.status when that is undefined or null,
ensuring you safely access error.response and handle undefined values before
assigning to the status variable so downstream branches use the real HTTP
status.

Comment on lines 50 to 58
if (status === 401) {
if (isServer) {
const { redirect } = await import('next/navigation');
redirect('/login');
} else {
const currentPath = window.location.pathname + window.location.search;
window.location.href = `/login?error=unauthorized&path=${encodeURIComponent(currentPath)}`;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

401 클라이언트 리다이렉트는 /login에서 루프 가능성 가드 필요
로그인 페이지에서 401이 다시 터지면 /login?...로 계속 이동할 수 있어, 최소한 현재 경로가 /login일 때는 리다이렉트를 스킵하는 방어 로직을 권장합니다.

     } else {
+        if (window.location.pathname === '/login') {
+          throw errorResponse;
+        }
         const currentPath = window.location.pathname + window.location.search;
         window.location.href = `/login?error=unauthorized&path=${encodeURIComponent(currentPath)}`;
     }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/api/core/index.ts around lines 50-58, the redirect-on-401 logic needs a
guard to avoid redirect loops back to /login; before calling redirect('/login')
on the server, obtain the current request path from the server request/context
and skip the redirect if the path is '/login' (or startsWith '/login');
similarly on the client, check window.location.pathname (or pathname+search) and
only set window.location.href to the login URL when the current path is not
'/login' (or doesn’t start with '/login') so repeated 401s on the login page
won’t trigger continuous redirects.

Comment on lines 50 to 63
if (status === 401) {
if (isServer) {
const { redirect } = await import('next/navigation');
redirect('/login');
} else {
const currentPath = window.location.pathname + window.location.search;
window.location.href = `/login?error=unauthorized&path=${encodeURIComponent(currentPath)}`;
}
}
if (status === 404) {
const { notFound } = await import('next/navigation');
notFound();
}

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

Next.js notFound() function server-only api client-side compatibility

💡 Result:

Short answer: notFound() is a server-only API — it is designed to be called from Server Components, route handlers, or Server Functions (files/functions marked to run on the server). Calling notFound() from a Client Component will not work and will produce errors; instead you must either (a) perform the check on the server and call notFound() there, or (b) call a server action (a function marked "use server") which calls notFound(), or (c) handle navigation on the client (e.g. router.replace to a 404 route or your custom not-found UI). [1][2][3]

Pointers and sources:

  • notFound() docs (server-only behavior & usage examples). [1]
  • Server Functions / "use server" — create server functions that client code can call to run server-only logic (including calling notFound()). [2]
  • Explanation of server-only vs client bundles and the server-only package (prevents importing server-only code into client). Useful when you want to ensure not to leak server-only code into the client. [3]

If you want, tell me which component/file you’re trying to call notFound() from and I’ll give a concrete refactor (server function pattern or client navigation) with code.


🌐 Web query:

Next.js app router next/navigation notFound() can be called from client component

💡 Result:

Short answer: No — notFound() is a server-side App‑Router function and cannot be directly invoked inside a Client Component. Use a server-side route/handler or a Server Action to call notFound(), or navigate the client to a 404 route (e.g. router.push('/404')) from the client instead. [1][2]

References

  • notFound() docs (throws to terminate server rendering / used inside route segments). [1]
  • redirect() docs (explicitly shows client usage for redirect to contrast behavior). [2]

Sources

  1. Next.js docs — notFound. [1]
  2. Next.js docs — redirect (Client Component example). [2]

🌐 Web query:

Next.js "use server" directive notFound() next/navigation client-side runtime error

💡 Result:

Likely cause

  • You're calling notFound() or using the "use server" directive from code that Next.js is treating as a Client Component (or importing a "use server" file into something that runs on the client). notFound() and Server Functions must run in server context; "use server" files must only export async server functions and cannot be shipped to the browser. [1][2]

How to fix (short)

  1. Ensure the module that calls notFound() is a Server Component (no "use client" at top). notFound() is server-only. [1]
  2. If you need a Server Action callable from the client, put it in its own file with 'use server' at the very top and export an async function; import that server file only into Server Components and pass the function to Client Components via props. Do NOT put 'use server' inside a file that Next treats as a client component. [2][3]
  3. Verify exported values in 'use server' files are async functions (not objects/values). If any export is non-async, you’ll get the invalid "use server" value error. [3]
  4. Check your import graph: a server-only file must not be imported (directly or transitively) into a client component. Move shared code into server-safe or client-safe modules accordingly. [2][3]

If you want, paste the minimal file(s) (page/component + any imports) and I’ll point exactly which file should be server vs client and what to change.

Sources

  • notFound() docs. [1]
  • 'use server' directive docs + Server Actions guidance. [2]
  • Invalid "use server" value / common errors. [3]

References
[1] Next.js — Functions: notFound.
[2] Next.js — Directives: 'use server'.
[3] Next.js — Invalid "use server" Value.


클라이언트에서 notFound() 호출은 런타임 에러 발생(서버 전용 API)

현재 코드(59-62줄)는 클라이언트에서도 next/navigationnotFound()를 호출합니다. notFound()는 Next.js 서버 전용 API로, 클라이언트 측에서 실행되면 런타임 크래시가 발생합니다. 401 처리와 동일하게 isServer로 분기하여 서버에서는 notFound() 호출, 클라이언트에서는 /404로 이동하도록 처리해야 합니다.

-    if (status === 404) {
-      const { notFound } = await import('next/navigation');
-      notFound();
-    }
+    if (status === 404) {
+      if (isServer) {
+        const { notFound } = await import('next/navigation');
+        notFound();
+      } else {
+        window.location.href = '/404';
+      }
+    }
📝 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.

Suggested change
if (status === 401) {
if (isServer) {
const { redirect } = await import('next/navigation');
redirect('/login');
} else {
const currentPath = window.location.pathname + window.location.search;
window.location.href = `/login?error=unauthorized&path=${encodeURIComponent(currentPath)}`;
}
}
if (status === 404) {
const { notFound } = await import('next/navigation');
notFound();
}
if (status === 401) {
if (isServer) {
const { redirect } = await import('next/navigation');
redirect('/login');
} else {
const currentPath = window.location.pathname + window.location.search;
window.location.href = `/login?error=unauthorized&path=${encodeURIComponent(currentPath)}`;
}
}
if (status === 404) {
if (isServer) {
const { notFound } = await import('next/navigation');
notFound();
} else {
window.location.href = '/404';
}
}
🤖 Prompt for AI Agents
In src/api/core/index.ts around lines 50 to 63, the code calls next/navigation's
notFound() unconditionally which will crash on the client; update the 404
handling to mirror the 401 branch by checking isServer: if isServer, import and
call notFound(); else, compute current path if needed and set
window.location.href to '/404' (or '/404?path=...' if you want to preserve path)
so client-side navigation doesn't call the server-only API.

@Chiman2937 Chiman2937 merged commit a3b65d9 into main Dec 15, 2025
7 checks passed
@Chiman2937 Chiman2937 deleted the chiyoung-fix/axios branch December 15, 2025 00:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready For Review! 리뷰 받을 준비가 되었습니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants