Skip to content

Conversation

@Hwanggyuun
Copy link
Contributor

@Hwanggyuun Hwanggyuun commented Sep 8, 2025

📌 Related Issues

✅ 체크 리스트

  • PR 제목의 형식을 잘 작성했나요? e.g. [Feat/#이슈번호] PR 템플릿 작성
  • 빌드가 성공했나요? (pnpm build)
  • 컨벤션을 지켰나요?
  • 이슈는 등록했나요?
  • 리뷰어와 라벨을 지정했나요?

📄 Tasks

저번 해커톤 때 사용했던 설정을 보고 작성하였습니다.

⭐ PR Point (To Reviewer)

하지만 constansts 파일 부분을 다 뺐는데
이유는 401 error는 같지만 나머지 에러가 조금이나마 다 달라서 하나로 묶는 것이 이상했기 때문입니다.
그리고 requestConfig: any => requestConfig: AxiosRequestConfig 로 바꿔 좀 더 타입을 안정성 있게 구축했습니다.


Record<string, unknown> 은 “모든 string 키에 값이 있다”는 인덱스 시그니처를 요구합니다.
반면 LoginRequestDTO 같은 보통의 인터페이스는 특정 키만 갖고 있고, “모든 string 키”를 보장하지 않죠.
그래서 LoginRequestDTO → Record<string, unknown> 로는 할당 불가이기 때문에 unknown으로 수정 완

📷 Screenshot

🔔 ETC

Summary by CodeRabbit

  • New Features
    • 인증 실패(401) 시 세션을 정리하고 자동으로 홈으로 이동합니다.
    • 타입 기반의 범용 API 요청 유틸리티가 추가되어 일관된 요청/응답 처리가 가능합니다.
    • 공통 API 응답 래퍼 타입이 추가되었습니다.
  • Refactor
    • 모든 API 요청에 공통 설정(기본 URL, 10초 타임아웃, JSON 헤더) 적용으로 안정성 향상.
    • 요청 시 저장된 토큰을 자동 첨부하여 로그인 유지.
    • 쿼리 기본 동작(재시도 1회, 신선도 2분, 캐시 보존 5분) 및 개발 환경 로깅으로 디버깅 개선.
  • Chores
    • axios 의존성 추가.

@coderabbitai
Copy link

coderabbitai bot commented Sep 8, 2025

Walkthrough

환경변수 기반 Axios 인스턴스, 공통 요청 유틸리티, 표준 응답 타입, React Query 클라이언트 및 axios 의존성 추가 — 토큰 주입·401 처리·기본 쿼리 옵션·개발모드 에러 로깅을 포함한 API 기초 설정을 추가했습니다.

Changes

Cohort / File(s) Change Summary
Dependencies
package.json
axios@^1.11.0 의존성 추가.
Axios 인스턴스 / 인터셉터
src/api/axiosInstance.ts
VITE_API_BASE_URL 기반 baseURL, 10s timeout, Accept: application/json 설정. 요청 인터셉터에서 localStorage.accessToken을 Bearer 토큰으로 주입. 응답 인터셉터에서 401 시 accessToken 제거 및 ROUTES.HOME로 리다이렉트. axiosInstance 기본 export 추가.
React Query 클라이언트
src/api/queryClient.ts
QueryClient 싱글톤(queryClient) 생성·export. QueryCache.onError는 DEV 모드에서 콘솔 로깅. 쿼리 기본옵션: retry: 1, staleTime: 2*60*1000, gcTime: 5*60*1000.
요청 유틸리티
src/api/request.ts
제네릭 request<T> 추가: HTTPMethod, HTTPMethodType, RequestConfig 정의. JSON Content-Type 자동 설정, 쿼리/바디/헤더/withCredentials 처리, axiosInstance 사용, Axios 에러 판별(isAxiosError) 및 DEV 로깅 후 에러 재던지기. 반환값으로 response.data.data.
API 타입
src/api/types.ts
제네릭 BaseResponse<T> 인터페이스 추가: success?: boolean, code?: number, message?: string, data: T.
App 변경
src/App.tsx
파일 내 로컬 QueryClient 생성 제거; src/api/queryClient에서 queryClient를 import 하여 사용하도록 변경.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor U as UI/Caller
    participant R as request<T>()
    participant A as axiosInstance
    participant S as API Server
    rect #f8f9fa
      note right of A: 공통 설정·토큰 주입·응답 처리
    end

    U->>R: RequestConfig(method,url,query,body,headers)
    R->>A: AxiosRequestConfig 구성 후 요청
    A->>A: Request Interceptor\n(Authorization: Bearer accessToken)
    A->>S: HTTP 요청
    S-->>A: 2xx 응답 (BaseResponse)
    A-->>R: response.data
    R-->>U: data (T)

    alt 401 Unauthorized
        S-->>A: 401 에러
        A->>A: localStorage.accessToken 제거
        A->>U: 리다이렉트(ROUTES.HOME)
    end

    alt 네트워크/기타 에러
        S-->>A: 오류/타임아웃
        A-->>R: AxiosError
        R->>R: DEV 모드 로깅 후 재던지기
        R-->>U: 에러 throw
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Pre-merge checks (4 passed, 1 inconclusive)

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description Check ❓ Inconclusive 설명에 관련 이슈와 체크리스트, PR Point가 포함되어 있으나 Tasks 섹션이 실제 구현된 변경 사항을 구체적으로 나열하지 않고 일반적인 언급에 그쳐 주요 작업 내역이 불충분하게 보입니다. Tasks 섹션에 axios 의존성 추가, axiosInstance·queryClient·request 유틸·타입 정의 파일 생성, App.tsx 업데이트 등 구체적인 작업 항목을 목록 형태로 추가해주세요.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed 제목 “[init/#110] api 기본 세팅”은 PR의 핵심 변경 사항인 API 초기 설정 작업을 명확하고 간결하게 요약하고 있어 변경 내역과 완전히 일치합니다.
Linked Issues Check ✅ Passed PR에서는 axios 의존성 추가, 중앙화된 axiosInstance 설정, React Query 클라이언트 구성, 제네릭 HTTP 요청 유틸 및 BaseResponse 타입 정의, App.tsx의 queryClient 참조 전환 등 “api 기초 세팅”(#110)의 핵심 요구 사항을 모두 충족하고 있습니다.
Out of Scope Changes Check ✅ Passed 모든 변경 사항이 API 기본 설정 범위 내에 있으며, 이 외의 불필요하거나 관련 없는 코드 변경은 발견되지 않습니다.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5cf6b35 and b5e5b1c.

📒 Files selected for processing (1)
  • src/api/request.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/api/request.ts
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch init/#110/api-setting

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
Copy link

github-actions bot commented Sep 8, 2025

✅ 빌드에 성공했습니다! 🎉

Copy link

@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

🧹 Nitpick comments (5)
src/api/axiosInstance.ts (3)

31-35: 401 처리 시 히스토리 오염 방지 및 리다이렉트 루프 가드

현재는 HOME으로 href 이동이라 뒤로가기로 보호 페이지로 쉽게 회귀할 수 있고, 이미 HOME인 경우에도 불필요한 네비게이션이 발생합니다. replace와 경로 가드를 권장합니다.

-      window.location.href = ROUTES.HOME;
+      if (window.location.pathname !== ROUTES.HOME) {
+        window.location.replace(ROUTES.HOME);
+      }

4-10: baseURL 누락 시 탐지하기

환경 변수 미설정으로 인해 빈 baseURL로 나가는 사고를 피하려면 개발 모드에서 경고/에러를 내는 가드를 추가하세요.

가능한 접근:

  • DEV에서 VITE_API_BASE_URL falsy 시 console.warn 또는 throw
  • e2e/로컬 프로필별 .env 검증 스크립트 추가

12-18: 로컬스토리지 토큰 주입 방식에 대한 보안 고려

XSS에 노출되면 accessToken 탈취 위험이 있습니다. 장기적으로는 httpOnly 쿠키 + CSRF 대책(또는 Double Submit/SameSite)으로의 전환을 검토하세요. 단기적으로는 CSP 강화, DOM XSS 린트, 신뢰되지 않은 문자열의 안전한 렌더링을 권장합니다.

src/api/request.ts (2)

26-37: GET 요청에 body가 실리는 혼동 방지

axios는 GET의 data를 전송하지 않지만, config에 data를 넣으면 디버깅이 어렵습니다. 바디 허용 메서드에서만 data를 설정하세요. 또한 Content-Type 기본 설정 병합을 단순화할 수 있습니다.

-  const requestConfig: AxiosRequestConfig = {
-    method,
-    url,
-    params: query,
-    data: body,
-  };
+  const requestConfig: AxiosRequestConfig = {
+    method,
+    url,
+    params: query,
+  };
+
+  if (body !== undefined && method !== HTTPMethod.GET) {
+    requestConfig.data = body;
+  }
 
-  if (headers) {
-    requestConfig.headers = headers;
-  } else if (body && !(body instanceof FormData)) {
-    requestConfig.headers = { 'Content-Type': 'application/json' };
-  }
+  // 헤더 병합: 제공된 헤더가 있으면 우선하되, JSON 바디면 기본 Content-Type 보장
+  requestConfig.headers = {
+    ...(body && !(body instanceof FormData) ? { 'Content-Type': 'application/json' } : {}),
+    ...(headers ?? {}),
+  };

39-42: 서버 표준 응답(success/code) 확인 로직 검토

백엔드가 success=false로 에러를 표현하는 경우(2xx + 실패 메시지)에도 현재는 data를 그대로 반환합니다. 필요 시 success=false 또는 특정 code 범위에서 throw하도록 정책을 정해 주세요.

원하시면 success/code 규칙을 반영한 공통 에러 처리 분기(예: 성공 시에만 data 반환)를 제안해 드리겠습니다.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between df56043 and 4404713.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • package.json (1 hunks)
  • src/api/axiosInstance.ts (1 hunks)
  • src/api/queryClient.ts (1 hunks)
  • src/api/request.ts (1 hunks)
  • src/api/types.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/api/types.ts (1)
api/data-contracts.ts (10)
  • BaseResponsePromisePlaceResponseDTO (717-727)
  • BaseResponsePlaceSummaryInfoResponseDTO (987-997)
  • BaseResponsePromiseStatusResponseDTO (692-702)
  • BaseResponseVoid (40-50)
  • BaseErrorResponse (13-20)
  • BaseResponsePinResponseDTO (1070-1080)
  • BaseResponsePendingPromiseResponseDTO (763-773)
  • BaseResponsePromiseManagementResponseDTO (851-861)
  • BaseResponsePromiseStatusConfirmedPromiseResponseDTO (809-819)
  • BaseResponsePinPageResponseDTO (1115-1125)
src/api/axiosInstance.ts (2)
src/router/constant/Routes.ts (1)
  • ROUTES (1-8)
api/http-client.ts (3)
  • constructor (69-82)
  • ApiConfig (45-52)
  • T (139-185)
src/api/request.ts (1)
src/api/types.ts (1)
  • BaseResponse (1-5)
🔇 Additional comments (3)
package.json (2)

20-20: axios 추가 적절합니다

Swagger로 생성된 클라이언트와 신규 axios 유틸들에 필요한 코어 의존성 추가로 보이며, 버전 범위도 합리적입니다.


15-30: axios 버전/보안 승인
현재 ^1.11.0이 2025-09-08 기준 최신 안정화 릴리스이며, 1.11.x에 대한 알려진 CVE가 없습니다.

src/api/request.ts (1)

1-11: axios 클라이언트 중복 사용 여부 및 일원화 검증 필요
swagger-typescript-api로 생성된 모든 API 클라이언트가 자체 axios 인스턴스를 생성하지 않고, 공통 axiosInstance를 주입받도록 구성됐는지 확인해 주세요.
또한, src 디렉터리 전역에서 import 'axios' 또는 require('axios')로 직접 사용한 부분이 없는지 재검토가 필요합니다.

@github-actions
Copy link

github-actions bot commented Sep 8, 2025

✅ 빌드에 성공했습니다! 🎉

Copy link

@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

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

52-56: OR 우선순위/폴백 버그로 메시지가 비어도 폴백이 적용되지 않음

status + ' ' + message는 항상 truthy여서 “알 수 없는 오류...”가 표시되지 않습니다. 안전한 결합과 폴백을 적용하세요.

-      const displayMessage = status + ' ' + message;
+      const combined = [status, message ?? ''].filter(Boolean).join(' ').trim();
+      const displayMessage = combined || '알 수 없는 오류가 발생했습니다.';
       if (import.meta.env.DEV) {
         console.error(`[실패] ${url} : ${displayMessage}`);
       }
🧹 Nitpick comments (3)
src/api/request.ts (3)

33-37: 헤더 병합 로직 개선 — JSON 본문 시 Content-Type 보장

현재는 headers가 전달되면 JSON 본문이어도 Content-Type을 설정하지 않습니다. 서버에 따라 문제될 수 있으니 병합 방식으로 보장하세요. FormData일 땐 설정하지 말아야 합니다.

-  if (headers) {
-    requestConfig.headers = headers;
-  } else if (body && !(body instanceof FormData)) {
-    requestConfig.headers = { 'Content-Type': 'application/json' };
-  }
+  if (body && !(body instanceof FormData)) {
+    requestConfig.headers = { 'Content-Type': 'application/json', ...(headers ?? {}) };
+  } else if (headers) {
+    requestConfig.headers = headers;
+  }

15-21: 요청 설정 타입 범위 확장 제안(배열/nullable 지원)

쿼리/바디 입력이 실제 사용에서 배열·nullable을 포함하는 경우가 많습니다. 초기에 넓혀두면 캐스팅을 줄일 수 있습니다.

 export interface RequestConfig {
   method: HTTPMethodType;
   url: string;
-  query?: Record<string, string | number | boolean>;
-  body?: Record<string, unknown> | FormData;
+  query?: Record<string, string | number | boolean | null | undefined>;
+  body?: Record<string, unknown> | string | Blob | FormData;
   headers?: Record<string, string>;
 }

48-61: 에러 표준화 가벼운 제안

error.response가 있는 경우에도 data?.message 타입이 string이 아닐 수 있습니다. 메시지 생성 시 문자열 강제/트리밍을 보장해 로그 품질을 높이세요.

-      const { status, data } = error.response;
-      const message = data?.message;
+      const { status, data } = error.response;
+      const message = typeof data?.message === 'string' ? data.message : '';
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4404713 and 6d95d4f.

📒 Files selected for processing (3)
  • src/App.tsx (1 hunks)
  • src/api/request.ts (1 hunks)
  • src/api/types.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/api/types.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/api/request.ts (2)
src/api/types.ts (1)
  • BaseResponse (1-6)
api/http-client.ts (6)
  • HttpClient (62-186)
  • T (139-185)
  • FullRequestParams (24-38)
  • ApiConfig (45-52)
  • mergeRequestParams (88-108)
  • constructor (69-82)
🪛 GitHub Check: build
src/api/request.ts

[failure] 41-41:
Type 'T | undefined' is not assignable to type 'T'.

🪛 GitHub Actions: CI/CD Pipeline
src/api/request.ts

[error] 41-41: TypeScript error TS2322: Type 'T | undefined' is not assignable to type 'T' (src/api/request.ts:41).

🔇 Additional comments (1)
src/App.tsx (1)

4-6: 중앙 집중 QueryClient 싱글턴 도입 좋습니다

App에서 인스턴스를 생성하지 않고 공용 queryClient를 주입해 HMR/리렌더 시 재생성 문제를 피할 수 있습니다. 👍

@github-actions
Copy link

github-actions bot commented Sep 8, 2025

✅ 빌드에 성공했습니다! 🎉

@github-actions
Copy link

github-actions bot commented Sep 9, 2025

✅ 빌드에 성공했습니다! 🎉

@github-actions
Copy link

github-actions bot commented Sep 9, 2025

✅ 빌드에 성공했습니다! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[init] api 기초 세팅

2 participants