-
Notifications
You must be signed in to change notification settings - Fork 2
[#252] ✨ 커뮤니티 api 연동 #253
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
[#252] ✨ 커뮤니티 api 연동 #253
Conversation
Walkthrough이번 변경 사항은 커뮤니티와 팀 관련 페이지, 훅, 서비스, 타입, 그리고 상태 관리 리듀서의 업데이트 및 신규 추가를 포함합니다. Changes
Sequence Diagram(s)sequenceDiagram
participant U as 사용자
participant P as UpdateCommunityPage
participant H as useCommunity (훅)
participant M as useUpdateCommunity (훅)
participant S as updateCommunity (서비스)
U->>P: URL에 포함된 커뮤니티 ID로 편집 페이지 오픈
P->>P: useParams로 커뮤니티 ID 추출
P->>H: 커뮤니티 상세 정보 요청
H-->>P: 커뮤니티 상세 정보 반환
U->>P: 폼 작성 후 제출
P->>M: onSubmit에서 mutate(formData) 호출
M->>S: API 요청 (커뮤니티 업데이트)
S-->>M: 업데이트 응답 반환
M-->>P: 상태 갱신 및 데이터 새로고침
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 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: 3
🧹 Nitpick comments (9)
src/app/(pages)/community/[id]/edit/page.tsx (2)
25-28: 사용하지 않는 import 제거해보세요!
useCreateCommunity는 여기서 사용되지 않는 것으로 보입니다. 필요하지 않다면 제거하여 가독성과 유지보수성을 높이면 좋겠습니다.import { useCommunity, - useCreateCommunity, useUpdateCommunity, } from '@/queries/community'
73-75: 로딩 및 에러 처리 UI를 개선하면 어떨까요?
단순히'd'문자열만 보여주는 것보다는 로딩 시 스피너나 안내 문구, 에러 시 사용자에게 명확한 오류 메시지를 제공하는 방식을 추천합니다.src/app/(pages)/community/page.tsx (1)
67-68: 더 나은 로딩/에러 UI로 사용자 경험을 높여보세요.
현재 단순히<div>d</div>로 표시하고 있는데, 간단한 안내 문구나 스피너를 추가해주시면 사용자 입장에서 더 친절하게 느껴질 것입니다.src/queries/community/index.ts (3)
44-57: 기본 쿼리 옵션에 대한 설정을 검토해 보세요.
현재useQuery에서staleTime이나cacheTime등의 옵션을 지정하지 않았습니다. 특정 화면에서 재방문 시 캐싱된 데이터를 재활용하거나 적절히 무효화하려면, 쿼리 옵션을 구체적으로 설정하면 좋습니다.
87-100: 에러 상황 처리 로직 구현을 권장합니다.
useCreateCommunity에서는onError콜백이 없어, 에러 발생 시 사용자에게 알림이 부족할 수 있습니다. 알림(Toast)이나 UI 메시지를 통해 적절히 대응하도록 개선하는 것이 좋습니다.
122-136: 에러 처리 시 사용자 안내를 보강할 수 있습니다.
현재useDeleteCommunity에서onError는console.error에 기록하기만 합니다. UI에 안내 메시지를 주거나 재시도 혹은 취소 선택지를 제시하면, 사용자 만족도가 높아질 것입니다.src/app/(pages)/community/[id]/page.tsx (2)
45-46: 에러 및 로딩 상태를 좀 더 상세히 처리해 주세요.
현재isLoading과isError상황에서<div>d</div>만 반환하고 있습니다. 사용자 입장에서 분명한 안내가 되도록 로딩 스피너나 에러 메시지 등을 보여주는 편이 좋겠습니다.
131-157: 삭제 버튼의 후속 처리에도 사용자 피드백을 고려해 보세요.
모달에서 삭제가 확인되면deleteCommunity를 호출하지만, 에러나 요청 지연이 발생할 수도 있습니다. 추가적인 로딩 상태나 에러 안내 UI를 제공하면 더 나은 UX를 구현할 수 있습니다.src/services/community/index.ts (1)
1-86: API 경로와 반복되는 로직에 대한 개선을 고려해 보세요.
각 엔드포인트에"v1/community"같은 경로가 반복적으로 등장합니다. 추후 관리가 쉽도록 상수화하거나 전역 설정(예:.env또는 공용 config 파일)으로 분리해 유지보수성을 높일 수 있습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
src/app/(pages)/community/[id]/edit/page.tsx(1 hunks)src/app/(pages)/community/[id]/page.tsx(4 hunks)src/app/(pages)/community/new/page.tsx(4 hunks)src/app/(pages)/community/page.tsx(6 hunks)src/app/(pages)/team/[id]/edit/page.tsx(1 hunks)src/app/(pages)/team/new/page.tsx(0 hunks)src/app/(pages)/team/page.tsx(4 hunks)src/queries/community/index.ts(1 hunks)src/services/community/index.ts(1 hunks)src/stores/community/communityListFilterReducer.ts(1 hunks)src/types/api/Community.types.d.ts(2 hunks)src/types/api/Post.types.d.ts(1 hunks)
💤 Files with no reviewable changes (1)
- src/app/(pages)/team/new/page.tsx
✅ Files skipped from review due to trivial changes (1)
- src/types/api/Post.types.d.ts
🔇 Additional comments (21)
src/app/(pages)/team/page.tsx (4)
5-5: 불필요한 import 제거로 코드가 더 깔끔해졌네요! 👍필요없는
useState와Grid컴포넌트 import를 제거하셨군요. 코드 정리가 잘 되었습니다.Also applies to: 14-14
77-80: 사용자 경험을 향상시키는 훌륭한 개선입니다!팀 타입 변경 시
goToPage(1)을 호출하여 첫 페이지로 이동하도록 한 로직은 매우 합리적입니다. 사용자가 필터를 변경할 때 페이지를 리셋하는 것은 일관된 사용자 경험을 제공하는 좋은 패턴입니다.
91-94: 일관된 패턴 적용 👍팀 프로젝트 버튼에도 같은 패턴을 적용하셨네요. 일관성 있는 코드 스타일로 유지보수가 더 쉬워집니다.
105-108: 멘토링 버튼도 동일한 패턴으로 잘 구현하셨습니다!모든 팀 타입 버튼에 동일한 패턴을 적용하여 코드의 일관성을 유지하셨네요. 이렇게 하면 다른 개발자들도 코드를 쉽게 이해할 수 있습니다.
src/types/api/Community.types.d.ts (2)
10-10: 명확한 타입 정의로 코드 품질 향상!
Order타입을 명시적으로 정의함으로써 정렬 옵션을 명확히 했습니다. 이는 타입스크립트의 장점을 잘 활용한 예시입니다. 'recent', 'likes', 'views'와 같은 문자열 리터럴 타입을 사용하여 가능한 값을 제한한 것이 좋습니다.
30-34: API 쿼리 파라미터의 체계적인 타입 정의 👏
GetCommunityListQuery타입을 통해 API 요청에 필요한 파라미터 구조를 명확히 정의했습니다. 이런 방식은 프론트엔드와 백엔드 간의 계약을 명확히 하고, 타입 안정성을 높여 개발 과정에서 발생할 수 있는 오류를 줄여줍니다.특히
category에 빈 문자열을 허용한 부분은 "모든 카테고리" 옵션을 위한 실용적인 접근법입니다.src/app/(pages)/team/[id]/edit/page.tsx (2)
194-194: 폼 초기값 설정 개선으로 사용자 경험 향상!
Controller컴포넌트의defaultValue를 빈 문자열에서teamContent로 변경한 것은 매우 중요한 개선입니다. 이제 사용자가 팀 정보를 편집할 때 기존 내용이 에디터에 올바르게 표시될 것입니다.이전에는 폼이 렌더링될 때 에디터가 빈 상태로 시작했을 가능성이 있었습니다. 이 변경으로 사용자 경험이 크게 향상됩니다.
98-101: 콘솔 로그 제거로 코드 품질 향상!
onSubmit함수에서 불필요한 console.log를 제거하셨네요. 프로덕션 코드에서 디버깅용 콘솔 로그를 제거하는 것은 코드 품질을 높이는 좋은 습관입니다.src/stores/community/communityListFilterReducer.ts (3)
1-4: 타입 재사용으로 일관성 유지 👍
GetCommunityListQuery타입을 재사용하여FilterState를 정의한 것은 좋은 접근법입니다. 이렇게 하면 API 요청과 상태 관리 간의 일관성을 유지할 수 있습니다.
5-10: 액션 타입 정의가 명확해요!필터 관련 액션들을 명확하게 정의했습니다. 각 액션 타입과 페이로드의 관계가 잘 구성되어 있습니다.
11-15: 초기 상태 설정이 적절합니다기본값으로 검색어는 빈 문자열, 정렬은 '최신순', 카테고리는 빈 문자열로 설정한 것은 대부분의 사용자 경험에 맞는 합리적인 선택입니다.
src/app/(pages)/community/[id]/edit/page.tsx (1)
39-49: 커뮤니티 정보 Fetch 로직이 인상적입니다!
useCommunity를 통해communityId를 받아오는 흐름이 명확하고 유지보수하기도 편해 보입니다. 좋은 시도입니다.src/app/(pages)/community/page.tsx (2)
120-142: 검색 폼 로직이 깔끔합니다!
dispatch로 검색어를 반영해주는 구조가 명확하고, 코드 가독성도 좋습니다. 훌륭한 아이디어예요!
259-265: 커뮤니티 목록 동적 렌더링, 아주 잘하셨어요!
communityList.map(...)을 통해 각 아이템을 NextLink로 감싸는 방식이 직관적이며, 재사용성을 높였습니다. 응원합니다!src/app/(pages)/community/new/page.tsx (3)
21-28: Zod 스키마를 활용한 폼 검증이 훌륭합니다!
간결하면서도 필요한 필드를 꼼꼼히 검증하고 있어, 프로젝트의 안정성에 큰 도움이 될 것 같습니다.
35-35: zodResolver 적용이 잘 되었습니다.
React Hook Form과 Zod를 결합해 폼 오류를 바로잡는 로직이 매끄럽습니다. 신규 기능 추가 시에도 확장하기 편해 보이네요.
106-118: 에디터의 에러 처리 표시가 인상적입니다!
fieldState.error를 활용해 사용자에게 바로 피드백을 주는 구조가 좋습니다. 폼의 유효성을 강화하는 코딩 센스가 돋보이네요.src/queries/community/index.ts (2)
59-72: 초기 데이터 사용 시 주의가 필요합니다.
initialData옵션으로 이미 캐싱된 정보를 우선 표시하는 것은 사용자 경험 향상에 좋지만, 혹시 오래된 데이터가 표시될 가능성도 있으니enabled나refetchOnWindowFocus등의 옵션을 조정해 최신 정보를 보장하도록 해주세요.
174-182: 인기 커뮤니티 조회 로직이 간결합니다.
useCommunityTop5훅은 최소한의 로직으로 작성되어 있어 가독성이 좋습니다. 불필요한 복잡도가 없으니 현재 구현 그대로 두셔도 무난해 보입니다.src/app/(pages)/community/[id]/page.tsx (2)
40-46: 게시물 소유 여부 판별 로직을 실제 인증 결과값으로 대체해 주세요.
communityId % 2로isOwnPost를 결정하는 것은 임시 구현으로 보입니다. 추후 실제 인증 정보(예: 로그인 사용자 ID)와 게시물 작성자를 비교하여 소유 여부를 판단하도록 개선해주세요.
162-180: 댓글 UI가 잘 구성되었습니다.
Comment와CommentList컴포넌트를 통해 댓글 기능을 분리하고 있어 유지보수가 용이합니다. 다만 추후 실제 API 연동 시에는 상태 관리와 페이징(무한 스크롤 등)을 고려하면 더욱 유연해질 것입니다.
| export const communityListFilterReducer = ( | ||
| state: FilterState, | ||
| action: FilterAction | ||
| ): FilterState => { | ||
| switch (action.type) { | ||
| case 'SET_SEARCH_TERM': | ||
| return { ...state, searchTerm: action.payload } | ||
| case 'SET_SORT_BY': | ||
| return { ...state, sortBy: action.payload } | ||
| case 'SET_CATEGORY': | ||
| return { ...state, category: action.payload } | ||
| default: | ||
| return state | ||
| } | ||
| } |
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
'RESET_FILTERS' 액션 처리가 누락되었습니다
리듀서 함수 구현이 깔끔하지만, FilterAction 타입에 정의된 'RESET_FILTERS' 액션을 처리하는 case가 없습니다. 필터 초기화 기능이 필요하다면 이 부분을 추가해야 합니다.
다음과 같이 'RESET_FILTERS' 케이스를 추가하는 것을 제안합니다:
switch (action.type) {
case 'SET_SEARCH_TERM':
return { ...state, searchTerm: action.payload }
case 'SET_SORT_BY':
return { ...state, sortBy: action.payload }
case 'SET_CATEGORY':
return { ...state, category: action.payload }
+ case 'RESET_FILTERS':
+ return communityListFilterInitialState
default:
return state
}📝 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 const communityListFilterReducer = ( | |
| state: FilterState, | |
| action: FilterAction | |
| ): FilterState => { | |
| switch (action.type) { | |
| case 'SET_SEARCH_TERM': | |
| return { ...state, searchTerm: action.payload } | |
| case 'SET_SORT_BY': | |
| return { ...state, sortBy: action.payload } | |
| case 'SET_CATEGORY': | |
| return { ...state, category: action.payload } | |
| default: | |
| return state | |
| } | |
| } | |
| export const communityListFilterReducer = ( | |
| state: FilterState, | |
| action: FilterAction | |
| ): FilterState => { | |
| switch (action.type) { | |
| case 'SET_SEARCH_TERM': | |
| return { ...state, searchTerm: action.payload } | |
| case 'SET_SORT_BY': | |
| return { ...state, sortBy: action.payload } | |
| case 'SET_CATEGORY': | |
| return { ...state, category: action.payload } | |
| case 'RESET_FILTERS': | |
| return communityListFilterInitialState | |
| default: | |
| return state | |
| } | |
| } |
| const createCommunitySchema = z.object({ | ||
| communityTitle: z.string().nonempty('제목을 입력해주세요.'), | ||
| communityContent: z.string().nonempty('내용을 입력해주세요.'), | ||
| communityCategory: z.enum(['SKILL', 'CAREER', 'OTHER'], { | ||
| errorMap: () => ({ message: '질문 유형을 선택해주세요.' }), | ||
| }), | ||
| isComment: z.boolean().optional(), | ||
| }) |
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
스키마 명칭을 좀 더 직관적으로 정리해보세요.
현재 createCommunitySchema를 업데이트 페이지에서도 사용하는데, 혼동을 줄이기 위해 commonCommunitySchema 혹은 updateCommunitySchema 같은 이름을 고려해보세요.
| // 팀 모집글 수정 | ||
| export const useUpdateCommunity = ( | ||
| communityId: Id | ||
| ): UseMutationResult< | ||
| ApiResponse<UpdateCommunityResponse>, | ||
| Error, | ||
| UpdateCommunityRequest | ||
| > => { | ||
| const router = useRouter() | ||
| const queryClient = useQueryClient() | ||
| return useMutation({ | ||
| mutationFn: data => updateCommunity(communityId, data), | ||
| onSuccess: ({ result }) => { | ||
| queryClient.invalidateQueries({ queryKey: ['community', communityId] }) | ||
|
|
||
| router.push(`/community/${result.id}`) | ||
| }, | ||
| }) | ||
| } |
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
에러 핸들링과 로깅을 보강해 주세요.
useUpdateCommunity에서도 성공 시 로직만 존재하고, 에러 발생 시 대처가 이루어지지 않습니다. 에러를 캡처하거나 안내를 위한 onError 처리 로직을 추가하면 유지보수와 사용자 경험 양쪽에 도움이 됩니다.
yongb2n
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.
고생하셨습니다 ㅎㅎㅎ
📌 PR 템플릿
🏷️ PR 타입 (PR Type)
📝 요약 (Summary)
🔍 상세 내용 (Describe your changes)
🔗 관련 이슈 또는 링크 (Issue Number or Link)
✅ 체크리스트 (Checklist)
📸 스크린샷 (선택 사항)
2025-03-05.23.56.07.mov
2025-03-05.23.57.00.mov
📝 기타 사항
Summary by CodeRabbit
새로운 기능
리팩토링