Skip to content
 
 

Repository files navigation

MateTrip (Travel Planning Tool)

MateTrip은 실시간 협업을 통해 여행 계획을 손쉽게 세울 수 있는 웹 애플리케이션입니다. 친구들과 함께 지도를 보며 일정을 조율하고, 화상 채팅으로 소통하며, AI 추천을 통해 최적의 여행 경로를 찾을 수 있습니다.

Design Reference: Travel Planning Tool Design (Figma)

✨ Key Features (주요 기능)

1. 🗺️ 실시간 협업 지도 (Real-Time Collaborative Map)

  • 동시 편집: 여러 사용자가 동시에 지도 위에서 장소를 추가, 삭제, 이동할 수 있으며, 모든 변경 사항이 실시간으로 반영됩니다.
  • 커서 공유: 다른 사용자의 마우스 커서 위치와 현재 보고 있는 화면 영역을 실시간으로 공유하여 원활한 소통을 돕습니다.
  • 카테고리 필터링: 관광지, 숙소, 맛집 등 카테고리별로 장소를 필터링하여 지도에 표시할 수 있습니다.

2. 📅 드래그 앤 드롭 일정 관리 (Drag & Drop Itinerary)

  • 직관적인 UI: @dnd-kit을 활용하여 장소 카드를 드래그하여 날짜별 일정에 쉽게 추가하거나 순서를 변경할 수 있습니다.
  • 경로 시각화: 일정에 추가된 장소들 간의 이동 경로와 소요 시간, 거리를 지도와 리스트에서 즉시 확인할 수 있습니다.
  • 장소 보관함: 관심 있는 장소를 임시 보관함에 담아두고 언제든지 일정으로 옮길 수 있습니다.

3. 🤖 AI 기반 여행 추천 및 최적화 (AI Recommendation & Optimization)

  • AI 여행 가이드: 챗봇에게 여행 스타일이나 선호도를 말하면 적절한 장소를 추천해줍니다.
  • 경로 최적화: 선택한 장소들을 가장 효율적으로 방문할 수 있는 최적의 경로를 AI가 계산하여 제안합니다.
  • 자동 일정 생성: 여행 기간과 목적지만 입력하면 AI가 전체 여행 일정을 자동으로 생성해줍니다.

4. 📹 화상 및 음성 채팅 (Video & Voice Chat)

  • Amazon Chime SDK 연동: 별도의 프로그램 설치 없이 웹 브라우저 내에서 고화질 화상 통화와 음성 채팅이 가능합니다.
  • 화면 공유: 여행 계획을 세우면서 서로의 얼굴을 보거나 필요한 정보를 화면으로 공유할 수 있습니다.

5. 📍 풍부한 장소 정보 (Rich Place Information)

  • 상세 정보 제공: Kakao Maps API와 자체 데이터를 결합하여 장소의 사진, 주소, 개요, 카테고리 등 상세한 정보를 제공합니다.
  • 주변 장소 추천: 선택한 장소 주변의 인기 있는 관광지나 맛집을 자동으로 추천해줍니다.

🛠️ Tech Stack (기술 스택)

Frontend

  • Core: React 19, TypeScript, Vite
  • State Management: Zustand
  • Styling: Tailwind CSS, Radix UI, Framer Motion
  • Maps: React Kakao Maps SDK, Kakao Mobility API
  • Real-Time: Socket.io-client
  • Drag & Drop: @dnd-kit
  • Communication: Amazon Chime SDK
  • Forms: React Hook Form

DevOps & Tools

  • Package Manager: npm
  • Linting & Formatting: ESLint, Prettier
  • Deployment: AWS (Frontend & Backend)

🧩 Technical Challenges (기술적 도전 과제)

1. 실시간 동시성 제어 (Real-Time Concurrency Control)

  • 문제: 여러 사용자가 동시에 같은 일정을 수정할 때 데이터 충돌이 발생할 수 있음.
  • 해결: Socket.io를 활용하여 모든 이벤트를 중앙 서버를 통해 브로드캐스팅하고, 낙관적 UI 업데이트(Optimistic UI Update)를 적용하여 사용자 경험을 저해하지 않으면서 데이터 일관성을 유지했습니다.

2. 대용량 지도 데이터 렌더링 최적화 (Map Rendering Optimization)

  • 문제: 지도에 수많은 마커와 경로를 표시할 때 성능 저하 발생.
  • 해결: 현재 뷰포트(Viewport) 내에 있는 장소만 렌더링하는 가시성 필터링(Visibility Filtering)과 마커 클러스터링 기술을 도입하여 렌더링 성능을 최적화했습니다. 또한, React.memouseMemo를 적극 활용하여 불필요한 리렌더링을 방지했습니다.

3. 복잡한 드래그 앤 드롭 인터랙션 (Complex Drag & Drop Interactions)

  • 문제: 지도, 사이드바, 보관함 등 서로 다른 컨텍스트 간의 드래그 앤 드롭을 매끄럽게 연결해야 하는 복잡성 발생.
  • 해결: @dnd-kitSortableContext를 활용하되, 각 영역(보관함, 일자별 일정)을 독립적인 Droppable 영역으로 관리하고, onDragEnd 이벤트 핸들러에서 드래그 소스와 타겟의 ID를 분석하여 상태 업데이트 로직을 분기 처리함으로써 유연한 이동을 구현했습니다.

