At the Place
사용자의 취향을 조사해 맞춤형 카페를 찾아주는 플랫폼입니다.
ReactNext.jsTypeScriptTailwind CSSZustandReact query

이미지 로딩 중...

📌 주제
- 사용자의 취향을 조사해 맞춤형 카페를 찾아주는 플랫폼입니다.
✋🏻 역할
- 페이지 구성 & 유저 플로우
- 플랫폼 로고
- 디자인
- 배포
🤔 배경
엣더플레이스를 만들게 된 계기는 스터디를 같이 했던 친구와 작업이 가능한 카페를 찾다가 생각하게 된 아이디어입니다. 노트북을 두고 쓰기 넉넉한 테이블과 충전이 가능한 콘센트, 너무 시끄럽지 않은 공간 등 내가 지향하는 작업하기 좋은 공간을 지닌 카페를 찾기 위해 검색을 열심히 하던 중 “내 취향을 기반으로 카페를 추천해주면 좋겠다” 라는 생각을 하게 되었고, 백엔드 개발자 한 분을 구해 기획부터 디자인, DB 구축, 배포까지 해볼 수 있었던 좋은 경험이었습니다.
📝주요 구현 사항
로그인 / 회원가입
- JWT 토큰 방식
- 로그인 성공 시 서버로부터 토큰 발급 → 브라우저 localStorage에 저장
- Axios 인터셉터로 매 요청 시 자동으로 Authorization: Bearer <token> 헤더를 삽입해 중복 코드 제거
- React Query + Zustand
- React Query useMutation으로 로그인, 회원가입 로직 분리 → 로딩/에러 상태 관리
- 로그인 성공 후 Zustand 스토어에 유저 정보 저장 → NavMenu 등에서 구독하여 UI 업데이트
- 소셜 로그인
- Kakao 로그인 연동: OAuth 흐름으로 카카오 인증 후 서버/클라이언트에 토큰 전달
- 동일한 “토큰 발급 → 스토어 저장” 프로세스를 재활용
- 폼 검증 & 에러 핸들링
- 이메일, 비밀번호 정규식 체크 함수 & 에러 상황별 핸들링 함수 분리 ⇒ 재사용성과 가독성 향상
이미지 로딩 중...

이미지 로딩 중...

마이 페이지
- 프로필 이미지 변경 (ProfileImageModal)
- 모달에서 파일 선택 시 미리보기(URL.createObjectURL)를 표시하여 사용자 편의성 확보
- “예” 버튼 클릭 시 updateProfileImage(React Query mutationFn) 호출 → 서버에 이미지 업로드 → onSuccess에서 refetch( )로 최신 프로필 경로 재조회
- 재조회된 이미지 URL을 Zustand의 setUserInfo로 업데이트하며 UI 갱신
- 찜 목록
- 찜한 카페 확인 & 카페 상세 페이지 이동
- 스크롤 없이 카드 그리드 배치를 통해 반응형 레이아웃 제공
이미지 로딩 중...

취향 찾기
이미지 로딩 중...

이미지 로딩 중...

