====== π’ Node.js λ°±μλ μ€μ ======
Phaser Baduk Metaverse νλ‘μ νΈμ ''Node.js'' λ°±μλ μ€μ κ³Ό ꡬμ±μ λν΄ μμΈν μ€λͺ
ν©λλ€.
----
===== 1. Node.jsλ 무μμΈκ°μ? =====
''Node.js''λ ''JavaScript''λ₯Ό μλ²μμ μ€νν μ μκ² ν΄μ£Όλ λ°νμ νκ²½μ
λλ€. μΉ λΈλΌμ°μ μμλ§ μ€νλλ ''JavaScript''λ₯Ό μλ²μμλ μ€νν μ μκ² ν΄μ€λλ€.
**μ£Όμ νΉμ§:**
* ''JavaScript''λ‘ μλ²λ₯Ό λ§λ€ μ μμ΅λλ€.
* λΉλκΈ° μ²λ¦¬μ κ°μ μ΄ μμ΅λλ€.
* ''npm''μ ν΅ν΄ λ€μν ν¨ν€μ§λ₯Ό μ¬μ©ν μ μμ΅λλ€.
* λΉ λ₯Έ κ°λ°μ΄ κ°λ₯ν©λλ€.
----
===== 2. νλ‘μ νΈ κ°μ =====
μ΄ νλ‘μ νΈλ ''Node.js''λ₯Ό κΈ°λ°μΌλ‘ νλ©°, μΉ νμ΄μ§λ₯Ό μλ²μμ λ λλ§νκ³ ν΄λΌμ΄μΈνΈμμ μ€μκ° ν΅μ κΈ°λ₯μ μ 곡ν©λλ€.
**μ£Όμ κΈ°μ μ€ν:**
* **''Express.js''** - μΉ νλ μμν¬
* **''Socket.IO''** - μ€μκ° ν΅μ λΌμ΄λΈλ¬λ¦¬
* **''PM2''** - νλ‘μΈμ€ κ΄λ¦¬ λꡬ
----
===== 3. μλ² κ΅¬μ‘° λ° μ£Όμ νμΌ =====
Phaser Baduk Metaverse νλ‘μ νΈμ ν΅μ¬ μλ² νμΌμΈ ''server.js''μ ꡬ쑰μ κ° λΆλΆμ μν μ λν΄ μ€λͺ
ν©λλ€.
==== 1) μ΄κΈ° μ€μ λ° λͺ¨λ λΆλ¬μ€κΈ° ====
μλ² κ΅¬λμ νμν λͺ¨λλ€μ λΆλ¬μ€κ³ , μ ν리μΌμ΄μ
μΈμ€ν΄μ€λ₯Ό μ΄κΈ°νν©λλ€.
const express = require('express'); // μΉ μλ² νλ μμν¬
const http = require('http'); // HTTP μλ² λͺ¨λ
const socketIo = require('socket.io'); // μ€μκ° μΉ μμΌ λΌμ΄λΈλ¬λ¦¬
const path = require('path'); // νμΌ κ²½λ‘ μ²λ¦¬ μ νΈλ¦¬ν°
**κ° λͺ¨λμ μν :**
* ''express'' - μΉ μλ²λ₯Ό μ½κ² λ§λ€ μ μλ νλ μμν¬
* ''http'' - ''HTTP'' μλ²λ₯Ό μμ±νλ κΈ°λ³Έ λͺ¨λ
* ''socket.io'' - μ€μκ° μλ°©ν₯ ν΅μ μ μν λΌμ΄λΈλ¬λ¦¬
* ''path'' - νμΌ κ²½λ‘λ₯Ό μμ νκ² μ²λ¦¬νλ μ νΈλ¦¬ν°
==== 2) μ ν리μΌμ΄μ
μΈμ€ν΄μ€ μμ± ====
const app = express(); // Express μ ν리μΌμ΄μ
μμ±
const server = http.createServer(app); // HTTP μλ² μμ± (Express μ±μ κΈ°λ°μΌλ‘)
const io = socketIo(server); // Socket.IO μλ² μμ± (HTTP μλ²μ μ°κ²°)
**μ€λͺ
:**
* ''app'' - ''Express'' μ ν리μΌμ΄μ
κ°μ²΄
* ''server'' - ''HTTP'' μλ² κ°μ²΄ (''Express'' μ±μ κΈ°λ°μΌλ‘ μμ±)
* ''io'' - ''Socket.IO'' μλ² κ°μ²΄ (''HTTP'' μλ²μ μ°κ²°)
==== 3) μ μ νμΌ μλΉ λ° λΌμ°ν
====
ν΄λΌμ΄μΈνΈ(νλ‘ νΈμλ)μ μ 곡λ μ μ νμΌ(''HTML'', ''CSS'', ''JS'', μ΄λ―Έμ§ λ±)μ μ€μ νκ³ , κΈ°λ³Έ κ²½λ‘μ λν λΌμ°νΈλ₯Ό μ μν©λλ€.
// 'public' λλ ν 리μ μλ μ μ νμΌλ€μ ν΄λΌμ΄μΈνΈμκ² μ 곡
app.use(express.static(path.join(dirname, 'public')));
// λ£¨νΈ κ²½λ‘('/')λ‘ μ κ·Ό μ 'public' λλ ν 리 λ΄μ 'index.html' νμΌ μ μ‘
app.get('/', (req, res) => {
res.sendFile(path.join(dirname, 'public', 'index.html'));
});
**μ€λͺ
:**
* ''express.static()'' - μ μ νμΌμ μΉμμ μ κ·Ό κ°λ₯νκ² ν©λλ€.
* ''path.join(dirname, 'public')'' - νμ¬ λλ ν 리μ ''public'' ν΄λ κ²½λ‘μ
λλ€.
* ''app.get('/')'' - λ£¨νΈ κ²½λ‘λ‘ μ κ·Όνμ λ μ€νλλ ν¨μμ
λλ€.
==== 4) Socket.IO μ΄λ²€νΈ μ²λ¦¬ ====
ν΄λΌμ΄μΈνΈμ μλ² κ°μ μ€μκ° ν΅μ μ λ΄λΉνλ ''Socket.IO'' μ΄λ²€νΈ νΈλ€λ¬λ₯Ό μ€μ ν©λλ€.
// Socket.IO μ°κ²° μ΄λ²€νΈ μ²λ¦¬
io.on('connection', (socket) => {
// μλ‘μ΄ ν΄λΌμ΄μΈνΈκ° μ°κ²°λ λλ§λ€ μ€ν
console.log('μλ‘μ΄ ν΄λΌμ΄μΈνΈ μ°κ²°:', socket.id);
// 'join-game' μ΄λ²€νΈ μμ μ νΉμ κ²μλ°©μ ν΄λΌμ΄μΈνΈ μ‘°μΈ
socket.on('join-game', (gameId) => {
socket.join(gameId); // ν΄λΉ gameIdλ₯Ό κ°μ§ λ°©μ μμΌμ μΆκ°
console.log(`νλ μ΄μ΄κ° κ²μ ${gameId}μ μ°Έκ°νμ΅λλ€.`);
});
// ν΄λΌμ΄μΈνΈ μ°κ²° ν΄μ μ μ€ν
socket.on('disconnect', () => {
console.log('ν΄λΌμ΄μΈνΈ μ°κ²° ν΄μ :', socket.id);
});
});
**μ€λͺ
:**
* ''io.on('connection')'' - μλ‘μ΄ ν΄λΌμ΄μΈνΈκ° μ°κ²°λ λ μ€νλ©λλ€.
* ''socket.on('join-game')'' - ν΄λΌμ΄μΈνΈκ° κ²μ μ°Έκ° μμ²μ λ³΄λΌ λ μ€νλ©λλ€.
* ''socket.join(gameId)'' - νΉμ κ²μλ°©μ μμΌμ μΆκ°ν©λλ€.
* ''socket.on('disconnect')'' - ν΄λΌμ΄μΈνΈ μ°κ²°μ΄ λμ΄μ§ λ μ€νλ©λλ€.
==== 5) μλ² ν¬νΈ μ€μ λ° μ€ν ====
νκ²½ λ³μμμ ν¬νΈ λ²νΈλ₯Ό κ°μ Έμ€κ±°λ κΈ°λ³Έκ°(3000)μ μ¬μ©νμ¬ μλ²λ₯Ό μ§μ λ ν¬νΈμμ μ€νν©λλ€.
// νκ²½ λ³μμμ PORTλ₯Ό κ°μ Έμ€κ±°λ κΈ°λ³Έκ° 3000 μ¬μ©
const PORT = process.env.PORT || 3000;
// μλ²λ₯Ό μ§μ λ ν¬νΈμμ μ€ννκ³ , μ±κ³΅ μ μ½μμ λ©μμ§ μΆλ ₯
server.listen(PORT, () => {
console.log(`μλ²κ° ν¬νΈ ${PORT}μμ μ€ν μ€μ
λλ€.`);
console.log(`http://localhost:${PORT}μμ μ μνμΈμ.`);
});
**μ€λͺ
:**
* ''process.env.PORT'' - νκ²½ λ³μμμ ν¬νΈ λ²νΈλ₯Ό κ°μ Έμ΅λλ€.
* ''|| 3000'' - νκ²½ λ³μκ° μμΌλ©΄ κΈ°λ³Έκ° 3000μ μ¬μ©ν©λλ€.
* ''server.listen()'' - μλ²λ₯Ό μ§μ λ ν¬νΈμμ μμν©λλ€.
* μ½λ°± ν¨μλ μλ² μμ μ±κ³΅ μ μ€νλλ ν¨μμ
λλ€.
----
===== 4. μμ‘΄μ± κ΄λ¦¬ (package.json) =====
νλ‘μ νΈμ νμν λΌμ΄λΈλ¬λ¦¬ λ° μ€ν¬λ¦½νΈλ₯Ό μ μνλ ''package.json'' νμΌμ μ£Όμ λ΄μ©μ μ€λͺ
ν©λλ€.
==== 1) νλ‘μ νΈ μ 보 ====
^ ν€ ^ μ€λͺ
^
| name | νλ‘μ νΈ μ΄λ¦ |
| version | νλ‘μ νΈ λ²μ |
| description | νλ‘μ νΈμ λν κ°λ΅ν μ€λͺ
|
| main | νλ‘μ νΈμ μ§μ
μ νμΌ (μ¬κΈ°μλ ''server.js'') |
==== 2) μ€ν¬λ¦½νΈ ====
μμ£Ό μ¬μ©λλ λͺ
λ Ήμ΄λ₯Ό λ¨μΆνμ¬ μ μν©λλ€.
^ μ€ν¬λ¦½νΈ ^ μ€λͺ
^ λͺ
λ Ήμ΄ ^
| start | νλ‘λμ
νκ²½μμ μλ²λ₯Ό μμν©λλ€. | ''node server.js'' |
| dev | κ°λ° νκ²½μμ ''nodemon''μ μ¬μ©νμ¬ μλ²λ₯Ό μμν©λλ€. μ½λ λ³κ²½ μ μλ μ¬μμλ©λλ€. | ''nodemon server.js'' |
| pm2 | ''PM2''λ₯Ό μ¬μ©νμ¬ μλ²λ₯Ό μμν©λλ€. (νλ‘μΈμ€ κ΄λ¦¬μ©) | ''pm2 start server.js'' |
==== 3) μμ‘΄μ± λͺ©λ‘ ====
^ μμ‘΄μ± ^ λ²μ ^ μ€λͺ
^
| express | 4.18.2 | Node.js μΉ μ ν리μΌμ΄μ
νλ μμν¬ |
| socket.io | 4.7.2 | μ€μκ° μλ°©ν₯ μΉ μμΌ ν΅μ λΌμ΄λΈλ¬λ¦¬ |
| cors | 2.8.5 | κ΅μ°¨ μΆμ² 리μμ€ κ³΅μ (CORS) λ―Έλ€μ¨μ΄ |
| helmet | 7.0.0 | 보μ ν€λ μ€μ λ―Έλ€μ¨μ΄ |
| compression | 1.7.4 | μλ΅ μμΆ λ―Έλ€μ¨μ΄ |
| express-rate-limit | 6.7.0 | μμ² μ ν λ―Έλ€μ¨μ΄ |
==== 4) κ°λ° μμ‘΄μ± λͺ©λ‘ ====
^ μμ‘΄μ± ^ λ²μ ^ μ€λͺ
^
| nodemon | 2.0.22 | κ°λ° μ μ½λ λ³κ²½ κ°μ§νμ¬ μλ² μλ μ¬μμ |
| jest | 29.5.0 | JavaScript ν
μ€νΈ νλ μμν¬ |
| supertest | 6.3.3 | HTTP ν
μ€νΈ λΌμ΄λΈλ¬λ¦¬ |
----
===== 5. νκ²½ μ€μ =====
==== 1) νκ²½ λ³μ μ€μ ====
νλ‘μ νΈ λ£¨νΈμ ''.env'' νμΌμ μμ±νμ¬ νκ²½ λ³μλ₯Ό μ€μ ν©λλ€:
# μλ² ν¬νΈ μ€μ
PORT=3000
# λ°μ΄ν°λ² μ΄μ€ μ°κ²° μ 보
MONGODB_URI=mongodb://localhost:27017/baduk_metaverse
# JWT μν¬λ¦Ώ ν€
JWT_SECRET=your-secret-key-here
# νκ²½ μ€μ
NODE_ENV=development
**μ£Όμ νκ²½ λ³μ:**
* ''PORT'' - μλ²κ° μ€νλ ν¬νΈ λ²νΈ
* ''MONGODB_URI'' - ''MongoDB'' λ°μ΄ν°λ² μ΄μ€ μ°κ²° λ¬Έμμ΄
* ''JWT_SECRET'' - ''JWT'' ν ν° μνΈνμ μ¬μ©ν μν¬λ¦Ώ ν€
* ''NODE_ENV'' - νμ¬ νκ²½ (''development''/''production'')
==== 2) νκ²½ λ³μ μ¬μ©λ² ====
// dotenv ν¨ν€μ§λ₯Ό μ¬μ©νμ¬ .env νμΌ λ‘λ
require('dotenv').config();
// νκ²½ λ³μ μ¬μ©
const PORT = process.env.PORT || 3000;
const MONGODB_URI = process.env.MONGODB_URI;
const JWT_SECRET = process.env.JWT_SECRET;
**μ€λͺ
:**
* ''require('dotenv').config()'' - ''.env'' νμΌμ λ‘λν©λλ€.
* ''process.env.λ³μλͺ
'' - νκ²½ λ³μ κ°μ κ°μ Έμ΅λλ€.
* ''|| κΈ°λ³Έκ°'' - νκ²½ λ³μκ° μμ λ κΈ°λ³Έκ°μ μ¬μ©ν©λλ€.
----
===== 6. νλ‘μ νΈ κ΅¬μ‘° =====
**κΆμ₯νλ νλ‘μ νΈ ν΄λ ꡬ쑰:**
baduk-metaverse/
βββ server.js # λ©μΈ μλ² νμΌ
βββ package.json # νλ‘μ νΈ μ€μ νμΌ
βββ .env # νκ²½ λ³μ νμΌ
βββ .gitignore # Git 무μ νμΌ λͺ©λ‘
βββ public/ # μ μ νμΌ ν΄λ
β βββ index.html # λ©μΈ HTML νμΌ
β βββ css/ # CSS νμΌλ€
β βββ js/ # ν΄λΌμ΄μΈνΈ JavaScript νμΌλ€
β βββ images/ # μ΄λ―Έμ§ νμΌλ€
βββ routes/ # λΌμ°νΈ νμΌλ€
β βββ games.js # κ²μ κ΄λ ¨ λΌμ°νΈ
β βββ users.js # μ¬μ©μ κ΄λ ¨ λΌμ°νΈ
β βββ statistics.js # ν΅κ³ κ΄λ ¨ λΌμ°νΈ
βββ controllers/ # 컨νΈλ‘€λ¬ νμΌλ€
β βββ BadukGameController.js
β βββ UserController.js
β βββ StatisticsController.js
βββ models/ # λ°μ΄ν° λͺ¨λΈ νμΌλ€
β βββ BadukGame.js
β βββ User.js
β βββ BadukGameState.js
βββ middleware/ # λ―Έλ€μ¨μ΄ νμΌλ€
β βββ auth.js # μΈμ¦ λ―Έλ€μ¨μ΄
β βββ errorHandler.js # μλ¬ μ²λ¦¬ λ―Έλ€μ¨μ΄
βββ utils/ # μ νΈλ¦¬ν° νμΌλ€
β βββ BadukMoveValidator.js
β βββ helpers.js
βββ tests/ # ν
μ€νΈ νμΌλ€
βββ server.test.js
βββ game.test.js
**κ° ν΄λμ μν :**
* ''public/'' - ν΄λΌμ΄μΈνΈμκ² μ 곡ν νμΌλ€
* ''routes/'' - ''URL'' κ²½λ‘λ³ μ²λ¦¬ λ‘μ§
* ''controllers/'' - λΉμ¦λμ€ λ‘μ§ μ²λ¦¬
* ''models/'' - λ°μ΄ν° ꡬ쑰 μ μ
* ''middleware/'' - μμ² μ²λ¦¬ μ€κ° λ¨κ³
* ''utils/'' - κ³΅ν΅ μ νΈλ¦¬ν° ν¨μλ€
* ''tests/'' - ν
μ€νΈ μ½λλ€
----
===== 7. κ°λ° νκ²½ μ€μ =====
==== 1) Node.js μ€μΉ ====
**Windowsμμ Node.js μ€μΉ:**
* ''Node.js'' 곡μ μΉμ¬μ΄νΈ (''https://nodejs.org'') λ°©λ¬Έ
* ''LTS'' λ²μ λ€μ΄λ‘λ λ° μ€μΉ
* μ€μΉ μλ£ ν ν°λ―Έλμμ νμΈ:
node --version
npm --version
==== 2) νλ‘μ νΈ μ΄κΈ°ν ====
# μ ν΄λ μμ± λ° μ΄λ
mkdir baduk-metaverse
cd baduk-metaverse
# npm νλ‘μ νΈ μ΄κΈ°ν
npm init -y
# νμν ν¨ν€μ§ μ€μΉ
npm install express socket.io cors helmet compression express-rate-limit
# κ°λ°μ© ν¨ν€μ§ μ€μΉ
npm install --save-dev nodemon
==== 3) κΈ°λ³Έ μλ² νμΌ μμ± ====
''server.js'' νμΌμ μμ±νκ³ κΈ°λ³Έ μ½λλ₯Ό μμ±ν©λλ€:
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const path = require('path');
const app = express();
const server = http.createServer(app);
const io = socketIo(server);
// μ μ νμΌ μλΉ
app.use(express.static(path.join(dirname, 'public')));
// κΈ°λ³Έ λΌμ°νΈ
app.get('/', (req, res) => {
res.sendFile(path.join(dirname, 'public', 'index.html'));
});
// Socket.IO μ°κ²° μ²λ¦¬
io.on('connection', (socket) => {
console.log('μλ‘μ΄ ν΄λΌμ΄μΈνΈ μ°κ²°:', socket.id);
socket.on('disconnect', () => {
console.log('ν΄λΌμ΄μΈνΈ μ°κ²° ν΄μ :', socket.id);
});
});
// μλ² μμ
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`μλ²κ° ν¬νΈ ${PORT}μμ μ€ν μ€μ
λλ€.`);
});
==== 4) package.json μ€ν¬λ¦½νΈ μ€μ ====
{
"name": "baduk-metaverse",
"version": "1.0.0",
"description": "Phaser Baduk Metaverse νλ‘μ νΈ",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
"test": "jest"
},
"dependencies": {
"express": "^4.18.2",
"socket.io": "^4.7.2",
"cors": "^2.8.5",
"helmet": "^7.0.0",
"compression": "^1.7.4",
"express-rate-limit": "^6.7.0"
},
"devDependencies": {
"nodemon": "^2.0.22",
"jest": "^29.5.0"
}
}
----
===== 8. μλ² μ€ν λ° ν
μ€νΈ =====
==== 1) κ°λ° λͺ¨λλ‘ μλ² μ€ν ====
npm run dev
**μ€λͺ
:**
* ''nodemon''μ μ¬μ©νμ¬ μλ²λ₯Ό μ€νν©λλ€.
* μ½λ λ³κ²½ μ μλμΌλ‘ μλ²κ° μ¬μμλ©λλ€.
* κ°λ° μ€μ λ§€μ° μ μ©ν©λλ€.
==== 2) νλ‘λμ
λͺ¨λλ‘ μλ² μ€ν ====
npm start
**μ€λͺ
:**
* ''node''λ₯Ό μ¬μ©νμ¬ μλ²λ₯Ό μ€νν©λλ€.
* μ½λ λ³κ²½ μ μλμΌλ‘ μλ²λ₯Ό μ¬μμν΄μΌ ν©λλ€.
* μ€μ μλΉμ€ νκ²½μμ μ¬μ©ν©λλ€.
==== 3) μλ² ν
μ€νΈ ====
**λΈλΌμ°μ μμ ν
μ€νΈ:**
* λΈλΌμ°μ μ΄κΈ°
* ''http://localhost:3000'' μ μ
* μλ²κ° μ μμ μΌλ‘ μλ΅νλμ§ νμΈ
**ν°λ―Έλμμ ν
μ€νΈ:**
curl http://localhost:3000
----
===== 9. λλ²κΉ
λ° λ‘κΉ
=====
==== 1) μ½μ λ‘κΉ
====
// κΈ°λ³Έ λ‘κΉ
console.log('μΌλ° λ©μμ§');
console.error('μλ¬ λ©μμ§');
console.warn('κ²½κ³ λ©μμ§');
// κ°μ²΄ λ‘κΉ
const gameData = { id: 1, name: 'λ°λ κ²μ' };
console.log('κ²μ λ°μ΄ν°:', gameData);
// μκ°κ³Ό ν¨κ» λ‘κΉ
console.log(`${new Date().toISOString()} - μλ² μμλ¨`);
==== 2) λ‘κΉ
λ―Έλ€μ¨μ΄ ====
// μμ² λ‘κΉ
λ―Έλ€μ¨μ΄
app.use((req, res, next) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
next();
});
// μλ¬ λ‘κΉ
λ―Έλ€μ¨μ΄
app.use((err, req, res, next) => {
console.error('μλ² μλ¬:', err);
res.status(500).json({ error: 'μλ² λ΄λΆ μ€λ₯κ° λ°μνμ΅λλ€.' });
});
==== 3) λλ²κΉ
λꡬ ====
**Node.js λ΄μ₯ λλ²κ±° μ¬μ©:**
node --inspect server.js
**Chrome DevToolsμμ λλ²κΉ
:**
* Chrome λΈλΌμ°μ μ΄κΈ°
* %%chrome://inspect%% μ μ
* "Open dedicated DevTools for Node" ν΄λ¦
----
===== 10. μ±λ₯ μ΅μ ν =====
==== 1) μμΆ μ€μ ====
const compression = require('compression');
// μλ΅ μμΆ λ―Έλ€μ¨μ΄
app.use(compression());
==== 2) μΊμ± μ€μ ====
// μ μ νμΌ μΊμ±
app.use(express.static(path.join(dirname, 'public'), {
maxAge: '1d', // 1μΌκ° μΊμ
etag: true // ETag μ¬μ©
}));
==== 3) μμ² μ ν ====
const rateLimit = require('express-rate-limit');
// API μμ² μ ν
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15λΆ
max: 100, // IPλΉ μ΅λ 100κ° μμ²
message: 'λ무 λ§μ μμ²μ΄ λ°μνμ΅λλ€.'
});
app.use('/api/', limiter);
----
===== 11. 보μ μ€μ =====
==== 1) Helmet λ―Έλ€μ¨μ΄ ====
const helmet = require('helmet');
// 보μ ν€λ μ€μ
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'", "ws:", "wss:"]
}
}
}));
==== 2) CORS μ€μ ====
const cors = require('cors');
// CORS μ€μ
app.use(cors({
origin: process.env.NODE_ENV === 'production'
? ['https://yourdomain.com']
: ['http://localhost:3000'],
credentials: true
}));
==== 3) μ
λ ₯ λ°μ΄ν° κ²μ¦ ====
// μ
λ ₯ λ°μ΄ν° κ²μ¦ μμ
app.post('/api/games', (req, res) => {
const { gameType, settings } = req.body;
// νμ νλ κ²μ¦
if (!gameType) {
return res.status(400).json({ error: 'κ²μ νμ
μ΄ νμν©λλ€.' });
}
// λ°μ΄ν° νμ
κ²μ¦
if (typeof gameType !== 'string') {
return res.status(400).json({ error: 'κ²μ νμ
μ λ¬Έμμ΄μ΄μ΄μΌ ν©λλ€.' });
}
// μΆκ° μ²λ¦¬...
});
----
===== 12. λ€μ λ¨κ³ =====
''Node.js'' κΈ°λ³Έμ λ°°μ λ€λ©΄ λ€μμ νμ΅ν΄λ³΄μΈμ:
* **''Express.js''** - μΉ νλ μμν¬ μ¬ν νμ΅
* **''Socket.IO''** - μ€μκ° ν΅μ ꡬν
* **λ°μ΄ν°λ² μ΄μ€ μ°λ** - ''MongoDB'', ''MySQL'' λ±
* **μΈμ¦ μμ€ν
** - ''JWT'', ''Passport.js'' λ±
* **ν
μ€νΈ μμ±** - ''Jest'', ''Mocha'' λ±
**μΆμ² νμ΅ μμ:**
- [[wiki:it:dream_of_enc:metaverse:express|π Express.js μΉ νλ μμν¬]]
- [[wiki:it:dream_of_enc:metaverse:socketio|π Socket.IO μ€μκ° ν΅μ ]]
- [[wiki:it:dream_of_enc:metaverse:pm2|β‘ PM2 νλ‘μΈμ€ κ΄λ¦¬]]
---
//μ΄ νμ΄μ§λ μλμΌλ‘ μμ±λμμ΅λλ€.//
---