์ฌ๋ฌ ๋ธ๋ผ์ฐ์ ๊ฒ์์ ํ๊ณณ์์ ์ฆ๊ธฐ๋ ๊ฒ์ ํ๋ธ์ ๋๋ค. Next.js ํ๋ก ํธ์๋ + ๋ ๋ฆฝ Socket.io ๋ฉํฐํ๋ ์ด์ด ์๋ฒ๋ก ๊ตฌ์ฑ๋ ํ์คํ ํ๋ก์ ํธ๋ก, ์๋ก ๋ค๋ฅธ 4๊ฐ์ ๋ ๋๋ง ์์ง(2D Canvas / Babylon.js / CesiumJS / Three.js + cannon-es)์ผ๋ก ๋ง๋ 7๊ฐ์ ๊ฒ์์ ์ ๊ณตํฉ๋๋ค.
๐ ๋ผ์ด๋ธ ๋ฐ๋ชจ: https://games.writingdeveloper.blog
| ๐ฌ JELLY CATCHER (์ค๋ฌผ๋ฆฌ ์ธํ๋ฝ๊ธฐ) | ๐ ์ญ์ ๊ตญ์ (๊ฐ๋ฝ๊ตญ์ ์๋น) |
|---|---|
![]() |
![]() |
| ๐๏ธ Dust Drifter (์ฌ๋ง ์์ ์ฃผํ) | ๐ฃ ๋งํค๋ง says (๋ ๋ชฉ์๋ฆฌ ์ฌ์ด๋จผ) |
![]() |
![]() |
๐ฑ ๋ชจ๋ฐ์ผ ํฐ์น ์กฐ์ โ ๋์ฃผ ๊ฒ์์ ํ๋ฉด d-pad์ ์ค์์ดํ๋ก ํ๋ ์ดํ ์ ์์ต๋๋ค.
![]()
- 7๊ฐ ๊ฒ์ ยท 4๊ฐ์ ๋ ๋ฆฝ ๋ ๋๋ง ์์ง โ 2D Canvas, Babylon.js(3D), CesiumJS(์ค์ ์ง๊ตฌ๋ณธ), Three.js + cannon-es(๋ฌผ๋ฆฌ ์ธํ๋ฝ๊ธฐ / ๋ก์ฐํด๋ฆฌ 3D) ํตํฉ
- ํ์คํ ์ค์๊ฐ ๋ฉํฐํ๋ ์ด์ด ๊ตฌ์กฐ โ Socket.io ๊ธฐ๋ฐ ๋ฃธ ๋งค์นญ/๋ก๋น + ๊ถ์ ์๋ฒ(authoritative server) ๊ตฌํ (๋์ฃผยท์๋ฐ์ด๋ฒยท๋นํ ๋ท์ฝ๋๋
server/ยทpublic/shared/์ ๊ตฌํ. ํ์ฌ ๋ผ์ด๋ธ ๋ฐ๋ชจ๋ ์ฑ๊ธํ๋ ์ด์ด๋ก ์๋น) - ๋ชจ๋ ธ๋ ํฌ ๊ตฌ์กฐ โ Next.js ์ฑ๊ณผ ๊ฒ์ ์๋ฒ๋ฅผ ํ ์ ์ฅ์์์ ๊ด๋ฆฌ, ๊ฐ๊ฐ ๋ ๋ฆฝ ๋ฐฐํฌ
- ํ ์คํธ & CI โ Vitest ๋จ์/ํตํฉ ํ ์คํธ + Playwright E2E + GitHub Actions ์๋ํ
- ํ์ ์์ ์ฑ โ TypeScript, ESLint, Prettier ์ผ๊ด ์ ์ฉ
- Three.js 0.184 + cannon-es ๊ธฐ๋ฐ ์ค์ ๋ฌผ๋ฆฌ ์ธํ๋ฝ๊ธฐ (์ผ๋ณธ ์์ผ์ด๋ํ)
- ์คํ๋ง-๊ทธ๋ฆฝ ์ง๊ฒ ๋ฌผ๋ฆฌ (์ง์ง๋ก ๋ฏธ๋๋ฌ์ง๋ค!) ยท 3์ข ๊ธฐ๊ณ(์ ค๋ฆฌ ยท ์ธํ ยท ๊ณต) ์ ํ
- ์ฝค๋ณด ๋ฐฐ์จ ยท ๋ง์ผ์คํค ยท ๊ฒฐ๊ณผ/๋ฆฌํ๋ ์ด ยท ๋์ /์นด๋ ๊ฒฐ์ ์ฐ์ถ
- ์กฐ์: ์๋ ๋ก๊ทธ ์กฐ์ด์คํฑ ยท ํฐ์น ์กฐ์ ยท ํ /ํ์น ์ค
- ๋น๋ ์๋ ์์ฒด์๊ฒฐํ ESM (importmap CDN ๋ก๋)
- ๋งํค๋ง(๋ณต์ข ) ยท ๋ ์ (๊ฑฐ๋ถ) ๋ ์ ๋ง์ ์์ฑ ๋ช ๋ น ์ฌ์ด๋จผ-says ๋ฐ์ ๊ฒ์
- ํ์๋ณ ๊ธ๋ฆฌํ/๋ง ์ ์ด์ค ๋ถํธํ ยท ์ฝค๋ณด ยท ๋ผ์ด๋๋ณ ๋์ด๋
- ์กฐ์:
๋ฐฉํฅํคยท ํฐ์น ์กฐ์
- Three.js ๊ธฐ๋ฐ ๋์ ์ญ ์ฌ์ผ ํ๋ซํผ ๊ฐ๋ฝ๊ตญ์ ์๋น ๊ฒ์
- ๋ฐ์น๊ธฐ ํ์ด๋ฐ ยท ์๋ 5 ์ํคํ์ ยท ์ฆ๊ธฐโ๋์ คโ๋ง์ฐจ 5์จ์ด๋ธ ยท ์ฝค๋ณด ์ค์ฝ์ด
- ์ ์ฐจ์ ์ํธ ยท ์๋๋ณ ๊ธฐ๊ด์ฐจ ยท ์น์ค๋์ค ํจ๊ณผ์
- ์กฐ์:
WASDยท ํฐ์น ์กฐ์ด์คํฑ ์ฃผ๋ฐฉ ์๋น
- HTML5 Canvas ๊ธฐ๋ฐ 2D ๊ฒ์ (์ค๋ค์ดํฌ ๋ณํ)
- ๊ฒฝ์ฐฐ์ฐจ๋ก๋ถํฐ ์๋์ฐจ๋ฅผ ์กฐ์ข ํด ๋์ฃผ
- ์กฐ์:
๋ฐฉํฅํค/WASDยท ํฐ์น d-pad ยท ์ค์์ดํ (๋ฐ์ํ ์บ๋ฒ์ค) -
์ค์๊ฐ 2โ4์ธ ๊ฒฝ์ ๋ฉํฐํ๋ ์ด์ด ๋ท์ฝ๋๊ฐ
server/ยทpublic/shared/์ ๊ตฌํ๋์ด ์์ผ๋ฉฐ, ์๋ฒ ์ฐ๊ฒฐ ์ ํ์ฑํ๋ฉ๋๋ค(ํ์ฌ ๋ผ์ด๋ธ๋ ์ฑ๊ธํ๋ ์ด์ด).
- Babylon.js ๊ธฐ๋ฐ 3D ์คํ ์๋ + Havok ๋ฌผ๋ฆฌ ์์ง
- ์๋ฐ์ด๋ฒ ์์คํ (์ฒด๋ ฅ ยท ์คํ๋ฏธ๋ ยท ๋ฐฐ๊ณ ํ ยท ๊ฐ์ฆ)
- ์บ๋ฆญํฐ ์ปค์คํฐ๋ง์ด์ง ยท ๋ฎ/๋ฐค ์ฌ์ดํด ยท ํ๊ฒ
- ์กฐ์:
WASD์ด๋ ยท ๋ง์ฐ์ค ์์ (PC ๊ถ์ฅ) -
์ค์๊ฐ 2โ4์ธ ํ๋ ๋ฉํฐํ๋ ์ด์ด ๋ท์ฝ๋๊ฐ ๊ตฌํ๋์ด ์์ผ๋ฉฐ, ์๋ฒ ์ฐ๊ฒฐ ์ ํ์ฑํ๋ฉ๋๋ค(ํ์ฌ ๋ผ์ด๋ธ๋ ์ฑ๊ธํ๋ ์ด์ด).
- CesiumJS ๊ธฐ๋ฐ 3D ๋นํ ์๋ฎฌ๋ ์ดํฐ (์ค์ ์์ฑ ์ง๋ ์ ๋นํ)
- 6๊ฐ ๋์ ์์ ์์น (์์ธ ยท ๋ด์ ยท ํ๋ฆฌ ยท ๋์ฟ ยท ๋๋ฐ์ด ยท ์๋๋)
- 3๊ฐ์ง ๋ชจ๋ (์์ ๋นํ ยท ์ฒดํฌํฌ์ธํธ ๋ ์ด์ค ยท ์๋ฐ์ด๋ฒ)
- ๋ฆฌ์ผํ ๋นํ ๋ฌผ๋ฆฌ (์๋ ฅ ยท ํญ๋ ฅ ยท ์คํจ) + HUD (์๋/๊ณ ๋/์ฐ๋ฃ/๋์นจ๋ฐ)
- ์กฐ์:
W/Sํผ์น ยทA/D๋กค ยทQ/E์ ยทShift/Ctrl์ค๋กํ (PC ๊ถ์ฅ)
- Three.js ๊ธฐ๋ฐ 3D ๋ก์ฐํด๋ฆฌ ์ฌ๋ง ์คํ ์๋ (์ฑ๊ธํ๋ ์ด์ด)
- ์์ ์ฃผํ + ์ ๊ธฐ๋ฃจ ํํ(7) + ๋น๋๋ ์์ง๋ฌผ(20) + ๋ฎโ๋ฐค ์ํ
- ๋จผ์ง ํํฐํด ๋๋ฆฌํํธ ยท ๋ ๋น ์์ด ยท 3์ธ์นญ/ํ๋๋ทฐ ์นด๋ฉ๋ผ
- ๋น๋ ์๋ ์์ฒด์๊ฒฐํ ESM (Three.js๋ฅผ importmap CDN์ผ๋ก ๋ก๋)
- ์กฐ์:
โโโโ/WASD์ฃผํ ยทSpace๋๋ฆฌํํธ ยทC์นด๋ฉ๋ผ ยทR๋ฆฌ์ (PC ๊ถ์ฅ)
ํ๋ก ํธ์๋(Vercel)์ ๊ฒ์ ์๋ฒ(์ปจํ ์ด๋)๋ฅผ ๋ถ๋ฆฌํด, ์ ์ ๊ฒ์์ CDN์์ ์๋นํ๊ณ ์ค์๊ฐ ํต์ ๋ง WebSocket์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค.
โโโโโโโโโโโโโโโโโโโโโโโโโโโ WebSocket (WSS) โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Vercel โ Frontend โ <โโโโโโโโโโโโโโโโโโโโโโโโโโโ> โ Game Server (Docker) โ
โ Next.js + ์ ์ ๊ฒ์ โ Socket.io โ Node.js + Socket.io โ
โ (App Router, iframe) โ โ โโ LobbyManager / Room โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โโ GameSession (๊ฒ์๋ณ) โ
โ โ โโ SocketManager โ
๊ฐ ๊ฒ์์ /public ์์ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
์ ์ ์ผ๋ก ์๋น๋๊ณ , ๋ฃธ ๋งค์นญ ยท ๊ถ์ ์ํ ๋๊ธฐํ
๋ฉํฐํ๋ ์ด์ด ์ ๋์ ์ผ๋ก
socket.io-client ๋ก๋
- ํด๋ผ์ด์ธํธ ๊ณต์ ์ฝ๋ (
public/shared/):GameClient(Socket.io ๋ํผ),StateBuffer/InputBuffer(๋ณด๊ฐยท์์ธก),LobbyUI - ์๋ฒ (
server/): ๋ฃธ ์ฝ๋ ์์ฑยท๋งค์นญ, ๊ฒ์๋ณ ์ธ์ ๋ก์ง(escape/flight/survival), ํ/์ฐ๊ฒฐ ๊ด๋ฆฌ,/health์๋ํฌ์ธํธ - ๋ฉํฐํ๋ ์ด์ด๊ฐ ํ์ํ ๋๋ง ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ์์
socket.io-client๋ฅผ ๋์ ๋ก๋ํ๋ฏ๋ก, ์ฑ๊ธํ๋ ์ด๋ ์๋ฒ ์์ด ๋์
| ์์ญ | ๊ธฐ์ |
|---|---|
| ํ๋ ์์ํฌ | Next.js 16 (App Router) ยท React 19 |
| ์ธ์ด | TypeScript 5 |
| ์คํ์ผ | Tailwind CSS 4 |
| ๊ฒ์ ์์ง | HTML5 Canvas ยท Babylon.js ยท CesiumJS ยท Three.js |
| ๋ฉํฐํ๋ ์ด์ด | Socket.io (์๋ฒ/ํด๋ผ์ด์ธํธ) |
| ์๋ฒ | Node.js ยท better-sqlite3 ยท Docker |
| ํ ์คํธ | Vitest ยท Playwright |
| CI/CD | GitHub Actions ยท Vercel |
- Node.js 20+
- (์ ํ) Cesium Ion ํ ํฐ โ ๋นํ ๊ฒ์์ 3D ์ง๋์ฉ (๋ฌด๋ฃ)
git clone https://github.com/writingdeveloper/Mini-Games.git
cd Mini-Games
npm installํ ํฐ ์์ด๋ ํ๋ธ์ ๋์ฃผยท์๋ฐ์ด๋ฒ ๊ฒ์์ ์ ์ ๋์ํฉ๋๋ค. ๋นํ ๊ฒ์ ์ง๋์ ๋ฉํฐํ๋ ์ด์ด๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ํ๋ก์ ํธ ๋ฃจํธ์ .env.local์ ๋ง๋์ธ์ (.env.example ์ฐธ๊ณ ):
# ๋นํ ๊ฒ์ 3D ์ง๋์ฉ (https://cesium.com/ion/tokens)
CESIUM_TOKEN=your_cesium_ion_token_here
# ๋ฉํฐํ๋ ์ด์ด ์๋ฒ ์ฃผ์ (๋ฏธ์ค์ ์ ๋ฉํฐํ๋ ์ด์ด ๋ฒํผ ๋นํ์ฑํ)
NEXT_PUBLIC_GAME_SERVER_URL=https://your-game-server.example.comnpm run dev๋ธ๋ผ์ฐ์ ์์ http://localhost:3000 ์ ์.
npm run build # ์ ์ ๋น๋
npm start # ํ๋ก๋์
์คํcd server
npm install
npm run dev # ๊ฐ๋ฐ (tsx watch)
# ๋๋ Docker
docker compose up -d --build์์ธํ ๋ฐฐํฌ ๊ฐ์ด๋๋ server/DEPLOY.md ์ฐธ๊ณ .
npm run test # Vitest ๋จ์ + ํตํฉ ํ
์คํธ
npm run test:coverage # ์ปค๋ฒ๋ฆฌ์ง ๋ฆฌํฌํธ
npm run test:e2e # Playwright E2E
npm run lint # ESLint
npm run type-check # TypeScript ํ์
๊ฒ์ฌCI(.github/workflows/ci.yml)์์ push/PR ์ lint ยท type-check ยท ๋จ์ ํ
์คํธ ยท E2E ยท ์๋ฒ ๊ฒ์ฆ์ ์๋ ์คํํฉ๋๋ค.
Mini-Games/
โโโ app/ # Next.js App Router
โ โโโ page.tsx # ๋ฉ์ธ ํ๋ธ ํ์ด์ง
โ โโโ layout.tsx # ๋ฃจํธ ๋ ์ด์์
โ โโโ error-boundary.tsx # ๊ฒ์ ๋ก๋ ์๋ฌ ์ฒ๋ฆฌ
โ โโโ escape-game/page.tsx # ๋์ฃผ ๊ฒ์ ๋ผ์ฐํธ (๋ชจ๋ ์ ํ)
โ โโโ survival-game/page.tsx # ์๋ฐ์ด๋ฒ ๋ผ์ฐํธ (๋ชจ๋ ์ ํ)
โ โโโ flight-game/page.tsx # ๋นํ ๊ฒ์ ๋ผ์ฐํธ
โ โโโ desert-game/page.tsx # Dust Drifter ๋ผ์ฐํธ
โ โโโ ppopgi/page.tsx # JELLY CATCHER ๋ฝ๊ธฐ(์ธํ๋ฝ๊ธฐ) ๋ผ์ฐํธ
โ โโโ makima-says/page.tsx # ๋งํค๋ง says ๋ผ์ฐํธ
โ โโโ garak-guksu/page.tsx # ์ญ์ ๊ตญ์ ๋ผ์ฐํธ
โโโ public/
โ โโโ escape-game/ # 2D Canvas ๊ฒ์
โ โโโ survival-game/ # Babylon.js 3D (game-modular.js + src/)
โ โโโ flight-game/ # CesiumJS 3D (game.js + src/)
โ โโโ desert-game/ # Three.js 3D ๋ก์ฐํด๋ฆฌ (src/ ESM, importmap)
โ โโโ ppopgi/ # Three.js 0.184 + cannon-es ๋ฌผ๋ฆฌ ์ธํ๋ฝ๊ธฐ (src/ ESM, importmap)
โ โโโ makima-says/ # ๋งํค๋ง says ๋ ๋ชฉ์๋ฆฌ ์ฌ์ด๋จผ (src/ ESM)
โ โโโ garak-guksu/ # ์ญ์ ๊ตญ์ ๊ฐ๋ฝ๊ตญ์ ์๋น (Three.js, src/ ESM)
โ โโโ shared/ # ๋ฉํฐํ๋ ์ด์ด ๊ณต์ ํด๋ผ์ด์ธํธ
โ โโโ networking/ # GameClient ยท State/InputBuffer ยท MessageTypes
โ โโโ lobby/ # LobbyUI
โโโ server/ # Socket.io ๋ฉํฐํ๋ ์ด์ด ์๋ฒ (TypeScript)
โ โโโ src/
โ โ โโโ index.ts # ์๋ฒ ์ํธ๋ฆฌ + /health
โ โ โโโ lobby/ # LobbyManager ยท Room ยท RoomCodeGenerator
โ โ โโโ games/ # escape / flight / survival ๊ฒ์ ์ธ์
โ โ โโโ network/ # SocketManager ยท MessageTypes
โ โโโ Dockerfile
โ โโโ docker-compose.yml
โโโ __tests__/ # Vitest ๋จ์/ํตํฉ ํ
์คํธ
โโโ e2e/ # Playwright E2E ํ
์คํธ
โโโ scripts/ # ๋น๋ ์ ํ๊ฒฝ๋ณ์ ์ฃผ์
์คํฌ๋ฆฝํธ
โโโ .github/workflows/ci.yml # CI ํ์ดํ๋ผ์ธ
- ๋ฉํฐํ๋ ์ด์ด ์๋ฒ ์ฌ๊ฐ๋ (๋์ฃผ ยท ์๋ฐ์ด๋ฒ ยท ๋นํ ๋ฐํ์ ํตํฉ)
- ๊ฒ์๋ณ ์คํฌ๋ฆฐ์ท/GIF ์ถ๊ฐ
- ๋ชจ๋ฐ์ผ ํฐ์น ์กฐ์ โ ์ธํ๋ฝ๊ธฐ ยท ๋งํค๋ง ยท ์ญ์ ๊ตญ์ ยท ๋์ฃผ ์ง์
- ๋ชจ๋ฐ์ผ ํฐ์น ์กฐ์ โ ์๋ฐ์ด๋ฒ ยท ๋นํ ยท ์ฌ๋ง(3D ํค๋ณด๋ ๊ฒ์) ํ์ฅ
- ๊ฒ์๋ณ ๋ฒ ์คํธ ๊ธฐ๋ก/๋์ ๊ณผ์ ํ๋ธ ํตํฉ
MIT ยฉ 2026 Si Hyeong Lee





