[Fix] WTH-254 : clubId가 세팅되지 않는 문제 수정#46
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthrough클럽 ID/이름을 쿠키와 클라이언트 스토어에 영속화하고, 허브·게시판 관련 컴포넌트들이 쿠키 기반 clubId/clubName을 사용하도록 변경했으며, ClubGuard를 추가해 자동 클럽 선택 및 동기화 흐름을 도입했습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Page as Main Page
participant ClubGuard
participant API as /clubs API
participant Cookies as Next Cookies
participant Store as Client Store
participant Router as Next Router
User->>Page: 방문
Page->>ClubGuard: 렌더
ClubGuard->>Store: useClubId 조회
alt clubId 없음
ClubGuard->>API: GET /clubs
API-->>ClubGuard: club 목록
ClubGuard->>Cookies: setClubCookie(id,name)
ClubGuard->>Store: setClub(id,name)
ClubGuard->>Router: router.refresh()
Router-->>Page: 새로고침 후 재렌더
else clubId 있음
ClubGuard-->>Page: children 렌더
end
sequenceDiagram
participant User
participant HubActionCard
participant Cookies as Next Cookies
participant Store as Client Store
participant Router as Next Router
User->>HubActionCard: 'go' 버튼 클릭 (clubId, clubName)
HubActionCard->>Cookies: setClubCookie(clubId, clubName)
Cookies-->>HubActionCard: 쿠키 저장 완료
HubActionCard->>Store: setClub(clubId, clubName)
Store-->>HubActionCard: 상태 업데이트
HubActionCard->>Router: router.push(href)
Router-->>User: 네비게이션 완료
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
🤖 Claude 테스트 제안
변경된 컴포넌트에 대해 Claude가 생성한 테스트 코드입니다. 검토 후 적합한 부분만 사용하세요.
|
PR 테스트 결과✅ Jest: 통과 🎉 모든 테스트를 통과했습니다! |
🤖 Claude 테스트 제안
변경된 컴포넌트에 대해 Claude가 생성한 테스트 코드입니다. 검토 후 적합한 부분만 사용하세요.
|
PR 테스트 결과✅ Jest: 통과 🎉 모든 테스트를 통과했습니다! |
PR 검증 결과✅ TypeScript: 통과 |
1 similar comment
PR 검증 결과✅ TypeScript: 통과 |
|
구현한 기능 Preview: https://weeth-1imxce94x-weethsite-4975s-projects.vercel.app |
|
구현한 기능 Preview: https://weeth-gxqf8u74n-weethsite-4975s-projects.vercel.app |
🤖 Claude 테스트 제안
변경된 컴포넌트에 대해 Claude가 생성한 테스트 코드입니다. 검토 후 적합한 부분만 사용하세요.
|
PR 테스트 결과✅ Jest: 통과 🎉 모든 테스트를 통과했습니다! |
PR 검증 결과✅ TypeScript: 통과 🎉 모든 검증을 통과했습니다! |
|
구현한 기능 Preview: https://weeth-9epl5dx3l-weethsite-4975s-projects.vercel.app |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/home/UnreadNoticeBox.tsx (1)
8-38:⚠️ Potential issue | 🟡 MinorPrettier 체크 실패를 먼저 정리해 주세요.
CI에서 이 파일의
Prettier --check경고가 보고되었습니다. 머지 전 해당 파일 포맷 정리가 필요합니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/home/UnreadNoticeBox.tsx` around lines 8 - 38, This file fails Prettier --check; run Prettier to reformat the component file (e.g., run prettier --write on the file or run your editor's format command) to fix spacing, trailing commas, and JSX formatting in the UnreadNoticeBox component (references: function UnreadNoticeBox, useUnreadNoticeQuery, stripHtml, onTransitionEnd). After formatting, re-run Prettier --check/CI to ensure the warning is resolved before merging.src/stores/useClubStore.ts (1)
1-36:⚠️ Potential issue | 🟡 Minor이 파일은 Prettier 체크를 통과하지 못하고 있습니다.
CI 경고 기준으로, 병합 전 해당 파일에 formatter를 재적용해 스타일 불일치를 정리해 주세요.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/stores/useClubStore.ts` around lines 1 - 36, This file fails Prettier formatting; run your formatter (e.g. prettier --write) on the file containing useClubStore, useClubId, useClubName and useClubActions, fix any spacing/commas/indentation differences and re-save so the exported create/devtools/persist/combine block and the hook exports conform to the project's Prettier rules, then re-commit the formatted file so CI passes.
🧹 Nitpick comments (2)
src/stores/useClubStore.ts (1)
16-18:setClubId호출 시clubName잔존 가능성이 있습니다.Line 16에서
clubId만 갱신하면 이후 UI가 이전clubName을 계속 표시할 수 있습니다. 상태 일관성을 위해setClubId는clubName을 함께 초기화하는 편이 안전합니다.리팩터 제안
- setClubId: (clubId: string) => set({ clubId }, false, 'setClubId'), + setClubId: (clubId: string) => set({ clubId, clubName: null }, false, 'setClubId'),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/stores/useClubStore.ts` around lines 16 - 18, The setClubId updater leaves clubName stale; update setClubId to reset clubName as well (e.g., set({ clubId, clubName: '' }, false, 'setClubId')) so state stays consistent—note setClub already sets both clubId and clubName, so make setClubId mirror that behavior by clearing clubName when only the id is provided.src/components/layout/ClubGuard.tsx (1)
14-21: 로컬Club인터페이스 대신 기존 타입을 재사용하는 것을 고려해보세요.
src/types/mypage.ts에ClubDto타입이 이미 정의되어 있습니다. 로컬 인터페이스를 정의하는 대신 기존 타입을 import하면 API 응답 구조 변경 시 타입 안전성이 향상됩니다.♻️ 권장 수정안
+import type { ClubDto } from '@/types/mypage'; +import type { ApiResponse } from '@/types'; // 또는 적절한 경로 -interface Club { - id: string; - name: string; -} - -interface MyClubsResponse { - data: Club[]; -} +type MyClubsResponse = ApiResponse<ClubDto[]>;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/layout/ClubGuard.tsx` around lines 14 - 21, Replace the local Club and MyClubsResponse interfaces in ClubGuard.tsx with the existing ClubDto type from src/types/mypage.ts: import ClubDto and change MyClubsResponse to use data: ClubDto[] (remove the local interface Club and any references to it) so the component (e.g., ClubGuard) reuses the shared ClubDto type for type safety when the API changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/app/`(private)/(main)/board/(with-nav)/[id]/page.tsx:
- Around line 12-17: 현재 페이지에서 params의 id를 바로 Number(id)로 변환하고
boardServerApi.getPostById를 호출해 예외 경로(잘못된 id, NaN, 404 등)를 처리하지 않아 런타임 500이 발생할
수 있습니다; 수정하려면 params에서 id를 받아 parseInt/Number 변환 후 isNaN 체크를 하고
clubId(cookies().get(CLUB_ID_KEY)) 존재도 확인한 뒤 boardServerApi.getPostById 호출을
try/catch로 감싸며, API가 404/NotFound을 반환하거나 id가 유효하지 않으면 Next.js의 notFound()를 호출하거나
적절한 에러경로로 분기하도록 변경하고, 성공 시에만 PostDetailContent에 response.data를 전달하도록 구현하세요.
In `@src/app/`(private)/(main)/board/(with-nav)/layout.tsx:
- Around line 15-18: The call to boardServerApi.getBoards in layout.tsx can
throw and crash the whole layout; wrap the getBoards call in a try/catch (or
handle the promise rejection) around the code that uses clubId and
boardServerApi.getBoards, and on error set a safe fallback (e.g., responseData =
[] or boards = []) so the rest of the layout can render; ensure you still return
null when clubId is missing, but prevent exceptions from propagating by
defaulting response.data to an empty array before sorting/using it.
In `@src/app/`(private)/(main)/board/edit/[id]/page.tsx:
- Around line 20-22: The handler returns null when clubId is missing which is
inconsistent with other missing-resource handling; change the early-return to
call notFound() instead. Locate the clubId retrieval
(cookies().get(CLUB_ID_KEY)?.value) and replace the "if (!clubId) return null"
with a call to notFound() so missing CLUB_ID_KEY is treated the same as an
absent post; ensure subsequent logic using postId and boardServerApi.getPostById
remains unchanged.
In `@src/components/auth/hub/ClubCreatingPage.tsx`:
- Around line 57-61: The current logic calls setApiDone(true) even when
result.clubId is missing, allowing progression without proper club setup; update
the flow so setApiDone(true) is only called when result.clubId exists (the same
branch that sets createdClubIdRef.current and calls setClub), and handle the
missing clubId case by setting an error state or keeping the API-unfinished
state and logging/throwing an error so the UI does not advance; modify the block
around createdClubIdRef.current, setClub, setApiDone and use result.clubId as
the gate.
In `@src/components/layout/ClubGuard.tsx`:
- Around line 35-41: The current check only verifies club exists but can pass
undefined id/name into setClubCookie and setClub; update the .then(async (res)
=> { ... }) block to validate that club.id and club.name are present and
non-empty before calling setClubCookie(club.id, club.name), setClub(club.id,
club.name), and router.refresh(); if either field is missing, bail out (or
handle gracefully—e.g., log an error/warning and avoid setting cookies/state) so
you never persist "undefined" into cookies or state.
In `@src/hooks/board/useBoardQuery.ts`:
- Around line 41-45: getNextPageParam already defensively handles missing
page.data.data but select still assumes every page has data.data.content; update
the select callback in useBoardQuery.ts to guard for missing data by using
optional chaining and a default empty array so it never tries to access .content
on undefined (e.g., treat page.data?.data?.content as possibly undefined and
replace with []), and also handle the case where the top-level data is undefined
(return an empty array instead of crashing).
---
Outside diff comments:
In `@src/components/home/UnreadNoticeBox.tsx`:
- Around line 8-38: This file fails Prettier --check; run Prettier to reformat
the component file (e.g., run prettier --write on the file or run your editor's
format command) to fix spacing, trailing commas, and JSX formatting in the
UnreadNoticeBox component (references: function UnreadNoticeBox,
useUnreadNoticeQuery, stripHtml, onTransitionEnd). After formatting, re-run
Prettier --check/CI to ensure the warning is resolved before merging.
In `@src/stores/useClubStore.ts`:
- Around line 1-36: This file fails Prettier formatting; run your formatter
(e.g. prettier --write) on the file containing useClubStore, useClubId,
useClubName and useClubActions, fix any spacing/commas/indentation differences
and re-save so the exported create/devtools/persist/combine block and the hook
exports conform to the project's Prettier rules, then re-commit the formatted
file so CI passes.
---
Nitpick comments:
In `@src/components/layout/ClubGuard.tsx`:
- Around line 14-21: Replace the local Club and MyClubsResponse interfaces in
ClubGuard.tsx with the existing ClubDto type from src/types/mypage.ts: import
ClubDto and change MyClubsResponse to use data: ClubDto[] (remove the local
interface Club and any references to it) so the component (e.g., ClubGuard)
reuses the shared ClubDto type for type safety when the API changes.
In `@src/stores/useClubStore.ts`:
- Around line 16-18: The setClubId updater leaves clubName stale; update
setClubId to reset clubName as well (e.g., set({ clubId, clubName: '' }, false,
'setClubId')) so state stays consistent—note setClub already sets both clubId
and clubName, so make setClubId mirror that behavior by clearing clubName when
only the id is provided.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e835822a-85f4-4766-bf1b-a140e3ec170c
📒 Files selected for processing (23)
src/app/(private)/(auth)/hub/page.tsxsrc/app/(private)/(main)/board/(with-nav)/[id]/page.tsxsrc/app/(private)/(main)/board/(with-nav)/layout.tsxsrc/app/(private)/(main)/board/edit/[id]/page.tsxsrc/app/(private)/(main)/layout.tsxsrc/app/api/proxy/[...path]/route.tssrc/components/auth/hub/ClubCreatingPage.tsxsrc/components/auth/hub/ClubJoiningPage.tsxsrc/components/auth/hub/HubActionCard.tsxsrc/components/auth/hub/InviteCodeForm.tsxsrc/components/board/CategorySelector.tsxsrc/components/board/PostCard/PostCardListContent.tsxsrc/components/home/NoticeBoardBox.tsxsrc/components/home/UnreadNoticeBox.tsxsrc/components/layout/ClubGuard.tsxsrc/components/layout/index.tssrc/hooks/board/useBoardQuery.tssrc/hooks/home/useWritePost.tssrc/lib/actions/club.tssrc/lib/apis/cookies.tssrc/lib/stripHtml.tssrc/stores/index.tssrc/stores/useClubStore.ts
💤 Files with no reviewable changes (1)
- src/hooks/home/useWritePost.ts
woneeeee
left a comment
There was a problem hiding this comment.
저두 MVP에서는 하나의 동아리만 가입되는걸로 알고 있어요!! 일단 0번으로 세팅되도록 하고 MVP 이후에 다시 수정해보아요 🦦!! 동아리 생성 이후 응답으로 clubId가 오고 있지 않고 있군요.... ㅜㅜㅜㅜ 내일 회의때 말해봅시당..ㅜ.ㅜ 수고하셨어요 !!!
dalzzy
left a comment
There was a problem hiding this comment.
확인했습니다!!!! 코드래빗이 달아준 리뷰만 확인해주시면 될 것 같아용
동아리 생성 시 clubId 필요한거는,,,, 제가 동아리 생성 api 연결하면서 요청드렸어야 됐는데 생각을 못했네요 ,,, ㅠㅠ
감사합니다........ 최고 👍🏻
JIN921
left a comment
There was a problem hiding this comment.
이제 클럽 아이디 하드코딩 없이 쓸 수 잇다...!!~~!! 수고하셨습니다!! 지원님 말씀대로 동아리는 1개만 가능해서 현재 구현단에서는 문제될 부분 없을 거 같습니다!
🤖 Claude 테스트 제안
변경된 컴포넌트에 대해 Claude가 생성한 테스트 코드입니다. 검토 후 적합한 부분만 사용하세요.
|
PR 테스트 결과✅ Jest: 통과 🎉 모든 테스트를 통과했습니다! |
PR 검증 결과✅ TypeScript: 통과 🎉 모든 검증을 통과했습니다! |
|
구현한 기능 Preview: https://weeth-3y2ulkyph-weethsite-4975s-projects.vercel.app |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/app/`(private)/(main)/board/(with-nav)/[id]/page.tsx:
- Around line 19-20: The current call to boardServerApi.getPostById uses
.catch(() => null) which swallows all errors and maps every failure to
notFound(); change this to only treat a 404 or missing response data as notFound
and rethrow or let other errors propagate to the error boundary. Replace the
.catch(() => null) pattern with a try/catch around boardServerApi.getPostById
(or inspect the caught error from getPostById), call notFound() only when
response?.data is falsy or when the caught error indicates HTTP 404 (e.g.,
error.response?.status === 404), and rethrow or throw the original error for
network/5xx/auth errors so they reach the error boundary.
In `@src/stores/useClubStore.ts`:
- Around line 16-18: setClubId currently only updates clubId and leaves clubName
stale, causing mismatched club state; update the setClubId updater to also clear
clubName (set clubName to null or the initialState value) so that calling
setClubId resets the name; locate the setter in useClubStore (setClubId) and
mirror the behavior of reset/initialState when clearing club identity to avoid
stale data (ensure types for clubName allow null if needed).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 39a2e20f-63fa-4d33-ab1d-bc74c9c38485
📒 Files selected for processing (7)
src/app/(private)/(main)/board/(with-nav)/[id]/page.tsxsrc/app/(private)/(main)/board/(with-nav)/layout.tsxsrc/components/auth/hub/ClubCreatingPage.tsxsrc/components/home/UnreadNoticeBox.tsxsrc/components/layout/ClubGuard.tsxsrc/hooks/board/useBoardQuery.tssrc/stores/useClubStore.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- src/app/(private)/(main)/board/(with-nav)/layout.tsx
- src/hooks/board/useBoardQuery.ts
- src/components/home/UnreadNoticeBox.tsx
- src/components/auth/hub/ClubCreatingPage.tsx
- src/components/layout/ClubGuard.tsx
🤖 Claude 테스트 제안
변경된 컴포넌트에 대해 Claude가 생성한 테스트 코드입니다. 검토 후 적합한 부분만 사용하세요.
|
PR 테스트 결과✅ Jest: 통과 🎉 모든 테스트를 통과했습니다! |
PR 검증 결과✅ TypeScript: 통과 🎉 모든 검증을 통과했습니다! |
|
구현한 기능 Preview: https://weeth-qqgbwqegf-weethsite-4975s-projects.vercel.app |
✅ PR 유형
어떤 변경 사항이 있었나요?
📌 관련 이슈번호
✅ Key Changes
ClubId 문제 수정
clubId/clubName 쿠키 및 store 세팅:
useClubStore에 clubName 필드와 setClub 액션을 추가하고, lib/apis/cookies.ts에 CLUB_ID_KEY/CLUB_NAME_KEY 쿠키 상수 및 setClubCookie Server Action 추가동아리 생성/가입/이동 시
clubId세팅: ClubCreatingPage, ClubJoiningPage, InviteCodeForm, HubActionCard에서 동아리 생성·가입·이동 시 쿠키와 store에 clubId/clubName을 세팅하도록 수정ClubGuard컴포넌트 추가: (main) 레이아웃에 ClubGuard를 감싸서, clubId가 store에 없을 경우 /clubs API를 호출해 자동 복구하드코딩된
clubId제거: 게시판 상세([id]/page.tsx), 레이아웃(layout.tsx), 수정 페이지(edit/[id]/page.tsx)에서 하드코딩된 clubId를 쿠키 기반 clubId로 교체기타 버그 수정
프록시 API gzip 문제 수정: accept-encoding 헤더를 제거하고, response.body 스트림 대신 response.arrayBuffer()로 응답 본문을 읽어 gzip 바이너리가 그대로 전달되는 문제 해결
stripHtml 유틸 추출: 홈에서 마크다운 content가 그대로 보이는 문제가 있어서, NoticeBoardBox, UnreadNoticeBox에 HTML strip 로직을 추가
프로필 미완성 모달 수정: "다음에 하기" 클릭 시
/board/write로 이동하는 동작이 있어 제거📸 스크린샷 or 실행영상
🎸 기타 사항 or 추가 코멘트
ClubGuard는 store에clubId가 없는 경우에만 API를 호출 (정상 상태에서는 추가 요청 X)clubId쿠키가 없는 상태에서는 잠깐 null이 렌더링되고,ClubGuard가 복구 → router.refresh() → RSC가 쿠키를 읽어 정상 렌더링되는 흐름ClubGuard의 경우 우선/clubs에서 0번 항목 동아리를 불러오게 해뒀습니다!mvp에서는 여러 동아리 가입이 안 되...는 걸로 알아서 이렇게 해둿는데... 아니라면 수정해보겟습니당...ㅎ_ㅎ
그리고 동아리 생성 이후 응답으로
clubId가 오고 있지 않아서...clubId세팅이 어려운 문제가 잇엇는데,요건 월요일 회의 때 배겐드 분들께 요청드리려고... 미리 반영만 해둿습니당
Summary by CodeRabbit
새로운 기능
개선사항