์ฌ์ด๋ ํ๋ก์ ํธ ๋ฉ์ดํธ๋ ๊ฐ๋ฐ์๋ค์ด ์ฌ์ด๋ ํ๋ก์ ํธ๋ฅผ ํจ๊ป ์งํํ ํ์์ ์ฐพ๊ณ ํ์ ํ ์ ์๋ ํ๋ซํผ์ ๋๋ค.
- ์ด๋ฉ์ผ & ๋น๋ฐ๋ฒํธ ๊ธฐ๋ฐ ํ์๊ฐ์ /๋ก๊ทธ์ธ
- JWT ๊ธฐ๋ฐ ์ธ์ ๊ด๋ฆฌ (next-auth)
- bcryptjs ๋น๋ฐ๋ฒํธ ํด์ฑ ๋ฐ ๋ฏธ๋ค์จ์ด ์ ๊ทผ ์ ์ด
- ํ๋ก์ ํธ ์์ฑ: ์ธ๋ค์ผ ๋๋๊ทธ & ๋๋กญ ์ ๋ก๋(Cloudinary), ๊ธฐ์ ์คํ ํ๊ทธ ์ ํ, Tiptap ๊ธฐ๋ฐ ๋ฆฌ์น ํ ์คํธ ์๋ํฐ ์ง์
- ํ๋ก์ ํธ ์กฐํ: ์นดํ ๊ณ ๋ฆฌ / ์ํ / ์ ๋ ฌ ํํฐ๋ง ๋ฐ ํค์๋ ๊ฒ์
- ํตํฉ ๋์๋ณด๋: ํ๋ก์ ํธ๋ณ ์นธ๋ฐ ๋ณด๋์ WBS๋ฅผ ํ ํ๋ฉด์์ ๊ด๋ฆฌ
- ์จ๋ณด๋ฉ ์์ ๋: ์ด๊ธฐ ์ง์ ์ ์ง๊ตฐ, ๊ฒฝ๋ ฅ ๋ฑ ํ์ ์ ๋ณด๋ฅผ ์ ๋ ฅ๋ฐ๋ ๋จ๊ณ๋ณ ๊ฐ์ด๋
- ํ๋กํ ๊ด๋ฆฌ: ๊ธฐ๋ณธ ์ ๋ณด ๋ฐ ์ปค๋ฎค๋์ผ์ด์ ์ฑํฅ(MBTI, ์จ/์คํ๋ผ์ธ ์ ํธ๋) ๊ด๋ฆฌ
- ๊ธฐ์ ์คํ (Skill Stack):
skillicons.dev๊ธฐ๋ฐ์ ์ง๊ด์ ์ธ ์์ด์ฝ UI, ์ฃผ์ ๊ธฐ์ ๋ฐ ์๋ จ๋ ์๊ฐํ - ๊ฐ๋ฐ์ ํ๋ ์งํ:
- GitHub ์ฐ๋: ์ปค๋ฐ ํ๋(Green Light), ์ธ์ด ์ฌ์ฉ๋, Top Skills ์๋ ๋ถ์
- Solved.ac (๋ฐฑ์ค): ์๊ณ ๋ฆฌ์ฆ ํฐ์ด, ๋ญํฌ, ์คํธ๋ฆญ ์นด๋ ํ์
- Tech Blog: Velog ๋ฑ ๊ธฐ์ ๋ธ๋ก๊ทธ ์ต์ ๊ธ RSS ์๋ ์์ง
- ๊ฐ์ฉ์ฑ ์ค์ผ์ค๋ฌ: ์ฃผ๊ฐ ํ์ ๊ฐ๋ฅ ์๊ฐ ๋๋๊ทธ ์ ํ ๋ฐ ์๊ฐํ
- ๋ง์ดํ์ด์ง: ๋ณธ์ธ์ด ์ ์ถํ ์ง์ ๋ด์ญ(์ง์ ํ๋ก์ ํธ, ์ญํ , ์ํ) ํ์ธ
- ์ง์ํ๊ธฐ: ํฌ๋ง ์ญํ ์ ํ ๋ฐ ์ง์ ๋ฉ์์ง ์์ฑ
- ์ง์์ ๊ด๋ฆฌ: ํ๋ก์ ํธ ์์ฑ์๊ฐ ์ง์์ ๋ชฉ๋ก ํ์ธ ๋ฐ ์๋ฝ/๊ฑฐ์ ์ฒ๋ฆฌ
- ์นธ๋ฐ ๋ณด๋ (Kanban Board):
dnd-kit๊ธฐ๋ฐ์ To Do / In Progress / Done ์ ๋ฌด ๊ด๋ฆฌ- ๋๋๊ทธ & ๋๋กญ์ผ๋ก ์ง๊ด์ ์ธ ์ํ ๋ณ๊ฒฝ
- ์ค์๊ฐ Presence(ํ์ฌ ์ ์์) ํ์ ๋ฐ ๋ฆฌ์์ค ์ ๊ธ(์ถฉ๋ ๋ฐฉ์ง)
- WBS (Work Breakdown Structure):
gantt-task-react๊ธฐ๋ฐ์ ๊ฐํธ ์ฐจํธ (์ผ / ์ฃผ / ์ ๋ทฐ ์ง์)- ์์ ๊ฐ ์์กด์ฑ(Dependency) ์ค์ ๋ฐ ์๊ฐํ
- ์ผ์ ์ถฉ๋ ๊ฐ์ง ๋ฐ ๊ฒฝ๊ณ ์๋ฆผ
- ํ์๋ผ์ธ์์ ๋๋๊ทธ๋ก ์ง์ ์์ ๊ธฐ๊ฐ ์กฐ์
- ์ค์๊ฐ ๋๊ธฐํ:
Socket.io๊ธฐ๋ฐ์ ๋ ธํธ ์์ฑ/์์ /์ญ์ /์ ํ ์ํ ์ค์๊ฐ ์ ํ
ํ์ฌ UI ํ๋กํ ํ์ ๋จ๊ณ์ ๋๋ค. ๋ฐฑ์๋ API ๋ฐ ๋ชจ๋ธ์ ๊ตฌํ ์๋ฃ, ์ค์๊ฐ ์ฐ๋ ์์ ์งํ ์ค์ ๋๋ค.
- ์ฑํ ๋ฐฉ ์ ํ: INQUIRY(๋ฌธ์), RECRUIT(์ธํฐ๋ทฐ), TEAM(ํ ์ฑํ ๋ฐฉ), DM(1:1), SYSTEM(๊ฐ์ด๋ ๋ด)
- ์ฑํ ๋ฐฉ ์์ฑ ์ ์นดํ ๊ณ ๋ฆฌ๋ณ ์์คํ ์๋ด ๋ฉ์์ง ์๋ ๋ฐ์ก
- DM ์ค๋ณต ๋ฐฉ์ง ๋ก์ง (๋์ผ ์ฐธ์ฌ์ ๊ตฌ์ฑ์ ๋ฐฉ ์ฌํ์ฉ)
- ์ค์๊ฐ ์๋ฆผ ์์คํ (์ง์ ๊ฒฐ๊ณผ, ์ ์ง์์ ์๋ฆผ ๋ฑ)
- Zustand ๊ธฐ๋ฐ ์๋ฆผ ์คํ ์ด
| ๋ถ๋ฅ | ๊ธฐ์ |
|---|---|
| Framework | Next.js 14.2 (App Router) |
| Language | TypeScript 5.3 |
| Styling | Tailwind CSS 3.4, Styled Components 6 |
| State Management | Zustand 4.5, Zundo (Undo/Redo) |
| ๋๋๊ทธ & ๋๋กญ | dnd-kit (์นธ๋ฐ), gantt-task-react (WBS) |
| ์๋ํฐ | Tiptap 2 (Rich Text Editor, Code Block) |
| ์ผ์ | react-schedule-selector |
| ๊ธฐํ UI | react-slick (์บ๋ฌ์ ), react-markdown |
| ๋ถ๋ฅ | ๊ธฐ์ |
|---|---|
| Runtime | Node.js 20.x |
| Server | Next.js API Routes + Express (Socket.io ์ ์ฉ) |
| Database | MongoDB Atlas (Mongoose 8.x) |
| ์ค์๊ฐ | Socket.io 4.8 |
| ์ธ์ฆ | next-auth 4, jsonwebtoken, bcryptjs |
| ์ด๋ฏธ์ง | Cloudinary 2 |
| GraphQL | graphql-request (GitHub API ์ฐ๋) |
| RSS | rss-parser (Tech Blog ์ฐ๋) |
| OG | open-graph-scraper |
| ๋ถ๋ฅ | ๊ธฐ์ |
|---|---|
| Linting | ESLint 8.56, Prettier |
| Dev Server | nodemon + ts-node |
| Deployment | Render.com (Free Plan) |
- Node.js 20.x ๊ถ์ฅ (>=18 ์ง์)
- npm 8 ์ด์
1. ์ ์ฅ์ ํด๋ก
git clone https://github.com/kimis0719/sideProjectMate.git
cd sideProjectMate2. ์์กด์ฑ ์ค์น
npm install3. ํ๊ฒฝ ๋ณ์ ์ค์
ํ๋ก์ ํธ ๋ฃจํธ์ .env.local ํ์ผ์ ์์ฑํ๊ณ ์๋ ๋ณ์๋ค์ ์ค์ ํ์ธ์.
# MongoDB
MONGODB_URI=mongodb+srv://<user>:<pass>@<cluster>/<db>?retryWrites=true&w=majority
# Auth
JWT_SECRET=your_secure_jwt_secret
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your_nextauth_secret
# Cloudinary (์ด๋ฏธ์ง ์
๋ก๋)
CLOUDINARY_CLOUD_NAME=...
CLOUDINARY_API_KEY=...
CLOUDINARY_API_SECRET=...4. ๊ฐ๋ฐ ์๋ฒ ์คํ
# ๊ฐ๋ฐ ๋ชจ๋ (nodemon + ts-node, ํฌํธ 3000)
npm run dev
# ํ๋ก๋์
๋น๋ ๋ฐ ์คํ
npm run build
npm run start5. ๋ธ๋ผ์ฐ์ ํ์ธ
http://localhost:3000
sideProjectMate/
โโโ server.ts # Express + Socket.io ์ปค์คํ
์๋ฒ
โโโ next.config.js
โโโ render.yaml # Render.com ๋ฐฐํฌ ์ค์
โโโ src/
โโโ app/ # Next.js App Router ํ์ด์ง
โ โโโ api/ # API Routes
โ โ โโโ applications/ # ์ง์ CRUD
โ โ โโโ auth/ # ์ธ์ฆ (next-auth)
โ โ โโโ chat/ # ์ฑํ
๋ฐฉ ์์ฑ/์กฐํ/๋ฉ์์ง
โ โ โโโ cloudinary/ # ์ด๋ฏธ์ง ์
๋ก๋
โ โ โโโ common-codes/ # ๊ณตํต ์ฝ๋ (์ง๊ตฐ, ๊ธฐ์ ๋ฑ)
โ โ โโโ kanban/ # ์นธ๋ฐ ๋ณด๋ CRUD
โ โ โโโ notifications/ # ์๋ฆผ
โ โ โโโ projects/ # ํ๋ก์ ํธ CRUD
โ โ โโโ proxy/ # ์ธ๋ถ API ํ๋ก์ (CORS ์ฐํ)
โ โ โโโ status/ # ์๋ฒ ์ํ ํ์ธ
โ โ โโโ tech-stacks/ # ๊ธฐ์ ์คํ ๋ชฉ๋ก
โ โ โโโ users/ # ์ ์ ํ๋กํ, GitHub, Solved.ac
โ โ โโโ utils/ # ์ ํธ API
โ โ โโโ wbs/ # WBS(๊ฐํธ ์ฐจํธ) CRUD
โ โโโ chat/ # ์ฑํ
UI (ํ๋กํ ํ์
)
โ โโโ dashboard/[pid]/ # ํตํฉ ๋์๋ณด๋
โ โ โโโ kanban/ # ์นธ๋ฐ ๋ณด๋ ํ์ด์ง
โ โ โโโ wbs/ # WBS ํ์ด์ง
โ โโโ kanban/[pid]/ # ์นธ๋ฐ ๋ณด๋ ๋
๋ฆฝ ๊ฒฝ๋ก
โ โโโ login/ # ๋ก๊ทธ์ธ
โ โโโ register/ # ํ์๊ฐ์
โ โโโ mypage/ # ๋ง์ดํ์ด์ง (๋ด ์ง์ ๋ด์ญ)
โ โโโ profile/[id]/ # ๊ณต๊ฐ ํ๋กํ
โ โโโ tech/ # ๊ธฐ์ ์คํ/ํ๋ ์งํ ํ์ด์ง
โ โโโ projects/ # ํ๋ก์ ํธ ๋ชฉ๋ก, ์์ธ, ์์ฑ/์์
โ โ โโโ [pid]/
โ โ โโโ new/
โ โโโ layout.tsx
โ โโโ page.tsx # ๋ฉ์ธ ํ์ด์ง
โโโ components/ # ์ฌ์ฌ์ฉ ์ปดํฌ๋ํธ
โ โโโ board/ # ์นธ๋ฐ ๋ณด๋
โ โโโ chat/ # ์ฑํ
UI
โ โโโ common/ # ๊ณตํต ์ปดํฌ๋ํธ
โ โโโ dashboard/ # ํตํฉ ๋์๋ณด๋
โ โโโ editor/ # Tiptap ์๋ํฐ
โ โโโ profile/ # ํ๋กํ & ์จ๋ณด๋ฉ
โ โโโ projects/ # ํ๋ก์ ํธ ๊ด๋ จ
โ โโโ wbs/ # WBS(๊ฐํธ ์ฐจํธ)
โโโ store/ # Zustand ์คํ ์ด
โ โโโ boardStore.ts # ์นธ๋ฐ ๋ณด๋ ์ํ
โ โโโ wbsStore.ts # WBS ์ํ (Undo/Redo ํฌํจ)
โ โโโ modalStore.ts # ๋ชจ๋ฌ ์ํ
โโโ lib/
โ โโโ models/ # Mongoose ์คํค๋ง
โ โ โโโ User.ts
โ โ โโโ Project.ts
โ โ โโโ Application.ts
โ โ โโโ Notification.ts
โ โ โโโ Availability.ts
โ โ โโโ ChatRoom.ts
โ โ โโโ ChatMessage.ts
โ โ โโโ Comment.ts
โ โ โโโ CommonCode.ts
โ โ โโโ Post.ts
โ โ โโโ ProjectMember.ts
โ โ โโโ Skill.ts
โ โ โโโ TechStack.ts
โ โ โโโ kanban/ # Board, Section, Note ๋ชจ๋ธ
โ โ โโโ wbs/ # Task ๋ชจ๋ธ
โ โโโ store/
โ โ โโโ notificationStore.ts
โ โโโ blog/ # RSS ํ์ฑ ์ ํธ
โ โโโ github/ # GitHub GraphQL ์ฐ๋
โ โโโ utils/ # WBS ์์กด์ฑ ๊ณ์ฐ ๋ฑ ํฌํผ
โโโ hooks/ # ์ปค์คํ
ํ
โโโ constants/ # ์์ ์ ์
โโโ types/ # TypeScript ํ์
์ ์
๊ฐ๋ฐ ์๋ฒ๋ Express + Socket.io ์ปค์คํ
์๋ฒ(server.ts)๋ก ๊ตฌ๋๋ฉ๋๋ค.
| ์ด๋ฒคํธ (Client โ Server) | ์ค๋ช |
|---|---|
join-board |
์นธ๋ฐ ๋ณด๋ ๋ฃธ ์ ์ |
user-activity |
๋ณด๋ Presence ์ ๋ณด ์ ์ก (์ ์์ ๋ชฉ๋ก ๊ฐฑ์ ) |
leave-board |
์นธ๋ฐ ๋ณด๋ ๋ฃธ ์ดํ |
update-note / create-note / delete-note |
๋ ธํธ ๋ณ๊ฒฝ ์ค์๊ฐ ์ ํ |
update-section / create-section / delete-section |
์น์ ๋ณ๊ฒฝ ์ค์๊ฐ ์ ํ |
request-lock / release-lock |
๋ ธํธ/์น์ ํธ์ง ์ ๊ธ (์ถฉ๋ ๋ฐฉ์ง) |
sync-board |
Undo/Redo ์ ์ ์ฒด ๋ณด๋ ๋๊ธฐํ |
select-note / deselect-note |
์ค์๊ฐ ๋ ธํธ ์ ํ ์ํ ๊ณต์ |
join-project |
ํ๋ก์ ํธ ๋ฃธ ์ ์ (์จ๋ผ์ธ ์ํ ๋ฑ๋ก) |
resource-update |
ํ๋ก์ ํธ ๋ฆฌ์์ค ๋ณ๊ฒฝ ์๋ฆผ |
project-update |
ํ๋ก์ ํธ ์ํ/๊ฐ์ ๋ณ๊ฒฝ ์๋ฆผ |
join-chat-room / leave-chat-room |
์ฑํ ๋ฐฉ ๋ฃธ ์ ์/์ดํ |
send-notification |
์ค์๊ฐ ์๋ฆผ ์ ์ก |
npm run dev # ๊ฐ๋ฐ ์๋ฒ ์คํ (nodemon + ts-node)
npm run build # ํ๋ก๋์
๋น๋ (Next.js ๋น๋ + server.ts ์ปดํ์ผ)
npm run start # ํ๋ก๋์
์๋ฒ ์คํ (dist/server.js)
npm run lint # ESLint ์คํ
npm run format # Prettier ํฌ๋งทํ
render.yaml์ด ์ค์ ๋์ด ์์ด GitHub ์ฐ๋ ์ ์๋ ๋ฐฐํฌ๋ฉ๋๋ค.
- Render.com ๋ก๊ทธ์ธ ํ "New Web Service" ์์ฑ
- GitHub ์ ์ฅ์ ์ฐ๊ฒฐ
- Build Command:
npm install && npm run build - Start Command:
npm start - Environment Variables์
.env.localํญ๋ชฉ ๋์ผํ๊ฒ ์ ๋ ฅ - ๋ฐฐํฌ ์์
"Unsupported Server Component type" ์๋ฌ
- ํด๋ผ์ด์ธํธ ํ
(
useState,useEffect๋ฑ)์ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ ์ต์๋จ์'use client'์ง์์ด๊ฐ ์๋์ง ํ์ธํ์ธ์.
Socket.io ์ฐ๊ฒฐ ์คํจ
npm run dev์คํ ํ ํฐ๋ฏธ๋์์> Ready on http://localhost:3000๋ฉ์์ง๋ฅผ ํ์ธํ์ธ์.- ํด๋ผ์ด์ธํธ ์ธก Socket.io ๊ฒฝ๋ก(
/api/socket/io)๊ฐserver.ts์path์ค์ ๊ณผ ์ผ์นํ๋์ง ํ์ธํ์ธ์.
์ฑํ ๊ธฐ๋ฅ์ด ๋์ํ์ง ์์์
- ํ์ฌ ์ฑํ UI๋ Mock ๋ฐ์ดํฐ ๊ธฐ๋ฐ ํ๋กํ ํ์ ์ ๋๋ค. DB ์ฐ๋ ์์ ์ด ์งํ ์ค์ ๋๋ค.
- Issue ์์ฑ
- Fork & Branch ์์ฑ (
feature/amazing-feature) - Commit & Push
- Pull Request ์์ฒญ
์ด ํ๋ก์ ํธ๋ MIT ๋ผ์ด์ผ์ค๋ฅผ ๋ฐ๋ฆ ๋๋ค.