-
Notifications
You must be signed in to change notification settings - Fork 0
[Feature/#19] API 연결을 위한 기본 세팅 #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
The head ref may contain hidden characters: "feature/#19-api-\uC5F0\uACB0\uC744-\uC704\uD55C-\uAE30\uBCF8-\uC138\uD305"
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
이 PR은 API 연결을 위한 기본 인프라를 구축하는 작업입니다. Axios 인스턴스 설정, React Query 커스텀 훅, 비동기 처리를 위한 에러/로딩 UI 컴포넌트, 그리고 404 에러 페이지를 추가했습니다.
Changes:
- Axios 인스턴스와 인터셉터 뼈대 구축
- React Query 래퍼 훅 구현 (useCustomQuery, useCustomSuspenseQuery, useCustomInfiniteQuery, useCustomMutation)
- 비동기 에러/로딩 처리를 위한 AsyncBoundary 및 SuspenseFallback 컴포넌트 추가
- 404 및 에러 페이지 구현 및 라우터 설정
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| src/shared/api/axios.ts | Axios 인스턴스 생성 및 기본 설정 (baseURL, headers, credentials), 응답 인터셉터 뼈대 추가 |
| src/shared/hooks/customQuery.ts | React Query 훅들의 기본값(staleTime, retry, refetchOnWindowFocus) 통일을 위한 커스텀 래퍼 훅 구현 |
| src/shared/ui/common/SuspenseFallback/SuspenseFallback.tsx | Suspense의 fallback으로 사용될 로딩 UI 컴포넌트 |
| src/shared/ui/common/AsyncBoundary/AsyncBoundary.tsx | ErrorBoundary와 Suspense를 결합한 비동기 처리 래퍼 컴포넌트 |
| src/shared/ui/common/AsyncBoundary/AsyncBoundaryFallback.tsx | 에러 발생 시 표시될 fallback UI 컴포넌트 |
| src/shared/ui/common/AsyncBoundary/AsyncBoundaryFallback.styles.ts | AsyncBoundaryFallback의 스타일 정의 |
| src/pages/common/ErrorPage/ErrorPage.tsx | 404 및 라우팅 에러를 처리하는 페이지 컴포넌트 |
| src/pages/common/ErrorPage/ErrorPage.styles.ts | ErrorPage의 스타일 정의 |
| src/routes/Router.tsx | 404 에러 페이지를 위한 와일드카드 라우트 추가 |
| refetchOnWindowFocus, | ||
| queryKey: ignoredQueryKey, | ||
| queryFn: ignoredQueryFn, | ||
| ...restOptions | ||
| } = safeOptions | ||
| void refetchOnWindowFocus | ||
| void ignoredQueryKey | ||
| void ignoredQueryFn |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refetchOnWindowFocus, ignoredQueryKey, ignoredQueryFn을 구조 분해한 뒤 void 문으로 무시하는 패턴은 불필요한 코드입니다. 이미 restOptions에서 제외했으므로 void 문을 사용할 필요가 없습니다. 구조 분해 시 각 변수 앞에 언더스코어를 붙이거나, ESLint 설정에서 unused vars를 허용하는 것이 더 명확합니다.
| refetchOnWindowFocus, | |
| queryKey: ignoredQueryKey, | |
| queryFn: ignoredQueryFn, | |
| ...restOptions | |
| } = safeOptions | |
| void refetchOnWindowFocus | |
| void ignoredQueryKey | |
| void ignoredQueryFn | |
| refetchOnWindowFocus: _refetchOnWindowFocus, | |
| queryKey: _ignoredQueryKey, | |
| queryFn: _ignoredQueryFn, | |
| ...restOptions | |
| } = safeOptions |
| const combinedStyle: CSSProperties = { | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| gap, | ||
| ...style, | ||
| } |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
매 렌더링마다 combinedStyle 객체를 새로 생성하면 불필요한 리렌더링을 유발할 수 있습니다. style prop이 변경될 때만 새 객체를 생성하도록 useMemo를 사용하거나, 인라인 스타일 대신 CSS-in-JS 라이브러리(예: @emotion/styled)를 활용하는 것이 성능상 더 유리합니다.
| font-size: 14px; | ||
| cursor: pointer; | ||
| background: ${theme.colors.primary}; | ||
| color: ${theme.colors.white}; |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
버튼에 키보드 접근성을 위한 추가 속성이 필요합니다. "다시 시도" 버튼은 에러 복구의 핵심 기능이므로, 키보드 포커스 시 시각적 피드백을 제공하도록 :focus-visible 스타일을 추가하고, Enter와 Space 키로 활성화될 수 있도록 보장해야 합니다. 현재 <button> 요소를 사용하고 있어 기본 키보드 접근성은 확보되지만, 포커스 스타일을 명시적으로 추가하는 것이 좋습니다.
| color: ${theme.colors.white}; | |
| color: ${theme.colors.white}; | |
| &:focus-visible { | |
| outline: 2px solid ${theme.colors.primary}; | |
| outline-offset: 2px; | |
| } |
| return ( | ||
| <div style={combinedStyle} aria-live="polite" {...rest}> | ||
| <div>{label}</div> | ||
| <div>{children}</div> |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
로딩 메시지를 담는 내부 <div> 요소들이 의미론적으로 불명확합니다. 26번 라인의 label은 <p> 태그로, 27번 라인의 children 컨테이너는 용도에 따라 적절한 시맨틱 태그(예: <section>)로 변경하는 것이 접근성 측면에서 더 나습니다. 또한 로딩 중임을 시각적으로 표현하기 위해 스피너나 애니메이션을 추가하는 것도 고려해야 합니다.
| return ( | |
| <div style={combinedStyle} aria-live="polite" {...rest}> | |
| <div>{label}</div> | |
| <div>{children}</div> | |
| const spinnerStyle: CSSProperties = { | |
| width: 16, | |
| height: 16, | |
| borderRadius: '50%', | |
| border: '2px solid #ccc', | |
| borderTopColor: '#555', | |
| } | |
| return ( | |
| <div style={combinedStyle} aria-live="polite" role="status" {...rest}> | |
| <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}> | |
| <div aria-hidden="true" style={spinnerStyle} /> | |
| <p style={{ margin: 0 }}>{label}</p> | |
| </div> | |
| <section>{children}</section> |
| const { staleTime, retry, refetchOnWindowFocus, ...restOptions } = safeOptions | ||
| void refetchOnWindowFocus |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refetchOnWindowFocus를 구조 분해한 뒤 void refetchOnWindowFocus로 무시하는 패턴은 불필요한 코드입니다. 이미 restOptions에서 제외했으므로 void 문을 사용할 필요가 없습니다. 구조 분해 시 _refetchOnWindowFocus처럼 언더스코어를 붙이거나, ESLint 설정에서 unused vars를 허용하는 것이 더 명확합니다.
| const { staleTime, retry, refetchOnWindowFocus, ...restOptions } = safeOptions | |
| void refetchOnWindowFocus | |
| const { staleTime, retry, refetchOnWindowFocus: _refetchOnWindowFocus, ...restOptions } = safeOptions |
| const { staleTime, retry, refetchOnWindowFocus, ...restOptions } = safeOptions | ||
| void refetchOnWindowFocus |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refetchOnWindowFocus를 구조 분해한 뒤 void refetchOnWindowFocus로 무시하는 패턴은 불필요한 코드입니다. 이미 restOptions에서 제외했으므로 void 문을 사용할 필요가 없습니다. 구조 분해 시 _refetchOnWindowFocus처럼 언더스코어를 붙이거나, ESLint 설정에서 unused vars를 허용하는 것이 더 명확합니다.
| const { staleTime, retry, refetchOnWindowFocus, ...restOptions } = safeOptions | |
| void refetchOnWindowFocus | |
| const { staleTime, retry, refetchOnWindowFocus: _refetchOnWindowFocus, ...restOptions } = | |
| safeOptions |
| ) | ||
| } | ||
|
|
||
| export default SuspenseFallback |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
프로젝트의 배럴 파일 규칙에 따르면 src/shared/ui/common/*/index.ts 패턴을 따라야 합니다. SuspenseFallback 컴포넌트를 외부에서 import할 수 있도록 src/shared/ui/common/SuspenseFallback/index.ts 파일을 추가하여 export { default } from './SuspenseFallback' 형태로 배럴을 생성해주세요. 이는 다른 공통 UI 컴포넌트들(Checkbox, Modal 등)의 패턴과 일관성을 유지하기 위함입니다.
| ) | ||
| } | ||
|
|
||
| export default AsyncBoundary |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
프로젝트의 배럴 파일 규칙에 따르면 src/shared/ui/common/*/index.ts 패턴을 따라야 합니다. AsyncBoundary 컴포넌트를 외부에서 import할 수 있도록 src/shared/ui/common/AsyncBoundary/index.ts 파일을 추가하여 주요 export들을 배럴로 제공해주세요. 이는 다른 공통 UI 컴포넌트들의 패턴과 일관성을 유지하기 위함입니다.
| const BaseButton = styled.button` | ||
| border: 0; | ||
| border-radius: 10px; | ||
| padding: 10px 16px; | ||
| font-size: 14px; | ||
| cursor: pointer; | ||
| ` | ||
|
|
||
| export const PrimaryButton = styled(BaseButton)` | ||
| background: ${theme.colors.primary}; | ||
| color: ${theme.colors.white}; | ||
| ` | ||
|
|
||
| export const SecondaryButton = styled(BaseButton)` | ||
| background: ${theme.colors.lightGray}; | ||
| color: ${theme.colors.textPrimary}; | ||
| ` |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
버튼들에 키보드 접근성을 위한 포커스 스타일이 필요합니다. "뒤로가기"와 "홈으로" 버튼은 사용자의 주요 네비게이션 수단이므로, 키보드 사용자가 현재 포커스된 버튼을 명확하게 식별할 수 있도록 :focus-visible 스타일을 추가해야 합니다. 예를 들어 outline 또는 box-shadow를 사용하여 포커스 상태를 시각적으로 표시하세요.
🔗 관련 이슈
🧩 작업 요약 (TL;DR)
🔄 변경 유형
해당되는 항목에 체크해주세요.
📌 주요 변경 사항
🖼️ 스크린샷 / 영상 (선택)
🧠 리뷰 요청 포인트
🚧 미완 / 후속 작업
💬 기타 참고 사항
.github/instructions/capstone.instructions.md 파일을 지침으로 삼으세요.
폴더/파일 위치가 프로젝트 구조 규칙과 일치하는지
컴포넌트가 단일 책임 원칙(SRP)을 지키는지
import 방향이 올바른지 (shared → features 역방향 없음)
명명/케이스가 일관적인지 (PascalCase vs camelCase)
배럴(index.ts) 사용이 현 패턴을 따르는지
응답은 한국어로, 발견된 위반 항목과 추천 구조를 포함해주세요.
리뷰를 달아주세요