Project
— Overview
날짜별 장소를 등록하고 여행 일정을 시각적으로 관리하는 풀스택 웹 앱. React 프론트엔드와 Node.js/Express REST API, MongoDB Atlas를 조합했다.
일정 생성·수정·삭제와 함께 각 날짜별 방문지 순서를 드래그로 재정렬할 수 있으며, JWT 인증으로 사용자별 일정을 분리 저장한다.
— Core Logic
MongoDB 스키마는 여행 → 날짜 배열 → 장소 배열의 중첩 구조로 설계한다. 하나의 Document 안에 전체 일정이 담기므로 조회 시 JOIN이 불필요하다.
// models/Trip.js
const spotSchema = new Schema({
name: { type: String, required: true },
address: String,
lat: Number,
lng: Number,
memo: String,
});
const daySchema = new Schema({
date: { type: Date, required: true },
spots: [spotSchema],
});
const tripSchema = new Schema({
title: { type: String, required: true },
days: [daySchema],
owner: { type: Schema.Types.ObjectId, ref: 'User', required: true },
}, { timestamps: true });models/Trip.js — MongoDB nested schema
React 상태는 불변 업데이트 패턴을 사용한다. 특정 날짜의 장소를 추가할 때
전체 days 배열을 새로 생성해 리렌더링을 보장한다.
// 장소 추가 — 불변 업데이트
function addSpot(dayIndex, spot) {
setTrip(prev => {
const days = prev.days.map((day, i) =>
i === dayIndex
? { ...day, spots: [...day.spots, spot] }
: day
);
return { ...prev, days };
});
}hooks/useTrip.js — immutable state update
— How It Works
localStorage에 저장한다. 이후 모든 API 요청 헤더에 토큰을 포함한다.day 배열이 자동 생성된다.PATCH /trips/:id 요청을 보낸다.