Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Walkthrough미팅 생성 후 meetingType을 localStorage에 저장하고, 추천 페이지에서 API 기반 미팅 데이터를 통해 meetingType과 카테고리를 파생시킨 후 필터링된 카테고리 목록을 지도 컴포넌트로 전달합니다. API 응답에 purposes 필드가 추가되었습니다. Changes
Sequence DiagramsequenceDiagram
participant User as 사용자
participant RecommendPage as Recommend<br/>페이지
participant API as API 서버
participant Storage as localStorage
participant KakaoMap as KakaoMap<br/>컴포넌트
User->>RecommendPage: 추천 페이지 진입
RecommendPage->>API: useCheckMeeting(meetingId)
API-->>RecommendPage: MeetingStatusData<br/>(purposes, meetingType)
RecommendPage->>RecommendPage: purposes에서<br/>defaultCategory 파생
RecommendPage->>Storage: 카테고리 캐시
RecommendPage->>Storage: 데이터 읽기
Storage-->>RecommendPage: 캐시된 값
RecommendPage->>RecommendPage: effectiveCategory 계산<br/>(selected > default)
RecommendPage->>RecommendPage: meetingType 기반<br/>카테고리 필터링
RecommendPage->>KakaoMap: selectedCategory,<br/>onCategoryChange,<br/>filteredCategories 전달
User->>KakaoMap: 카테고리 변경
KakaoMap->>RecommendPage: onCategoryChange
RecommendPage->>RecommendPage: selectedCategory 업데이트
RecommendPage->>Storage: 선택 카테고리 저장
RecommendPage->>RecommendPage: selectedPlaceId 초기화
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 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 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 |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@app/recommend/page.tsx`:
- Line 103: 현재 category 필드에 직접 할당된 category: place.categoryGroupName이 빈 문자열이나
undefined일 때 배지가 비어 보이는 문제가 있습니다; categoryGroupName이 falsy(빈 문자열 포함)인 경우
place.categoryName으로 대체되도록 수정하세요 — 예: category에 place.categoryGroupName이 유효한 값인지
확인하고(빈 문자열 체크 포함) 유효하지 않으면 place.categoryName을 할당하도록 변경하여 category:
place.categoryGroupName 대신 안전한 fallback을 사용하도록 고치세요.
- Around line 29-48: The meetingType useMemo currently has the
localStorage.setItem call commented out on the same line so the API-derived
firstPurpose never gets cached; inside the block that checks
meetingData.data.purposes and determines firstPurpose (the code dealing with
meetingData, firstPurpose, and meetingId), move the
localStorage.setItem(`meeting_${meetingId}_meetingType`, firstPurpose) out of
the comment and execute it before returning firstPurpose (ensuring typeof window
!== 'undefined' remains satisfied) so the value is persisted for future lookups
used by the cachedType logic.
In `@components/map/kakaoMapRecommend.tsx`:
- Around line 29-37: The category ID for the study-cafe is inconsistent:
ALL_CATEGORIES currently uses id '스터디카페' while the rest of the app (e.g., the
value sent from create/page and returned by the API, and the comparisons using
selectedCategory in kakaoMapRecommend.tsx) uses '스터디 카페' with a space; update
the ALL_CATEGORIES entry for the study cafe so its id is '스터디 카페' to match
selectedCategory checks and filtering logic, and verify any other places that
construct or compare this category string use the same exact value.
🧹 Nitpick comments (2)
app/recommend/page.tsx (2)
51-66:useMemo내부에서localStorage.setItem부수 효과가 발생합니다.React의
useMemo는 순수 계산을 위한 훅입니다. Strict Mode에서 두 번 실행되거나, React가 결과를 버릴 수도 있습니다.localStorage캐싱은 별도의useEffect로 분리하는 것이 더 안전합니다.동일한 패턴이
meetingTypeuseMemo(Line 36, 현재 주석 처리됨)에도 적용됩니다.♻️ useEffect로 캐싱 로직 분리 예시
const defaultCategory = useMemo(() => { if (typeof window === 'undefined') return ''; if (meetingData?.data?.purposes && meetingData.data.purposes.length > 1) { const subCategory = meetingData.data.purposes[meetingData.data.purposes.length - 1]; if (subCategory) { - localStorage.setItem(`meeting_${meetingId}_category`, subCategory); return subCategory; } } const cachedCategory = localStorage.getItem(`meeting_${meetingId}_category`); return cachedCategory || ''; }, [meetingId, meetingData]); + // API에서 가져온 카테고리를 localStorage에 캐싱 + useEffect(() => { + if (meetingData?.data?.purposes && meetingData.data.purposes.length > 1) { + const subCategory = meetingData.data.purposes[meetingData.data.purposes.length - 1]; + if (subCategory) { + localStorage.setItem(`meeting_${meetingId}_category`, subCategory); + } + } + }, [meetingId, meetingData]);
73-75:currentCategory와effectiveCategory가 동일한 값입니다.
effectiveCategory = currentCategory = selectedCategory || defaultCategory로, 두 변수가 불필요하게 중복됩니다. 하나로 통합하면 가독성이 향상됩니다.♻️ 변수 통합 제안
- const currentCategory = selectedCategory || defaultCategory; - - const effectiveCategory = currentCategory; + const effectiveCategory = selectedCategory || defaultCategory;
| const meetingType = useMemo(() => { | ||
| if (typeof window === 'undefined') return null; | ||
|
|
||
| // 1. API에서 purposes 가져오기 (참여자도 접근 가능) | ||
| if (meetingData?.data?.purposes && meetingData.data.purposes.length > 0) { | ||
| const firstPurpose = meetingData.data.purposes[0]; | ||
| if (firstPurpose === '회의' || firstPurpose === '친목') { | ||
| // localStorage에도 저장 (다음 접근 시 빠르게 사용) localStorage.setItem(`meeting_${meetingId}_meetingType`, firstPurpose); | ||
| return firstPurpose as '회의' | '친목'; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| const cachedType = localStorage.getItem(`meeting_${meetingId}_meetingType`); | ||
| if (cachedType === '회의' || cachedType === '친목') { | ||
| return cachedType as '회의' | '친목'; | ||
| } | ||
|
|
||
| return null; | ||
| }, [meetingId, meetingData]); |
There was a problem hiding this comment.
localStorage.setItem 호출이 주석 안에 포함되어 실행되지 않습니다.
Line 36에서 localStorage.setItem(...) 호출이 주석(//)과 같은 줄에 있어 실행되지 않습니다. API에서 가져온 meetingType이 localStorage에 캐싱되지 않으므로, API 데이터가 없는 후속 접근 시 fallback이 작동하지 않습니다.
🐛 주석과 코드를 분리
if (meetingData?.data?.purposes && meetingData.data.purposes.length > 0) {
const firstPurpose = meetingData.data.purposes[0];
if (firstPurpose === '회의' || firstPurpose === '친목') {
- // localStorage에도 저장 (다음 접근 시 빠르게 사용) localStorage.setItem(`meeting_${meetingId}_meetingType`, firstPurpose);
+ // localStorage에도 저장 (다음 접근 시 빠르게 사용)
+ localStorage.setItem(`meeting_${meetingId}_meetingType`, firstPurpose);
return firstPurpose as '회의' | '친목';
}
}🤖 Prompt for AI Agents
In `@app/recommend/page.tsx` around lines 29 - 48, The meetingType useMemo
currently has the localStorage.setItem call commented out on the same line so
the API-derived firstPurpose never gets cached; inside the block that checks
meetingData.data.purposes and determines firstPurpose (the code dealing with
meetingData, firstPurpose, and meetingId), move the
localStorage.setItem(`meeting_${meetingId}_meetingType`, firstPurpose) out of
the comment and execute it before returning firstPurpose (ensuring typeof window
!== 'undefined' remains satisfied) so the value is persisted for future lookups
used by the cachedType logic.
| id: index + 1, | ||
| name: place.placeName, | ||
| category: place.categoryGroupName || place.categoryName, | ||
| category: place.categoryGroupName, |
There was a problem hiding this comment.
categoryGroupName이 빈 값일 때의 fallback 제거.
이전에 categoryName으로의 fallback이 있었으나 제거되었습니다. categoryGroupName이 빈 문자열이나 undefined인 경우 카테고리 배지가 비어 보일 수 있습니다.
🛡️ fallback 추가 제안
- category: place.categoryGroupName,
+ category: place.categoryGroupName || place.categoryName || '',📝 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.
| category: place.categoryGroupName, | |
| category: place.categoryGroupName || place.categoryName || '', |
🤖 Prompt for AI Agents
In `@app/recommend/page.tsx` at line 103, 현재 category 필드에 직접 할당된 category:
place.categoryGroupName이 빈 문자열이나 undefined일 때 배지가 비어 보이는 문제가 있습니다;
categoryGroupName이 falsy(빈 문자열 포함)인 경우 place.categoryName으로 대체되도록 수정하세요 — 예:
category에 place.categoryGroupName이 유효한 값인지 확인하고(빈 문자열 체크 포함) 유효하지 않으면
place.categoryName을 할당하도록 변경하여 category: place.categoryGroupName 대신 안전한
fallback을 사용하도록 고치세요.
| // 전체 카테고리 목록 | ||
| const ALL_CATEGORIES = [ | ||
| { id: '식당', label: '식당', icon: '/icon/place/restaurant' }, | ||
| { id: '놀거리', label: '놀거리', icon: '/icon/place/play' }, | ||
| { id: '술집', label: '술집', icon: '/icon/place/bar' }, | ||
| { id: '카페', label: '카페', icon: '/icon/place/cafe' }, | ||
| { id: '놀거리', label: '놀거리', icon: '/icon/place/play' }, | ||
| { id: '스터디카페', label: '스터디카페', icon: '/icon/place/studycafe' }, | ||
| { id: '장소 대여', label: '장소 대여', icon: '/icon/place/rent' }, | ||
| ]; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for both spelling variants of study cafe category
echo "=== Searching for '스터디카페' (no space) ==="
rg '스터디카페' --type=ts --type=tsx -n
echo ""
echo "=== Searching for '스터디 카페' (with space) ==="
rg '스터디 카페' --type=ts --type=tsx -nRepository: SWYP-mingling/Frontend
Length of output: 224
🏁 Script executed:
#!/bin/bash
# Search for both spelling variants without file type restriction
echo "=== Searching for '스터디카페' (no space) ==="
rg '스터디카페' -n --glob='*.tsx' --glob='*.ts'
echo ""
echo "=== Searching for '스터디 카페' (with space) ==="
rg '스터디 카페' -n --glob='*.tsx' --glob='*.ts'Repository: SWYP-mingling/Frontend
Length of output: 533
🏁 Script executed:
#!/bin/bash
# Check the recommend page to see how selectedCategory is used and compared
echo "=== Content of recommend/page.tsx to understand data flow ==="
rg 'selectedCategory|defaultCategory|purposes' -n --glob='*.tsx' app/
echo ""
echo "=== Check kakaoMapRecommend.tsx line 141 (selectedCategory comparison) ==="
sed -n '135,150p' components/map/kakaoMapRecommend.tsxRepository: SWYP-mingling/Frontend
Length of output: 2855
'스터디카페'와 '스터디 카페'의 불일치로 카테고리 선택이 동작하지 않습니다.
app/create/page.tsx Line 227에서 목적으로 '스터디 카페'(띄어쓰기 있음)를 전송하고, API에서도 이 값을 그대로 반환합니다. 그러나 kakaoMapRecommend.tsx에서 ALL_CATEGORIES의 ID는 '스터디카페'(띄어쓰기 없음)로 정의되어 있습니다. 결과적으로 selectedCategory === cat.id 비교(Line 141)가 실패하여 카테고리 하이라이트가 표시되지 않으며, 필터링 로직(Line 57)도 정상 작동하지 않습니다.
둘 중 하나로 통일해야 합니다.
🐛 권장 사항: ALL_CATEGORIES의 ID를 create 페이지와 일치시키기
- { id: '스터디카페', label: '스터디카페', icon: '/icon/place/studycafe' },
+ { id: '스터디 카페', label: '스터디 카페', icon: '/icon/place/studycafe' },또는 app/create/page.tsx Line 227의 값을 '스터디카페'로 변경하세요.
🤖 Prompt for AI Agents
In `@components/map/kakaoMapRecommend.tsx` around lines 29 - 37, The category ID
for the study-cafe is inconsistent: ALL_CATEGORIES currently uses id '스터디카페'
while the rest of the app (e.g., the value sent from create/page and returned by
the API, and the comparisons using selectedCategory in kakaoMapRecommend.tsx)
uses '스터디 카페' with a space; update the ALL_CATEGORIES entry for the study cafe
so its id is '스터디 카페' to match selectedCategory checks and filtering logic, and
verify any other places that construct or compare this category string use the
same exact value.
🚀 QA 지도 하위 카테고리 수정
📝 변경사항
1. 상위 카테고리 기반 하위 카테고리 동적 표시
2. 모임 참여자 카테고리 정보 접근 개선
purposes정보를 가져와 추천 장소 확인 가능useCheckMeeting훅을 통해 모임 정보 API에서purposes배열을 가져와 상위/하위 카테고리 추출3. 카테고리 클릭 시 장소 리스트 자동 요청
queryKey에category를 포함하여 카테고리 변경 시 자동 refetch 구현4. 카테고리 정보 캐싱
API에서 가져온 카테고리 정보를 localStorage에 저장하여 다음 접근 시 빠르게 사용
모임 생성 시 상위 카테고리(
meetingType)도 localStorage에 저장여기에 변경된 내용을 적어주세요.
✅ 체크리스트
📸 스크린샷
💬 리뷰어 전달사항
Summary by CodeRabbit
릴리스 노트