-
Notifications
You must be signed in to change notification settings - Fork 3
Feat/105/my crew api 연결 #109
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
Conversation
|
Caution Review failedThe pull request is closed. Walkthrough이번 변경 사항은 Changes
Suggested reviewers
Poem
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/_apis/crew/crew-list.tsOops! 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: 13
🧹 Outside diff range and nitpick comments (7)
src/app/(crew)/my-crew/participation/page.tsx (1)
7-19: 컴포넌트 개선을 위한 제안사항이 있습니다.현재 구현은 작동하지만, 다음과 같은 개선사항들을 고려해보시면 좋을 것 같습니다:
- 에러 상태 처리
- 로딩 상태 표시
- 불필요한 div 래퍼 제거
- 타입 안전성 강화
다음과 같이 개선해보시는 건 어떨까요?:
export default function MyCrewParticipationPage() { - const { data, ref, isFetchingNextPage } = useInfiniteScroll(useGetMyCrewParticipationQuery()); + const { + data, + ref, + isFetchingNextPage, + isError, + error, + isLoading + } = useInfiniteScroll(useGetMyCrewParticipationQuery()); + + if (isError) { + return <div>에러가 발생했습니다: {error?.message}</div>; + } + + if (isLoading) { + return <div>로딩 중...</div>; + } - return ( - <div> - <CrewCardList - inWhere="my-crew" - data={data ?? { pages: [], pageParams: [] }} - ref={ref} - isFetchingNextPage={isFetchingNextPage} - /> - </div> - ); + return ( + <CrewCardList + inWhere="my-crew" + data={data ?? { pages: [], pageParams: [] }} + ref={ref} + isFetchingNextPage={isFetchingNextPage} + /> + ); }src/app/(crew)/my-crew/layout.tsx (3)
8-14: 성능 최적화를 위한 제안
myCrewTabs배열을 컴포넌트 외부로 이동하여 렌더링마다 재생성되는 것을 방지하는 것이 좋습니다.다음과 같이 수정해보세요:
+const myCrewTabs = [ + { label: '내가 참여한 크루', id: 'joined-crew', route: '/my-crew/participation' }, + { label: '내가 만든 크루', id: 'made-crew', route: '/my-crew/creation' }, +]; export default function MyCrewLayout({ children }: { children: ReactNode }) { const router = useRouter(); const currentPath = usePathname(); - const myCrewTabs = [ - { label: '내가 참여한 크루', id: 'joined-crew', route: '/my-crew/participation' }, - { label: '내가 만든 크루', id: 'made-crew', route: '/my-crew/creation' }, - ]; const [currentTab, setCurrentTab] = useState(myCrewTabs[0].id);
21-24: useCallback을 사용한 최적화가 필요합니다
find콜백 함수를 매 렌더링마다 재생성하는 것을 방지하기 위해useCallback을 사용하는 것이 좋습니다.다음과 같이 수정해보세요:
+const findActiveTabId = useCallback((path: string) => { + return myCrewTabs.find((tab) => tab.route === path)?.id; +}, []); useEffect(() => { - const activeTabId = myCrewTabs.find((tab) => tab.route === currentPath)?.id; + const activeTabId = findActiveTabId(currentPath); if (activeTabId) setCurrentTab(activeTabId); }, [currentPath, findActiveTabId]);
26-40: 스타일링 개선 제안Tailwind 클래스를 더 의미있게 구성하고, 반응형 디자인을 개선할 수 있습니다.
다음과 같이 수정해보세요:
- <div className="py-8 md:py-12.5"> + <section className="crew-layout py-8 md:py-12.5 lg:py-16"> - <div className="px-3 md:px-8 lg:px-11.5"> + <div className="crew-tabs-container px-3 md:px-8 lg:px-11.5 max-w-screen-xl mx-auto"> <Tabs variant="default" tabs={myCrewTabs} activeTab={currentTab} onTabClick={(id) => { handleTabClick(id); }} /> </div> - <div className="mt-8 px-3 md:px-8 lg:px-11.5">{children}</div> + <div className="crew-content mt-8 px-3 md:px-8 lg:px-11.5 max-w-screen-xl mx-auto">{children}</div> - </div> + </section>src/components/common/crew-list/crew-card-list.tsx (1)
Line range hint
1-85: 컴포넌트 구조 개선을 제안드립니다.현재 컴포넌트가 너무 많은 책임을 가지고 있습니다. 로딩 상태, 빈 상태, 카드 목록 렌더링 등의 책임을 분리하면 코드의 재사용성과 유지보수성이 향상될 것 같습니다.
다음과 같은 구조로 분리하는 것을 제안드립니다:
// LoadingState.tsx export const LoadingState = () => ( <div className="flex justify-center py-10"> <Loader size="sm" /> </div> ); // EmptyState.tsx export const EmptyState = () => ( <div className="flex justify-center py-10"> <p>데이터가 없습니다.</p> </div> ); // CrewCardList.tsx function CrewCardList({ data, isFetchingNextPage, inWhere }: CrewCardListProps, ref: React.Ref<HTMLDivElement>) { if (data?.pages[0] === undefined) return <LoadingState />; if (!crewDataList.length) return <EmptyState />; // ... 나머지 렌더링 로직 }src/components/common/crew-list/crew-card.tsx (2)
Line range hint
31-33: 하드코딩된 라우트를 실제 API 연동으로 교체해주세요.현재
/crew/detail/1로 하드코딩된 라우트가 있습니다. 주석에서 언급된 것처럼 API 연결 후에는id를 사용하여 동적 라우트를 구성해야 합니다.다음과 같이 수정해주세요:
- // NOTE: api연결 후 되돌리기 - // const CREWPAGE = `/crew/detail/${id}`; - const CREWPAGE = `/crew/detail/1`; + const CREWPAGE = `/crew/detail/${id}`;
Line range hint
29-40: prefetch 로직 최적화를 제안드립니다.현재 구현된 prefetch 로직에 대해 다음과 같은 개선사항을 제안드립니다:
prefetchedSet을useMemo를 통해 메모이제이션handleCardMouseUp함수를useCallback으로 최적화다음과 같이 수정하는 것을 추천드립니다:
- const [prefetched, setPrefetched] = useState(new Set()); + const [prefetched, setPrefetched] = useState(() => new Set()); + + const handleCardMouseUp = useCallback(() => { + if (!prefetched.has(CREWPAGE)) { + router.prefetch(CREWPAGE); + setPrefetched(prev => new Set(prev).add(CREWPAGE)); + } + }, [CREWPAGE, prefetched, router]);추가로 필요한 import문:
import { useCallback } from 'react';
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (10)
src/_apis/crew/get-my-crew-creation-list.ts(1 hunks)src/_apis/crew/get-my-crew-participation-list.ts(1 hunks)src/_queries/crew-queries.tsx(3 hunks)src/app/(crew)/my-crew/creation/page.tsx(1 hunks)src/app/(crew)/my-crew/layout.tsx(1 hunks)src/app/(crew)/my-crew/page.tsx(1 hunks)src/app/(crew)/my-crew/participation/page.tsx(1 hunks)src/components/common/crew-list/crew-card-list.tsx(1 hunks)src/components/common/crew-list/crew-card.tsx(1 hunks)src/types/crew-card.d.ts(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- src/app/(crew)/my-crew/page.tsx
🔇 Additional comments (9)
src/app/(crew)/my-crew/creation/page.tsx (1)
1-5: 코드 구조가 깔끔하고 적절합니다!
'use client' 지시문과 import 구문이 올바르게 구성되어 있습니다.
src/app/(crew)/my-crew/participation/page.tsx (2)
1-5: 코드 구성이 깔끔합니다!
필요한 의존성들이 명확하게 임포트되어 있고, 클라이언트 사이드 렌더링을 위한 'use client' 지시문이 적절하게 배치되어 있습니다.
11-16: CrewCardList 컴포넌트의 타입 정의를 확인해주세요.
CrewCardList 컴포넌트에 전달되는 데이터 타입이 올바르게 정의되어 있는지 확인이 필요합니다.
src/_apis/crew/get-my-crew-creation-list.ts (1)
1-2: 타입 정의와 임포트가 잘 구성되어 있습니다!
필요한 유틸리티와 타입들이 적절하게 임포트되어 있으며, 절대 경로를 사용한 임포트 패턴이 일관성 있게 적용되어 있습니다.
src/_apis/crew/get-my-crew-participation-list.ts (1)
1-2: 타입 정의 확인 필요
MyCrewListResponse와 PageableTypes 타입이 올바르게 정의되어 있는지 확인이 필요합니다.
src/app/(crew)/my-crew/layout.tsx (1)
1-7: 코드가 잘 구성되어 있습니다!
컴포넌트 선언과 import문이 Next.js의 클라이언트 컴포넌트 패턴을 잘 따르고 있습니다.
src/_queries/crew-queries.tsx (2)
1-8: 코드가 깔끔하게 구성되어 있습니다!
import 문과 타입 정의가 잘 구성되어 있으며, 필요한 의존성들이 명확하게 정의되어 있습니다.
24-24: 에러 메시지가 더 정확해졌습니다!
"Response is null" 에서 "Response is undefined"로 변경한 것이 TypeScript의 타입 시스템과 더 잘 부합합니다.
src/components/common/crew-list/crew-card.tsx (1)
13-13: 인터페이스 변경이 적절합니다!
inWhere 프로퍼티의 타입을 확장하여 'main-crew'를 추가한 것은 컴포넌트의 재사용성을 높이는 좋은 접근입니다.
| import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll'; | ||
| import CrewCardList from '@/src/components/common/crew-list/crew-card-list'; | ||
|
|
||
| export default function MyCrewParticipationPage() { |
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.
컴포넌트 이름과 디렉토리 위치가 일치하지 않습니다.
현재 컴포넌트 이름은 MyCrewParticipationPage이지만 creation 디렉토리에 위치해 있습니다. 컴포넌트의 실제 목적에 맞게 이름을 변경하는 것이 좋겠습니다.
다음과 같이 수정하는 것을 제안드립니다:
-export default function MyCrewParticipationPage() {
+export default function MyCrewCreationPage() {📝 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 default function MyCrewParticipationPage() { | |
| export default function MyCrewCreationPage() { |
| export default function MyCrewParticipationPage() { | ||
| const { data, ref, isFetchingNextPage } = useInfiniteScroll(useGetMyCrewCreationQuery()); | ||
| return ( | ||
| <div> | ||
| <CrewCardList | ||
| inWhere="my-crew" | ||
| data={data ?? { pages: [], pageParams: [] }} | ||
| ref={ref} | ||
| isFetchingNextPage={isFetchingNextPage} | ||
| /> | ||
| </div> | ||
| ); | ||
| } |
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 default function MyCrewParticipationPage() {
- const { data, ref, isFetchingNextPage } = useInfiniteScroll(useGetMyCrewCreationQuery());
+ const { data, ref, isFetchingNextPage, isError, error, isLoading } = useInfiniteScroll(useGetMyCrewCreationQuery());
+
+ if (isError) {
+ return <div>에러가 발생했습니다: {error.message}</div>;
+ }
+
+ if (isLoading) {
+ return <div>로딩 중...</div>;
+ }
return (
<div>
<CrewCardList
inWhere="my-crew"
data={data ?? { pages: [], pageParams: [] }}
ref={ref}
isFetchingNextPage={isFetchingNextPage}
/>
</div>
);
}Committable suggestion skipped: line range outside the PR's diff.
| export async function getMyCrewCreationList(pageable: PageableTypes) { | ||
| const { page, size, sort = ['string'] } = pageable; | ||
|
|
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']의 기본값이 적절하지 않아 보입니다. API에서 실제로 지원하는 정렬 필드값으로 설정하는 것이 좋습니다.
다음과 같이 수정하는 것을 제안드립니다:
- const { page, size, sort = ['string'] } = pageable;
+ const { page, size, sort = ['createdAt'] } = pageable; // 또는 API가 지원하는 다른 정렬 필드Committable suggestion skipped: line range outside the PR's diff.
| try { | ||
| const response = await fetchApi<MyCrewListResponse>( | ||
| `/api/crews/hosted?page=${page}&size=${size}&sort=${sort}`, | ||
| { | ||
| method: 'GET', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| credentials: 'include', // 인증 정보를 요청에 포함 | ||
| }, | ||
| ); | ||
| return response; | ||
| } catch (error) { | ||
| // 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.
🛠️ Refactor suggestion
에러 처리를 개선해주세요
현재 구현된 에러 처리에 대해 몇 가지 개선사항을 제안드립니다:
- console.error 대신 적절한 에러 로깅 서비스를 사용하는 것이 좋습니다
- undefined 반환보다는 구체적인 에러 상태를 전달하는 것이 좋습니다
- 네트워크 오류와 같은 특정 에러 케이스에 대한 처리가 필요합니다
다음과 같은 개선된 구현을 제안드립니다:
try {
const response = await fetchApi<MyCrewListResponse>(
`/api/crews/hosted?page=${page}&size=${size}&sort=${sort}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
},
);
return response;
} catch (error) {
- // eslint-disable-next-line no-console
- console.error(error);
- return undefined;
+ if (error instanceof Error) {
+ throw new Error(`크루 목록을 가져오는데 실패했습니다: ${error.message}`);
+ }
+ throw new Error('알 수 없는 에러가 발생했습니다');
}📝 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.
| try { | |
| const response = await fetchApi<MyCrewListResponse>( | |
| `/api/crews/hosted?page=${page}&size=${size}&sort=${sort}`, | |
| { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| credentials: 'include', // 인증 정보를 요청에 포함 | |
| }, | |
| ); | |
| return response; | |
| } catch (error) { | |
| // eslint-disable-next-line no-console | |
| console.error(error); | |
| return undefined; | |
| } | |
| } | |
| try { | |
| const response = await fetchApi<MyCrewListResponse>( | |
| `/api/crews/hosted?page=${page}&size=${size}&sort=${sort}`, | |
| { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| credentials: 'include', // 인증 정보를 요청에 포함 | |
| }, | |
| ); | |
| return response; | |
| } catch (error) { | |
| if (error instanceof Error) { | |
| throw new Error(`크루 목록을 가져오는데 실패했습니다: ${error.message}`); | |
| } | |
| throw new Error('알 수 없는 에러가 발생했습니다'); | |
| } | |
| } |
| const response = await fetchApi<MyCrewListResponse>( | ||
| `/api/crews/hosted?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.
💡 Codebase verification
Swagger/OpenAPI 문서에 /api/crews/hosted 엔드포인트가 누락되었습니다
API 엔드포인트가 Swagger/OpenAPI 문서에 포함되지 않았습니다. 문서를 추가하여 API 사용에 대한 명확한 가이드를 제공해 주세요.
🔗 Analysis chain
API 엔드포인트 검증이 필요합니다
API 엔드포인트가 백엔드 구현과 일치하는지 확인이 필요합니다.
Swagger/OpenAPI 문서 확인을 위한 추가 검증이 필요합니다
Swagger/OpenAPI 문서 재검색이 필요합니다
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# API 엔드포인트 정의 확인
rg -g "*.ts" -g "*.js" "/api/crews/hosted"
# Swagger/OpenAPI 문서 확인
fd -g "swagger*.{json,yaml}" -g "openapi*.{json,yaml}"
Length of output: 317
Script:
#!/bin/bash
# 모든 문서 파일에서 API 엔드포인트 확인
rg "/api/crews/hosted"
# 다양한 문서 파일 검색
fd -g "*{api,swagger,openapi}*.{json,yaml,md}"
Length of output: 181
Script:
#!/bin/bash
# 모든 파일에서 API 엔드포인트 확인
rg "/api/crews/hosted"
# 다양한 문서 형식에서 API 관련 내용 검색
rg "/api/crews/hosted" --type md --type json --type yaml
Length of output: 189
| const handleTabClick = (id: string) => { | ||
| const targetRoute = myCrewTabs.find((tab) => tab.id === id)?.route; | ||
| if (targetRoute) router.push(targetRoute); | ||
| }; |
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
에러 처리 개선이 필요합니다
targetRoute가 없는 경우에 대한 처리가 누락되어 있습니다. 사용자에게 적절한 피드백을 제공하는 것이 좋습니다.
다음과 같이 수정해보세요:
const handleTabClick = (id: string) => {
const targetRoute = myCrewTabs.find((tab) => tab.id === id)?.route;
- if (targetRoute) router.push(targetRoute);
+ if (targetRoute) {
+ router.push(targetRoute);
+ } else {
+ console.error(`탭 ID ${id}에 해당하는 경로를 찾을 수 없습니다.`);
+ // TODO: 사용자에게 에러 메시지 표시
+ }
};Committable suggestion skipped: line range outside the PR's diff.
src/_queries/crew-queries.tsx
Outdated
| export function useGetMyCrewCreationQuery() { | ||
| return { | ||
| queryKey: ['my-crew-creation'], | ||
| queryFn: ({ pageParam = 0 }) => | ||
| getMyCrewCreationList({ page: pageParam, size: 6, sort: ['string'] }).then((response) => { | ||
| if (response === undefined) { | ||
| throw new Error('Response is undefined'); | ||
| } | ||
| return response; | ||
| }), | ||
| getNextPageParam: (lastPage: MyCrewListResponse, allPages: MyCrewListResponse[]) => | ||
| lastPage.hasNext ? allPages.length : 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.
🛠️ Refactor suggestion
참여 쿼리와 동일한 개선이 필요합니다.
앞서 언급된 동일한 문제점들이 있습니다:
- sort 매개변수가 하드코딩되어 있습니다
- size가 고정되어 있습니다
참여 쿼리와 동일한 방식으로 개선하는 것을 제안드립니다:
-export function useGetMyCrewCreationQuery() {
+export function useGetMyCrewCreationQuery(
+ options?: {
+ sortBy?: string[];
+ pageSize?: number;
+ }
+) {
+ const { sortBy = ['createdAt'], pageSize = 6 } = options ?? {};
return {
queryKey: ['my-crew-creation'],
queryFn: ({ pageParam = 0 }) =>
- getMyCrewCreationList({ page: pageParam, size: 6, sort: ['string'] }).then((response) => {
+ getMyCrewCreationList({ page: pageParam, size: pageSize, sort: sortBy }).then((response) => {추가로, 두 쿼리 훅이 매우 유사한 구조를 가지고 있으므로, 공통 로직을 추출하여 재사용할 수 있는 유틸리티 함수를 만드는 것도 고려해보시면 좋을 것 같습니다.
📝 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 function useGetMyCrewCreationQuery() { | |
| return { | |
| queryKey: ['my-crew-creation'], | |
| queryFn: ({ pageParam = 0 }) => | |
| getMyCrewCreationList({ page: pageParam, size: 6, sort: ['string'] }).then((response) => { | |
| if (response === undefined) { | |
| throw new Error('Response is undefined'); | |
| } | |
| return response; | |
| }), | |
| getNextPageParam: (lastPage: MyCrewListResponse, allPages: MyCrewListResponse[]) => | |
| lastPage.hasNext ? allPages.length : undefined, | |
| }; | |
| } | |
| export function useGetMyCrewCreationQuery( | |
| options?: { | |
| sortBy?: string[]; | |
| pageSize?: number; | |
| } | |
| ) { | |
| const { sortBy = ['createdAt'], pageSize = 6 } = options ?? {}; | |
| return { | |
| queryKey: ['my-crew-creation'], | |
| queryFn: ({ pageParam = 0 }) => | |
| getMyCrewCreationList({ page: pageParam, size: pageSize, sort: sortBy }).then((response) => { | |
| if (response === undefined) { | |
| throw new Error('Response is undefined'); | |
| } | |
| return response; | |
| }), | |
| getNextPageParam: (lastPage: MyCrewListResponse, allPages: MyCrewListResponse[]) => | |
| lastPage.hasNext ? allPages.length : undefined, | |
| }; | |
| } |
src/_queries/crew-queries.tsx
Outdated
| return { | ||
| queryKey: ['my-crew-participation'], | ||
| queryFn: ({ pageParam = 0 }) => | ||
| getMyCrewParticipationList({ page: pageParam, size: 6, sort: ['string'] }).then( | ||
| (response) => { | ||
| if (response === undefined) { | ||
| throw new Error('Response is undefined'); | ||
| } | ||
| return response; | ||
| }, | ||
| ), | ||
| getNextPageParam: (lastPage: MyCrewListResponse, allPages: MyCrewListResponse[]) => | ||
| lastPage.hasNext ? allPages.length : 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.
🛠️ Refactor suggestion
정렬 매개변수와 페이지 크기를 구성 가능하게 개선해보세요.
현재 코드에서 개선이 필요한 부분들이 있습니다:
- sort 매개변수가 ['string']으로 하드코딩되어 있습니다
- size가 6으로 고정되어 있습니다
다음과 같이 개선하는 것을 제안드립니다:
-export function useGetMyCrewParticipationQuery() {
+export function useGetMyCrewParticipationQuery(
+ options?: {
+ sortBy?: string[];
+ pageSize?: number;
+ }
+) {
+ const { sortBy = ['createdAt'], pageSize = 6 } = options ?? {};
return {
queryKey: ['my-crew-participation'],
queryFn: ({ pageParam = 0 }) =>
- getMyCrewParticipationList({ page: pageParam, size: 6, sort: ['string'] }).then(
+ getMyCrewParticipationList({ page: pageParam, size: pageSize, sort: sortBy }).then(Committable suggestion skipped: line range outside the PR's diff.
| interface CrewCardListProps { | ||
| data: InfiniteData<MainCrewListResponse | MyCrewListResponse | undefined>; | ||
| isFetchingNextPage: boolean; | ||
| inWhere?: undefined; | ||
| inWhere?: 'my-crew' | 'main-crew'; |
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.
타입 안전성 개선이 필요합니다.
inWhere 프로퍼티에서 undefined 타입이 제거되었는데, 이는 상위 컴포넌트에서 해당 prop을 필수로 전달해야 함을 의미합니다. 기존 코드와의 호환성 문제가 발생할 수 있습니다.
다음과 같이 수정하는 것을 제안드립니다:
interface CrewCardListProps {
data: InfiniteData<MainCrewListResponse | MyCrewListResponse | undefined>;
isFetchingNextPage: boolean;
- inWhere?: 'my-crew' | 'main-crew';
+ inWhere: 'my-crew' | 'main-crew' | undefined;
}Committable suggestion skipped: line range outside the PR's diff.
| ? data?.pages.flatMap((page) => page?.content 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
타입 가드를 추가하여 런타임 안전성을 개선해주세요.
현재 타입 단언(type assertion)을 사용하고 있는데, 이는 런타임에서 타입 안전성을 보장하지 않습니다.
다음과 같이 타입 가드를 추가하는 것을 추천드립니다:
const crewDataList =
- (inWhere === 'my-crew'
- ? data?.pages.flatMap((page) => page?.content as MyCrewList[])
- : data?.pages?.flatMap((page) => page?.content as MainCrewList[])) ?? [];
+ (inWhere === 'my-crew'
+ ? data?.pages.flatMap((page) =>
+ Array.isArray(page?.content) && page.content.every(item => 'currentCount' in item)
+ ? page.content
+ : []
+ )
+ : data?.pages?.flatMap((page) =>
+ Array.isArray(page?.content) && page.content.every(item => 'isConfirmed' in item)
+ ? page.content
+ : []
+ )) ?? [];📝 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.
| ? data?.pages.flatMap((page) => page?.content as MyCrewList[]) | |
| : data?.pages?.flatMap((page) => page?.content as MainCrewList[])) ?? []; | |
| (inWhere === 'my-crew' | |
| ? data?.pages.flatMap((page) => | |
| Array.isArray(page?.content) && page.content.every(item => 'currentCount' in item) | |
| ? page.content | |
| : [] | |
| ) | |
| : data?.pages?.flatMap((page) => | |
| Array.isArray(page?.content) && page.content.every(item => 'isConfirmed' in item) | |
| ? page.content | |
| : [] | |
| )) ?? []; |
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: 7
🧹 Outside diff range and nitpick comments (6)
src/_queries/crew/my-crew-creation-list-query.ts (2)
9-13: 에러 처리를 개선해주세요.현재 구현된 에러 처리가 너무 단순합니다. 사용자에게 더 명확한 에러 메시지를 제공하면 좋을 것 같습니다.
다음과 같은 개선을 제안드립니다:
- if (response === undefined) { - throw new Error('Response is undefined'); - } - return response; + if (response === undefined) { + throw new Error('크루 목록을 불러오는데 실패했습니다. 잠시 후 다시 시도해주세요.'); + } + return response;
4-17: React Query 설정을 보완해주세요.무한 스크롤 구현 시 사용자 경험 향상을 위해 다음 설정들을 추가하면 좋을 것 같습니다:
- 재시도 로직
- 캐시 설정
- 에러 바운더리 처리
다음과 같은 개선을 제안드립니다:
export function useGetMyCrewCreationQuery() { return { queryKey: ['my-crew-creation'], + retry: 1, + staleTime: 5 * 60 * 1000, // 5분 + cacheTime: 30 * 60 * 1000, // 30분 queryFn: ({ pageParam = 0 }) =>src/_apis/crew/my-crew-participation-list.ts (1)
15-15: 인증 관련 주석을 영문으로 변경해주세요.코드 일관성을 위해 한글 주석을 영문으로 변경하는 것이 좋겠습니다.
- credentials: 'include', // 인증 정보를 요청에 포함 + credentials: 'include', // Include authentication information in the requestsrc/_queries/crew/crew-list-queries.tsx (1)
17-17: 에러 메시지를 더 구체적으로 개선하면 좋을 것 같습니다.디버깅을 용이하게 하기 위해 에러 메시지에 컨텍스트 정보를 추가하는 것이 좋습니다.
다음과 같이 개선하는 것을 제안드립니다:
- throw new Error('Response is undefined'); + throw new Error(`크루 목록 조회 응답이 undefined입니다. 조건: ${JSON.stringify(condition)}`);src/app/_components/find-crew/find-crew.tsx (2)
Line range hint
41-47: 검색 기능 최적화 제안현재 검색 기능이 즉시 실행되고 있습니다. 성능 최적화를 위해 debounce를 적용하는 것이 좋을 것 같습니다.
다음과 같이 개선해보시는 건 어떨까요?:
+ import { useDebouncedCallback } from 'use-debounce'; const handleSearch = () => { if (searchRef.current) { setMainCategory(''); setSubCategory(''); - setSearch(searchRef.current.value); + debouncedSearch(searchRef.current.value); } }; + const debouncedSearch = useDebouncedCallback( + (value: string) => { + setSearch(value); + }, + 500 + );
Line range hint
41-47: 상태 업데이트 최적화 제안검색 시 여러 상태(mainCategory, subCategory, search)를 개별적으로 업데이트하고 있어 불필요한 리렌더링이 발생할 수 있습니다.
상태 업데이트를 하나로 묶어서 처리하는 것을 제안드립니다:
const handleSearch = () => { if (searchRef.current) { - setMainCategory(''); - setSubCategory(''); - setSearch(searchRef.current.value); + setSearchState({ + mainCategory: '', + subCategory: '', + search: searchRef.current.value + }); } }; + const setSearchState = (state: { + mainCategory: string; + subCategory: string; + search: string; + }) => { + setMainCategory(state.mainCategory); + setSubCategory(state.subCategory); + setSearch(state.search); + };Also applies to: 71-82
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (10)
src/_apis/crew/my-crew-creation-list.ts(1 hunks)src/_apis/crew/my-crew-participation-list.ts(1 hunks)src/_queries/crew/crew-list-queries.tsx(2 hunks)src/_queries/crew/my-crew-creation-list-query.ts(1 hunks)src/_queries/crew/my-crew-participation-list-query.ts(1 hunks)src/app/(crew)/my-crew/creation/page.tsx(1 hunks)src/app/(crew)/my-crew/participation/page.tsx(1 hunks)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.stories.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/app/(crew)/my-crew/creation/page.tsx
- src/app/(crew)/my-crew/participation/page.tsx
🔇 Additional comments (10)
src/app/(crew)/page.tsx (2)
Line range hint 1-24: 구현이 깔끔하고 잘 되어있습니다.
- 서버 컴포넌트에서 초기 데이터를 가져오는 방식이 적절합니다.
- 페이지네이션 파라미터와 검색 조건이 명확하게 구조화되어 있습니다.
- 무한 스크롤을 위한 데이터 구조가 잘 설계되어 있습니다.
1-1: API 모듈 경로 변경이 일관되게 적용되었는지 확인이 필요합니다.
API 모듈의 경로가 변경되었습니다. 이러한 변경이 다른 파일들에서도 일관되게 적용되었는지 확인이 필요합니다.
다음 스크립트를 실행하여 이전 경로를 사용하는 파일이 있는지 확인하겠습니다:
✅ Verification successful
Let me verify if there are any other files that might be using similar import patterns by searching more broadly.
API 모듈 경로 변경이 정상적으로 완료되었습니다.
검증 결과, 이전 경로(get-crew-list)를 사용하는 파일이 없으며, 새로운 경로(crew-list)가 일관되게 적용되어 있습니다. 다음 파일들이 새로운 경로를 올바르게 사용하고 있습니다:
- src/_apis/crew/crew-list.ts (API 구현 파일)
- src/_queries/crew/crew-list-queries.tsx (쿼리 관련 파일)
- src/app/(crew)/page.tsx (페이지 컴포넌트)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: 이전 API 경로를 사용하는 파일 검색
echo "이전 경로 사용 확인:"
rg -l "from ['\"']@/src/_apis/crew/get-crew-list"
echo "\n새 경로 사용 확인:"
rg -l "from ['\"']@/src/_apis/crew/crew-list"
Length of output: 245
Script:
#!/bin/bash
# 더 넓은 범위로 crew-list 관련 파일들을 검색
echo "crew-list 관련 모든 파일 검색:"
fd "crew-list" --type f
echo "\n_apis/crew 디렉토리의 파일 목록:"
ls -la src/_apis/crew/
echo "\nget-crew-list 문자열을 포함하는 모든 파일:"
rg "get-crew-list"
Length of output: 647
src/_queries/crew/my-crew-creation-list-query.ts (1)
4-17: React Query 패턴이 잘 구현되어 있습니다.
무한 스크롤을 위한 기본적인 구조가 잘 갖춰져 있습니다.
src/_queries/crew/my-crew-participation-list-query.ts (1)
1-3: 필요한 의존성이 올바르게 임포트되었습니다!
API 함수와 타입 정의가 명확하게 임포트되어 있습니다.
src/_apis/crew/my-crew-creation-list.ts (1)
1-2: 타입 정의와 유틸리티 임포트가 적절합니다!
필요한 타입과 유틸리티가 명확하게 임포트되어 있습니다.
src/_apis/crew/my-crew-participation-list.ts (1)
1-2: 타입 안전성 개선이 필요합니다.
MyCrewListResponse 타입이 임포트되어 있지만, API 응답의 구체적인 형태를 알 수 없습니다. 타입 정의를 명시적으로 문서화하는 것이 좋겠습니다.
✅ Verification successful
타입 정의가 명확하게 되어있습니다.
MyCrewListResponse 타입이 crew-card.d.ts 파일에 명시적으로 정의되어 있으며, 응답 데이터의 구조가 명확합니다:
content:MyCrewList[]타입의 배열 또는undefinedhasNext: 페이지네이션을 위한 불리언 값
타입 안전성이 적절히 보장되어 있어 별도의 개선이 필요하지 않습니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check the type definition of MyCrewListResponse
rg -t typescript "type MyCrewListResponse" src/types/
Length of output: 90
Script:
#!/bin/bash
# Search for MyCrewListResponse type definition with ripgrep
rg "MyCrewListResponse" --type-add 'ts:*.{ts,tsx}' --type ts
# Also check for interface definition
rg "interface MyCrewListResponse" --type-add 'ts:*.{ts,tsx}' --type ts
# Search for the file that might contain the type
fd "crew-card.ts"
Length of output: 1513
Script:
#!/bin/bash
# Check the content of the type definition file
cat src/types/crew-card.d.ts
Length of output: 1401
src/_queries/crew/crew-list-queries.tsx (1)
1-1: 상대 경로에서 절대 경로로의 변경이 적절합니다.
절대 경로를 사용하면 파일 구조 변경 시 더 유연하게 대응할 수 있으며, 코드의 가독성도 향상됩니다.
src/components/common/crew-list/crew-card-list.stories.tsx (2)
4-4: 쿼리 import 경로 변경이 적절합니다.
쿼리 관련 코드의 구조가 더 체계적으로 개선되었습니다. 크루 관련 쿼리들을 별도의 디렉토리로 분리한 것이 코드 구조를 더 명확하게 만들었습니다.
4-4: 다른 파일들에서도 import 경로가 일관되게 변경되었는지 확인이 필요합니다.
다음 스크립트를 실행하여 프로젝트 전체에서 이전 import 경로를 사용하는 파일이 있는지 확인해주세요:
✅ Verification successful
Let me verify if there are any other crew-related query imports in the codebase to ensure we haven't missed anything.
모든 crew 관련 쿼리 import가 새로운 경로로 올바르게 사용되고 있습니다.
검증 결과, 모든 파일에서 새로운 경로 구조(@/src/_queries/crew/)를 일관되게 사용하고 있으며, 이전 import 경로를 사용하는 파일이 없음을 확인했습니다. 다음 파일들이 모두 올바른 import 경로를 사용하고 있습니다:
- src/components/common/crew-list/crew-card-list.stories.tsx
- src/app/_components/find-crew/find-crew.tsx
- src/app/(crew)/my-crew/creation/page.tsx
- src/app/(crew)/my-crew/participation/page.tsx
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: 이전 import 경로를 사용하는 파일 검색
echo "이전 import 경로 사용 확인:"
rg "from ['|\"]@/src/_queries/crew-queries['|\"]"
echo -e "\n새로운 import 경로 사용 확인:"
rg "from ['|\"]@/src/_queries/crew/crew-list-queries['|\"]"
Length of output: 484
Script:
#!/bin/bash
# Description: crew 관련 쿼리 import 전체 검색
echo "crew 관련 모든 쿼리 import 검색:"
rg "from ['|\"]@/src/_queries/crew" -A 1
echo -e "\n_queries 디렉토리 내의 crew 관련 파일 확인:"
fd . "src/_queries" --type f | grep -i "crew"
Length of output: 1364
src/app/_components/find-crew/find-crew.tsx (1)
7-7: 쿼리 파일 구조 변경 검증 필요
쿼리 파일의 구조가 더 체계적으로 개선되었습니다. 다만, 다른 컴포넌트들도 이 새로운 경로를 일관되게 사용하고 있는지 확인이 필요합니다.
✅ Verification successful
쿼리 파일 구조 변경이 적절하게 이루어짐
쿼리 파일이 src/_queries/crew/crew-list-queries.tsx로 체계적으로 구조화되었으며, 이를 사용하는 모든 컴포넌트들(find-crew.tsx와 crew-card-list.stories.tsx)이 새로운 경로를 일관되게 사용하고 있습니다. 이전 경로(crew-queries)를 사용하는 파일이 없어 마이그레이션이 완전히 이루어진 것으로 확인됩니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: 기존 crew-queries 임포트 사용 여부 확인
# Test: 이전 경로를 사용하는 파일 검색
rg -l "@/src/_queries/crew-queries"
# Test: 새로운 경로를 사용하는 파일 검색
rg -l "@/src/_queries/crew/crew-list-queries"
Length of output: 184
Script:
#!/bin/bash
# Description: 쿼리 파일 구조 변경 관련 추가 검증
# Test 1: crew 관련 쿼리 파일들의 위치 확인
fd "crew.*queries" src/_queries -t f
# Test 2: crew-list-queries 파일 내용 확인
rg "useGetCrewListQuery" -A 5 -B 5
# Test 3: 다른 crew 관련 쿼리 사용 패턴 확인
rg "use.*CrewQuery" --type ts
Length of output: 4587
| return { | ||
| queryKey: ['my-crew-creation'], | ||
| queryFn: ({ pageParam = 0 }) => | ||
| getMyCrewCreationList({ page: pageParam, size: 6, sort: ['string'] }).then((response) => { |
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']으로 하드코딩되어 있습니다. 이는 실제 정렬 로직에 문제를 일으킬 수 있습니다.
다음과 같이 수정하는 것을 제안드립니다:
- getMyCrewCreationList({ page: pageParam, size: 6, sort: ['string'] }).then((response) => {
+ getMyCrewCreationList({ page: pageParam, size: 6, sort: ['createdAt,DESC'] }).then((response) => {📝 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.
| getMyCrewCreationList({ page: pageParam, size: 6, sort: ['string'] }).then((response) => { | |
| getMyCrewCreationList({ page: pageParam, size: 6, sort: ['createdAt,DESC'] }).then((response) => { |
| export function useGetMyCrewParticipationQuery() { | ||
| return { | ||
| queryKey: ['my-crew-participation'], | ||
| queryFn: ({ pageParam = 0 }) => | ||
| getMyCrewParticipationList({ page: pageParam, size: 6, sort: ['string'] }).then( | ||
| (response) => { | ||
| if (response === undefined) { | ||
| throw new Error('Response is undefined'); | ||
| } | ||
| return response; | ||
| }, | ||
| ), | ||
| getNextPageParam: (lastPage: MyCrewListResponse, allPages: MyCrewListResponse[]) => | ||
| lastPage.hasNext ? allPages.length : 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.
🛠️ Refactor suggestion
쿼리 구현에 대한 몇 가지 개선사항이 있습니다.
다음 사항들을 검토해주시기 바랍니다:
sort파라미터가['string']으로 하드코딩되어 있는데, 이는 올바른 정렬 기준이 아닌 것 같습니다.- 페이지 크기(
size: 6)가 하드코딩되어 있어 재사용성이 제한됩니다. - 에러 처리가 너무 일반적입니다.
다음과 같이 개선하는 것을 제안드립니다:
-export function useGetMyCrewParticipationQuery() {
+export function useGetMyCrewParticipationQuery({
+ pageSize = 6,
+ sortOrder = ['createdAt,desc']
+}: {
+ pageSize?: number;
+ sortOrder?: string[];
+} = {}) {
return {
queryKey: ['my-crew-participation'],
queryFn: ({ pageParam = 0 }) =>
- getMyCrewParticipationList({ page: pageParam, size: 6, sort: ['string'] }).then(
+ getMyCrewParticipationList({ page: pageParam, size: pageSize, sort: sortOrder }).then(
(response) => {
if (response === undefined) {
- throw new Error('Response is undefined');
+ throw new Error('크루 참여 목록을 가져오는데 실패했습니다.');
}
return response;
},
),
getNextPageParam: (lastPage: MyCrewListResponse, allPages: MyCrewListResponse[]) =>
lastPage.hasNext ? allPages.length : undefined,
};
}추가로, 타입 안전성을 위해 API 응답 타입을 명시적으로 지정하는 것이 좋습니다:
queryFn: ({ pageParam = 0 }): Promise<MyCrewListResponse> => {| const response = await fetchApi<MyCrewListResponse>( | ||
| `/api/crews/hosted?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 쿼리 파라미터에 대한 인코딩이 누락되어 있습니다. 잠재적인 보안 위험을 방지하기 위해 encodeURIComponent를 사용하여 파라미터를 인코딩해주세요.
다음과 같이 수정을 제안드립니다:
- `/api/crews/hosted?page=${page}&size=${size}&sort=${sort}`,
+ `/api/crews/hosted?page=${encodeURIComponent(page)}&size=${encodeURIComponent(size)}&sort=${encodeURIComponent(sort.join(','))}`,Committable suggestion skipped: line range outside the PR's diff.
| } catch (error) { | ||
| // 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.
🛠️ Refactor suggestion
에러 처리 로직을 개선해주세요.
현재 에러 처리에 몇 가지 개선이 필요해 보입니다:
console.error는 프로덕션 환경에서 적절하지 않습니다- 에러 발생 시
undefined를 반환하면 타입 안전성이 저하됩니다 - 호출자에게 구체적인 에러 정보가 전달되지 않습니다
다음과 같은 개선된 구현을 제안드립니다:
- } catch (error) {
- // eslint-disable-next-line no-console
- console.error(error);
- return undefined;
+ } catch (error: unknown) {
+ 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.
| } catch (error) { | |
| // eslint-disable-next-line no-console | |
| console.error(error); | |
| return undefined; | |
| } | |
| } catch (error: unknown) { | |
| const errorMessage = error instanceof Error ? error.message : '크루 목록을 불러오는 중 오류가 발생했습니다'; | |
| throw new Error(errorMessage); | |
| } |
| import { MyCrewListResponse, PageableTypes } from '@/src/types/crew-card'; | ||
|
|
||
| export async function getMyCrewCreationList(pageable: PageableTypes) { | ||
| const { page, size, sort = ['string'] } = pageable; |
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
정렬 기본값 수정이 필요합니다
코드베이스 분석 결과, 다음과 같은 문제점들이 확인되었습니다:
['string']이라는 기본값이 여러 crew API 호출에서 동일하게 사용되고 있습니다find-crew컴포넌트에서는'latest'를 기본 정렬값으로 사용하고 있습니다ConditionTypes에서는sortType이'LATEST' | 'POPULAR'타입으로 정의되어 있습니다
개선 제안:
sort기본값을['createdAt,desc']와 같이 의미 있는 값으로 변경PageableTypes인터페이스의sort타입을 더 구체적으로 정의하여 유효한 정렬 옵션만 허용하도록 수정
🔗 Analysis chain
sort 매개변수의 기본값을 검토해주세요.
sort의 기본값으로 설정된 ['string']이 의미 있는 정렬 기준으로 보이지 않습니다. 다음과 같은 개선을 제안드립니다:
- 실제 정렬 기준(예: 'createdAt', 'name' 등)을 기본값으로 설정
- 정렬 기준에 대한 타입을 명시적으로 정의
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: 백엔드 API에서 지원하는 정렬 기준 확인
# API 문서나 관련 코드에서 정렬 옵션 검색
rg -t ts -t js "sort.*=.*\[.*\].*crews"
Length of output: 41
Script:
#!/bin/bash
# Let's check the file content and its imports to understand the context better
cat src/_apis/crew/my-crew-creation-list.ts
# Also search for any pageable interface or type definitions
rg -t ts "interface.*Pageable" -A 5
rg -t ts "type.*Pageable" -A 5
# Search for any usage of sort parameter in crew-related files
rg -t ts "sort.*crews?" src/_apis/crew/
Length of output: 1081
Script:
#!/bin/bash
# Let's check if there are any other crew list API calls that might show the sort parameter usage
rg -t ts "/api/crews.*sort" -B 2 -A 2
# Check for any constants or enums that might define sort options
rg -t ts "enum.*Sort" -A 5
rg -t ts "const.*sort.*=" -A 5
# Check the crew-card type file completely to understand the context better
cat src/types/crew-card.d.ts
Length of output: 4722
| export async function getMyCrewParticipationList(pageable: PageableTypes) { | ||
| const { page, size, sort = ['string'] } = pageable; |
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']으로 설정되어 있는데, 이는 실제 정렬에 적용하기에 적절하지 않은 값으로 보입니다. 유효한 정렬 기준을 기본값으로 설정하는 것이 좋겠습니다.
다음과 같이 수정을 제안드립니다:
- const { page, size, sort = ['string'] } = pageable;
+ const { page, size, sort = ['createdAt,desc'] } = pageable;📝 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 async function getMyCrewParticipationList(pageable: PageableTypes) { | |
| const { page, size, sort = ['string'] } = pageable; | |
| export async function getMyCrewParticipationList(pageable: PageableTypes) { | |
| const { page, size, sort = ['createdAt,desc'] } = pageable; |
| try { | ||
| const response = await fetchApi<MyCrewListResponse>( | ||
| `/api/crews/joined?page=${page}&size=${size}&sort=${sort}`, | ||
| { | ||
| method: 'GET', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| credentials: 'include', // 인증 정보를 요청에 포함 | ||
| }, | ||
| ); | ||
| return response; | ||
| } catch (error) { |
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
에러 처리 개선이 필요합니다.
현재 구현은 모든 에러를 콘솔에 출력하고 undefined를 반환하고 있습니다. 이는 다음과 같은 문제가 있습니다:
- 에러 타입에 따른 구체적인 처리가 없습니다
- 사용자에게 적절한 에러 메시지를 전달할 수 없습니다
다음과 같이 개선을 제안드립니다:
try {
const response = await fetchApi<MyCrewListResponse>(
`/api/crews/joined?page=${page}&size=${size}&sort=${sort}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
},
);
return response;
} catch (error) {
- // eslint-disable-next-line no-console
- console.error(error);
- return undefined;
+ if (error instanceof Error) {
+ throw new Error(`크루 참여 목록을 가져오는데 실패했습니다: ${error.message}`);
+ }
+ throw new Error('알 수 없는 에러가 발생했습니다');
}📝 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.
| try { | |
| const response = await fetchApi<MyCrewListResponse>( | |
| `/api/crews/joined?page=${page}&size=${size}&sort=${sort}`, | |
| { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| credentials: 'include', // 인증 정보를 요청에 포함 | |
| }, | |
| ); | |
| return response; | |
| } catch (error) { | |
| try { | |
| const response = await fetchApi<MyCrewListResponse>( | |
| `/api/crews/joined?page=${page}&size=${size}&sort=${sort}`, | |
| { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| credentials: 'include', | |
| }, | |
| ); | |
| return response; | |
| } catch (error) { | |
| if (error instanceof Error) { | |
| throw new Error(`크루 참여 목록을 가져오는데 실패했습니다: ${error.message}`); | |
| } | |
| throw new Error('알 수 없는 에러가 발생했습니다'); | |
| } |
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: 6
🧹 Outside diff range and nitpick comments (6)
src/_apis/crew/my-crew-hosted-list.ts (2)
14-14: 주석 개선 필요한글 주석이 간단한 설명만 포함하고 있습니다. 더 자세한 설명을 추가하면 좋을 것 같습니다.
다음과 같이 주석을 개선하는 것을 제안드립니다:
- credentials: 'include', // 인증 정보를 요청에 포함 + credentials: 'include', // 쿠키 기반 인증을 위해 credentials 포함 (JWT 토큰 전송)
8-8: URL 생성 방식 개선 필요URL 쿼리 파라미터를 템플릿 리터럴로 직접 구성하는 것은 특수 문자나 인코딩 문제를 발생시킬 수 있습니다.
URLSearchParams를 사용하여 URL을 구성하는 것을 추천드립니다:- `/api/crews/hosted?page=${page}&size=${size}&sort=${sort}`, + `/api/crews/hosted?${new URLSearchParams({ + page: page.toString(), + size: size.toString(), + sort: sort.join(','), + })}`,src/app/(crew)/my-crew/joined/page.tsx (2)
7-19: 로딩 및 에러 상태 처리 추가 필요현재 구현은 기본적인 기능은 잘 동작하지만, 사용자 경험 향상을 위해 다음 사항들을 고려해보시면 좋을 것 같습니다:
- 초기 로딩 상태 표시
- 에러 발생 시 처리 방법
- 데이터가 없을 때의 빈 상태 처리
다음과 같이 개선해보시는 건 어떨까요?:
export default function MyCrewParticipationPage() { - const { data, ref, isFetchingNextPage } = useInfiniteScroll(useGetMyCrewJoinedQuery()); + const { + data, + ref, + isFetchingNextPage, + isLoading, + error + } = useInfiniteScroll(useGetMyCrewJoinedQuery()); + + if (isLoading) return <LoadingSpinner />; + if (error) return <ErrorMessage message="크루 목록을 불러오는데 실패했습니다" />; + return ( <div> <CrewCardList inWhere="my-crew" data={data ?? { pages: [], pageParams: [] }} ref={ref} isFetchingNextPage={isFetchingNextPage} /> + {data?.pages[0]?.length === 0 && ( + <EmptyState message="참여중인 크루가 없습니다" /> + )} </div> ); }
7-19: 성능 최적화 제안크루 목록이 많아질 경우를 대비하여 다음과 같은 성능 최적화를 고려해보시면 좋을 것 같습니다:
- react-virtual이나 react-window 같은 가상화 라이브러리 도입 검토
- 불필요한 리렌더링 방지를 위한 메모이제이션 적용
이러한 최적화는 현재 당장 필요하지 않을 수 있지만, 추후 데이터가 늘어날 경우를 대비하여 미리 고려해보시면 좋을 것 같습니다.
src/_queries/crew/my-crew-hosted-list-query.ts (2)
6-6: queryKey 최적화 제안현재 queryKey가 정적으로 설정되어 있습니다. 페이지 크기나 정렬 기준이 변경될 경우를 대비하여, 이러한 매개변수들을 queryKey에 포함시키는 것이 좋습니다.
-queryKey: ['my-crew-creation'], +queryKey: ['my-crew-creation', 6, sort],
9-13: 에러 처리 개선 제안현재 에러 처리가 단순히 응답이 undefined인 경우만을 확인합니다. API 응답의 다양한 실패 케이스를 처리할 수 있도록 에러 처리를 보강하면 좋겠습니다.
-if (response === undefined) { - throw new Error('Response is undefined'); -} -return response; +if (!response) { + throw new Error('API 응답이 없습니다.'); +} +if ('error' in response) { + throw new Error(`API 오류: ${response.error}`); +} +return response;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (9)
src/_apis/crew/my-crew-hosted-list.ts(1 hunks)src/_apis/crew/my-crew-joined-list.ts(1 hunks)src/_queries/crew/my-crew-hosted-list-query.ts(1 hunks)src/_queries/crew/my-crew-joined-list-query.ts(1 hunks)src/app/(crew)/my-crew/hosted/page.tsx(1 hunks)src/app/(crew)/my-crew/joined/page.tsx(1 hunks)src/app/(crew)/my-crew/layout.tsx(1 hunks)src/app/(crew)/my-crew/page.tsx(1 hunks)src/components/common/crew-list/crew-card-list.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/app/(crew)/my-crew/layout.tsx
- src/app/(crew)/my-crew/page.tsx
- src/components/common/crew-list/crew-card-list.tsx
🔇 Additional comments (6)
src/_apis/crew/my-crew-hosted-list.ts (1)
5-5: sort 기본값 검토 필요
sort 매개변수의 기본값으로 ['string']을 사용하는 것이 적절해 보이지 않습니다. 정렬 기준을 더 명확하게 지정하는 것이 좋을 것 같습니다.
다음 스크립트를 실행하여 다른 API에서 사용되는 정렬 기준을 확인해보세요:
✅ Verification successful
sort 매개변수의 기본값이 적절합니다
PageableTypes 인터페이스에 따르면 sort 필드가 string[] 타입으로 정의되어 있으며, 다른 API 엔드포인트들도 동일한 기본값 ['string']을 사용하고 있습니다. 이는 일관된 패턴이며 타입 정의와도 일치합니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# API 엔드포인트에서 사용되는 정렬 기준 검색
rg -g "*.ts" -g "*.js" "sort.*=.*\[.*\]" ./src
Length of output: 320
Script:
#!/bin/bash
# Check the pageable type definition and usage
ast-grep --pattern 'type Pageable'
Length of output: 36
Script:
#!/bin/bash
# Check interface or type definitions related to pageable
rg -g "*.ts" "interface.*Pageable|type.*Pageable" -A 5
Length of output: 292
src/_apis/crew/my-crew-joined-list.ts (1)
1-2: 코드가 깔끔하고 명확합니다!
필요한 유틸리티와 타입들이 적절하게 임포트되어 있습니다.
src/app/(crew)/my-crew/hosted/page.tsx (1)
1-6: 코드 구성이 깔끔하고 명확합니다!
'use client' 지시문과 필요한 의존성들이 잘 정의되어 있습니다.
src/app/(crew)/my-crew/joined/page.tsx (1)
1-6: 의존성 선언이 적절합니다!
클라이언트 사이드 렌더링을 위한 'use client' 지시문과 필요한 커스텀 훅 및 컴포넌트들이 올바르게 임포트되어 있습니다.
src/_queries/crew/my-crew-joined-list-query.ts (2)
1-3: 임포트 구성이 적절합니다!
필요한 API 함수와 타입 정의가 명확하게 임포트되어 있습니다.
1-1: API 구현 확인이 필요합니다
getMyCrewJoinedList API 함수의 구현을 확인하여 타입 정의와 일치하는지 검증이 필요합니다.
✅ Verification successful
API 구현이 올바르게 되어있음을 확인했습니다
getMyCrewJoinedList API 함수가 다음과 같이 정확하게 구현되어 있습니다:
- 타입 정의(
MyCrewListResponse,PageableTypes)와 일치하는 구현 fetchApi유틸리티를 사용한 적절한 HTTP 요청 처리- 페이지네이션 파라미터 처리 및 응답 타입 검증
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# API 구현 확인
ast-grep --pattern 'export function getMyCrewJoinedList'
Length of output: 58
Script:
#!/bin/bash
# Search for API implementation file
fd "my-crew-joined-list" --type f
# Search for API function implementation with ripgrep for broader match
rg "getMyCrewJoinedList" -A 5
Length of output: 1668
Script:
#!/bin/bash
# Check type definitions
rg "MyCrewListResponse" -A 5
rg "PageableTypes" -A 5
# Check fetchApi implementation
rg "fetchApi" --type ts -A 5
Length of output: 15883
| const response: { data: MyCrewListResponse } = await fetchApi( | ||
| `/api/crews/hosted?page=${page}&size=${size}&sort=${sort}`, | ||
| { | ||
| method: 'GET', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| credentials: 'include', // 인증 정보를 요청에 포함 | ||
| }, | ||
| ); | ||
| return response.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.
에러 처리 로직 추가 필요
API 호출 실패 시 적절한 에러 처리가 없습니다. 네트워크 오류나 서버 오류에 대한 처리를 추가하는 것이 좋겠습니다.
다음과 같이 에러 처리를 추가하는 것을 제안드립니다:
export async function getMyCrewHostedList(pageable: PageableTypes) {
const { page, size, sort = ['string'] } = pageable;
- const response: { data: MyCrewListResponse } = await fetchApi(
- `/api/crews/hosted?page=${page}&size=${size}&sort=${sort}`,
- {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- },
- credentials: 'include', // 인증 정보를 요청에 포함
- },
- );
- return response.data;
+ try {
+ const response: { data: MyCrewListResponse } = await fetchApi(
+ `/api/crews/hosted?page=${page}&size=${size}&sort=${sort}`,
+ {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ credentials: 'include',
+ },
+ );
+ return response.data;
+ } catch (error) {
+ if (error instanceof Error) {
+ throw new Error(`내가 주최한 크루 목록을 가져오는데 실패했습니다: ${error.message}`);
+ }
+ throw error;
+ }
}📝 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 response: { data: MyCrewListResponse } = await fetchApi( | |
| `/api/crews/hosted?page=${page}&size=${size}&sort=${sort}`, | |
| { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| credentials: 'include', // 인증 정보를 요청에 포함 | |
| }, | |
| ); | |
| return response.data; | |
| } | |
| export async function getMyCrewHostedList(pageable: PageableTypes) { | |
| const { page, size, sort = ['string'] } = pageable; | |
| try { | |
| const response: { data: MyCrewListResponse } = await fetchApi( | |
| `/api/crews/hosted?page=${page}&size=${size}&sort=${sort}`, | |
| { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| credentials: 'include', | |
| }, | |
| ); | |
| return response.data; | |
| } catch (error) { | |
| if (error instanceof Error) { | |
| throw new Error(`내가 주최한 크루 목록을 가져오는데 실패했습니다: ${error.message}`); | |
| } | |
| throw error; | |
| } | |
| } |
| export async function getMyCrewJoinedList(pageable: PageableTypes) { | ||
| const { page, size, sort = ['string'] } = pageable; | ||
|
|
||
| const response: { data: MyCrewListResponse } = await fetchApi( | ||
| `/api/crews/joined?page=${page}&size=${size}&sort=${sort}`, | ||
| { | ||
| method: 'GET', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| credentials: 'include', // 인증 정보를 요청에 포함 | ||
| }, | ||
| ); | ||
| return response.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.
🛠️ Refactor suggestion
에러 처리와 코드 일관성 개선이 필요합니다.
다음과 같은 개선사항들을 제안드립니다:
- API 호출 실패 시 에러 처리 로직 추가
- 영어로 된 코드베이스 일관성을 위해 한글 주석을 영어로 변경
- 페이지네이션 파라미터 유효성 검사 추가
다음과 같이 수정해보시는 건 어떨까요?:
export async function getMyCrewJoinedList(pageable: PageableTypes) {
const { page, size, sort = ['string'] } = pageable;
+
+ if (page < 0 || size <= 0) {
+ throw new Error('Invalid pagination parameters');
+ }
- const response: { data: MyCrewListResponse } = await fetchApi(
- `/api/crews/joined?page=${page}&size=${size}&sort=${sort}`,
- {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- },
- credentials: 'include', // 인증 정보를 요청에 포함
- },
- );
- return response.data;
+ try {
+ const response: { data: MyCrewListResponse } = await fetchApi(
+ `/api/crews/joined?page=${page}&size=${size}&sort=${sort}`,
+ {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ credentials: 'include', // Include authentication information
+ },
+ );
+ return response.data;
+ } catch (error) {
+ throw new Error(`Failed to fetch joined crew list: ${error.message}`);
+ }
}📝 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 async function getMyCrewJoinedList(pageable: PageableTypes) { | |
| const { page, size, sort = ['string'] } = pageable; | |
| const response: { data: MyCrewListResponse } = await fetchApi( | |
| `/api/crews/joined?page=${page}&size=${size}&sort=${sort}`, | |
| { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| credentials: 'include', // 인증 정보를 요청에 포함 | |
| }, | |
| ); | |
| return response.data; | |
| } | |
| export async function getMyCrewJoinedList(pageable: PageableTypes) { | |
| const { page, size, sort = ['string'] } = pageable; | |
| if (page < 0 || size <= 0) { | |
| throw new Error('Invalid pagination parameters'); | |
| } | |
| try { | |
| const response: { data: MyCrewListResponse } = await fetchApi( | |
| `/api/crews/joined?page=${page}&size=${size}&sort=${sort}`, | |
| { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| credentials: 'include', // Include authentication information | |
| }, | |
| ); | |
| return response.data; | |
| } catch (error) { | |
| throw new Error(`Failed to fetch joined crew list: ${error.message}`); | |
| } | |
| } |
| const response: { data: MyCrewListResponse } = await fetchApi( | ||
| `/api/crews/joined?page=${page}&size=${size}&sort=${sort}`, | ||
| { | ||
| method: 'GET', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| credentials: 'include', // 인증 정보를 요청에 포함 | ||
| }, | ||
| ); |
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 응답에 대한 런타임 타입 검증이 필요합니다
현재 MyCrewListResponse 타입은 TypeScript 인터페이스로만 정의되어 있어, 런타임에서 실제 API 응답이 예상된 형식과 일치하는지 확인할 수 없습니다. 다음과 같은 개선이 필요합니다:
zod또는 유사한 런타임 타입 검증 라이브러리를 사용하여 API 응답 스키마를 정의하고 검증src/utils/api.ts의fetchApi함수에서 응답 데이터 검증 로직 추가MyCrewListResponse타입에 대한 검증 스키마 구현
예시 코드:
import { z } from 'zod';
const MyCrewListSchema = z.object({
content: z.array(MyCrewSchema),
hasNext: z.boolean()
});
// fetchApi 호출 후 데이터 검증
const validatedData = MyCrewListSchema.parse(response.data);🔗 Analysis chain
API 응답 타입 검증이 필요합니다.
API 응답의 타입 안전성을 보장하기 위해 런타임 타입 검증을 추가하는 것이 좋습니다.
Let's check the actual type definition and its usage to verify runtime type checking.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if MyCrewListResponse type is properly defined and used consistently
# Search for MyCrewListResponse type definition and usage
echo "Searching for type definition..."
rg "type MyCrewListResponse" -A 5
echo "Searching for type usage..."
rg "MyCrewListResponse"
Length of output: 1367
Script:
#!/bin/bash
# Check the MyCrewListResponse type definition and any runtime type validation
echo "Checking MyCrewListResponse type definition:"
rg -A 10 "interface MyCrewListResponse" src/types/crew-card.d.ts
echo "\nChecking for any runtime type validation (e.g., zod, io-ts):"
rg -l "zod|io-ts|runtypes|ajv|class-validator"
echo "\nChecking fetchApi implementation for any type validation:"
rg -A 10 "function fetchApi"
Length of output: 1523
| export default function MyCrewParticipationPage() { | ||
| const { data, ref, isFetchingNextPage } = useInfiniteScroll(useGetMyCrewHostedQuery()); | ||
| return ( | ||
| <div> | ||
| <CrewCardList | ||
| inWhere="my-crew" | ||
| data={data ?? { pages: [], pageParams: [] }} | ||
| ref={ref} | ||
| isFetchingNextPage={isFetchingNextPage} | ||
| /> | ||
| </div> | ||
| ); | ||
| } |
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 default function MyCrewParticipationPage() {
- const { data, ref, isFetchingNextPage } = useInfiniteScroll(useGetMyCrewHostedQuery());
+ const {
+ data,
+ ref,
+ isFetchingNextPage,
+ isError,
+ error,
+ isLoading
+ } = useInfiniteScroll(useGetMyCrewHostedQuery());
+
+ if (isLoading) {
+ return <div>로딩 중...</div>;
+ }
+
+ if (isError) {
+ return <div>에러가 발생했습니다: {error?.message}</div>;
+ }
return (
<div>
<CrewCardList
inWhere="my-crew"
data={data ?? { pages: [], pageParams: [] }}
ref={ref}
isFetchingNextPage={isFetchingNextPage}
/>
</div>
);
}📝 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 default function MyCrewParticipationPage() { | |
| const { data, ref, isFetchingNextPage } = useInfiniteScroll(useGetMyCrewHostedQuery()); | |
| return ( | |
| <div> | |
| <CrewCardList | |
| inWhere="my-crew" | |
| data={data ?? { pages: [], pageParams: [] }} | |
| ref={ref} | |
| isFetchingNextPage={isFetchingNextPage} | |
| /> | |
| </div> | |
| ); | |
| } | |
| export default function MyCrewParticipationPage() { | |
| const { | |
| data, | |
| ref, | |
| isFetchingNextPage, | |
| isError, | |
| error, | |
| isLoading | |
| } = useInfiniteScroll(useGetMyCrewHostedQuery()); | |
| if (isLoading) { | |
| return <div>로딩 중...</div>; | |
| } | |
| if (isError) { | |
| return <div>에러가 발생했습니다: {error?.message}</div>; | |
| } | |
| return ( | |
| <div> | |
| <CrewCardList | |
| inWhere="my-crew" | |
| data={data ?? { pages: [], pageParams: [] }} | |
| ref={ref} | |
| isFetchingNextPage={isFetchingNextPage} | |
| /> | |
| </div> | |
| ); | |
| } |
| return { | ||
| queryKey: ['my-crew-creation'], | ||
| queryFn: ({ pageParam = 0 }) => | ||
| getMyCrewHostedList({ page: pageParam, size: 6, sort: ['string'] }).then((response) => { |
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: ['string']은 올바른 정렬 매개변수가 아닌 것으로 보입니다. 정렬 기준을 명확하게 지정해주시거나, API 요구사항에 맞는 적절한 값으로 변경해주세요.
예시 수정안:
-sort: ['string']
+sort: ['createdAt,desc'] // 또는 API 요구사항에 맞는 다른 정렬 기준Committable suggestion skipped: line range outside the PR's diff.
| export function useGetMyCrewJoinedQuery() { | ||
| return { | ||
| queryKey: ['my-crew-participation'], | ||
| queryFn: ({ pageParam = 0 }) => | ||
| getMyCrewJoinedList({ page: pageParam, size: 6, sort: ['string'] }).then((response) => { | ||
| if (response === undefined) { | ||
| throw new Error('Response is undefined'); | ||
| } | ||
| return response; | ||
| }), | ||
| getNextPageParam: (lastPage: MyCrewListResponse, allPages: MyCrewListResponse[]) => | ||
| lastPage.hasNext ? allPages.length : 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.
🛠️ Refactor suggestion
쿼리 구성에 대한 개선 제안
현재 구현에서 다음과 같은 개선이 필요해 보입니다:
- 정렬 파라미터가
['string']으로 하드코딩되어 있습니다. - 페이지 크기(size)가 고정값 6으로 설정되어 있어 유연성이 떨어집니다.
- 에러 처리가 너무 일반적입니다.
다음과 같이 개선하는 것을 제안드립니다:
-export function useGetMyCrewJoinedQuery() {
+export function useGetMyCrewJoinedQuery({
+ pageSize = 6,
+ sortOption = ['createdAt,desc']
+}: {
+ pageSize?: number;
+ sortOption?: string[];
+} = {}) {
return {
- queryKey: ['my-crew-participation'],
+ queryKey: ['my-crew-participation', pageSize, sortOption],
queryFn: ({ pageParam = 0 }) =>
- getMyCrewJoinedList({ page: pageParam, size: 6, sort: ['string'] }).then((response) => {
+ getMyCrewJoinedList({ page: pageParam, size: pageSize, sort: sortOption }).then((response) => {
if (response === undefined) {
- throw new Error('Response is undefined');
+ throw new Error('크루 목록을 가져오는데 실패했습니다.');
}
return response;
}),
getNextPageParam: (lastPage: MyCrewListResponse, allPages: MyCrewListResponse[]) =>
lastPage.hasNext ? allPages.length : undefined,
};
}이렇게 수정하면:
- 페이지 크기와 정렬 옵션을 외부에서 설정할 수 있습니다.
- 쿼리 키가 설정값을 포함하여 더 정확한 캐시 관리가 가능합니다.
- 에러 메시지가 더 구체적으로 제공됩니다.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function useGetMyCrewJoinedQuery() { | |
| return { | |
| queryKey: ['my-crew-participation'], | |
| queryFn: ({ pageParam = 0 }) => | |
| getMyCrewJoinedList({ page: pageParam, size: 6, sort: ['string'] }).then((response) => { | |
| if (response === undefined) { | |
| throw new Error('Response is undefined'); | |
| } | |
| return response; | |
| }), | |
| getNextPageParam: (lastPage: MyCrewListResponse, allPages: MyCrewListResponse[]) => | |
| lastPage.hasNext ? allPages.length : undefined, | |
| }; | |
| } | |
| export function useGetMyCrewJoinedQuery({ | |
| pageSize = 6, | |
| sortOption = ['createdAt,desc'] | |
| }: { | |
| pageSize?: number; | |
| sortOption?: string[]; | |
| } = {}) { | |
| return { | |
| queryKey: ['my-crew-participation', pageSize, sortOption], | |
| queryFn: ({ pageParam = 0 }) => | |
| getMyCrewJoinedList({ page: pageParam, size: pageSize, sort: sortOption }).then((response) => { | |
| if (response === undefined) { | |
| throw new Error('크루 목록을 가져오는데 실패했습니다.'); | |
| } | |
| return response; | |
| }), | |
| getNextPageParam: (lastPage: MyCrewListResponse, allPages: MyCrewListResponse[]) => | |
| lastPage.hasNext ? allPages.length : 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.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (6)
src/_queries/crew/crew-list-queries.tsx(2 hunks)src/_queries/crew/my-crew-hosted-list-query.ts(1 hunks)src/_queries/crew/my-crew-joined-list-query.ts(1 hunks)src/app/(crew)/my-crew/hosted/page.tsx(1 hunks)src/app/(crew)/my-crew/joined/page.tsx(1 hunks)src/app/(crew)/page.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/_queries/crew/my-crew-hosted-list-query.ts
- src/app/(crew)/my-crew/hosted/page.tsx
- src/app/(crew)/my-crew/joined/page.tsx
🔇 Additional comments (7)
src/_queries/crew/my-crew-joined-list-query.ts (2)
10-13: 예외 처리 로직이 적절합니다.
응답이 undefined일 때 에러를 발생시키는 로직이 적절하게 구현되어 있습니다. 이는 데이터 불러오기 실패 시 명확한 에러 메시지를 제공하여 디버깅에 도움이 됩니다.
15-16: 페이지네이션 로직이 잘 구현되어 있습니다.
getNextPageParam 함수를 통해 다음 페이지가 있는지 여부를 판단하고, 있을 경우 총 페이지 수를 반환하는 로직이 적절합니다. 이는 무한 스크롤 구현에 필수적인 요소입니다.
src/_queries/crew/crew-list-queries.tsx (4)
1-1: 경로 업데이트 승인
getCrewList 함수의 가져오기 경로가 '@/src/_apis/crew/crew-list'로 변경되었습니다. 이는 프로젝트의 일관된 경로 구조를 따르는 것으로 보입니다.
21-30: API 호출 및 에러 처리 로직 검토
getCrewList API를 호출하고, 응답이 undefined일 경우 "Response is undefined"라는 에러를 발생시킵니다. 이는 에러 상황을 보다 명확하게 표현하며, 이전의 "Response is null" 메시지보다 개선된 점입니다. 그러나, 에러 메시지가 사용자에게 충분히 이해가능한지 추가적인 검토가 필요할 수 있습니다.
11-11: 기본값 설정 검토
pageable 객체에서 size와 sort를 추출하며, sort에는 기본값 ['string']이 설정되어 있습니다. 이 기본값이 적절한지 검토할 필요가 있습니다. 일반적으로 정렬 파라미터의 기본값은 데이터의 특성에 따라 결정되므로, 'string'이 적절한지 확인이 필요합니다.
#!/bin/bash
# 기본 정렬 파라미터 검증
echo "기본 정렬 파라미터: 'string'"4-10: 함수 시그니처 변경 검토
useGetCrewListQuery 함수의 시그니처가 { condition, pageable }: { condition: ConditionTypes; pageable: PageableTypes; }로 변경되었습니다. 이 변경은 함수의 사용성을 향상시키고, 더 명확한 파라미터 구조를 제공합니다. 변경된 시그니처가 다른 코드와의 호환성에 문제가 없는지 확인하는 것이 중요합니다.
src/app/(crew)/page.tsx (1)
40-47: 코드 구조 개선 확인
useGetCrewListQuery 함수의 파라미터 구조가 개선되어 가독성과 유지보수성이 향상되었습니다. 새로운 condition 객체와 pageable 객체를 통해 쿼리 파라미터를 더 명확하게 구분하고, 페이지네이션을 관리하는 방식이 추가되었습니다. 이 변경으로 인해 데이터 페칭 로직이 더욱 체계적으로 구성되었음을 확인할 수 있습니다.
| export function useGetMyCrewJoinedQuery({ pageable }: { pageable: PageableTypes }) { | ||
| const { size, sort = ['string'] } = pageable; | ||
| return { |
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
정렬 파라미터를 더 유연하게 설정하세요.
현재 정렬 파라미터가 ['string']으로 고정되어 있어 유연성이 떨어집니다. 이를 외부에서 입력받을 수 있도록 변경하는 것이 좋겠습니다. 예를 들어, 기본값을 ['createdAt,desc']로 설정하고, 필요에 따라 변경할 수 있도록 합니다.
minkyung5x5
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.
수고하셨습니다-!!!
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 (2)
src/_apis/crew/my-crew-hosted-list.ts (1)
4-5: 타입 안전성 개선이 필요합니다
sort파라미터의 기본값이['string']으로 설정되어 있는데, 이는 실제 사용되는 정렬 값을 명확하게 표현하지 못합니다.다음과 같이 개선하는 것을 제안드립니다:
+ type SortOption = 'createdAt' | 'name' | 'memberCount'; - export async function getMyCrewHostedList(pageable: PageableTypes) { - const { page, size, sort = ['string'] } = pageable; + export async function getMyCrewHostedList(pageable: Omit<PageableTypes, 'sort'> & { sort?: SortOption[] }) { + const { page, size, sort = ['createdAt'] } = pageable;src/components/common/input/pop-over-calendar/index.tsx (1)
47-47: className 문자열이 너무 길어 가독성이 떨어짐스타일링 코드가 인라인으로 작성되어 있어 컴포넌트의 로직을 파악하기 어렵습니다.
Tailwind CSS 클래스를 별도의 상수로 분리하거나, CSS 모듈을 사용하는 것을 추천드립니다:
const BUTTON_STYLES = { base: 'flex h-11 items-center justify-between rounded-xl border-0 px-3 py-2.5 text-base font-medium', default: 'bg-white text-gray-800 hover:bg-white hover:text-gray-800', focused: 'focus:bg-black focus:text-white' };그리고 컴포넌트에서는 다음과 같이 사용:
- className="flex h-11 items-center justify-between rounded-xl border-0 bg-white px-3 py-2.5 text-base font-medium text-gray-800 hover:bg-white hover:text-gray-800 focus:bg-black focus:text-white" + className={`${BUTTON_STYLES.base} ${BUTTON_STYLES.default} ${BUTTON_STYLES.focused}`}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
src/_apis/crew/my-crew-hosted-list.ts(1 hunks)src/_apis/crew/my-crew-joined-list.ts(1 hunks)src/components/common/input/pop-over-calendar/index.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/_apis/crew/my-crew-joined-list.ts
🔇 Additional comments (1)
src/_apis/crew/my-crew-hosted-list.ts (1)
1-2: 타입 선언과 임포트가 깔끔합니다!
필요한 유틸리티와 타입들이 잘 정의되어 있습니다.
| } catch (error) { | ||
| // eslint-disable-next-line no-console | ||
| console.error(error); | ||
| } | ||
| return 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.
에러 처리 로직 개선이 필요합니다
현재 에러 처리에는 몇 가지 문제가 있습니다:
- 에러 발생 시 조용히
null을 반환하여 호출자가 에러 상황을 인지하기 어렵습니다 - 콘솔 로그만 남기고 실제 에러 처리가 없습니다
- 다양한 에러 상황(네트워크 오류, 인증 오류 등)에 대한 구체적인 처리가 없습니다
다음과 같이 개선하는 것을 제안드립니다:
} catch (error) {
- // eslint-disable-next-line no-console
- console.error(error);
+ if (error instanceof Error) {
+ throw new Error(`내가 주최한 크루 목록을 가져오는데 실패했습니다: ${error.message}`);
+ }
+ throw new Error('알 수 없는 에러가 발생했습니다');
}
- return null;📝 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.
| } catch (error) { | |
| // eslint-disable-next-line no-console | |
| console.error(error); | |
| } | |
| return null; | |
| } | |
| } catch (error) { | |
| if (error instanceof Error) { | |
| throw new Error(`내가 주최한 크루 목록을 가져오는데 실패했습니다: ${error.message}`); | |
| } | |
| throw new Error('알 수 없는 에러가 발생했습니다'); | |
| } | |
| } |
| onFocus={() => { | ||
| setInputTheme('dark'); | ||
| if (!opened) open(); | ||
| }} | ||
| onBlur={() => { | ||
| setInputTheme('white'); | ||
| if (opened) close(); | ||
| }} |
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
포커스 및 블러 이벤트 처리 개선 필요
키보드 접근성과 사용자 경험 향상을 위해 다음 사항들을 고려해주세요:
- 포커스/블러 이벤트와 팝오버 상태 변경 사이에 발생할 수 있는 경쟁 상태를 방지하기 위해 타이머 추가
- ESC 키 처리 추가
- 스크린 리더 사용자를 위한 ARIA 속성 추가
다음과 같이 개선해보세요:
+ const [timeoutId, setTimeoutId] = useState<NodeJS.Timeout | null>(null);
onFocus={() => {
setInputTheme('dark');
- if (!opened) open();
+ if (timeoutId) clearTimeout(timeoutId);
+ if (!opened) {
+ open();
+ }
}}
onBlur={() => {
setInputTheme('white');
- if (opened) close();
+ const id = setTimeout(() => {
+ if (opened) close();
+ }, 200);
+ setTimeoutId(id);
}}
+ aria-haspopup="true"
+ aria-expanded={opened}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: 5
🧹 Outside diff range and nitpick comments (4)
src/_apis/crew/crew-list.ts (1)
19-21: 에러 메시지 현지화 필요에러 메시지가 영어로 작성되어 있습니다. 한국어 사용자를 위해 메시지를 현지화하는 것이 좋습니다.
- throw new Error('Failed to get crew list: No data received'); + throw new Error('크루 목록을 가져오는데 실패했습니다: 데이터가 수신되지 않았습니다');src/components/common/crew-list/crew-card-list.tsx (2)
27-28: 초기 로딩 상태의 UX 개선이 필요합니다.데이터가 없을 때 바로
null을 반환하면 사용자가 로딩 중인지 알 수 없습니다.다음과 같은 개선을 제안드립니다:
- // 초기 로딩시 데이터 없을때 - if (!data.pages.length) return null; + // 초기 로딩시 스켈레톤 UI 표시 + if (!data.pages.length) { + return ( + <div className="grid gap-4"> + {[...Array(4)].map((_, index) => ( + <CrewCardSkeleton key={index} /> + ))} + </div> + ); + }
72-76: 무한 스크롤 에러 처리가 필요합니다.현재 로딩 상태만 처리되어 있고 에러 상태에 대한 처리가 없습니다.
다음과 같은 개선을 제안드립니다:
+ interface CrewCardListProps { + data: InfiniteData<MyCrewListResponse | MainCrewListResponse, unknown>; + isFetchingNextPage: boolean; + inWhere?: 'my-crew' | 'main-crew'; + hasNextPage: boolean; + error?: Error; + } {isFetchingNextPage && ( <div className="flex justify-center py-10"> <Loader size="sm" /> </div> )} + {error && ( + <div className="flex justify-center py-10 text-red-500"> + 데이터를 불러오는데 실패했습니다. 다시 시도해주세요. + </div> + )} + {!hasNextPage && ( + <div className="flex justify-center py-10 text-gray-500"> + 모든 데이터를 불러왔습니다. + </div> + )}src/app/(crew)/page.tsx (1)
131-138: 에러 메시지를 더 구체적으로 개선하면 좋겠습니다.로딩 상태와 에러 상태 처리가 잘 구현되어 있습니다. 다만, 에러 메시지를 사용자에게 더 도움이 되도록 개선하면 좋겠습니다.
다음과 같이 수정하는 것을 제안합니다:
- {status === 'error' && <p className="py-10 text-center">에러가 발생했습니다.</p>} + {status === 'error' && ( + <p className="py-10 text-center"> + 데이터를 불러오는 중 문제가 발생했습니다. <br /> + 잠시 후 다시 시도해 주세요. + </p> + )}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (9)
src/_apis/crew/crew-list.ts(1 hunks)src/_queries/crew/crew-list-queries.tsx(2 hunks)src/_queries/crew/my-crew-hosted-list-query.ts(1 hunks)src/_queries/crew/my-crew-joined-list-query.ts(1 hunks)src/app/(crew)/my-crew/hosted/page.tsx(1 hunks)src/app/(crew)/my-crew/joined/page.tsx(1 hunks)src/app/(crew)/page.tsx(3 hunks)src/components/common/crew-list/crew-card-list.tsx(2 hunks)src/hooks/use-infinite-scroll.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- src/_queries/crew/crew-list-queries.tsx
- src/_queries/crew/my-crew-hosted-list-query.ts
- src/_queries/crew/my-crew-joined-list-query.ts
- src/app/(crew)/my-crew/hosted/page.tsx
- src/app/(crew)/my-crew/joined/page.tsx
🔇 Additional comments (3)
src/hooks/use-infinite-scroll.ts (2)
13-19: useInfiniteQuery 설정에 status 추가 적용이 잘 되었습니다.
쿼리의 상태 관리를 위해 status 필드를 추가한 것은 좋은 개선사항입니다. 이를 통해 컴포넌트에서 로딩, 에러, 성공 상태를 더 세밀하게 처리할 수 있게 되었습니다.
29-29: 반환값에 status 추가에 대한 검증이 필요합니다.
status 필드가 반환값에 추가되었습니다. 이 변경으로 인해 이 훅을 사용하는 기존 컴포넌트들에 영향이 있을 수 있습니다.
다음 스크립트를 실행하여 이 훅을 사용하는 모든 컴포넌트를 확인해주세요:
✅ Verification successful
Let me analyze the findings from the shell script results. I can see several components using the useInfiniteScroll hook, and some of them are already using the status field in their destructuring:
src/app/(crew)/page.tsx- Already usesstatussrc/app/(crew)/my-crew/joined/page.tsx- Already usesstatussrc/app/(crew)/my-crew/hosted/page.tsx- Already usesstatus
While other components don't use the status field:
src/components/common/writable-gathering-card/writable-gathering-card-list.stories.tsxsrc/components/common/review-list/review-card-list.stories.tsxsrc/components/common/crew-list/crew-card-list.stories.tsxsrc/app/(crew)/mypage/page.tsx
Since these are story files (.stories.tsx) and they are used for component documentation/testing, and the actual components in production are already using the status field, I can generate the final response.
status 필드 추가는 안전합니다
status 필드는 이미 실제 프로덕션 컴포넌트들(/my-crew/joined, /my-crew/hosted, /crew/page)에서 사용되고 있습니다. 나머지 사용처는 Storybook 문서용 파일들이므로 영향이 없습니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Find all components using useInfiniteScroll hook
rg -l "useInfiniteScroll" | grep -E "\.(tsx|ts)$" | while read -r file; do
echo "=== $file ==="
rg "useInfiniteScroll" "$file" -A 5 -B 5
done
Length of output: 8602
src/app/(crew)/page.tsx (1)
39-48: 쿼리 파라미터 구조가 잘 개선되었습니다.
페이지네이션 관련 파라미터를 pageable 객체로 분리하고, 검색 조건을 condition 객체로 구조화한 것이 좋은 접근입니다.
src/_apis/crew/crew-list.ts
Outdated
| } catch (error) { | ||
| // eslint-disable-next-line no-console | ||
| console.error(error); | ||
| } | ||
| return 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
에러 처리 개선 필요
현재 구현된 에러 처리 방식에 몇 가지 개선이 필요합니다:
- 콘솔 로그는 민감한 정보를 노출할 수 있습니다
null반환은 타입 안전성을 저해할 수 있습니다- 에러 정보가 상위 컴포넌트로 전달되지 않습니다
다음과 같은 개선을 제안드립니다:
} catch (error) {
- // eslint-disable-next-line no-console
- console.error(error);
+ const errorMessage = error instanceof Error ? error.message : '알 수 없는 오류가 발생했습니다';
+ throw new Error(`크루 목록 조회 실패: ${errorMessage}`);
}
- return null;📝 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.
| } catch (error) { | |
| // eslint-disable-next-line no-console | |
| console.error(error); | |
| } | |
| return null; | |
| } catch (error) { | |
| const errorMessage = error instanceof Error ? error.message : '알 수 없는 오류가 발생했습니다'; | |
| throw new Error(`크루 목록 조회 실패: ${errorMessage}`); | |
| } |
| try { | ||
| const response: { data: MainCrewListResponse } = await fetchApi( | ||
| `/api/crews/search?keyword=${keyword}&mainLocation=${mainLocation}&mainCategory=${mainCategory}&subCategory=${subCategory}&sortType=${sortType}&page=${page}&size=${size}&sort=${sort}`, | ||
| { | ||
| method: 'GET', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| credentials: 'include', // 인증 정보를 요청에 포함 | ||
| }, | ||
| credentials: 'include', // 인증 정보를 요청에 포함 | ||
| }, | ||
| ); | ||
| ); |
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 호출 보안 강화 필요
credentials: 'include'를 사용할 때 보안상 주의가 필요합니다. CSRF 공격에 취약할 수 있으므로 적절한 CSRF 토큰 처리가 필요합니다.
다음과 같은 보안 강화를 권장드립니다:
headers: {
'Content-Type': 'application/json',
+ 'X-CSRF-Token': getCsrfToken(), // CSRF 토큰 추가
},Committable suggestion skipped: line range outside the PR's diff.
| inWhere === 'my-crew' | ||
| ? data.pages.flatMap((page) => page.content 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.
타입 안전성 강화가 필요합니다.
현재 타입 단언(as)을 사용하고 있어 런타임에서 타입 안전성이 보장되지 않습니다.
다음과 같이 타입 가드를 사용하여 안전성을 개선해주세요:
const crewDataList =
- inWhere === 'my-crew'
- ? data.pages.flatMap((page) => page.content as MyCrewList[])
- : data.pages.flatMap((page) => page.content as MainCrewList[]);
+ inWhere === 'my-crew'
+ ? data.pages.flatMap((page) => {
+ if (!Array.isArray(page?.content)) return [];
+ return page.content.filter((item): item is MyCrewList =>
+ 'currentCount' in item && 'totalGathering' in item
+ );
+ })
+ : data.pages.flatMap((page) => {
+ if (!Array.isArray(page?.content)) return [];
+ return page.content.filter((item): item is MainCrewList =>
+ 'participantCount' in item && 'isConfirmed' in item
+ );
+ });📝 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.
| inWhere === 'my-crew' | |
| ? data.pages.flatMap((page) => page.content as MyCrewList[]) | |
| : data.pages.flatMap((page) => page.content as MainCrewList[]); | |
| inWhere === 'my-crew' | |
| ? data.pages.flatMap((page) => { | |
| if (!Array.isArray(page?.content)) return []; | |
| return page.content.filter((item): item is MyCrewList => | |
| 'currentCount' in item && 'totalGathering' in item | |
| ); | |
| }) | |
| : data.pages.flatMap((page) => { | |
| if (!Array.isArray(page?.content)) return []; | |
| return page.content.filter((item): item is MainCrewList => | |
| 'participantCount' in item && 'isConfirmed' in item | |
| ); | |
| }); |
src/app/(crew)/page.tsx
Outdated
| import { Divider, Loader, TextInput } from '@mantine/core'; | ||
| import { isErrored } from 'stream'; |
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.
사용하지 않는 import 문을 제거해주세요.
stream에서 가져온 isErrored가 코드에서 사용되지 않고 있습니다.
다음과 같이 수정해주세요:
-import { Divider, Loader, TextInput } from '@mantine/core';
-import { isErrored } from 'stream';
+import { Divider, Loader, TextInput } from '@mantine/core';Committable suggestion skipped: line range outside the PR's diff.
🔖 Issue Ticket
#105
✍️ Description
나의 크루페이지 백엔드 API 연결했습니다~
✅ Checklist
PR
Test
Summary by CodeRabbit
새로운 기능
MyCrewLayout컴포넌트 추가: 크루 관련 탭 관리 기능 제공.MyCrewHostedPage및MyCrewJoinedPage컴포넌트 추가: 사용자의 크루 참여 정보를 표시하며 무한 스크롤 기능 지원.useGetMyCrewHostedQuery및useGetMyCrewJoinedQuery훅 추가: 각각 호스팅된 크루 및 가입한 크루 목록을 가져오는 기능 제공.getMyCrewHostedList및getMyCrewJoinedList비동기 함수 추가: 사용자의 호스팅된 크루 및 가입한 크루 목록을 API를 통해 가져오는 기능 제공.변경 사항
MyCrewPage컴포넌트 리팩토링: 탭 인터페이스를 단일 리디렉션으로 변경하여 사용자 상호작용 방식 변경.CrewCardListProps및CrewCardProps인터페이스 업데이트: 데이터 구조의 유연성 향상.HomePage컴포넌트의 쿼리 매개변수 구조 개선: 더 나은 데이터 조직 및 페이지네이션 제어 추가.HeroCrew컴포넌트에서 사용하지 않는 버튼 컴포넌트의 임포트 제거.useInfiniteScroll훅에 상태 정보 추가: 데이터 가져오기 상태에 대한 추가 정보 제공.