๊ฐ์ ์ด์ฐจ๋ฅผ ํ๋ ์ฌ๋๋ค๊ณผ ์ค์๊ฐ์ผ๋ก ์ํตํ๋ ์น ์ฑ์ ๋๋ค.
- ์จ๋: ๋์์ / ์ถ์์
- ํผ์ก๋: ์ฌ์ ๋ก์ / ๋ณดํต / ํผ์กํจ
- ๋์: ์ฌํจ / ๊ด์ฐฎ์
- ์ฒญ๊ฒฐ๋: 1~5์ ํ๊ฐ
- ์์: 1~5์ ํ๊ฐ
- Socket.io๋ฅผ ํตํ ์ค์๊ฐ ํฌํ ๊ฒฐ๊ณผ ์ ๋ฐ์ดํธ
- ์ผ๋ฐ ์ฑํ
- ์๋ฆฌ ์๋ณด ์์ฒญ
- ๋ถ์ค๋ฌผ ์ฐพ๊ธฐ/์ ๊ณ
- 10๋ถ ํ ์๋ ์ญ์ (TTL)
- ์ฑ์ถํ/์ํ ์ํฉ
- ์๋ฃ ์๊ธ ์ํฉ
- ์ด์ํ ๋์
- ์ค์๊ฐ ์๋ฆผ ์ ํ
- Frontend: Next.js 14 (App Router), TypeScript, Tailwind CSS
- UI Library: shadcn/ui
- Backend: Next.js API Routes
- Database: MongoDB (Mongoose)
- Real-time: Socket.io
- State Management: Zustand
.env.local ํ์ผ์ ์์ฑํ๊ณ ๋ค์ ๋ด์ฉ์ ์ถ๊ฐํ์ธ์:
# MongoDB Connection String
MONGODB_URI=mongodb://localhost:27017/trainmate
# ๋๋ MongoDB Atlas ์ฌ์ฉ ์
# MONGODB_URI=mongodb+srv://<username>:<password>@cluster.mongodb.net/trainmate
# Socket.io Server URL
NEXT_PUBLIC_SOCKET_URL=http://localhost:3001npm installnpm run dev์ด ๋ช ๋ น์ด๋ ๋ค์ ๋ ์๋ฒ๋ฅผ ๋์์ ์คํํฉ๋๋ค:
- Next.js ๊ฐ๋ฐ ์๋ฒ: http://localhost:3000
- Socket.io ์๋ฒ: http://localhost:3001
ํ์ํ ๊ฒฝ์ฐ ๊ฐ ์๋ฒ๋ฅผ ๋ณ๋๋ก ์คํํ ์ ์์ต๋๋ค:
# Next.js๋ง ์คํ
npm run dev:next
# Socket.io ์๋ฒ๋ง ์คํ
npm run dev:sockettrainmate/
โโโ src/
โ โโโ app/
โ โ โโโ page.tsx # ๋ฉ์ธ ํ์ด์ง (์ด์ฐจ ๋ฒํธ ์
๋ ฅ)
โ โ โโโ train/[id]/
โ โ โ โโโ page.tsx # ์ด์ฐจ ์์ธ ํ์ด์ง
โ โ โโโ api/
โ โ โโโ trains/[id]/ # ์ด์ฐจ ์ ๋ณด API
โ โ โโโ posts/ # ๊ฒ์๊ธ API
โ โโโ components/
โ โ โโโ ui/ # shadcn/ui ์ปดํฌ๋ํธ
โ โ โโโ VotingPanel.tsx # ํฌํ ํจ๋
โ โ โโโ CommunityBoard.tsx # ์ปค๋ฎค๋ํฐ ๊ฒ์ํ
โ โ โโโ EmergencyAlert.tsx # ๋น์ ์๋ฆผ
โ โโโ lib/
โ โ โโโ mongodb.ts # MongoDB ์ฐ๊ฒฐ
โ โ โโโ models.ts # Mongoose ์คํค๋ง
โ โ โโโ socket.ts # Socket.io ํด๋ผ์ด์ธํธ
โ โโโ types/
โ โโโ index.ts # TypeScript ํ์
์ ์
โโโ socket-server.js # Socket.io ์๋ฒ
โโโ Dockerfile # Docker ์ด๋ฏธ์ง ๋น๋ ์ค์
โโโ docker-compose.yml # Docker Compose ์ค์
โโโ package.json
{
trainNumber: string; // ์ด์ฐจ ๋ฒํธ (์: "2ํธ์ -2234")
line: string; // ํธ์ (์: "2ํธ์ ")
votes: VoteCount; // ํฌํ ๋ฐ์ดํฐ
lastUpdated: Date; // ๋ง์ง๋ง ์
๋ฐ์ดํธ ์๊ฐ
}{
trainNumber: string; // ์ด์ฐจ ๋ฒํธ
type: PostType; // 'community' | 'emergency' | 'seat' | 'lost'
content: string; // ๋ด์ฉ
imageUrl?: string; // ์ด๋ฏธ์ง URL (์ ํ)
createdAt: Date; // ์์ฑ ์๊ฐ
expiresAt: Date; // ๋ง๋ฃ ์๊ฐ (TTL)
}- ์ฌ์ฉ์๊ฐ ์ด์ฐจ ๋ฒํธ๋ก ์ ์
- Socket.io๋ก ํด๋น ์ด์ฐจ room์ join
- ํฌํ/๊ฒ์๊ธ ์์ฑ ์ ์๋ฒ๋ก ์ ์ก
- ์๋ฒ์์ MongoDB ์ ๋ฐ์ดํธ
- ๊ฐ์ room์ ๋ชจ๋ ์ฌ์ฉ์์๊ฒ broadcast
# ์ด๋ฏธ์ง ๋น๋
docker build -t trainmate .
# Docker Compose๋ก ์คํ (MongoDB ํฌํจ)
docker-compose up -d
# ๋ก๊ทธ ํ์ธ
docker-compose logs -f
# ์ ์
# http://localhost:3000-
์๋ฒ ์ค๋น (Ubuntu ๊ธฐ์ค)
# Docker ์ค์น curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER # Docker Compose ์ค์น sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
-
์ฝ๋ ๋ฐฐํฌ
# ํ๋ก์ ํธ ํด๋ก git clone https://github.com/YOUR_USERNAME/trainmate.git cd trainmate # ํ๊ฒฝ ๋ณ์ ์ค์ cp .env.example .env.production nano .env.production # MONGODB_URI, NEXT_PUBLIC_SOCKET_URL ๋ฑ ์์ # ๋น๋ ๋ฐ ์คํ docker build -t trainmate . docker-compose --env-file .env.production up -d
-
ํฌํธ ์ด๊ธฐ
- 3000 (Next.js)
- 3001 (Socket.io)
.env.production ์์:
MongoDB Atlas ์ฌ์ฉ ์ (๊ถ์ฅ):
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/trainmate?retryWrites=true&w=majority
NEXT_PUBLIC_SOCKET_URL=http://YOUR_SERVER_IP:3001
CORS_ORIGIN=http://YOUR_SERVER_IP:3000
NODE_ENV=production๋ก์ปฌ MongoDB ์ฌ์ฉ ์ (Docker Compose ๊ธฐ์ค):
MONGODB_URI=mongodb://mongodb:27017/trainmate
NEXT_PUBLIC_SOCKET_URL=http://YOUR_SERVER_IP:3001
CORS_ORIGIN=http://YOUR_SERVER_IP:3000
NODE_ENV=production# ๋ก๊ทธ ํ์ธ
docker-compose logs -f
# ์ฌ์์
docker-compose restart
# ์ค์ง
docker-compose down
# ์
๋ฐ์ดํธ
git pull
docker build -t trainmate .
docker-compose up -d- ์ต๋ช ์ฌ์ฉ์ ๋ฐฉ์์ผ๋ก ๋ณ๋์ ์ธ์ฆ์ด ์์ต๋๋ค.
- ๊ฒ์๊ธ์ 10๋ถ ํ ์๋ ์ญ์ ๋ฉ๋๋ค.
- ๋น์ ์๋ฆผ์ ์ค์ ๊ธด๊ธ ์ํฉ์๋ง ์ฌ์ฉํด์ฃผ์ธ์.
- MongoDB TTL ์ธ๋ฑ์ค๊ฐ ์ ๋๋ก ์๋ํ๋์ง ํ์ธํ์ธ์.
npx shadcn@latest add [component-name]src/app/api/ ๋๋ ํ ๋ฆฌ์ route.ts ํ์ผ์ ์์ฑํ์ธ์.
src/types/index.ts์ ์ด๋ฒคํธ ํ์ ์ ์socket-server.js์ ์๋ฒ ์ธก ํธ๋ค๋ฌ ์ถ๊ฐ- ํด๋ผ์ด์ธํธ์์
getSocket()์ผ๋ก ์ด๋ฒคํธ ์ก์์