Conversation
카카오맵 API 연동 장소 검색 및 약속 생성 폼 구현. - PlaceSearchModal: 카카오맵 API 기반 장소 검색 모달 - PlaceList: 검색 결과 목록 및 지도 마커 연동 - useKakaoMap, useKakaoPlaceSearch: 지도 및 장소 검색 훅 - useMeetingForm, useCreateMeeting: 약속 생성 폼 상태 관리 및 API 연동 - timeUtils, validation: 시간 유틸리티 및 폼 검증 로직 - MeetingCreatePage: 약속 설정 및 장소 검색 UI 통합
Walkthrough카카오맵 API를 통합한 약속 생성 기능을 추가합니다. 지도 검색, 장소 선택, 시간 설정, 참가자 수 관리 등의 기능을 제공하는 새로운 훅, 컴포넌트, API 엔드포인트 및 페이지를 구현합니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Page as MeetingCreatePage
participant PlaceModal as PlaceSearchModal
participant Map as Kakao Map API
participant PlaceAPI as Kakao Place Search
participant Server as Server
User->>Page: 약속 생성 폼 접근
User->>Page: 장소 검색 버튼 클릭
Page->>PlaceModal: 모달 오픈
PlaceModal->>Map: 지도 초기화
Map-->>PlaceModal: 지도 렌더링 완료
User->>PlaceModal: 검색어 입력 + Enter
PlaceModal->>PlaceAPI: 장소 검색 요청
PlaceAPI-->>PlaceModal: 검색 결과 (KakaoPlace[])
PlaceModal->>Map: 마커 렌더링
User->>PlaceModal: 장소 선택
PlaceModal->>Page: onSelectPlace(name, address, lat, lng)
Page->>Page: 폼 상태 업데이트 (location, 좌표)
PlaceModal->>PlaceModal: 모달 종료
User->>Page: 폼 입력 완료 (도서, 날짜·시간, 참가자 수)
User->>Page: 만들기 버튼 클릭
Page->>Page: validateForm() - 검증
alt 검증 실패
Page->>User: 오류 메시지 표시 + 스크롤
else 검증 성공
Page->>Server: POST /api/meetings (CreateMeetingRequest)
Server-->>Page: CreateMeetingResponse
Page->>User: 성공 알림 + 홈 이동
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested reviewers
🚥 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: 7
🤖 Fix all issues with AI agents
In `@src/features/meetings/hooks/useKakaoMap.ts`:
- Around line 31-33: The forEach callback in clearMarkers is using a concise
arrow that returns marker.setMap(null), which triggers the Biome lint rule;
update the callback used on markersRef.current.forEach inside the clearMarkers
function to use a block-bodied arrow so it calls marker.setMap(null) without
returning a value (i.e., change the callback to a block that invokes setMap and
no return), leaving the subsequent markersRef.current = [] assignment unchanged.
- Around line 21-26: Replace the three refs currently typed as any in
useKakaoMap.ts (mapRef, markersRef, infowindowRef) with concrete Kakao Maps
types so compile-time checks catch API misuse: install the community types (npm
install -D `@types/kakaomaps`) and change mapRef to useRef<kakao.maps.Map |
null>(null), markersRef to useRef<kakao.maps.Marker[]>([]), and infowindowRef to
useRef<kakao.maps.InfoWindow | null>(null); alternatively, if you maintain local
types, extend your kakaoMap.types.ts with equivalent kakao.maps.Map /
kakao.maps.Marker / kakao.maps.InfoWindow declarations and import those types
for the three refs.
In `@src/features/meetings/meetings.types.ts`:
- Around line 80-125: CreateMeetingResponse currently defines location:
MeetingLocation while CreateMeetingRequest allows location: MeetingLocation |
null; update the response type to match backend behavior by making
CreateMeetingResponse.location nullable (location: MeetingLocation | null) if
the backend can return no location, or verify backend always sends a location
and leave as-is; check and adjust the CreateMeetingResponse type (and any
consumers) to use MeetingLocation | null when backend can omit location.
In `@src/pages/Meetings/MeetingCreatePage.tsx`:
- Around line 101-105: The success handler for createMutation.mutate still uses
a placeholder navigate('/') with a TODO comment; replace this with the correct
post-create route using your app's route constants or route builder (e.g., call
the route constant or a function that builds the meeting detail/list path)
inside the onSuccess callback after awaiting openAlert; update the reference in
createMutation.mutate's onSuccess (and remove the comment) so navigation uses
the canonical route (e.g., Routes.MEETING_DETAIL or
buildMeetingRoute(meetingId)) instead of '/'.
- Around line 21-24: The component currently hardcodes gatheringId and
gatheringMaxCount, causing incorrect meeting creations; update MeetingCreatePage
to source these from a real data path (route params or API) instead of the
temporary constants: remove the fixed consts (gatheringId, gatheringMaxCount),
add state (e.g., useState) and a data fetch in the MeetingCreatePage component
(or accept them via props/route params) to populate gatheringId and
gatheringMaxCount, track a loading/ready flag, and keep the submit handler and
submit button disabled until the values are loaded/validated so submissions
cannot proceed with placeholder values.
- Around line 169-188: The place-validation error set by validateForm
(errors.location) isn't displayed; update MeetingCreatePage's place section
(inside the Container.Content that renders locationAddress, locationName and the
place-search Button) to conditionally render the errors.location message when
present (e.g., beneath the Button), using the same styling pattern as other
field errors so users see why submission is blocked; ensure you reference the
existing errors object and do not remove/alter locationAddress, locationName or
the setIsPlaceSearchOpen handler.
In `@src/shared/lib/utils.ts`:
- Around line 7-21: The spacing array contains a duplicate 'small' entry in the
spacing list (the spacing constant/array), remove one of the 'small' values or
rename the second occurrence to the intended token name (e.g., 'xbase' or
another unique token) so all entries are unique; update any references that
expect the renamed token accordingly (search for usages of spacing tokens if you
rename).
🧹 Nitpick comments (4)
src/shared/styles/base.css (1)
14-20: Firefox 지원 누락WebKit 브라우저만 타겟팅되어 있음. Firefox에서 일관된 스타일을 원하면 추가 규칙 필요.
♻️ Firefox 지원 추가 제안
input { + -moz-appearance: textfield; &::-webkit-outer-spin-button, &::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } }src/shared/ui/Datepicker.tsx (2)
33-46: 내부 state와 prop 동기화 패턴 재검토 권장문제:
valueprop과datestate를 useEffect로 동기화하는 패턴은 불필요한 re-render와 state 불일치 가능성이 있습니다.영향: Controlled component에서 부모가
value를 변경할 때 한 프레임 지연 발생 가능.대안: 내부 state 없이
value를 직접 사용하거나, 현재 패턴이 필요한 이유(예: Popover 닫기 전 임시 선택)가 있다면 주석으로 명시해 주세요.♻️ 내부 state 제거 제안
const DatePicker = React.forwardRef<HTMLButtonElement, DatePickerProps>(function DatePicker( { value, onChange, placeholder = '날짜 선택', className, disabled, isDisabled = false }, ref ) { - const [date, setDate] = React.useState<Date | null>(value) - - React.useEffect(() => { - setDate(value) - }, [value]) - const handleSelect = (selectedDate: Date) => { - setDate(selectedDate) onChange?.(selectedDate) } return ( <Popover> <PopoverTrigger asChild> <button ref={ref} type="button" - data-empty={!date} + data-empty={!value} disabled={isDisabled} ... > <CalendarDays size={20} /> - {date ? ( - format(date, 'yyyy.MM.dd') + {value ? ( + format(value, 'yyyy.MM.dd') ) : ( <span className="typo-subtitle5 text-grey-600">{placeholder}</span> )} </button> </PopoverTrigger> <PopoverContent className="p-0 border-none w-fit" align="start"> <Calendar mode="single" - selected={date ?? undefined} + selected={value ?? undefined} onSelect={handleSelect} required disabled={disabled} /> </PopoverContent> </Popover> ) })
15-16:disabledvsisDisabled네이밍 명확화 고려문제: 두 prop 모두 "disabled" 관련이지만 목적이 다릅니다.
disabled: Calendar 날짜 비활성화 (Matcher)isDisabled: 컴포넌트 전체 비활성화 (boolean)영향: 사용 시 혼란 가능.
대안:
disabledDates또는disabledMatcher로 명확히 구분하면 의도 파악이 쉬워집니다.src/features/meetings/components/PlaceSearchModal.tsx (1)
25-29:window.kakao타입을 정의된 타입 파일에 추가하거나@types/kakaomaps패키지 설치문제:
window.kakao: any로 선언되어 타입 안전성이 낮고, 공식 타입 정의 패키지가 설치되지 않았습니다.영향: Kakao Maps API 호출 시 타입 오류를 컴파일 단계에서 검출할 수 없어 런타임 버그 위험이 있습니다.
대안:
- 옵션 1:
npm install -D@types/kakaomaps``를 설치하고declare global제거- 옵션 2:
src/features/meetings/kakaoMap.types.ts에window.kakao타입을 추가한 후 이 파일에서 제거옵션 2 추천 (기존 kakaoMap.types.ts와 일관성 유지).
mgYang53
left a comment
There was a problem hiding this comment.
카카오맵 sdk 사용 시 타입이 정의되지 않아 불편할 수 있습니다.
저는 아래 라이브러리 사용해서 괜찮게 해결했었던 것 같아요. 참고하면 좋을 것 같습니다.
https://github.com/JaeSeoKim/react-kakao-maps-sdk
https://github.com/JaeSeoKim/kakao.maps.d.ts
🚀 풀 리퀘스트 제안
📋 작업 내용
약속 생성 UI 및 기능 구현
카카오 맵 & 키워드로 장소 검색하기 api 연동
📄 기타
책 조회 모달 & 모임 조회(모임인원 체크용) API 개발되면 붙여서 완성시킬 예정입니다.
Summary by CodeRabbit
릴리스 노트
새로운 기능
UI/스타일 개선