🎭 독립 데모 모드 (Backend-less Demo Mode)

포트폴리오 데모 배포판은 실제 NestJS 백엔드·FastAPI AI 서버 없이, 프론트엔드 혼자서 완전히 동작합니다.

  • REST API: Mock Service Worker(MSW)가 브라우저 안에서 네트워크 요청을 가로채 고정된 데모 데이터로 응답합니다(src/mocks/handlers/rest.ts).
  • Socket.io 실시간 기능: socket.io-client 패키지 자체를 직접 만든 가짜 구현(src/mocks/fake-socket-io.ts)으로 바꿔치기합니다. 실제 Socket.IO 프로토콜을 흉내 내는 대신, 이 앱이 실제로 쓰는 소켓 인터페이스(.on/.off/.emit/.disconnect/.connected/.id) 여섯 가지만 구현합니다.
    • 지도 협업(POI) 목서버: src/mocks/fake-socket-server/poi.ts
    • 채팅 목서버: src/mocks/fake-socket-server/chat.ts
  • 가상 협업 연출: 실제로 접속한 사용자가 한 명뿐이어도, 워크스페이스 입장 8초 뒤 가상 동행자("김동행")가 장소 하나를 자동으로 추가한 것처럼 이벤트를 흉내 내서 실시간 협업 기능을 보여줍니다.
  • AI 채팅 응답: @AI 채팅 응답은 실제 LLM이 아니라, 미리 정해둔 고정 데이터(장소 추천 2곳)로 응답합니다.

왜 이렇게 만들었나

원래 백엔드는 NestJS(REST + Socket.io 게이트웨이 2개) + FastAPI(AI 에이전트) + PostgreSQL(PostGIS·pgvector) + Redis 조합으로 되어 있어, 이 스택 전체를 상시 배포하려면 무료 호스팅 티어의 콜드 스타트·데이터베이스 자동 삭제 같은 제약을 감수해야 했습니다. 대신 프론트엔드만 독립적으로 배포해 핵심 기능(실시간 협업, AI 채팅)을 그대로 시연할 수 있는 방향을 선택했습니다.

로컬에서 데모 모드로 실행하기

.env에 아래 값을 추가하고 npm run dev를 실행하면, 실제 백엔드 없이도 전체 기능을 확인할 수 있습니다.

VITE_USE_MOCKS=true

이 값을 빼거나 false로 두면, 기존처럼 VITE_REACT_APP_SERVER_URL 등에 설정된 실제 백엔드에 연결합니다.

🚀 Getting Started (시작하기)

Prerequisites

  • Node.js (Latest LTS recommended)
  • npm

Installation

  1. Clone the repository

    git clone https://github.com/yourusername/matetrip-frontend.git
    cd matetrip-frontend
  2. Install dependencies

    npm install
  3. Environment Setup Create a .env file in the root directory and add necessary API keys:

    VITE_KAKAO_MAP_API_KEY=your_kakao_map_api_key
    VITE_API_URL=your_backend_api_url
  4. Run the development server

    npm run dev

📜 Scripts

  • npm run dev: 개발 서버 실행
  • npm run build: 프로덕션 빌드
  • npm run preview: 빌드된 결과물 미리보기
  • npm run lint: 코드 린팅
  • npm run format: 코드 포맷팅

👨‍💻 My Contributions (나의 기여)

1. 여행 계획 워크스페이스 (Travel Planning Workspace)

  • 실시간 협업 환경 구축: Socket.io를 활용하여 여러 사용자가 동시에 접속하여 여행 계획을 세울 수 있는 워크스페이스를 구현했습니다.
  • 지도 및 일정 동기화: usePoiSocket 훅을 개발하여 마커 추가/삭제, 일정 변경, 커서 이동 등의 이벤트를 실시간으로 동기화했습니다.
  • 드래그 앤 드롭 일정 관리: @dnd-kit을 사용하여 장소 보관함과 일자별 일정 간의 직관적인 드래그 앤 드롭 인터페이스를 구현했습니다.
  • PDF 내보내기 기능: html2canvasjspdf를 활용하여 완성된 여행 계획을 PDF 파일로 다운로드하는 기능을 구현했습니다.

2. 지도 및 장소 정보 (Map & Place Information)

  • 카카오 지도 연동: react-kakao-maps-sdk를 사용하여 지도를 띄우고, 마커, 커스텀 오버레이, 폴리라인 등을 렌더링했습니다.
  • 경로 시각화: 카카오 모빌리티 API를 연동하여 일정에 등록된 장소들 간의 이동 경로와 소요 시간을 지도 위에 시각화했습니다.
  • 장소 상세 정보 패널: 장소 클릭 시 상세 정보를 보여주는 패널을 구현하고, 주변 장소 추천 기능을 연동했습니다.