- 질문 단계 및 진행도(ProgressBar)
- 각 단계를 원형 아이콘 & 라벨로 표시
- 이미 답변한 단계를 클릭하면 이전 단계로 돌아가 수정 가능
- Yes/No 선택 시 다음 질문으로 이동 → 직관적이고 사용자의 인지 부하 최소화
- 상태 관리 & 로직
- 로컬state(answers)로 “Yes/No” 응답을 객체 형태로 저장 (예: { pet: true, groupSeat: false, ... })
- 모든 질문에 답변 완료되면(answers 길이 === 4) → “결과 확인”버튼 노출
- 필터링된 카페 데이터 요청 hook(useCafeFilterQuery)을 통해 서버로 “filter paramerter”를 전송 예) pet=1&terrace=1 형태 (true = 1, true인 값만 서버로 전송)
- 응답 성공 시 : zustand(useCafeListStore)의 setFilteredCafes로 카페 리스트 갱신 → /map 페이지 이동
- 결과가 없을 시 : 모달(useModalStore) 띄워 “조건에 맞는 카페가 없다” 안내 → 확인 버튼으로 초기화
지도
- 지도 초기화 & 마커 표시
- useMap 커스텀 훅을 통해 네이버 맵 API를 로드, 지도(mapRef.current)를 생성
- 카페 데이터를 순회하며 각각의 위치에 마커를 찍고, 클릭 시 InfoWindow 표시
- onMarkerClick(cafe)를 호출하여 “해당 카드로 스크롤”하도록 연결
- 카페 카드 리스트 & 스크롤 이동
- 하단에 수평 스크롤(
overflow-x-scroll)로 카페 카드(CafeCard) 목록을 배치 CafeCard에ref를 부여해 저장, 마커 클릭 시 scrollIntoView로 해당 카드 중앙으로 옮김- 지도 & 카드 리스트가 양방향 연동되어 편리한 검색/탐색 경험 제공
이미지 로딩 중...

- 현재 위치 찾기
- “내 위치” 버튼 클릭 시
- navigator.geolocation.getCurrentPosition을 통해 위치를 얻고,
- 지도 중심 및 새 마커로 시각화
- 커스텀 아이콘을 사용해 내 위치 마커와 카페 마커를 구분
- “내 위치” 버튼으로 사용자가 쉽게 현재 위치 주변 카페를 탐색
카페 상세 페이지
이미지 로딩 중...

이미지 로딩 중...

- 데이터 로딩 & 상태 관리
- URL parameter(cafeId)를 통해 서버로부터 카페 데이터(fetchCafeDetail)를 가져옴
- 카페 데이터 store에 저장 → 렌더 시점에 cafeInfo를 참조하여 UI 업데이트
- 컴포넌트 언마운트 시 clearCafeInfo( ) 로 store 초기화
- 캐러셀
- Swiper의 Coverflow Effect 사용
- [main, menu] 이미지를 배열로 받아 SwiperSlide에 배치
- 대표사진 + 메뉴사진을 캐러셀로 보여주어 “카페 분위기와 메뉴”를 동시에 확인
- 카페 정보 & 지도
- CafeInfoItem으로 카페 상세 정보를, StaticMap으로 정적 지도를 렌더
- 마커 좌표를 파라미터로 넘겨 지도를 시각화
- 데스트톱 뷰에선 병렬 레이아웃 적용
- 좋아요(찜) 기능
- 로그인하지 않은 상태면 “로그인이 필요한 서비스입니다” 모달 표출
- 찜 등록/해제 시 마이페이지에 자동 반영되어 일관된 상태를 유지
- heart_filled / heart_outline 아이콘으로 시각적으로 찜 등록/해제 표현
- 찜 버튼 클릭 시 useLikeToggleMutation으로 서버에 등록/해제 요청 → 성공 시 refetch( )를 통해 zustand userInfo를 업데이트 → UI 즉시 반영
🧠 성과
이 프로젝트를 통해 Next.js 환경에서 SSR과 CSR을 혼합해 사용하며 Hydration Error, 무한 루프 등
상태 불일치 이슈를 해결해 볼 수 있었습니다.
로그인/회원가입부터카페 필터링까지 전 과정의 UI/UX를 혼자 설계하고, React Query + Zustand로 인증·데이터 흐름을 효율화하며 개발 속도와 코드 유지보수성을 높였습니다.
또한, AWS 기반 서버와의 REST API 통신을 백엔드 팀원과 함께 설정하면서, 배포 과정에서 마주한 보안 그룹/포트 문제 등을 실무와 유사한 방식으로 트러블슈팅했습니다.
결과적으로 아이디어 기획부터 디자인, SSR/CSR 구조 설계, 배포까지 프로젝트 전반을 경험하며 프론트엔드와 백엔드 협업에 대한 이해도를 한층 더 확장할 수 있었습니다.