-
Notifications
You must be signed in to change notification settings - Fork 3
Feat/98/crew api 연결 #104
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
Feat/98/crew api 연결 #104
Conversation
commit 51cfe2f Author: Lee Youl <[email protected]> Date: Sat Nov 9 11:40:05 2024 +0900 🐛 Fix: MockData 날짜 형식 수정 commit 7b68352 Author: Lee Youl <[email protected]> Date: Sat Nov 9 11:38:06 2024 +0900 🐛 Fix: 이전날짜 선택 방지, isToday 날짜 비교 수정 commit f101987 Author: Lee Youl <[email protected]> Date: Sat Nov 9 11:19:20 2024 +0900 🐛 Fix: 폼 동작 개선 commit c408058 Author: Lee Youl <[email protected]> Date: Sat Nov 9 10:51:40 2024 +0900 🐛 Fix: isToday 함수 개선, 데이터 한국시간 기준으로 변경 commit 0683f5a Author: Lee Youl <[email protected]> Date: Fri Nov 8 21:49:45 2024 +0900 🐛 Fix: 버튼 링크로 교체 commit 43cdfa7 Author: Lee Youl <[email protected]> Date: Fri Nov 8 21:43:11 2024 +0900 🚨 Fix: 린트 오류 제거 commit 9657201 Author: Lee Youl <[email protected]> Date: Fri Nov 8 21:34:56 2024 +0900 🐛 Fix: 스크롤바 두개로 보이는 문제 수정 commit 63a8e1c Author: Lee Youl <[email protected]> Date: Fri Nov 8 21:27:25 2024 +0900 🐛 Fix: 유효성 검사 날짜 선택 오류 수정 commit 80f8554 Author: Lee Youl <[email protected]> Date: Fri Nov 8 21:24:46 2024 +0900 🐛 Fix: 에러상태인데 새로 값 채울 때 에러 해제하기, 리팩토링 commit af9fb91 Author: Lee Youl <[email protected]> Date: Fri Nov 8 20:46:00 2024 +0900 🐛 Fix: 크루 생성시 디테일 페이지로 이동, 리팩토링 commit f1fe204 Author: Lee Youl <[email protected]> Date: Fri Nov 8 20:31:17 2024 +0900 🐛 Fix: 텍스트 수정(약속 잡기 > 약속 만들기) commit 5cc6746 Author: Lee Youl <[email protected]> Date: Fri Nov 8 20:29:52 2024 +0900 🐛 Fix: 드롭다운 값 선택시 포커스 아웃 되도록 수정
|
Caution Review failedThe pull request is closed. Walkthrough이 풀 리퀘스트는 여러 파일에서의 변경 사항을 포함하고 있습니다. 주요 변경 사항으로는 Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Warning There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure. 🔧 eslint
src/components/client-provider.tsxOops! Something went wrong! :( ESLint: 8.57.1 ESLint couldn't determine the plugin "react-hooks" uniquely.
Please remove the "plugins" setting from either config or remove either plugin installation. If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team. Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 11
🧹 Outside diff range and nitpick comments (6)
src/app/_components/category/category-container/index.tsx (1)
34-38: 코드 최적화 제안현재 구현에서
category[categoryIndex ?? 0]가 여러 번 반복되고 있습니다. 이를 최적화하여 가독성과 유지보수성을 향상시킬 수 있습니다.다음과 같이 개선하는 것을 제안드립니다:
+ const selectedCategory = category[categoryIndex ?? 0]; - category={category[categoryIndex ?? 0].items} + category={selectedCategory.items} onChange={(newValue) => { setSubCategory(newValue); - setMainCategory(category[categoryIndex ?? 0].title.label); + setMainCategory(selectedCategory.title.label); }}src/types/crew-card.d.ts (2)
13-17: 정렬 필드의 타입 안전성 개선이 필요합니다
sort필드가 현재string[]로 정의되어 있어 타입 안전성이 부족합니다. 허용되는 정렬 기준을 명확히 정의하는 것이 좋겠습니다.다음과 같이 수정하는 것을 제안합니다:
+type SortField = 'createdDate' | 'participantCount'; +type SortDirection = 'asc' | 'desc'; +type SortOption = `${SortField},${SortDirection}`; export interface PageableTypes { page: number; size: number; - sort: string[]; + sort: SortOption[]; }
24-37: 타입 일관성 검토 및 문서화가 필요합니다
mainCategory와subCategory가ConditionTypes에서는 필수지만 여기서는 선택적입니다. 이러한 불일치가 의도된 것인지 확인이 필요합니다.- 각 필드의 의미와 제약사항에 대한 문서화가 있으면 좋겠습니다.
다음과 같이 문서화를 추가하는 것을 제안합니다:
export interface CrewCardListTypes { + /** 크루의 고유 식별자 */ id: number; + /** 메인 카테고리 (예: '운동', '취미' 등) */ mainCategory?: string; + /** 서브 카테고리 (예: '축구', '농구' 등) */ subCategory?: string; // ... 나머지 필드에 대해서도 비슷한 방식으로 문서화 추가 }src/components/common/crew-list/crew-card.tsx (1)
Line range hint
83-98: 참여자 수 표시와 ProgressBar 구현이 적절합니다.현재 참여자 수와 전체 인원 수가 명확히 표시되며, ProgressBar 컴포넌트와도 잘 연동되어 있습니다.
다만, 한 가지 제안사항이 있습니다:
참여자 수가 전체 인원 수를 초과하지 않도록 유효성 검사를 추가하는 것이 좋을 것 같습니다:
+const safeParticipantCount = Math.min(participantCount, totalCount); <span className="text-base font-medium"> - {participantCount}/{totalCount} + {safeParticipantCount}/{totalCount} </span>src/app/(crew)/page.tsx (1)
23-27: 지역 처리 로직 개선이 필요합니다.현재 구현에서 다음 사항들을 고려해보시기 바랍니다:
- 유효하지 않은
newValue처리selectedRegion이 undefined일 때의 처리다음과 같이 개선해보세요:
const handleRegionChange = (newValue: string) => { + if (!newValue) return ''; const selectedRegion = regionData.find((dataItem) => dataItem.main.value === newValue); if (selectedRegion?.main.label === '지역 전체') return ''; - return selectedRegion ? selectedRegion.main.label : ''; + return selectedRegion?.main.label ?? ''; };src/data/region.json (1)
2-5: 성능 최적화를 위한 제안지역 필터링 시 전체 배열을 순회하는 것을 방지하기 위해, 상수나 별도의 플래그를 사용하는 것을 고려해보세요.
- "main": { "label": "지역 전체", "value": "" }, + "main": { "label": "지역 전체", "value": "ALL" },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpublic/assets/images/img-default.jpgis excluded by!**/*.jpg
📒 Files selected for processing (14)
next.config.mjs(1 hunks)package.json(1 hunks)src/_apis/crew/get-crew-list.ts(1 hunks)src/_queries/crew-queries.tsx(1 hunks)src/app/(crew)/page.tsx(3 hunks)src/app/_components/category/category-container/index.tsx(2 hunks)src/app/_components/category/internal-category/index.tsx(1 hunks)src/app/_components/category/main-category/index.tsx(1 hunks)src/components/client-provider.tsx(2 hunks)src/components/common/crew-list/crew-card-list.tsx(2 hunks)src/components/common/crew-list/crew-card.tsx(4 hunks)src/data/region.json(1 hunks)src/hooks/useInfiniteScroll.ts(2 hunks)src/types/crew-card.d.ts(1 hunks)
🔇 Additional comments (21)
src/hooks/useInfiniteScroll.ts (2)
13-13: refetch 기능 추가가 적절합니다.
useInfiniteQuery에서 refetch 함수를 추출하여 수동으로 데이터를 새로고침할 수 있는 기능을 추가한 것이 좋습니다. 이는 사용자 인터랙션에 따라 데이터를 갱신해야 하는 경우에 유용할 것 같습니다.
28-28: refetch 노출에 따른 사용처 확인이 필요합니다.
refetch 기능을 외부로 노출함으로써 컴포넌트에서 데이터를 수동으로 새로고침할 수 있게 되었습니다. 이 기능이 crew 목록을 새로고침하는데 적절히 활용되는지 확인해주세요.
src/components/client-provider.tsx (1)
5-5: 적절한 import 구문 추가
React Query DevTools를 위한 import 구문이 올바르게 추가되었습니다.
next.config.mjs (1)
36-38: 환경 변수 유효성 검사가 필요합니다.
NEXT_PUBLIC_API_BASE_URL 환경 변수가 설정되지 않은 경우에 대한 처리가 필요합니다.
다음 스크립트로 환경 변수 설정을 확인할 수 있습니다:
환경 변수 검증을 위해 다음과 같은 수정을 제안합니다:
async rewrites() {
+ const apiBaseUrl = process.env.NEXT_PUBLIC_API_BASE_URL;
+ if (!apiBaseUrl) {
+ throw new Error('NEXT_PUBLIC_API_BASE_URL 환경 변수가 설정되지 않았습니다.');
+ }
return [
{
source: '/api/:path*',
- destination: `${process.env.NEXT_PUBLIC_API_BASE_URL}/:path*`,
+ destination: `${apiBaseUrl}/:path*`,
},
];
},src/app/_components/category/category-container/index.tsx (2)
26-29: 메인 카테고리 변경 시 서브 카테고리 초기화 처리가 적절합니다
메인 카테고리가 변경될 때 서브 카테고리를 초기화하는 것은 올바른 접근 방식입니다. 이는 유효하지 않은 카테고리 조합을 방지할 수 있습니다.
19-19: categoryIndex의 null 처리 검증 필요
categoryIndex를 null로 초기화하는 것은 잠재적인 런타임 에러를 발생시킬 수 있습니다. 컴포넌트의 다른 부분에서 categoryIndex가 null일 때의 처리가 올바르게 되어있는지 확인이 필요합니다.
✅ Verification successful
categoryIndex의 null 처리가 안전하게 구현되어 있습니다
categoryIndex가 null일 경우 널 병합 연산자(??)를 사용하여 기본값 0으로 안전하게 처리되고 있습니다. 다음과 같은 부분에서 확인됩니다:
category[categoryIndex ?? 0].itemscategory[categoryIndex ?? 0].title.label
따라서 초기값이 null이어도 런타임 에러가 발생하지 않습니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: categoryIndex가 null일 때의 처리가 있는지 확인
# categoryIndex 사용 부분 검색
rg -t typescript "categoryIndex" src/
Length of output: 72
Script:
#!/bin/bash
# Search for categoryIndex usage with proper file extensions
rg "categoryIndex" --type-add 'ts:*.{ts,tsx}' --type ts src/
Length of output: 673
src/types/crew-card.d.ts (1)
19-22: 응답 구조 변경에 따른 영향도 확인이 필요합니다
응답 구조가 변경되어 기존 코드에 영향을 줄 수 있습니다. 특히 data에서 content로의 변경과 hasNextPage에서 hasNext로의 변경은 주의가 필요합니다.
✅ Verification successful
Let me gather more information about the usage of the new field names to verify the impact.
응답 구조 변경에 대한 코드베이스 영향 확인 완료
CrewCardInformResponse 타입의 필드명 변경이 이미 관련 코드에 반영되어 있습니다:
crew-queries.tsx에서hasNext를 정상적으로 사용 중- 기존
data필드와hasNextPage필드는 다른 응답 타입들(WritableGatheringResponse, ReviewResponse 등)에서 사용되는 것으로, 이번 변경과는 무관
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: 변경된 필드명 사용 여부 확인
# data -> content로의 변경 영향 확인
rg "\.data\." --type ts
# hasNextPage -> hasNext로의 변경 영향 확인
rg "hasNextPage" --type ts
Length of output: 2169
Script:
#!/bin/bash
# Check for usage of new field names
rg "\.content\." --type ts
rg "\.hasNext\b" --type ts
# Check for CrewCardInformResponse usage
ast-grep --pattern 'CrewCardInformResponse'
Length of output: 781
src/app/_components/category/internal-category/index.tsx (2)
34-34: 🛠️ Refactor suggestion
pathname 매칭 로직 검토가 필요합니다
pathname?.includes(item.label ?? value)는 다음과 같은 잠재적 문제가 있습니다:
- URL에 라벨이 포함된 다른 문자열이 있을 경우 잘못된 매칭이 발생할 수 있습니다
- 라벨에 URL에서 사용할 수 없는 특수문자가 포함된 경우 매칭이 실패할 수 있습니다
#!/bin/bash
# URL 라우팅 패턴 확인
rg -A 5 "path|route" "src/app/page.tsx"
# 실제 사용되는 카테고리 값 확인
ast-grep --pattern 'const $_ = [{
$$$
}] as const'다음과 같이 정확한 매칭을 구현하는 것을 제안합니다:
-pathname?.includes(item.label ?? value)
+pathname?.includes(`/category/${encodeURIComponent(item.label ?? value)}`)33-33: 🛠️ Refactor suggestion
타입 안전성 개선이 필요합니다
item.label을 사용하는 것은 CategoryItem 타입에서 필수 필드임을 보장해야 합니다. 또한 부모 컴포넌트에서 기대하는 값과 일치하는지 확인이 필요합니다.
다음과 같이 타입 안전성을 개선하는 것을 제안합니다:
export interface CategoryItem {
- label?: string;
+ label: string; // 필수 필드로 변경
value: string;
}✅ Verification successful
Let me gather more information about the CategoryItem interface and its usage.
타입 안전성 검토 완료
CategoryItem 인터페이스에서 label 필드가 이미 필수 필드(string)로 정의되어 있어 타입 안전성이 보장되어 있습니다. 또한 부모 컴포넌트에서도 onChange 핸들러가 올바르게 문자열 값을 처리하고 있습니다.
src/types/category.d.ts에서label이 필수 문자열 필드로 정의됨InternalCategoryProps의onChange타입이(value: string) => void로 정확히 정의됨- 부모 컴포넌트들이 일관된 방식으로 값을 처리하고 있음
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# CategoryItem 타입 정의와 부모 컴포넌트의 사용법 확인
ast-grep --pattern 'interface CategoryItem {
$$$
}'
# 부모 컴포넌트에서 InternalCategory 사용 패턴 확인
rg -A 5 '<InternalCategory'
Length of output: 1992
Script:
#!/bin/bash
# Check for CategoryItem interface definition
ast-grep --pattern 'interface CategoryItem {
$$$
}'
# Check for type definitions in the component
ast-grep --pattern 'interface InternalCategoryProps {
$$$
}'
# Check how item.label is used in the component
rg -A 2 'item\.label' src/app/_components/category/internal-category/
Length of output: 1871
src/components/common/crew-list/crew-card-list.tsx (3)
Line range hint 1-56: 전반적인 구현이 잘 되어있습니다
- 무한 스크롤 구현이 적절합니다
- 로딩 상태 처리가 잘 되어있습니다
- 반응형 그리드 레이아웃이 효과적으로 구현되어있습니다
- 코드가 깔끔하고 유지보수가 용이합니다
34-42: CrewCard 컴포넌트 속성 이름이 개선되었습니다
기존의 모호했던 속성 이름들이 더 명확하고 의미있게 변경되었습니다:
location→mainLocationdetailedLocation→subLocationname→titlethumbnail→imageUrl
✅ Verification successful
CrewCard 컴포넌트의 속성 변경이 올바르게 적용되었습니다
CrewCardListTypes 인터페이스와 실제 컴포넌트 구현에서 변경된 속성들이 일관되게 적용되어 있음을 확인했습니다:
title,mainLocation,subLocation,imageUrl등의 새로운 속성명이 타입 정의와 일치합니다- 컴포넌트에서 이러한 속성들이 올바르게 사용되고 있습니다
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# CrewCard 컴포넌트의 props 타입 정의 확인
ast-grep --pattern 'interface CrewCardProps {
$$$
}'
Length of output: 56
Script:
#!/bin/bash
# CrewCard 컴포넌트의 props 타입 정의를 찾기 위한 다른 방법 시도
rg -A 15 "type CrewCardProps|interface CrewCardProps" --type typescript
# CrewCard 컴포넌트 파일 찾기
fd "crew-card" -e tsx -e ts
Length of output: 431
Script:
#!/bin/bash
# CrewCard 컴포넌트와 타입 정의 파일의 내용 확인
cat src/components/common/crew-list/crew-card.tsx
cat src/types/crew-card.d.ts
Length of output: 4755
17-17: API 응답 구조 변경 확인 필요
백엔드 API의 응답 구조가 data에서 content로 변경된 것으로 보입니다. 이 변경이 API 계약과 일치하는지 확인이 필요합니다.
✅ Verification successful
API 응답 구조가 올바르게 적용되었습니다
page.content를 사용하는 것이 정확합니다. API 응답 타입 CrewCardInformResponse와 페이지네이션 로직이 일관되게 구현되어 있으며, useGetCrewListQuery에서 반환되는 데이터 구조와도 일치합니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# API 응답 구조 변경이 다른 파일에도 영향을 미치는지 확인
rg -g '*.ts*' 'pages\.data'
Length of output: 29
Script:
#!/bin/bash
# Check for any usage of page.content in TypeScript files
rg -g '*.ts*' 'page\.content' -A 2
# Search for API response type definitions
ast-grep --pattern 'interface $_ {
$$$
content: $_
$$$
}'
# Look for pagination-related types
fd -e ts -e tsx | xargs rg 'type.*Page.*=' -A 2
Length of output: 445
Script:
#!/bin/bash
# API 응답 타입 정의 검색
ast-grep --pattern 'type Page = {
$$$
}'
# API 호출 관련 코드 검색
rg -g '*.ts*' 'useQuery|useInfiniteQuery' -B 2 -A 2
# 페이지네이션 관련 타입 임포트 검색
rg -g '*.ts*' 'import.*Page.*from' -A 1
Length of output: 3921
Script:
#!/bin/bash
# 크루 카드 타입 정의 확인
cat src/types/crew-card.ts
# 크루 리스트 API 호출 구현 확인
cat src/_apis/crew/get-crew-list.ts
# 크루 쿼리 구현 확인
cat src/_queries/crew-queries.tsx
Length of output: 1750
src/app/_components/category/main-category/index.tsx (1)
65-66: 라벨 기반 카테고리 처리로의 전환 검증 필요
카테고리 처리 방식이 value에서 label 기반으로 변경되었습니다. 이는 사용자 경험 측면에서 더 직관적일 수 있으나, 다음 사항들을 확인해 주시기 바랍니다:
- 라우팅 시스템이 한글 URL을 올바르게 처리하는지
- 다국어 지원 시 발생할 수 있는 문제는 없는지
✅ Verification successful
label 기반 카테고리 처리 방식이 일관되게 구현되어 있음을 확인
코드베이스 분석 결과, 다음과 같은 사항들이 확인되었습니다:
MainCategory와InternalCategory컴포넌트 모두label기반으로 일관되게 구현되어 있습니다.- 라우팅 처리도
label값을 기준으로 올바르게 동작하고 있습니다. create-crew-form에서 발견된title.value사용은 별도의 컨텍스트에서 사용되는 것으로, 현재 변경사항과 충돌하지 않습니다.
카테고리 처리 방식의 변경이 전체 시스템에서 일관성 있게 적용되어 있어 문제가 없을 것으로 판단됩니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the usage of label vs value in related components
# Check for any inconsistencies in category handling
# Search for title.value usage that might need to be updated
rg "title\.value" --type typescript
# Search for routing logic that might need adjustment
rg "usePathname.*includes" --type typescript
Length of output: 154
Script:
#!/bin/bash
# Search for title.value usage that might need to be updated
rg "title\.value"
# Search for routing logic that might need adjustment
rg "usePathname.*includes"
# Search for files containing both pathname and label
rg "pathname.*label"
# Find all TypeScript/JavaScript files in the category components
fd "\.(tsx?|jsx?)$" "src/app/_components/category"
Length of output: 1196
Script:
#!/bin/bash
# Check the implementation of category data structure
cat src/app/_components/category/main-category/index.tsx
# Check internal category implementation
cat src/app/_components/category/internal-category/index.tsx
# Look for category type definitions
rg "type.*Category" -A 5
Length of output: 4368
src/components/common/crew-list/crew-card.tsx (3)
7-7: 타입 임포트와 이미지 에셋 임포트가 적절히 구성되었습니다.
새로운 타입과 기본 이미지가 잘 임포트되었습니다.
Also applies to: 10-10
13-29: Props 인터페이스가 CrewCardListTypes를 확장하도록 개선되었습니다.
타입 정의가 더 체계적으로 구성되었으며, 선택적 속성 inWhere를 통해 마이크루 페이지에서의 사용성도 고려되었습니다.
67-74: 텍스트 표시 방식이 개선되었습니다.
제목과 위치 정보가 명확하게 구분되어 표시되며, 현재 약속 개수도 직관적으로 표현되었습니다.
src/app/(crew)/page.tsx (3)
6-6: LGTM: API 쿼리 훅 변경이 적절히 이루어졌습니다.
useGetCrewListQuery 로의 변경이 새로운 데이터 구조와 잘 맞습니다.
29-37: 쿼리 파라미터 타입 검증이 필요합니다.
useGetCrewListQuery에 전달되는 파라미터들의 타입이 ConditionTypes와 일치하는지 확인이 필요합니다.
#!/bin/bash
# Description: 쿼리 타입 정의 확인
# ConditionTypes 정의 확인
ast-grep --pattern 'type ConditionTypes = {
$$$
}'
# 쿼리 훅 구현 확인
ast-grep --pattern 'useGetCrewListQuery = (condition: ConditionTypes) => {
$$$
}'17-21: 상태 초기값 검증이 필요합니다.
빈 문자열로 초기화된 상태값들이 애플리케이션의 다른 부분에 영향을 미치지 않는지 확인이 필요합니다.
✅ Verification successful
상태값 초기화 변경은 안전해 보입니다.
파일 내에서 상태값들이 지역적으로 관리되고 있으며, 빈 문자열로 초기화하는 것이 문제가 되지 않을 것으로 판단됩니다. 상태값들은 컴포넌트 내부에서만 사용되는 필터링 용도로 보이며, 빈 문자열은 필터가 적용되지 않은 초기 상태를 나타내는 적절한 값입니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: 상태값이 빈 문자열일 때의 처리 검증
# 상태값 사용처 확인
rg -l "mainCategory|subCategory|region" --type tsx
Length of output: 140
Script:
#!/bin/bash
# 상태값 사용처를 더 정확하게 확인하기 위한 검색
rg "mainCategory|subCategory|region" --type tsx -A 3 -B 3
# 관련 타입 정의 확인
ast-grep --pattern 'type $_ = {
mainCategory?: $_
subCategory?: $_
region?: $_
$$$
}'
# API 호출이나 데이터 처리 로직 확인
ast-grep --pattern 'const $_ = ({mainCategory, subCategory, region}: $_) => {
$$$
}'
Length of output: 272
Script:
#!/bin/bash
# TypeScript/React 파일에서 상태값 사용처 확인
rg "mainCategory|subCategory|region" -t ts -t tsx -A 3 -B 3
# 조건부 렌더링이나 데이터 필터링 확인
ast-grep --pattern 'if ($$$mainCategory$$$) {
$$$
}'
# API 요청이나 데이터 처리 로직 확인
ast-grep --pattern 'useQuery($$$, {
$$$
mainCategory,
subCategory,
region,
$$$
})'
Length of output: 241
src/data/region.json (1)
2-5: 새로운 "지역 전체" 옵션이 적절하게 추가되었습니다.
필터링 기능을 위한 전체 지역 옵션의 구조가 기존 데이터 형식과 일관성있게 구현되었습니다.
src/_apis/crew/get-crew-list.ts (1)
9-9:
'sort' 기본값 확인 필요
sort의 기본값이 ['string']으로 설정되어 있습니다. 의도한 값인지 확인해주세요. 만약 실제 정렬 기준을 의미한다면 적절한 값으로 수정하는 것이 좋습니다.
src/components/client-provider.tsx
Outdated
|
|
||
| return ( | ||
| <QueryClientProvider client={queryClient}> | ||
| <ReactQueryDevtools initialIsOpen={false} /> |
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.
💡 Codebase verification
프로덕션 환경에서 ReactQueryDevtools 조건부 렌더링 필요
ReactQueryDevtools가 프로덕션 환경에서도 포함될 수 있는 상태입니다. 다음과 같이 수정이 필요합니다:
src/components/client-provider.tsx에서 process.env.NODE_ENV를 확인하여 개발 환경에서만 ReactQueryDevtools를 렌더링하도록 수정해야 합니다.
{process.env.NODE_ENV === 'development' && <ReactQueryDevtools initialIsOpen={false} />}🔗 Analysis chain
개발 환경에서만 사용되도록 확인 필요
ReactQueryDevtools가 적절하게 추가되었고 initialIsOpen이 false로 설정된 것이 좋습니다. 다만, 프로덕션 빌드에서는 이 컴포넌트가 제외되어야 합니다.
다음 스크립트로 프로덕션 빌드 설정을 확인하겠습니다:
Let me check the actual implementation to verify if the ReactQueryDevtools is conditionally rendered based on the environment.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: 프로덕션 빌드 설정에서 DevTools가 제외되는지 확인
# next.config.js 또는 next.config.mjs 파일에서 프로덕션 빌드 설정 확인
fd -e js -e mjs -g "next.config.*" --exec cat {} | grep -A 5 "production"
# package.json의 build 스크립트 확인
cat package.json | jq '.scripts.build'
Length of output: 127
Script:
#!/bin/bash
# Check how ReactQueryDevtools is imported and used
rg -A 3 "ReactQueryDevtools" --type tsx --type jsx
Length of output: 78
Script:
#!/bin/bash
# Check the implementation of client-provider.tsx and how ReactQueryDevtools is used
cat src/components/client-provider.tsx
Length of output: 808
| async rewrites() { | ||
| return [ | ||
| { | ||
| source: '/:path*', | ||
| destination: `${process.env.NEXT_PUBLIC_API_BASE_URL}/:path*`, | ||
| }, | ||
| ]; | ||
| }, |
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.
🛠️ Refactor suggestion
API 경로 재작성 구현이 필요한 경로로 제한되어야 합니다.
현재 구현은 모든 경로(/:path*)에 대해 API 재작성을 수행합니다. 이는 의도하지 않은 요청까지 API 서버로 전달될 수 있습니다.
다음과 같이 API 관련 경로만 재작성하도록 수정을 제안합니다:
async rewrites() {
return [
{
- source: '/:path*',
+ source: '/api/:path*',
destination: `${process.env.NEXT_PUBLIC_API_BASE_URL}/:path*`,
},
];
},📝 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.
| async rewrites() { | |
| return [ | |
| { | |
| source: '/:path*', | |
| destination: `${process.env.NEXT_PUBLIC_API_BASE_URL}/:path*`, | |
| }, | |
| ]; | |
| }, | |
| async rewrites() { | |
| return [ | |
| { | |
| source: '/api/:path*', | |
| destination: `${process.env.NEXT_PUBLIC_API_BASE_URL}/:path*`, | |
| }, | |
| ]; | |
| }, |
| export interface ConditionTypes { | ||
| keyword: string; | ||
| mainLocation: string; | ||
| mainCategory: string; | ||
| subCategory: string; | ||
| sortType: 'LATEST' | 'POPULAR'; | ||
| } |
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.
🛠️ Refactor suggestion
필터 조건의 선택적 필드 처리가 필요합니다
현재 모든 필드가 필수로 설정되어 있습니다. 실제 사용 시나리오를 고려할 때, 일부 필드는 선택적으로 처리되어야 할 것 같습니다.
다음과 같이 수정하는 것을 제안합니다:
export interface ConditionTypes {
- keyword: string;
- mainLocation: string;
- mainCategory: string;
- subCategory: string;
+ keyword?: string;
+ mainLocation?: string;
+ mainCategory?: string;
+ subCategory?: string;
sortType: 'LATEST' | 'POPULAR';
}📝 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.
| export interface ConditionTypes { | |
| keyword: string; | |
| mainLocation: string; | |
| mainCategory: string; | |
| subCategory: string; | |
| sortType: 'LATEST' | 'POPULAR'; | |
| } | |
| export interface ConditionTypes { | |
| keyword?: string; | |
| mainLocation?: string; | |
| mainCategory?: string; | |
| subCategory?: string; | |
| sortType: 'LATEST' | 'POPULAR'; | |
| } |
| "@storybook/nextjs": "^8.3.5", | ||
| "@storybook/react": "^8.3.5", | ||
| "@storybook/testing-library": "^0.2.2", | ||
| "@tanstack/react-query-devtools": "^5.59.20", |
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.
💡 Codebase verification
React Query와 DevTools 버전이 호환되지 않습니다
@tanstack/react-query-devtools@^5.59.20은 @tanstack/react-query@^5.59.20을 peer dependency로 요구하지만, 현재 프로젝트는 ^5.59.16을 사용하고 있습니다. 다음 중 하나의 조치가 필요합니다:
- @tanstack/react-query를 ^5.59.20으로 업그레이드
- @tanstack/react-query-devtools를 ^5.59.16으로 다운그레이드
🔗 Analysis chain
React Query DevTools 의존성이 적절히 추가되었습니다.
개발 도구로서 devDependencies에 올바르게 배치되었습니다. 다만 몇 가지 고려사항이 있습니다:
- 버전 호환성을 확인해주세요
- 재현 가능한 빌드를 위해 정확한 버전을 고정하는 것을 고려해보세요
패키지 버전 호환성을 확인하기 위해 다음 스크립트를 실행하세요:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify version compatibility between react-query and its devtools
# Extract and compare versions
QUERY_VERSION=$(cat package.json | jq -r '.dependencies["@tanstack/react-query"]')
DEVTOOLS_VERSION=$(cat package.json | jq -r '.devDependencies["@tanstack/react-query-devtools"]')
echo "React Query version: $QUERY_VERSION"
echo "DevTools version: $DEVTOOLS_VERSION"
# Check npm for compatibility information
npm view @tanstack/react-query-devtools@$DEVTOOLS_VERSION peerDependencies
Length of output: 679
| <Image | ||
| fill | ||
| objectFit="cover" | ||
| alt={title} | ||
| src={imageUrl === 'string' ? ImgDefault : imageUrl} | ||
| /> |
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.
이미지 처리 로직 개선이 필요합니다.
imageUrl === 'string' 비교는 적절하지 않아 보입니다. 이는 실제 URL 문자열과 'string' 리터럴을 비교하게 됩니다.
다음과 같이 수정하는 것을 제안드립니다:
- src={imageUrl === 'string' ? ImgDefault : imageUrl}
+ src={imageUrl || ImgDefault}📝 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.
| <Image | |
| fill | |
| objectFit="cover" | |
| alt={title} | |
| src={imageUrl === 'string' ? ImgDefault : imageUrl} | |
| /> | |
| <Image | |
| fill | |
| objectFit="cover" | |
| alt={title} | |
| src={imageUrl || ImgDefault} | |
| /> |
src/app/(crew)/page.tsx
Outdated
| onChange={(newValue) => { | ||
| setRegion(newValue as string); | ||
| }} |
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.
🛠️ Refactor suggestion
타입 캐스팅 개선이 필요합니다.
onChange 핸들러에서의 타입 캐스팅을 더 안전하게 처리할 수 있습니다.
다음과 같이 개선해보세요:
-onChange={(newValue) => {
- setRegion(newValue as string);
-}}
+onChange={(newValue: string | null) => {
+ if (newValue) setRegion(newValue);
+}}
-onChange={(newValue) => {
- setSort(newValue as string);
-}}
+onChange={(newValue: string | null) => {
+ if (newValue) setSort(newValue);
+}}Also applies to: 87-89
| { | ||
| "main": { "label": "지역 전체", "value": "" }, | ||
| "areas": [] | ||
| }, |
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.
💡 Codebase verification
중복된 지역 value 값이 발견되었습니다.
각 광역시/도의 구/군 단위에서 동일한 value 값이 중복 사용되고 있습니다:
- "jung" (중구) - 6개 지역에서 사용
- "dong" (동구) - 6개 지역에서 사용
- "seo" (서구) - 5개 지역에서 사용
- "nam" (남구) - 4개 지역에서 사용
- "buk" (북구) - 4개 지역에서 사용
- "gangseo" (강서구) - 2개 지역에서 사용
- "goseong" (고성군) - 2개 지역에서 사용
빈 문자열("")은 다른 지역과 중복되지 않지만, 위의 value들은 여러 지역에서 중복 사용되어 구분이 어려울 수 있습니다. 각 지역을 고유하게 식별할 수 있도록 상위 지역명을 prefix로 추가하는 등의 수정이 필요합니다.
🔗 Analysis chain
지역 value 값들의 중복 여부를 확인해주세요.
빈 문자열("")을 value로 사용하는 것이 다른 지역들의 value와 충돌하지 않는지 확인이 필요합니다.
Let me gather more context to understand the full structure of the region data.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for duplicate value entries in region.json
# Extract and count all values to find duplicates
jq -r '.[].main.value' src/data/region.json | sort | uniq -c | awk '$1 > 1 { print }'
# Also check area values within each region
jq -r '.[].areas[].value' src/data/region.json | sort | uniq -c | awk '$1 > 1 { print }'
Length of output: 272
Script:
#!/bin/bash
# Get the complete structure of region.json to understand the context of these duplicates
cat src/data/region.json
Length of output: 11425
| queryKey: [ | ||
| condition.keyword, | ||
| condition.mainLocation, | ||
| condition.mainCategory, | ||
| condition.subCategory, | ||
| condition.sortType, | ||
| ], |
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.
🛠️ Refactor suggestion
queryKey에 undefined 또는 null 값이 포함되지 않도록 처리하세요.
queryKey 배열에 condition 객체의 속성들이 포함되는데, 만약 어떤 속성이 undefined 또는 null인 경우 캐싱 키가 예상대로 작동하지 않을 수 있습니다. 이를 방지하기 위해 기본 값을 지정하거나 falsy한 값을 필터링하는 것이 좋습니다.
예를 들어, undefined나 null 값을 제거하려면 다음과 같이 수정할 수 있습니다:
queryKey: [
condition.keyword,
condition.mainLocation,
condition.mainCategory,
condition.subCategory,
condition.sortType,
].filter(Boolean),
src/_queries/crew-queries.tsx
Outdated
| condition.sortType, | ||
| ], | ||
| queryFn: ({ pageParam = 0 }) => | ||
| getCrewList(condition, { page: pageParam, size: 6, sort: ['string'] }), |
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.
'sort' 옵션에 올바른 정렬 기준을 사용하세요.
현재 sort: ['string']으로 설정되어 있어 실제 정렬 기준이 적용되지 않을 수 있습니다. condition.sortType을 사용하여 동적으로 정렬 기준을 지정하는 것이 좋습니다.
다음과 같이 수정할 수 있습니다:
- getCrewList(condition, { page: pageParam, size: 6, sort: ['string'] }),
+ getCrewList(condition, { page: pageParam, size: 6, sort: [condition.sortType] }),Committable suggestion skipped: line range outside the PR's diff.
src/_apis/crew/get-crew-list.ts
Outdated
| try { | ||
| const response = await fetchApi<CrewCardInformResponse>( | ||
| `/crews?_page=${page + 1}&_limit=${limit}`, | ||
| `/crews/search?keyword=${keyword}&mainLocation=${mainLocation}&mainCategory=${mainCategory}&subCategory=${subCategory}&sortType=${sortType}&page=${page}&size=${size}&sort=${sort}`, |
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.
🛠️ Refactor suggestion
쿼리 파라미터의 URL 인코딩 필요
쿼리 파라미터를 직접 문자열로 결합하면 특수 문자나 예기치 않은 입력으로 인해 오류가 발생할 수 있습니다. URLSearchParams를 사용하여 파라미터를 적절히 인코딩하는 것을 권장합니다.
수정 제안:
+ const params = new URLSearchParams({
+ keyword,
+ mainLocation,
+ mainCategory,
+ subCategory,
+ sortType,
+ page: page.toString(),
+ size: size.toString(),
+ sort: sort.join(','),
+ });
+ const response = await fetchApi<CrewCardInformResponse>(
+ `/crews/search?${params.toString()}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include', // 인증 정보를 요청에 포함
},
);Committable suggestion skipped: line range outside the PR's diff.
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.
params.toString 사용해서 코드 수정하면 좋을 것 같습니다!
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.
@minkyung5x5, 네, params.toString()을 사용하여 코드를 수정하면 좋을 것 같습니다! 수정해 주셔서 감사합니다.
If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!
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.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (10)
src/_queries/crew-queries.tsx (1)
13-16: 페이지 크기를 구성 가능하도록 개선하세요.현재 페이지 크기가 6으로 하드코딩되어 있습니다. 다양한 사용 사례에 대응하기 위해 이를 매개변수화하는 것이 좋습니다.
다음과 같이 수정하는 것을 제안합니다:
-export function useGetCrewListQuery(condition: ConditionTypes) { +export function useGetCrewListQuery(condition: ConditionTypes, pageSize: number = 6) { return { queryKey: [ condition.keyword, condition.mainLocation, condition.mainCategory, condition.subCategory, condition.sortType, ], queryFn: ({ pageParam = 0 }) => - getCrewList(condition, { page: pageParam, size: 6, sort: [condition.sortType] }), + getCrewList(condition, { page: pageParam, size: pageSize, sort: [condition.sortType] }),src/hooks/use-infinite-scroll.ts (1)
28-28: 반환 타입 명시 추천타입 안정성을 높이기 위해 명시적인 반환 타입을 추가하는 것이 좋습니다.
다음과 같이 반환 타입을 명시하는 것을 추천드립니다:
- return { data, ref, isFetchingNextPage, refetch }; + return { data, ref, isFetchingNextPage, refetch } as const;또는 인터페이스를 정의하여 사용:
interface InfiniteScrollResult<TData> { data: InfiniteData<TData> | undefined; ref: (node?: Element | null) => void; isFetchingNextPage: boolean; refetch: () => Promise<void>; }next.config.mjs (1)
보안: CORS 및 이미지 설정 수정이 필요합니다.
코드베이스 분석 결과, 다음과 같은 보안 개선이 필요합니다:
API 요청이
src/utils/api.ts에서 중앙 집중화되어 있으며,NEXT_PUBLIC_API_BASE_URL을 사용하고 있습니다. 따라서 CORS 설정을 API 요청 경로에만 제한하는 것이 안전합니다.이미지 도메인 설정도 API 서버와 동일한 방식으로 환경 변수를 통해 제한해야 합니다.
수정 제안:
images: { remotePatterns: [ { protocol: 'https', - hostname: '**', // 모든 도메인 허용 + hostname: process.env.NEXT_PUBLIC_API_BASE_URL + ? new URL(process.env.NEXT_PUBLIC_API_BASE_URL).hostname + : 'foggy-sideways-saltasaurus.glitch.me', }, ], }, async headers() { return [ { - source: '/:path*', // TODO: 모든 경로에 적용, 추후 수정 + source: '/api/:path*', // API 경로에만 CORS 적용 headers: [ // ... existing headers ... ], }, ]; },🔗 Analysis chain
Line range hint
3-29: 보안: CORS 및 이미지 설정 검토가 필요합니다.현재 구성에서 발견된 잠재적인 보안 문제:
- 이미지 호스트네임이 모든 도메인('**')을 허용하고 있습니다.
- CORS 헤더가 모든 경로('/:path*')에 적용되어 있습니다.
- TODO 주석에서 언급된 대로 경로 제한이 필요합니다.
다음과 같은 수정을 제안합니다:
images: { remotePatterns: [ { protocol: 'https', - hostname: '**', // 모든 도메인 허용 + hostname: process.env.NEXT_PUBLIC_IMAGE_DOMAIN, // 특정 도메인만 허용 }, ], }, async headers() { return [ { - source: '/:path*', // TODO: 모든 경로에 적용, 추후 수정 + source: '/api/:path*', // API 경로에만 CORS 적용 headers: [ // ... existing headers ... ], }, ]; },CORS 설정이 필요한 API 엔드포인트를 확인하기 위해 다음 스크립트를 실행하세요:
Let me analyze the API endpoints further to make a more informed decision about the CORS configuration.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # API 관련 파일들을 검색하여 엔드포인트 확인 fd -e ts -e js -e tsx -e jsx --exclude node_modules --exclude .next | xargs rg -l "fetch|axios|api"Length of output: 1199
Script:
#!/bin/bash # Check API routes and their patterns rg -A 5 "export.*handler|route.*=.*" src/app/api/ # Check actual API calls to external domains rg -A 2 "fetch\(|axios\." src/_apis/Length of output: 90
Script:
#!/bin/bash # Check API implementation and external service calls rg -A 3 "fetch\(|axios\.|baseURL|NEXT_PUBLIC_API" src/ # Check for environment variable usage rg "NEXT_PUBLIC" .env* || trueLength of output: 1184
src/components/common/crew-list/crew-card-list.stories.tsx (1)
31-39: 쿼리 파라미터 구조가 개선되었습니다만, 기본값 처리를 검토해주세요.빈 문자열을 사용하는 대신 의미있는 기본값을 설정하거나 옵셔널 파라미터로 처리하는 것이 좋을 것 같습니다.
다음과 같이 개선해보시는 건 어떨까요?
const { data, ref, isFetchingNextPage } = useInfiniteScroll( useGetCrewListQuery({ - keyword: '', - mainLocation: '', - mainCategory: '', - subCategory: '', + sortType: 'LATEST', + // 선택적 파라미터로 처리 + ...(keyword && { keyword }), + ...(mainLocation && { mainLocation }), + ...(mainCategory && { mainCategory }), + ...(subCategory && { subCategory }), - sortType: 'LATEST', }), );src/app/(crew)/my-crew/page.tsx (2)
Line range hint
15-17: TODO 주석에 대한 후속 조치가 필요합니다.현재 두 개의 TODO 주석이 있습니다:
- fetchCrewData 함수를 사용하여 데이터를 불러오기
- 리스트와는 다른 데이터 사용 필요성
이러한 요구사항들이 명확하게 정의되어 있지 않아 구현이 지연될 수 있습니다.
이러한 TODO 항목들을 추적하고 구현하기 위한 GitHub 이슈를 생성해드릴까요?
Line range hint
1-40: 컴포넌트 구조 개선이 필요합니다.현재 컴포넌트에서 다음과 같은 개선사항들이 필요해 보입니다:
- 무한 스크롤 로직이 주석 처리되어 있어 페이지네이션이 동작하지 않습니다.
- 탭 전환 시 데이터 로딩 상태 처리가 누락되어 있습니다.
- 에러 상태 처리가 구현되어 있지 않습니다.
다음과 같은 구조적 개선을 제안드립니다:
- 로딩 상태를 표시하는 스켈레톤 UI 추가
- 에러 바운더리 구현
- 탭 전환 시 데이터 리프레시 로직 추가
src/components/common/crew-list/crew-card-list.tsx (1)
71-71: 조건문 로직 단순화 승인
isConfirmed속성의 조건문이 삼항 연산자에서 논리 AND 연산자로 변경되었습니다. 더 간결하고 명확한 구현으로 보입니다.추가적인 개선사항으로, 타입 가드를 사용하여 타입 캐스팅을 줄일 수 있습니다:
function isMainCrewList(inform: MainCrewList | MyCrewList): inform is MainCrewList { return 'isConfirmed' in inform; }이후 조건문에서 다음과 같이 사용할 수 있습니다:
-isConfirmed={inWhere !== 'my-crew' && (inform as MainCrewList).isConfirmed} +isConfirmed={isMainCrewList(inform) && inform.isConfirmed}src/app/(crew)/page.tsx (3)
17-20: 상태 초기화 방식이 개선되었습니다.카테고리와 지역 상태의 초기값을 빈 문자열로 설정한 것은 좋은 접근입니다. 다만, 이러한 상태 관리 로직이 다른 컴포넌트에서도 재사용될 수 있으므로, 커스텀 훅으로 분리하는 것을 고려해보세요.
23-27: region 처리 로직을 개선할 수 있습니다.현재 구현은 작동하지만, 더 간단하고 안전하게 리팩토링할 수 있습니다.
-const handleRegionChange = (newValue: string) => { - const selectedRegion = regionData.find((dataItem) => dataItem.main.value === newValue); - if (selectedRegion?.main.label === '지역 전체') return ''; - return selectedRegion ? selectedRegion.main.label : ''; -}; +const handleRegionChange = (newValue: string) => { + const selectedRegion = regionData.find((dataItem) => dataItem.main.value === newValue)?.main; + return selectedRegion?.label === '지역 전체' ? '' : selectedRegion?.label ?? ''; +};
29-37: 쿼리 파라미터의 타입 안전성을 개선할 수 있습니다.현재 구현은 잘 작동하지만, 타입 안전성을 높이기 위해 상수와 타입을 추가하는 것이 좋습니다.
// src/constants/sort-types.ts export const SORT_TYPES = { LATEST: 'LATEST', POPULAR: 'POPULAR', } as const; export type SortType = typeof SORT_TYPES[keyof typeof SORT_TYPES];그리고 다음과 같이 적용하세요:
-sortType: sort === 'latest' ? 'LATEST' : 'POPULAR', +sortType: sort === 'latest' ? SORT_TYPES.LATEST : SORT_TYPES.POPULAR,
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (11)
next.config.mjs(1 hunks)src/_apis/crew/get-crew-list.ts(1 hunks)src/_queries/crew-queries.tsx(1 hunks)src/app/(crew)/my-crew/page.tsx(2 hunks)src/app/(crew)/page.tsx(3 hunks)src/app/_components/category/internal-category/index.tsx(1 hunks)src/components/common/crew-list/crew-card-list.stories.tsx(2 hunks)src/components/common/crew-list/crew-card-list.tsx(2 hunks)src/components/common/crew-list/crew-card.tsx(2 hunks)src/hooks/use-infinite-scroll.ts(2 hunks)src/types/crew-card.d.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/app/_components/category/internal-category/index.tsx
- src/components/common/crew-list/crew-card.tsx
- src/types/crew-card.d.ts
🔇 Additional comments (14)
src/_queries/crew-queries.tsx (2)
1-2: 임포트 구문이 적절합니다!
필요한 타입과 API 함수가 올바르게 임포트되어 있습니다.
6-12: 이전 리뷰 코멘트가 여전히 유효합니다.
queryKey 배열의 undefined/null 처리에 대한 이전 리뷰 코멘트를 참조해 주세요.
src/hooks/use-infinite-scroll.ts (1)
13-13: refetch 기능 추가에 대한 승인
useInfiniteQuery에서 refetch 함수를 추출하여 외부에서 데이터를 수동으로 새로고침할 수 있게 된 것은 좋은 개선사항입니다. 이를 통해 사용자 액션에 따른 데이터 갱신이 가능해졌습니다.
src/_apis/crew/get-crew-list.ts (5)
1-3: 타입 선언이 잘 구성되어 있습니다!
필요한 타입들이 깔끔하게 import되어 있습니다.
4-7: 함수 시그니처가 명확하게 정의되어 있습니다!
ConditionTypes와 PageableTypes를 사용하여 매개변수 타입이 잘 정의되어 있습니다.
19-19: 인증 설정이 적절히 추가되었습니다!
credentials: 'include' 설정으로 인증 정보가 요청에 포함되도록 처리된 것이 좋습니다.
8-9:
sort 매개변수의 기본값 검토 필요
sort = ['string']의 기본값이 의도된 값인지 확인이 필요합니다. 이는 실제 정렬에 사용되는 적절한 값이 아닌 것으로 보입니다.
다음과 같이 수정하는 것을 고려해보세요:
- const { page, size, sort = ['string'] } = pageable;
+ const { page, size, sort = ['createdAt,desc'] } = pageable;13-13:
쿼리 파라미터 처리 개선 필요
- URL 인코딩 누락: 특수 문자나 한글이 포함된 파라미터가 있을 경우 문제가 발생할 수 있습니다.
- undefined 값 처리 누락: 파라미터가 undefined일 경우 'undefined' 문자열이 쿼리에 포함될 수 있습니다.
다음과 같이 수정하는 것을 추천드립니다:
- `/crews/search?keyword=${keyword}&mainLocation=${mainLocation}&mainCategory=${mainCategory}&subCategory=${subCategory}&sortType=${sortType}&page=${page}&size=${size}&sort=${sort}`,
+ const params = new URLSearchParams();
+ if (keyword) params.append('keyword', keyword);
+ if (mainLocation) params.append('mainLocation', mainLocation);
+ if (mainCategory) params.append('mainCategory', mainCategory);
+ if (subCategory) params.append('subCategory', subCategory);
+ if (sortType) params.append('sortType', sortType);
+ if (page) params.append('page', page.toString());
+ if (size) params.append('size', size.toString());
+ if (sort?.length) params.append('sort', sort.join(','));
+ `/crews/search?${params.toString()}`,next.config.mjs (1)
34-41: API 경로 재작성이 올바르게 구현되었습니다.
이전 리뷰 의견에 따라 API 경로(/api/:path*)에 대해서만 재작성이 적용되도록 수정되었습니다.
src/components/common/crew-list/crew-card-list.stories.tsx (1)
2-2: 쿼리 훅 임포트가 올바르게 업데이트되었습니다.
API 변경사항에 맞춰 useGetCrewQuery에서 useGetCrewListQuery로 임포트가 정상적으로 변경되었습니다.
src/app/(crew)/my-crew/page.tsx (2)
4-4: 쿼리 훅 업데이트가 확인되었습니다.
useGetCrewQuery에서 useGetCrewListQuery로의 변경이 올바르게 이루어졌습니다.
20-20:
주석 처리된 코드의 업데이트가 필요합니다.
주석 처리된 코드에서 useGetCrewListQuery()가 파라미터 없이 호출되고 있습니다. API 변경사항에 따라 필요한 파라미터를 전달해야 합니다.
다음과 같이 수정하는 것을 제안드립니다:
- useInfiniteScroll<MyCrewListResponse>(useGetCrewListQuery());
+ useInfiniteScroll<MyCrewListResponse>(
+ useGetCrewListQuery({
+ condition: {
+ // TODO: Add necessary parameters based on my-crew requirements
+ }
+ })
+ );Likely invalid or redundant comment.
src/components/common/crew-list/crew-card-list.tsx (1)
35-35: 데이터 구조 변경 검증 필요
백엔드 API 응답 구조가 data에서 content로 변경되었습니다. 이 변경이 다른 컴포넌트나 페이지에 영향을 미치지 않는지 확인이 필요합니다.
src/app/(crew)/page.tsx (1)
6-6: API 변경이 올바르게 적용되었습니다.
useGetCrewQuery에서 useGetCrewListQuery로의 변경이 잘 이루어졌습니다.
| const { data, ref, isFetchingNextPage } = useInfiniteScroll( | ||
| useGetCrewListQuery({ | ||
| keyword: '', | ||
| mainLocation: '', | ||
| mainCategory: '', | ||
| subCategory: '', | ||
| sortType: 'LATEST', | ||
| }), | ||
| ); |
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.
🛠️ Refactor suggestion
스토리북 테스트 케이스 보강이 필요합니다.
현재는 기본 케이스만 테스트하고 있습니다. 다양한 필터 조건에 대한 테스트 케이스를 추가하면 좋을 것 같습니다.
다음과 같은 테스트 케이스들을 추가해보시는 것을 추천드립니다:
export const WithKeywordSearch: Story = {
render: () => (
<RenderCrewCardList initialCondition={{ keyword: '개발자', sortType: 'LATEST' }} />
),
};
export const WithLocationFilter: Story = {
render: () => (
<RenderCrewCardList initialCondition={{ mainLocation: '서울', sortType: 'LATEST' }} />
),
};
export const WithCategoryFilter: Story = {
render: () => (
<RenderCrewCardList
initialCondition={{
mainCategory: '개발',
subCategory: '웹개발',
sortType: 'LATEST'
}}
/>
),
};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.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (1)
.github/workflows/ci.yml (1)
80-81: 시크릿 사용에 대한 문서화가 필요합니다.repository secrets에 대한 설정 방법과 필요한 값을 README나 문서에 추가하면 다른 개발자들의 설정에 도움이 될 것 같습니다.
다음과 같은 내용을 README.md에 추가하는 것을 제안합니다:
+## 환경 변수 설정 + +GitHub Actions에서 사용되는 환경 변수: + +- `NEXT_PUBLIC_API_BASE_URL`: API 서버의 기본 URL + - 형식: `https://api.example.com` + - GitHub repository settings > Secrets > Actions에서 설정
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
.github/workflows/ci.yml(1 hunks)
🔇 Additional comments (1)
.github/workflows/ci.yml (1)
80-81: 환경 변수 설정이 올바르게 추가되었습니다.
API 베이스 URL을 GitHub 시크릿에서 가져오는 것은 보안상 좋은 방법입니다. 하지만 이 URL이 올바른 환경을 가리키는지 확인이 필요합니다.
다음 스크립트를 실행하여 환경 변수가 워크플로우에서 올바르게 사용되는지 확인하세요:
✅ Verification successful
환경 변수가 올바르게 구성되어 있음을 확인했습니다
환경 변수 NEXT_PUBLIC_API_BASE_URL가 다음 위치에서 적절하게 사용되고 있습니다:
next.config.mjs의 프록시 설정에서 API 대상 URL로 사용src/utils/api.ts에서 API 기본 URL로 사용되며, 로컬 개발 환경을 위한 대체 값도 적절히 설정됨
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: API 베이스 URL이 next.config.mjs에서 사용되는지 확인
# next.config.mjs에서 환경 변수 사용 확인
rg -l "NEXT_PUBLIC_API_BASE_URL" "next.config*"
# 다른 설정 파일에서도 확인
rg -l "NEXT_PUBLIC_API_BASE_URL" ".env*"
Length of output: 187
Script:
#!/bin/bash
# Check for Next.js configuration files and environment files with any extension
fd -e js -e mjs -e ts "next.config"
# Search for environment variable usage in the codebase
rg "NEXT_PUBLIC_API_BASE_URL"
# Look for any configuration or environment setup files
fd -g ".env*"
fd -g "*.config.*"
Length of output: 640
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.
Actionable comments posted: 4
🧹 Outside diff range and nitpick comments (4)
src/components/common/crew-list/crew-card-list.tsx (2)
35-35: 타입 안전성 개선이 필요합니다.데이터 구조 변경이 잘 이루어졌으나, 타입 단언(type assertion)을 사용하는 대신 타입 가드를 사용하면 더 안전한 타입 체크가 가능할 것 같습니다.
다음과 같이 개선해보세요:
-data?.pages?.flatMap((page) => page.content as MainCrewList[]) ?? []; +data?.pages?.flatMap((page) => { + if (!page.content) return []; + return page.content; +}) ?? [];
Line range hint
1-85: 컴포넌트 책임 분리 검토가 필요합니다.현재
CrewCardList컴포넌트가 메인 크루 목록과 마이 크루 목록을 모두 처리하고 있습니다. 이는 단일 책임 원칙(SRP)에 위배될 수 있으며, 향후 유지보수를 어렵게 만들 수 있습니다.다음과 같은 개선을 고려해보세요:
MainCrewCardList와MyCrewCardList컴포넌트로 분리- 공통 로직을 커스텀 훅으로 추출
- 제네릭을 활용한 재사용 가능한
BaseCrewCardList컴포넌트 구현src/app/_components/find-crew/find-crew.tsx (2)
22-29: 상태 관리 개선을 위한 제안필터링 관련 상태들을 하나의 객체로 그룹화하면 상태 관리가 더욱 효율적일 것 같습니다.
- const [mainCategory, setMainCategory] = useState(''); - const [subCategory, setSubCategory] = useState(''); - const [sort, setSort] = useState<string | null>('latest'); - const [region, setRegion] = useState<string>(''); - const [search, setSearch] = useState(''); + const [filters, setFilters] = useState({ + mainCategory: '', + subCategory: '', + sort: 'latest' as string | null, + region: '', + search: '' + });
69-129: 접근성 및 스타일 개선 제안UI 구현이 잘 되어있지만, 다음 사항들을 개선하면 좋을 것 같습니다:
- 검색 입력란에 aria-label 추가
- 매직 넘버로 되어있는 패딩값들을 상수로 분리
<TextInput value={search} onChange={(e) => setSearch(e.target.value)} leftSectionPointerEvents="none" + aria-label="크루 검색" leftSection={ <Image src={IcoSearch} alt="search" width={21} height={21} className="-mr-4" /> } placeholder="크루 이름, 위치를 검색하세요." inputClassNames="w-full h-11 pl-12 placeholder:text-gray-500 font-pretendard text-base font-medium text-gray-800 rounded-xl" />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
src/app/(crew)/page.tsx(1 hunks)src/app/_components/find-crew/find-crew.tsx(1 hunks)src/components/common/crew-list/crew-card-list.tsx(2 hunks)
🔇 Additional comments (4)
src/app/_components/find-crew/find-crew.tsx (2)
1-20: 코드가 깔끔하고 잘 구성되어 있습니다!
필요한 모든 의존성이 명확하게 임포트되어 있으며, Props 인터페이스가 잘 정의되어 있습니다.
38-50: 무한 스크롤 성능 검증이 필요합니다
무한 스크롤 구현이 잘 되어있지만, 데이터가 많아질 경우의 성능 영향을 확인해야 합니다.
✅ Verification successful
무한 스크롤 구현이 적절하게 최적화되어 있습니다
코드베이스 분석 결과:
useInfiniteScroll훅이@tanstack/react-query의useInfiniteQuery를 기반으로 구현되어 있어 데이터 캐싱이 적절히 처리됩니다- 페이지네이션 로직(
getNextPageParam)이 각 컴포넌트에서 일관되게 구현되어 있습니다 - 데이터 타입이 제네릭으로 잘 관리되고 있어 타입 안정성이 보장됩니다
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for potential performance bottlenecks in infinite scroll implementation
# Search for other infinite scroll implementations to compare
rg -l "useInfiniteScroll|InfiniteData" --type typescript
# Check for memory management patterns
ast-grep --pattern 'useEffect($$$) {
return () => {
$$$
}
}'
Length of output: 164
Script:
#!/bin/bash
# Search for infinite scroll implementations and related patterns
rg -t ts -t tsx "useInfiniteScroll|InfiniteData"
# Look for cleanup patterns in useEffect
rg -t ts -t tsx "useEffect.*return \(\) =>" -A 3
# Check pagination or data fetching logic
rg -t ts -t tsx "getNextPageParam|fetchNextPage" -A 2
# Search for scroll event listeners
rg -t ts -t tsx "addEventListener.*scroll|onScroll" -A 2
Length of output: 328
Script:
#!/bin/bash
# Search for infinite scroll and related patterns without file type flags
rg "useInfiniteScroll|InfiniteData"
# Look for cleanup patterns in useEffect
rg "useEffect.*return \(\) =>" -A 3
# Check pagination logic
rg "getNextPageParam|fetchNextPage" -A 2
# Find scroll event handlers
rg "addEventListener.*scroll|onScroll" -A 2
# Find the implementation of useInfiniteScroll hook
fd useInfiniteScroll
Length of output: 6047
src/app/(crew)/page.tsx (2)
11-16: 'sortType'와 'sort' 파라미터의 일관성 확인 필요
'getCrewList' 함수 호출 시 sortType은 문자열 'LATEST'를 사용하고, sort는 배열 ['LATEST']를 사용하고 있습니다. 이러한 차이가 의도된 것인지 확인 부탁드립니다.
25-25: 'initialData'가 null일 경우에 대한 처리 필요
getCrewList 호출 실패 시 initialData가 null 또는 undefined가 될 수 있으므로, FindCrew 컴포넌트에 전달하기 전에 해당 상황에 대한 처리가 필요합니다.
| } | ||
| crewMembers={inWhere === 'my-crew' ? (inform as MyCrewList).crewMembers : undefined} | ||
| isConfirmed={inWhere !== 'my-crew' ? (inform as MainCrewList).isConfirmed : undefined} | ||
| isConfirmed={inWhere !== 'my-crew' && (inform as MainCrewList).isConfirmed} |
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.
🛠️ Refactor suggestion
타입 안전성과 가독성 개선이 필요합니다.
현재 구현은 간결하지만, 타입 단언과 부정 조건을 함께 사용하고 있어 코드의 의도를 파악하기 어려울 수 있습니다.
다음과 같이 개선해보세요:
-isConfirmed={inWhere !== 'my-crew' && (inform as MainCrewList).isConfirmed}
+isConfirmed={inWhere === 'my-crew' ? false : inform.isConfirmed}또한, 타입 가드를 사용하여 타입 안전성을 높이는 것을 고려해보세요:
function isMainCrewList(crew: MainCrewList | MyCrewList): crew is MainCrewList {
return 'isConfirmed' in crew;
}| const handleRegionChange = (newValue: string) => { | ||
| const selectedRegion = regionData.find((dataItem) => dataItem.main.value === newValue); | ||
| if (selectedRegion?.main.label === '지역 전체') return ''; | ||
| return selectedRegion ? selectedRegion.main.label : ''; | ||
| }; |
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.
지역 처리 로직 개선이 필요합니다
현재 구현에는 다음과 같은 잠재적인 문제가 있습니다:
- regionData가 undefined일 경우에 대한 처리가 없습니다
- 존재하지 않는 지역값이 전달될 경우의 처리가 미흡합니다
다음과 같이 개선하는 것을 제안드립니다:
const handleRegionChange = (newValue: string) => {
+ if (!newValue) return '';
const selectedRegion = regionData.find((dataItem) => dataItem.main.value === newValue);
- if (selectedRegion?.main.label === '지역 전체') return '';
- return selectedRegion ? selectedRegion.main.label : '';
+ return selectedRegion?.main.label === '지역 전체' ? '' : selectedRegion?.main.label ?? '';
};📝 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.
| const handleRegionChange = (newValue: string) => { | |
| const selectedRegion = regionData.find((dataItem) => dataItem.main.value === newValue); | |
| if (selectedRegion?.main.label === '지역 전체') return ''; | |
| return selectedRegion ? selectedRegion.main.label : ''; | |
| }; | |
| const handleRegionChange = (newValue: string) => { | |
| if (!newValue) return ''; | |
| const selectedRegion = regionData.find((dataItem) => dataItem.main.value === newValue); | |
| return selectedRegion?.main.label === '지역 전체' ? '' : selectedRegion?.main.label ?? ''; | |
| }; |
| const initialData = await getCrewList( | ||
| { | ||
| keyword: '', | ||
| mainLocation: '', | ||
| mainCategory: '', | ||
| subCategory: '', | ||
| sortType: 'LATEST', | ||
| }, | ||
| { | ||
| page: 0, | ||
| size: 6, | ||
| sort: ['LATEST'], | ||
| }, | ||
| ); |
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.
🛠️ Refactor suggestion
'getCrewList' 호출에 대한 에러 처리 구현 권장
getCrewList 호출 시 발생할 수 있는 에러를 처리하기 위해 try-catch 블록을 추가하는 것을 권장합니다. 이는 애플리케이션의 안정성을 높여줍니다.
코드 수정 예시:
export default async function HomePage() {
+ let initialData;
+ try {
initialData = await getCrewList(
{
keyword: '',
mainLocation: '',
mainCategory: '',
subCategory: '',
sortType: 'LATEST',
},
{
page: 0,
size: 6,
sort: ['LATEST'],
},
);
+ } catch (error) {
+ // 에러 처리 로직 추가
+ console.error('Crew 리스트를 가져오는 중 에러 발생:', error);
+ initialData = null;
+ }
const infiniteData = {
pages: [initialData],
pageParams: [],
};
return <FindCrew initialData={infiniteData} />;
}Committable suggestion skipped: line range outside the PR's diff.
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.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (1)
src/components/common/crew-list/crew-card-list.tsx (1)
41-41: 사용자 경험 개선을 위한 제안단순히 "데이터가 없습니다"라는 메시지보다 더 구체적인 안내나 행동 유도가 필요해 보입니다.
다음과 같은 개선을 고려해보세요:
-<p>데이터가 없습니다.</p> +<div className="text-center"> + <p className="mb-2">아직 등록된 크루가 없습니다.</p> + <p className="text-sm text-gray-500">새로운 크루를 찾아보세요!</p> +</div>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
src/_apis/crew/get-crew-list.ts(1 hunks)src/app/_components/find-crew/find-crew.tsx(1 hunks)src/components/common/crew-list/crew-card-list.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/app/_components/find-crew/find-crew.tsx
🔇 Additional comments (4)
src/_apis/crew/get-crew-list.ts (3)
1-7: 함수 시그니처가 잘 정의되어 있습니다!
타입 정의와 함수 시그니처가 명확하게 작성되어 있습니다.
9-9: sort 매개변수의 기본값이 적절하지 않습니다
['string']이라는 기본값은 의미가 없습니다. 실제 정렬 기준을 반영하는 값으로 변경해주세요.
14-21: API 호출 설정이 적절합니다!
인증 정보 포함 설정과 헤더 구성이 잘 되어있습니다.
src/components/common/crew-list/crew-card-list.tsx (1)
71-71: 이전 리뷰 코멘트가 여전히 유효합니다.
src/_apis/crew/get-crew-list.ts
Outdated
| // eslint-disable-next-line no-console | ||
| console.error(error); | ||
| return { content: [], hasNext: false }; |
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.
에러 처리 방식 개선이 필요합니다
현재 구현은 다음과 같은 문제가 있습니다:
- 프로덕션 환경에서
console.error사용 - 에러를 숨기고 빈 결과를 반환하여 문제 진단이 어려움
- 호출자에게 적절한 에러 정보를 제공하지 않음
다음과 같이 개선하는 것을 제안합니다:
} catch (error) {
- // eslint-disable-next-line no-console
- console.error(error);
- return { content: [], hasNext: false };
+ const errorMessage = error instanceof Error
+ ? error.message
+ : '크루 목록을 가져오는데 실패했습니다';
+ throw new Error(errorMessage);
}📝 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.
| // eslint-disable-next-line no-console | |
| console.error(error); | |
| return { content: [], hasNext: false }; | |
| } catch (error) { | |
| const errorMessage = error instanceof Error | |
| ? error.message | |
| : '크루 목록을 가져오는데 실패했습니다'; | |
| throw new Error(errorMessage); | |
| } |
| try { | ||
| const response = await fetchApi<MainCrewListResponse>( | ||
| `/crews?_page=${page + 1}&_limit=${limit}`, | ||
| `/api/crews/search?keyword=${keyword}&mainLocation=${mainLocation}&mainCategory=${mainCategory}&subCategory=${subCategory}&sortType=${sortType}&page=${page}&size=${size}&sort=${sort}`, |
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.
쿼리 파라미터 처리 개선이 필요합니다
- URL 인코딩이 누락되어 있어 특수문자나 한글이 포함된 경우 문제가 발생할 수 있습니다.
- 템플릿 리터럴을 사용한 직접적인 문자열 결합은 보안상 위험할 수 있습니다.
다음과 같이 수정하는 것을 제안합니다:
- `/api/crews/search?keyword=${keyword}&mainLocation=${mainLocation}&mainCategory=${mainCategory}&subCategory=${subCategory}&sortType=${sortType}&page=${page}&size=${size}&sort=${sort}`,
+ const params = new URLSearchParams({
+ keyword,
+ mainLocation,
+ mainCategory,
+ subCategory,
+ sortType,
+ page: page.toString(),
+ size: size.toString(),
+ sort: sort.join(','),
+ });
+ `/api/crews/search?${params.toString()}`,Committable suggestion skipped: line range outside the PR's diff.
| (inWhere === 'my-crew' | ||
| ? data?.pages.flatMap((page) => page.data as MyCrewList[]) | ||
| : data?.pages.flatMap((page) => page.data as MainCrewList[])) ?? []; | ||
| : data?.pages?.flatMap((page) => page.content as MainCrewList[])) ?? []; |
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.
🛠️ Refactor suggestion
데이터 구조 변경에 대한 타입 안전성 개선이 필요합니다.
타입 단언(as)을 사용하는 대신 타입 가드를 활용하여 런타임 안전성을 높이는 것이 좋습니다.
다음과 같이 개선해보세요:
function isMainCrewListResponse(page: MainCrewListResponse | MyCrewListResponse): page is MainCrewListResponse {
return 'content' in page;
}
// 사용 예시
const crewDataList = data?.pages.flatMap((page) =>
isMainCrewListResponse(page) ? page.content : page.data
) ?? [];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.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (4)
src/_queries/crew-queries.tsx (3)
1-1: 사용하지 않는 import 문을 제거하세요.
UseInfiniteQueryOptions를 import 했지만 코드에서 사용하지 않고 있습니다.-import { UseInfiniteQueryOptions } from '@tanstack/react-query';
17-19: 에러 메시지를 더 구체적으로 작성하세요.현재 에러 메시지가 너무 일반적입니다. API 응답이 null인 상황에 대한 더 자세한 정보를 포함하면 디버깅에 도움이 될 것 같습니다.
- throw new Error('Response is null'); + throw new Error('크루 목록을 가져오는데 실패했습니다. 서버 응답이 null입니다.');
23-24: 타입 안전성을 개선하세요.
getNextPageParam함수의 반환 타입을 명시적으로 지정하면 타입 안전성이 향상될 것 같습니다.- getNextPageParam: (lastPage: MainCrewListResponse, allPages: MainCrewListResponse[]) => + getNextPageParam: (lastPage: MainCrewListResponse, allPages: MainCrewListResponse[]): number | undefined =>src/components/common/crew-list/crew-card-list.tsx (1)
38-51: 로딩 상태 처리가 개선되었습니다.초기 로딩과 빈 데이터 상태를 구분하여 처리한 것은 좋은 개선입니다. 하지만 사용자 경험을 위해 로딩 메시지와 빈 데이터 메시지를 상수로 분리하는 것이 좋겠습니다.
다음과 같이 개선해보세요:
const MESSAGES = { NO_DATA: '데이터가 없습니다.', } as const; // 컴포넌트에서 사용 <p>{MESSAGES.NO_DATA}</p>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
src/_apis/crew/get-crew-list.ts(1 hunks)src/_queries/crew-queries.tsx(1 hunks)src/app/_components/find-crew/find-crew.tsx(1 hunks)src/components/common/crew-list/crew-card-list.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/app/_components/find-crew/find-crew.tsx
🔇 Additional comments (6)
src/_apis/crew/get-crew-list.ts (4)
16-16: 인증 정보 포함이 적절히 구현되었습니다
credentials: 'include' 설정으로 인증이 필요한 API 요청을 올바르게 처리할 수 있습니다.
10-10:
URL 매개변수 처리 방식 개선이 필요합니다
현재 구현은 다음과 같은 문제점이 있습니다:
- URL 인코딩이 되어있지 않아 한글이나 특수문자 처리에 문제가 발생할 수 있습니다
- 템플릿 리터럴을 사용한 직접적인 문자열 결합은 보안상 위험합니다
다음과 같이 URLSearchParams를 사용하여 개선하는 것을 권장합니다:
- `/api/crews/search?keyword=${keyword}&mainLocation=${mainLocation}&mainCategory=${mainCategory}&subCategory=${subCategory}&sortType=${sortType}&page=${page}&size=${size}&sort=${sort}`,
+ const params = new URLSearchParams({
+ keyword,
+ mainLocation,
+ mainCategory,
+ subCategory,
+ sortType,
+ page: page.toString(),
+ size: size.toString(),
+ sort: sort.join(','),
+ });
+ `/api/crews/search?${params.toString()}`,21-23:
에러 처리 로직의 개선이 필요합니다
현재 에러 처리에는 다음과 같은 문제점이 있습니다:
- 프로덕션 환경에서
console.error사용 null반환으로 인한 타입 안전성 저하- 호출자에게 의미 있는 에러 정보를 제공하지 않음
다음과 같이 개선하는 것을 권장합니다:
- // eslint-disable-next-line no-console
- console.error(error);
- return null;
+ const errorMessage = error instanceof Error
+ ? error.message
+ : '크루 목록을 가져오는데 실패했습니다';
+ throw new Error(errorMessage);6-6:
sort 매개변수의 기본값이 적절하지 않습니다
['string']이라는 기본값은 의미가 불분명하며 실제 정렬에 사용하기에 부적절합니다. 다음과 같이 명확한 정렬 기준을 설정하는 것이 좋습니다:
- const { page, size, sort = ['string'] } = pageable;
+ const { page, size, sort = ['createdAt,desc'] } = pageable;Likely invalid or redundant comment.
src/_queries/crew-queries.tsx (1)
7-13: 이전 리뷰 의견이 여전히 유효합니다.
queryKey에서 undefined나 null 값을 처리하는 로직이 아직 구현되지 않았습니다.
src/components/common/crew-list/crew-card-list.tsx (1)
14-14: Props 타입 정의가 더 엄격해졌습니다.
데이터 타입에서 undefined를 제거한 것은 좋은 변경이지만, 실제로 데이터가 항상 존재한다는 것을 보장할 수 있는지 확인이 필요합니다.
Also applies to: 20-20
✅ Verification successful
데이터가 항상 정의되어 있습니다.
CrewCardList가 사용되는 모든 위치에서 data가 정의된 상태로 전달되고 있습니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if data is always defined in component usage
# Search for CrewCardList usage
rg -A 5 "CrewCardList"
Length of output: 7904
| ? data?.pages.flatMap((page) => page?.data as MyCrewList[]) | ||
| : data?.pages?.flatMap((page) => page?.content as MainCrewList[])) ?? []; |
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.
🛠️ Refactor suggestion
타입 단언 대신 타입 가드를 사용하는 것이 좋습니다.
현재 구현은 타입 단언(as)을 사용하고 있어 런타임 시 타입 안전성을 보장할 수 없습니다.
다음과 같이 타입 가드를 사용하여 개선해보세요:
function isMyCrewList(crew: any): crew is MyCrewList {
return 'data' in crew;
}
function isMainCrewList(crew: any): crew is MainCrewList {
return 'content' in crew;
}
const crewDataList = data?.pages.flatMap((page) =>
inWhere === 'my-crew'
? (isMyCrewList(page) ? page.data : [])
: (isMainCrewList(page) ? page.content : [])
) ?? [];| <li key={inform?.id} className="w-full"> | ||
| <CrewCard | ||
| inWhere={inWhere} | ||
| id={inform.id} | ||
| title={inform.title} | ||
| mainLocation={inform.mainLocation} | ||
| subLocation={inform.subLocation} | ||
| imageUrl={inform.imageUrl} | ||
| totalCount={inform.totalCount} | ||
| id={inform?.id} | ||
| title={inform?.title} | ||
| mainLocation={inform?.mainLocation} | ||
| subLocation={inform?.subLocation} | ||
| imageUrl={inform?.imageUrl} | ||
| totalCount={inform?.totalCount} | ||
| participantCount={ | ||
| inWhere === 'my-crew' | ||
| ? (inform as MyCrewList).currentCount | ||
| : (inform as MainCrewList).participantCount | ||
| ? (inform as MyCrewList)?.currentCount | ||
| : (inform as MainCrewList)?.participantCount | ||
| } | ||
| totalGatheringCount={ | ||
| inWhere === 'my-crew' | ||
| ? (inform as MyCrewList).totalGathering | ||
| : (inform as MainCrewList).totalGatheringCount | ||
| ? (inform as MyCrewList)?.totalGathering | ||
| : (inform as MainCrewList)?.totalGatheringCount | ||
| } | ||
| crewMembers={inWhere === 'my-crew' ? (inform as MyCrewList).crewMembers : undefined} | ||
| isConfirmed={inWhere !== 'my-crew' ? (inform as MainCrewList).isConfirmed : undefined} | ||
| crewMembers={inWhere === 'my-crew' ? (inform as MyCrewList)?.crewMembers : undefined} | ||
| isConfirmed={inWhere !== 'my-crew' && (inform as MainCrewList)?.isConfirmed} |
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.
🛠️ Refactor suggestion
CrewCard props 전달 방식 개선이 필요합니다.
현재 구현은 과도한 타입 단언과 옵셔널 체이닝을 사용하고 있습니다. 이는 코드의 안전성과 가독성을 저해할 수 있습니다.
다음과 같이 개선해보세요:
// 타입 가드 함수 사용
function getCrewCardProps(inform: MainCrewList | MyCrewList, inWhere?: 'my-crew') {
const baseProps = {
id: inform.id,
title: inform.title,
mainLocation: inform.mainLocation,
subLocation: inform.subLocation,
imageUrl: inform.imageUrl,
totalCount: inform.totalCount,
};
if (inWhere === 'my-crew' && 'currentCount' in inform) {
return {
...baseProps,
participantCount: inform.currentCount,
totalGatheringCount: inform.totalGathering,
crewMembers: inform.crewMembers,
isConfirmed: false,
};
}
if ('participantCount' in inform) {
return {
...baseProps,
participantCount: inform.participantCount,
totalGatheringCount: inform.totalGatheringCount,
crewMembers: undefined,
isConfirmed: inform.isConfirmed,
};
}
throw new Error('Invalid crew data type');
}
// 컴포넌트에서 사용
<CrewCard
inWhere={inWhere}
{...getCrewCardProps(inform, inWhere)}
/>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.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (3)
src/types/crew-card.d.ts (1)
9-12: 정렬 필드의 타입 안정성 개선이 필요합니다
sort필드가 현재string[]타입으로 정의되어 있어 잘못된 값이 전달될 수 있습니다. 유효한 정렬 옵션을 명시적으로 정의하는 것이 좋습니다.export interface PageableTypes { page: number; size: number; - sort: string[]; + sort: Array<'createdAt' | 'participantCount'>; }src/components/common/crew-list/crew-card-list.stories.tsx (1)
1-4: import 구문 정리가 필요합니다관련된 import들을 그룹화하여 가독성을 높이는 것이 좋겠습니다:
- React 관련
- 외부 라이브러리
- 내부 컴포넌트/훅
- 타입
다음과 같이 수정하는 것을 제안합니다:
// React import { useEffect, useState } from 'react'; // External libraries import type { Meta, StoryObj } from '@storybook/react'; import { InfiniteData } from '@tanstack/react-query'; // Internal imports import { useGetCrewListQuery } from '@/src/_queries/crew-queries'; import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll'; import ClientProvider from '@/src/components/client-provider'; // Types import { MainCrewListResponse } from '@/src/types/crew-card';src/components/common/crew-list/crew-card-list.tsx (1)
38-51: 로딩 상태 처리 로직 개선이 필요합니다.현재 구현은 초기 로딩과 빈 데이터 상태를 별도로 처리하고 있어 일관성이 떨어집니다. 다음과 같은 개선을 제안합니다:
type LoadingState = 'initial' | 'empty' | 'loaded'; function getLoadingState(data: CrewCardListProps['data']): LoadingState { if (data?.pages[0] === null) return 'initial'; if (!data?.pages.some(page => page?.content?.length || page?.data?.length)) return 'empty'; return 'loaded'; } const LoadingStateComponent: Record<LoadingState, JSX.Element> = { initial: <div className="flex justify-center py-10"><Loader size="sm" /></div>, empty: <div className="flex justify-center py-10"><p>데이터가 없습니다.</p></div>, loaded: null };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (5)
src/app/_components/find-crew/find-crew.tsx(1 hunks)src/components/common/crew-list/crew-card-list.stories.tsx(2 hunks)src/components/common/crew-list/crew-card-list.tsx(2 hunks)src/components/common/crew-list/crew-card.tsx(4 hunks)src/types/crew-card.d.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/app/_components/find-crew/find-crew.tsx
- src/components/common/crew-list/crew-card.tsx
🔇 Additional comments (5)
src/types/crew-card.d.ts (2)
1-7: 이전 리뷰 의견이 여전히 유효합니다
필터 조건의 선택적 필드 처리에 대한 이전 리뷰 의견이 아직 반영되지 않았습니다.
15-18: API 응답 구조와의 일관성 확인이 필요합니다
data에서 content로의 필드명 변경과 null 타입 추가가 백엔드 API 응답 구조와 일치하는지 확인해주세요.
src/components/common/crew-list/crew-card-list.stories.tsx (1)
62-62: 이전 리뷰 코멘트와 동일: 스토리북 테스트 케이스 보강 필요
src/components/common/crew-list/crew-card-list.tsx (2)
34-35: 이전 리뷰 코멘트 참조
타입 단언 관련 이슈는 이전 리뷰 코멘트에서 이미 다루어졌습니다.
59-79: 이전 리뷰 코멘트 참조
CrewCard props 전달 방식 개선에 대한 내용은 이전 리뷰 코멘트에서 이미 다루어졌습니다.
| mainCategory?: string; | ||
| subCategory?: string; |
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.
CrewMemberList 타입이 정의되어 있지 않습니다
crewMembers 필드가 CrewMemberList[] 타입을 참조하고 있으나, 해당 타입이 파일 내에 정의되어 있지 않습니다. CrewMember 인터페이스를 사용해야 할 것 같습니다.
export interface MainCrewList {
// ...
- crewMembers?: CrewMemberList[];
+ crewMembers?: CrewMember[];
}Also applies to: 32-32
| function RenderCrewCardList({ | ||
| initialData, | ||
| }: { | ||
| initialData: InfiniteData<MainCrewListResponse | null>; | ||
| }) { | ||
| const [data, setData] = useState<InfiniteData<MainCrewListResponse | null>>(initialData); | ||
| const { | ||
| data: CrewCardListData, | ||
| ref, | ||
| isFetchingNextPage, | ||
| } = useInfiniteScroll( | ||
| useGetCrewListQuery({ | ||
| keyword: '', | ||
| mainLocation: '', | ||
| mainCategory: '', | ||
| subCategory: '', | ||
| sortType: 'LATEST', | ||
| }), | ||
| ); | ||
|
|
||
| useEffect(() => { | ||
| if (CrewCardListData) { | ||
| setData(CrewCardListData); | ||
| } | ||
| }, [CrewCardListData]); |
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.
🛠️ Refactor suggestion
컴포넌트 구현 개선이 필요합니다
현재 구현에서 몇 가지 개선이 필요한 부분이 있습니다:
- 타입 안전성:
MainCrewListResponse | null에 대한 명시적인 타입가드가 필요합니다. - 에러 처리: API 호출 실패에 대한 처리가 없습니다.
- 로딩 상태: 초기 로딩 상태 처리가 필요합니다.
다음과 같은 개선을 제안합니다:
function RenderCrewCardList({
initialData,
}: {
initialData: InfiniteData<MainCrewListResponse | null>;
}) {
const [data, setData] = useState<InfiniteData<MainCrewListResponse | null>>(initialData);
const [error, setError] = useState<Error | null>(null);
const {
data: CrewCardListData,
ref,
isFetchingNextPage,
isLoading,
error: queryError,
} = useInfiniteScroll(
useGetCrewListQuery({
keyword: '',
mainLocation: '',
mainCategory: '',
subCategory: '',
sortType: 'LATEST',
}),
);
useEffect(() => {
if (queryError) {
setError(queryError as Error);
}
if (CrewCardListData) {
setData(CrewCardListData);
}
}, [CrewCardListData, queryError]);
if (error) {
return <ErrorComponent error={error} />;
}
if (isLoading) {
return <LoadingSpinner />;
}
return (
<CrewCardList
data={data}
ref={ref}
isFetchingNextPage={isFetchingNextPage}
/>
);
}| // CrewCardListProps 타입을 구분하여 정의 | ||
| interface MainCrewCardListProps { | ||
| data: InfiniteData<MainCrewListResponse> | undefined; | ||
| data: InfiniteData<MainCrewListResponse | null>; |
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.
🛠️ Refactor suggestion
타입 정의의 안전성 개선이 필요합니다.
MainCrewListResponse | null과 같은 유니온 타입은 런타임에서 예기치 않은 동작을 유발할 수 있습니다. 다음과 같은 개선을 제안합니다:
null대신undefined를 사용하여 옵셔널 값을 표현- 명시적인 타입 가드를 통한 null 체크
interface MainCrewCardListProps {
data: InfiniteData<MainCrewListResponse | undefined>;
// ...
}
// 타입 가드 예시
function isValidMainCrewResponse(response: MainCrewListResponse | undefined): response is MainCrewListResponse {
return response !== undefined;
}Also applies to: 20-20
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.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (4)
src/_queries/crew-queries.tsx (3)
1-1: 사용하지 않는 import 문을 제거하세요.
UseInfiniteQueryOptions를 import 했지만 코드에서 사용하지 않고 있습니다.다음과 같이 수정하세요:
-import { UseInfiniteQueryOptions } from '@tanstack/react-query';
14-22: 에러 처리를 더 구체적으로 개선하세요.현재 에러 처리가 너무 단순합니다. 다음과 같은 개선사항을 제안합니다:
- 더 구체적인 에러 메시지를 제공하세요
- 에러 타입을 구분하여 처리하세요
다음과 같이 수정하세요:
queryFn: ({ pageParam = 0 }) => getCrewList(condition, { page: pageParam, size: 6, sort: [condition.sortType] }).then( (response) => { if (response === undefined) { - throw new Error('Response is null'); + throw new Error(`크루 목록을 가져오는데 실패했습니다. 조건: ${JSON.stringify(condition)}`); } return response; }, ),
23-24: getNextPageParam 로직을 더 명시적으로 작성하세요.현재 구현이 동작은 하지만, 의도를 더 명확하게 표현할 수 있습니다.
다음과 같이 수정하세요:
- getNextPageParam: (lastPage: MainCrewListResponse, allPages: MainCrewListResponse[]) => - lastPage.hasNext ? allPages.length : undefined, + getNextPageParam: (lastPage: MainCrewListResponse, allPages: MainCrewListResponse[]) => { + const nextPage = lastPage.hasNext ? allPages.length : undefined; + return nextPage; + },src/types/crew-card.d.ts (1)
9-12: 페이지네이션 타입 개선이 필요합니다다음과 같은 개선사항을 제안드립니다:
sort필드의 타입을 구체적으로 정의하는 것이 좋습니다page와size에 대한 유효성 검사가 필요합니다export interface PageableTypes { - page: number; - size: number; - sort: string[]; + page: number & { __brand: 'NonNegativeInteger' }; + size: number & { __brand: 'PositiveInteger' }; + sort: Array<'asc' | 'desc'>; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (6)
src/_apis/crew/get-crew-list.ts(1 hunks)src/_queries/crew-queries.tsx(1 hunks)src/app/_components/find-crew/find-crew.tsx(1 hunks)src/components/common/crew-list/crew-card-list.stories.tsx(2 hunks)src/components/common/crew-list/crew-card-list.tsx(2 hunks)src/types/crew-card.d.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/app/_components/find-crew/find-crew.tsx
- src/components/common/crew-list/crew-card-list.tsx
🔇 Additional comments (9)
src/_apis/crew/get-crew-list.ts (2)
6-6:
정렬 매개변수의 기본값 수정 필요
sort 매개변수의 기본값으로 ['string']을 사용하는 것은 적절하지 않습니다. 실제 정렬 기준을 반영하는 의미 있는 기본값으로 변경해주세요.
- const { page, size, sort = ['string'] } = pageable;
+ const { page, size, sort = ['createdAt,desc'] } = pageable;Likely invalid or redundant comment.
10-10:
URL 매개변수 처리 개선 필요
쿼리 파라미터를 직접 문자열로 연결하는 것은 보안상 위험할 수 있으며, 특수문자나 한글이 포함된 경우 문제가 발생할 수 있습니다.
- `/api/crews/search?keyword=${keyword}&mainLocation=${mainLocation}&mainCategory=${mainCategory}&subCategory=${subCategory}&sortType=${sortType}&page=${page}&size=${size}&sort=${sort}`,
+ const params = new URLSearchParams({
+ keyword,
+ mainLocation,
+ mainCategory,
+ subCategory,
+ sortType,
+ page: page.toString(),
+ size: size.toString(),
+ sort: sort.join(','),
+ });
+ `/api/crews/search?${params.toString()}`,Likely invalid or redundant comment.
src/_queries/crew-queries.tsx (1)
7-13: 이전 리뷰 의견이 아직 해결되지 않았습니다.
queryKey 처리에 대한 이전 리뷰 의견이 아직 반영되지 않았습니다.
src/types/crew-card.d.ts (3)
1-7: 이전 리뷰 의견이 여전히 유효합니다
필터 조건의 필드들이 여전히 모두 필수로 설정되어 있습니다.
22-23: 카테고리 필드의 선택적 처리가 적절합니다
mainCategory와 subCategory를 선택적 필드로 변경한 것은 좋은 개선입니다. 이는 필터 조건의 유연성을 높여줍니다.
32-32: 이전 리뷰 의견이 여전히 유효합니다
CrewMemberList[] 타입 관련 이슈가 해결되지 않았습니다.
src/components/common/crew-list/crew-card-list.stories.tsx (3)
1-1: 필요한 의존성이 올바르게 추가되었습니다.
React Query와 상태 관리를 위한 필수 의존성들이 적절하게 import 되었습니다.
Also applies to: 3-4
32-56:
에러 처리와 로딩 상태 관리가 필요합니다.
이전 리뷰에서 언급된 개선사항들이 아직 반영되지 않았습니다:
다음과 같은 개선사항을 제안드립니다:
function RenderCrewCardList({
initialData,
}: {
initialData: InfiniteData<MainCrewListResponse | undefined>;
}) {
const [data, setData] = useState<InfiniteData<MainCrewListResponse | undefined>>(initialData);
+ const [error, setError] = useState<Error | null>(null);
const {
data: CrewCardListData,
ref,
isFetchingNextPage,
+ isLoading,
+ error: queryError,
} = useInfiniteScroll(
useGetCrewListQuery({
keyword: '',
mainLocation: '',
mainCategory: '',
subCategory: '',
sortType: 'LATEST',
}),
);
useEffect(() => {
+ if (queryError) {
+ setError(queryError as Error);
+ }
if (CrewCardListData) {
setData(CrewCardListData);
}
- }, [CrewCardListData]);
+ }, [CrewCardListData, queryError]);
+ if (error) {
+ return <ErrorComponent error={error} />;
+ }
+
+ if (isLoading) {
+ return <LoadingSpinner />;
+ }
return <CrewCardList data={data} ref={ref} isFetchingNextPage={isFetchingNextPage} />;
}62-63: 🛠️ Refactor suggestion
다양한 테스트 케이스 추가가 필요합니다.
기본 케이스만 구현되어 있어 컴포넌트의 다양한 상태를 테스트하기 어렵습니다.
다음과 같은 테스트 케이스 추가를 제안드립니다:
export const WithFilters: Story = {
render: () => (
<RenderCrewCardList
initialData={{
pages: [],
pageParams: [],
}}
initialFilters={{
keyword: '개발자',
mainLocation: '서울',
mainCategory: '개발',
subCategory: '웹개발',
}}
/>
),
};
export const WithError: Story = {
render: () => (
<RenderCrewCardList
initialData={{
pages: [],
pageParams: [],
}}
shouldError={true}
/>
),
};
export const Loading: Story = {
render: () => (
<RenderCrewCardList
initialData={{
pages: [],
pageParams: [],
}}
isLoading={true}
/>
),
};| // eslint-disable-next-line no-console | ||
| console.error(error); | ||
| return undefined; |
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.
에러 처리 방식 개선 필요
현재 에러 처리 방식에는 다음과 같은 문제가 있습니다:
- 프로덕션 환경에서
console.error사용 - 에러를 숨기고
undefined를 반환하여 문제 진단이 어려움 - 호출자에게 적절한 에러 정보를 제공하지 않음
} catch (error) {
- // eslint-disable-next-line no-console
- console.error(error);
- return undefined;
+ const errorMessage = error instanceof Error
+ ? error.message
+ : '크루 목록을 가져오는데 실패했습니다';
+ throw new Error(errorMessage);
}📝 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.
| // eslint-disable-next-line no-console | |
| console.error(error); | |
| return undefined; | |
| const errorMessage = error instanceof Error | |
| ? error.message | |
| : '크루 목록을 가져오는데 실패했습니다'; | |
| throw new Error(errorMessage); |
| export type MainCrewListResponse = { | ||
| content: MainCrewList[] | undefined; | ||
| hasNext: boolean; | ||
| }; |
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.
💡 Codebase verification
API 응답 구조 변경으로 인한 영향이 발견되었습니다
다음 파일에서 data 필드를 사용하고 있습니다. content로 변경이 필요합니다:
- src/app/api/mock-api/review.ts
- src/app/(crew)/api/mock-api/writable-gathering.ts
- src/app/(crew)/crew/detail/[id]/_components/crew-review-list.stories.tsx
- src/_queries/auth/auth-queries.tsx
🔗 Analysis chain
응답 구조 변경에 대한 검증이 필요합니다
data에서 content로의 필드명 변경과 undefined 타입 추가는 API 응답 구조의 변경을 의미합니다. 이 변경이 프론트엔드 전반에 미치는 영향을 확인해야 합니다.
rg 명령어에서 tsx 파일 형식을 인식하지 못했습니다.
API 응답 구조 변경의 영향을 받는 코드를 검색하기 위해 .ts 및 .tsx 파일을 대상으로 명령어를 수정하겠습니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# API 응답 구조 변경의 영향을 받는 코드 검색
rg -l "\.data\." --type ts --type tsx
Length of output: 67
Script:
#!/bin/bash
# API 응답 구조 변경의 영향을 받는 코드 검색
rg -l "\\.data\\." -g "*.ts" -g "*.tsx"
Length of output: 228
HaeJungg
left a comment
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.
정렬이나 검색이 많아 복잡한 부분인데 수고하셨습니다👏👏
| console.error(error); | ||
| return undefined; |
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.
이 에러처리를 굳이 여기서 하지 않고 페이지에서 한번에 api 유틸에 있는 ApiError를 사용해서 처리해도 좋을거같습니다!
src/components/client-provider.tsx
Outdated
|
|
||
| return ( | ||
| <QueryClientProvider client={queryClient}> | ||
| <ReactQueryDevtools initialIsOpen={false} /> |
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.
위에 코드 래빗의 의견처럼 디버깅 도구라 dev환경에서만 실행되도록 조건부 랜더링을 추가해야될거같아요!
| fill | ||
| objectFit="cover" | ||
| alt={title} | ||
| src={imageUrl === 'string' ? ImgDefault : imageUrl} |
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.
이미지 디폴트 처리가 필요할까요...??👀 어차피 폼에서 이미지를 안고르면 생성이 안되는걸루 알고 있어서요..!
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.
아핫 수정했습니다~~~ 잘못된 크루데이터는 삭제했어요~~
* Squashed commit of the following: commit 51cfe2f Author: Lee Youl <[email protected]> Date: Sat Nov 9 11:40:05 2024 +0900 🐛 Fix: MockData 날짜 형식 수정 commit 7b68352 Author: Lee Youl <[email protected]> Date: Sat Nov 9 11:38:06 2024 +0900 🐛 Fix: 이전날짜 선택 방지, isToday 날짜 비교 수정 commit f101987 Author: Lee Youl <[email protected]> Date: Sat Nov 9 11:19:20 2024 +0900 🐛 Fix: 폼 동작 개선 commit c408058 Author: Lee Youl <[email protected]> Date: Sat Nov 9 10:51:40 2024 +0900 🐛 Fix: isToday 함수 개선, 데이터 한국시간 기준으로 변경 commit 0683f5a Author: Lee Youl <[email protected]> Date: Fri Nov 8 21:49:45 2024 +0900 🐛 Fix: 버튼 링크로 교체 commit 43cdfa7 Author: Lee Youl <[email protected]> Date: Fri Nov 8 21:43:11 2024 +0900 🚨 Fix: 린트 오류 제거 commit 9657201 Author: Lee Youl <[email protected]> Date: Fri Nov 8 21:34:56 2024 +0900 🐛 Fix: 스크롤바 두개로 보이는 문제 수정 commit 63a8e1c Author: Lee Youl <[email protected]> Date: Fri Nov 8 21:27:25 2024 +0900 🐛 Fix: 유효성 검사 날짜 선택 오류 수정 commit 80f8554 Author: Lee Youl <[email protected]> Date: Fri Nov 8 21:24:46 2024 +0900 🐛 Fix: 에러상태인데 새로 값 채울 때 에러 해제하기, 리팩토링 commit af9fb91 Author: Lee Youl <[email protected]> Date: Fri Nov 8 20:46:00 2024 +0900 🐛 Fix: 크루 생성시 디테일 페이지로 이동, 리팩토링 commit f1fe204 Author: Lee Youl <[email protected]> Date: Fri Nov 8 20:31:17 2024 +0900 🐛 Fix: 텍스트 수정(약속 잡기 > 약속 만들기) commit 5cc6746 Author: Lee Youl <[email protected]> Date: Fri Nov 8 20:29:52 2024 +0900 🐛 Fix: 드롭다운 값 선택시 포커스 아웃 되도록 수정 * [WIP] Feat: GetCrewList API 연결 * ✨ Feat: 백엔드 api 연결 * 🐛 Fix: 처음 로딩시 카테고리 초기화 * 🐛 Fix: 카테고리 동작 개선 * 🐛 Fix: 지역 필터링 동작 개선 * ✨ Feat: 지역 전체 필터 추가 * 🚨 Fix: 타입 개선, 빌드 오류 수정 * 🚧 Chore: workflow 수정 * ♻️ Refactor 코드 개선 * 🐛 Fix: 코드 개선 * ✨ Feat: 검색 버튼 추가 * 🐛 Fix: 동작 개선 * 🚧 Chore: 경로 변경 * 🐛 Fix: 콘솔에러 추가 * ⚡️ Fix: 검색 엔터방식으로 변경 * 🐛 Fix: 동작개선, 에러메시지 보이기 * 💄 Design: 스타일 수정 * 🐛 Fix: 에러처리 추가 * 🚨 Fix: 빌드 오류 수정 * 🐛 Fix: 타입 수정 * 🐛 Fix: 디폴트이미지 삭제, 데브툴 조건부렌더링
🔖 Issue Ticket
#98
✍️ Description
크루 찾기 페이지
✅ Checklist
PR
Test
Summary by CodeRabbit
릴리스 노트
새로운 기능
FindCrew컴포넌트 추가: 사용자 기준에 따라 승무원 검색 및 필터링 기능 제공.ReactQueryDevtools추가: 개발 도구를 통해 쿼리 상태를 시각화 가능.region.json에 "지역 전체" 항목 추가: 모든 지역을 포함하는 범주 제공.변경 사항
getCrewListAPI 호출 방식 변경: 여러 조건을 기반으로 데이터 요청.CrewCardList및CrewCard컴포넌트의 데이터 구조 업데이트: 새로운 프로퍼티 사용.useGetCrewQuery를useGetCrewListQuery로 변경: 데이터 가져오는 방식 개선.CategoryContainer및InternalCategory컴포넌트의 상태 관리 간소화.Home컴포넌트를 비동기 함수로 변경하여 데이터 가져오기 방식 개선.TextInput컴포넌트의registerprop 통합: 폼 처리 기능 개선.CrewCardList컴포넌트의 데이터 접근 방식 및 렌더링 로직 조정: 더 강력한 데이터 처리 구현.버그 수정
useInfiniteScroll훅에refetch기능 추가: 데이터 새로 고침 가능.