포트폴리오로 돌아가기

At the Place

사용자의 취향을 조사해 맞춤형 카페를 찾아주는 플랫폼입니다.

ReactNext.jsTypeScriptTailwind CSSZustandReact query
At the Place

📌 주제

  • 사용자의 취향을 조사해 맞춤형 카페를 찾아주는 플랫폼입니다.

✋🏻 역할

  • 페이지 구성 & 유저 플로우
  • 플랫폼 로고
  • 디자인
  • 배포

🤔 배경

엣더플레이스를 만들게 된 계기는 스터디를 같이 했던 친구와 작업이 가능한 카페를 찾다가 생각하게 된 아이디어입니다. 노트북을 두고 쓰기 넉넉한 테이블과 충전이 가능한 콘센트, 너무 시끄럽지 않은 공간 등 내가 지향하는 작업하기 좋은 공간을 지닌 카페를 찾기 위해 검색을 열심히 하던 중 “내 취향을 기반으로 카페를 추천해주면 좋겠다” 라는 생각을 하게 되었고, 백엔드 개발자 한 분을 구해 기획부터 디자인, DB 구축, 배포까지 해볼 수 있었던 좋은 경험이었습니다.

📝주요 구현 사항

로그인 / 회원가입

  1. JWT 토큰 방식
    1. 로그인 성공 시 서버로부터 토큰 발급 → 브라우저 localStorage에 저장
    2. Axios 인터셉터로 매 요청 시 자동으로 Authorization: Bearer <token> 헤더를 삽입해 중복 코드 제거
  2. React Query + Zustand
    1. React Query useMutation으로 로그인, 회원가입 로직 분리 → 로딩/에러 상태 관리
    2. 로그인 성공 후 Zustand 스토어에 유저 정보 저장 → NavMenu 등에서 구독하여 UI 업데이트
  3. 소셜 로그인
    1. Kakao 로그인 연동: OAuth 흐름으로 카카오 인증 후 서버/클라이언트에 토큰 전달
    2. 동일한 “토큰 발급 → 스토어 저장” 프로세스를 재활용
  4. 폼 검증 & 에러 핸들링
    1. 이메일, 비밀번호 정규식 체크 함수 & 에러 상황별 핸들링 함수 분리 ⇒ 재사용성과 가독성 향상

마이 페이지

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

취향 찾기

  1. 질문 단계 및 진행도(ProgressBar)
    1. 각 단계를 원형 아이콘 & 라벨로 표시
    2. 이미 답변한 단계를 클릭하면 이전 단계로 돌아가 수정 가능
    3. Yes/No 선택 시 다음 질문으로 이동 → 직관적이고 사용자의 인지 부하 최소화
  2. 상태 관리 & 로직
    1. 로컬state(answers)로 “Yes/No” 응답을 객체 형태로 저장 (예: { pet: true, groupSeat: false, ... })
    2. 모든 질문에 답변 완료되면(answers 길이 === 4) → “결과 확인”버튼 노출
    3. 필터링된 카페 데이터 요청 hook(useCafeFilterQuery)을 통해 서버로 “filter paramerter”를 전송 예) pet=1&terrace=1 형태 (true = 1, true인 값만 서버로 전송)
    4. 응답 성공 시 : zustand(useCafeListStore)의 setFilteredCafes로 카페 리스트 갱신 → /map 페이지 이동
    5. 결과가 없을 시 : 모달(useModalStore) 띄워 “조건에 맞는 카페가 없다” 안내 → 확인 버튼으로 초기화

지도

  1. 지도 초기화 & 마커 표시
    • useMap 커스텀 훅을 통해 네이버 맵 API를 로드, 지도(mapRef.current)를 생성
    • 카페 데이터를 순회하며 각각의 위치에 마커를 찍고, 클릭 시 InfoWindow 표시
    • onMarkerClick(cafe)를 호출하여 “해당 카드로 스크롤”하도록 연결
  2. 카페 카드 리스트 & 스크롤 이동
    • 하단에 수평 스크롤(overflow-x-scroll)로 카페 카드(CafeCard) 목록을 배치
    • CafeCardref를 부여해 저장, 마커 클릭 시 scrollIntoView로 해당 카드 중앙으로 옮김
    • 지도 & 카드 리스트가 양방향 연동되어 편리한 검색/탐색 경험 제공
  • 현재 위치 찾기
    • “내 위치” 버튼 클릭 시
      • navigator.geolocation.getCurrentPosition을 통해 위치를 얻고,
      • 지도 중심 및 새 마커로 시각화
    • 커스텀 아이콘을 사용해 내 위치 마커와 카페 마커를 구분
    • “내 위치” 버튼으로 사용자가 쉽게 현재 위치 주변 카페를 탐색

카페 상세 페이지

  1. 데이터 로딩 & 상태 관리
    1. URL parameter(cafeId)를 통해 서버로부터 카페 데이터(fetchCafeDetail)를 가져옴
    2. 카페 데이터 store에 저장 → 렌더 시점에 cafeInfo를 참조하여 UI 업데이트
    3. 컴포넌트 언마운트 시 clearCafeInfo( ) 로 store 초기화
  2. 캐러셀
    1. Swiper의 Coverflow Effect 사용
    2. [main, menu] 이미지를 배열로 받아 SwiperSlide에 배치
    3. 대표사진 + 메뉴사진을 캐러셀로 보여주어 “카페 분위기와 메뉴”를 동시에 확인
  3. 카페 정보 & 지도
    1. CafeInfoItem으로 카페 상세 정보를, StaticMap으로 정적 지도를 렌더
    2. 마커 좌표를 파라미터로 넘겨 지도를 시각화
    3. 데스트톱 뷰에선 병렬 레이아웃 적용
  4. 좋아요(찜) 기능
    1. 로그인하지 않은 상태면 “로그인이 필요한 서비스입니다” 모달 표출
    2. 찜 등록/해제 시 마이페이지에 자동 반영되어 일관된 상태를 유지
    3. heart_filled / heart_outline 아이콘으로 시각적으로 찜 등록/해제 표현
    4. 찜 버튼 클릭 시 useLikeToggleMutation으로 서버에 등록/해제 요청 → 성공 시 refetch( )를 통해 zustand userInfo를 업데이트 → UI 즉시 반영

🧠 성과

이 프로젝트를 통해 Next.js 환경에서 SSR과 CSR을 혼합해 사용하며 Hydration Error, 무한 루프 등

상태 불일치 이슈를 해결해 볼 수 있었습니다.

로그인/회원가입부터카페 필터링까지 전 과정의 UI/UX를 혼자 설계하고, React Query + Zustand로 인증·데이터 흐름을 효율화하며 개발 속도와 코드 유지보수성을 높였습니다.

또한, AWS 기반 서버와의 REST API 통신을 백엔드 팀원과 함께 설정하면서, 배포 과정에서 마주한 보안 그룹/포트 문제 등을 실무와 유사한 방식으로 트러블슈팅했습니다.

결과적으로 아이디어 기획부터 디자인, SSR/CSR 구조 설계, 배포까지 프로젝트 전반을 경험하며 프론트엔드와 백엔드 협업에 대한 이해도를 한층 더 확장할 수 있었습니다.