3. UI/UX 및 스타일링 (UI/UX & Styling)

  • 반응형 레이아웃: Tailwind CSS를 활용하여 다양한 화면 크기에 대응하는 반응형 레이아웃을 구성했습니다.
  • 모달 및 컴포넌트: Radix UI 기반의 재사용 가능한 UI 컴포넌트(모달, 버튼, 입력 폼 등)를 개발하고 스타일링했습니다.
  • 사용자 경험 개선: 로딩 인디케이터, 스켈레톤 UI, 토스트 알림 등을 적절히 사용하여 사용자 경험을 향상시켰습니다.

4. 성능 최적화 및 버그 수정 (Optimization & Bug Fixes)

  • 렌더링 최적화: React.memo, useMemo, useCallback 등을 활용하여 불필요한 리렌더링을 방지하고 성능을 최적화했습니다.
  • 빌드 오류 수정: 배포 과정에서 발생하는 빌드 오류를 해결하고, 환경 변수 설정 등을 관리했습니다.
  • PDF 생성 최적화: 많은 양의 이미지와 지도가 포함된 PDF 생성 시 발생하는 성능 문제를 해결하고, 페이지 분할 로직을 개선했습니다.

🚀 Detailed Technical Contributions (상세 기술 기여)

1. Real-Time Collaboration Engine (실시간 협업 엔진)

  • Custom Hook 설계 (usePoiSocket): 소켓 연결의 생명주기를 관리하고, join, sync, mark, move 등 다양한 이벤트를 캡슐화하여 컴포넌트 로직을 분리했습니다.
  • 낙관적 업데이트 (Optimistic UI): 네트워크 지연을 최소화하기 위해 markPoi 등의 함수에서 서버 응답을 기다리지 않고 로컬 상태(pois)를 즉시 갱신하도록 구현했습니다. 이를 통해 사용자는 끊김 없는 경험을 할 수 있으며, 소켓 전송 실패 시 롤백 로직을 통해 데이터 정합성을 유지했습니다.
  • 커서 동기화 최적화: 마우스 이동 이벤트(mousemove)가 과도하게 발생하는 것을 방지하기 위해 스로틀링(Throttling)을 적용하여 CURSOR_MOVE 이벤트를 효율적으로 전송하고, 다른 사용자의 위치를 실시간으로 부드럽게 시각화했습니다.

2. Interactive Map System (인터랙티브 지도 시스템)

  • 뷰포트 기반 데이터 페칭 (Viewport-based Fetching): MapPanel 컴포넌트에서 지도의 idle 이벤트를 감지하여 현재 사용자가 보고 있는 영역(getBounds)에 해당하는 장소 데이터만 웹소켓으로 요청하도록 구현했습니다. 이는 초기 로딩 속도를 획기적으로 개선하고 불필요한 데이터 전송을 줄였습니다.
  • 렌더링 성능 최적화: useMemo를 활용하여 수천 개의 장소 데이터 중 현재 활성화된 카테고리와 일정에 포함된 장소만 필터링하여 렌더링하도록 최적화했습니다. 또한, React.memo로 마커 컴포넌트를 감싸 불필요한 리렌더링을 방지했습니다.
  • 경로 시각화 파이프라인: 카카오 모빌리티 API의 응답(RouteSegment)을 파싱하여 지도 위에 Polyline으로 경로를 그리고, 경로의 중간 지점을 계산하여 소요 시간과 거리를 표시하는 커스텀 오버레이를 동적으로 생성했습니다.

3. Complex Drag & Drop Logic (복잡한 드래그 앤 드롭 로직)

  • 다중 컨텍스트 지원: @dnd-kit을 사용하여 '장소 검색 결과', '장소 보관함', '일자별 일정'이라는 서로 다른 성격의 컨테이너 간 드래그 앤 드롭을 구현했습니다.
  • 상태 관리 분기 처리: onDragEnd 핸들러에서 드래그 소스(Source)와 타겟(Target) 컨테이너의 ID를 분석하여, 단순 순서 변경(reorderPois), 일정 간 이동(moveSchedule), 보관함 추가(markPoi) 등 다양한 시나리오에 맞는 소켓 이벤트를 발송하도록 정교하게 분기 처리했습니다.

4. PDF Generation Architecture (PDF 생성 아키텍처)

  • 동적 페이지네이션 알고리즘: 여행 일수가 늘어남에 따라 PDF 페이지를 동적으로 계산하는 로직을 구현했습니다. 첫 페이지에는 지도와 핵심 요약을 배치하고, 이후 페이지부터는 상세 일정을 3개씩 나누어 배치하여 가독성을 높였습니다.
  • CORS 이미지 프록시 처리: html2canvas로 화면을 캡처할 때 외부 이미지(카카오, 관광공사 등)로 인해 발생하는 CORS 오류(Tainted Canvas)를 해결하기 위해, 백엔드에 이미지 프록시 API(/proxy/image)를 연동하여 이미지를 우회 로딩하는 방식으로 PDF 생성 기능을 완성했습니다.

This project is part of a portfolio demonstrating advanced frontend development skills.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages