์‚ฌ์šฉ์ž ๋„๊ตฌ

์‚ฌ์ดํŠธ ๋„๊ตฌ


wiki:it:dream_of_enc:metaverse:express

๋ชฉ์ฐจ

๐Ÿš€ Express.js ์›น ํ”„๋ ˆ์ž„์›Œํฌ

Phaser Baduk Metaverse ํ”„๋กœ์ ํŠธ์˜ Express.js ์›น ํ”„๋ ˆ์ž„์›Œํฌ ๊ตฌํ˜„์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.


1. Express.js๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

Express.js๋Š” Node.js๋ฅผ ์œ„ํ•œ ๋น ๋ฅด๊ณ  ์œ ์—ฐํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. ์›น ์„œ๋ฒ„๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋„๊ตฌ๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ฃผ์š” ํŠน์ง•:

  • ์›น ์„œ๋ฒ„๋ฅผ ๋น ๋ฅด๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • RESTful API๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ •์  ํŒŒ์ผ(HTML, CSS, ์ด๋ฏธ์ง€ ๋“ฑ)์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฏธ๋“ค์›จ์–ด๋ฅผ ํ†ตํ•ด ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ์ดํ•ดํ•˜๊ธฐ

Express.js ํ”„๋กœ์ ํŠธ์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ:

  • server.js - ๋ฉ”์ธ ์„œ๋ฒ„ ํŒŒ์ผ
  • routes/ - ๋ผ์šฐํŠธ(URL ๊ฒฝ๋กœ) ๊ด€๋ฆฌ ํด๋”
  • controllers/ - ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ด€๋ฆฌ ํด๋”
  • middleware/ - ๋ฏธ๋“ค์›จ์–ด(์ค‘๊ฐ„ ์ฒ˜๋ฆฌ) ํด๋”
  • public/ - ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ œ๊ณตํ•  ํŒŒ์ผ๋“ค

3. ๊ธฐ๋ณธ ์„œ๋ฒ„ ์„ค์ •

1) ํ•„์š”ํ•œ ๋ชจ๋“ˆ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

๋จผ์ € ํ•„์š”ํ•œ ๋ชจ๋“ˆ๋“ค์„ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค:

const express = require('express');
const path = require('path');
const cors = require('cors');
const helmet = require('helmet');
const compression = require('compression');
const rateLimit = require('express-rate-limit');

๊ฐ ๋ชจ๋“ˆ์˜ ์—ญํ• :

  • express - ์›น ์„œ๋ฒ„ ํ”„๋ ˆ์ž„์›Œํฌ
  • path - ํŒŒ์ผ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ
  • cors - ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์—์„œ์˜ ์ ‘๊ทผ ํ—ˆ์šฉ
  • helmet - ๋ณด์•ˆ ๊ฐ•ํ™”
  • compression - ํŒŒ์ผ ์••์ถ•
  • rateLimit - ์š”์ฒญ ์ œํ•œ

2) Express ์•ฑ ์ƒ์„ฑ

const app = express();
const PORT = process.env.PORT || 3000;

์„ค๋ช…:

  • app - Express ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธ์Šคํ„ด์Šค
  • PORT - ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋  ํฌํŠธ ๋ฒˆํ˜ธ (๊ธฐ๋ณธ๊ฐ’: 3000)

3) ๋ณด์•ˆ ๋ฏธ๋“ค์›จ์–ด ์„ค์ •

app.use(helmet({
    contentSecurityPolicy: {
        directives: {
            defaultSrc: ["'self'"],
            styleSrc: ["'self'", "'unsafe-inline'"],
            scriptSrc: ["'self'", "'unsafe-inline'"],
            imgSrc: ["'self'", "data:", "https:"],
            connectSrc: ["'self'", "ws:", "wss:"]
        }
    }
}));

์ด ์„ค์ •์˜ ๋ชฉ์ :

  • ์›น์‚ฌ์ดํŠธ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • ์•…์„ฑ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ํ—ˆ์šฉ๋œ ๋ฆฌ์†Œ์Šค๋งŒ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

4) CORS ์„ค์ •

app.use(cors({
    origin: process.env.NODE_ENV === 'production' 
        ? ['https://yourdomain.com'] 
        : ['http://localhost:3000', 'http://localhost:8080'],
    credentials: true
}));

CORS๋ž€?

  • ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์—์„œ์˜ ์ ‘๊ทผ์„ ์ œ์–ดํ•˜๋Š” ๋ณด์•ˆ ์ •์ฑ…์ž…๋‹ˆ๋‹ค.
  • ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” localhost:3000, localhost:8080์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ํŠน์ • ๋„๋ฉ”์ธ(https://yourdomain.com)๋งŒ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

5) ์••์ถ• ๋ฐ ์š”์ฒญ ์ œํ•œ ์„ค์ •

// ์••์ถ• ๋ฏธ๋“ค์›จ์–ด
app.use(compression());
 
// ์š”์ฒญ ์ œํ•œ ์„ค์ •
const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15๋ถ„
    max: 100, // IP๋‹น ์ตœ๋Œ€ 100๊ฐœ ์š”์ฒญ
    message: '๋„ˆ๋ฌด ๋งŽ์€ ์š”์ฒญ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž ์‹œ ํ›„ ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.'
});
app.use('/api/', limiter);

์„ค๋ช…:

  • compression - ํŒŒ์ผ ํฌ๊ธฐ๋ฅผ ์ค„์—ฌ์„œ ์ „์†ก ์†๋„๋ฅผ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
  • rateLimit - ํ•œ ๋ฒˆ์— ๋„ˆ๋ฌด ๋งŽ์€ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

6) ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ ์„ค์ •

// JSON ํŒŒ์‹ฑ ๋ฏธ๋“ค์›จ์–ด
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));

์„ค๋ช…:

  • express.json() - JSON ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•ฉ๋‹ˆ๋‹ค.
  • express.urlencoded() - ํผ ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•ฉ๋‹ˆ๋‹ค.
  • limit: '10mb' - ์ตœ๋Œ€ 10mb๊นŒ์ง€ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

7) ์ •์  ํŒŒ์ผ ์„œ๋น™ ์„ค์ •

// ์ •์  ํŒŒ์ผ ์„œ๋น™
app.use(express.static(path.join(__dirname, 'public'), {
    maxAge: '1d',
    etag: true
}));

์„ค๋ช…:

  • public ํด๋”์˜ ํŒŒ์ผ๋“ค์„ ์›น์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
  • maxAge: '1d' - ํŒŒ์ผ์„ 1์ผ๊ฐ„ ์บ์‹œํ•ฉ๋‹ˆ๋‹ค.
  • etag: true - ํŒŒ์ผ ๋ณ€๊ฒฝ ๊ฐ์ง€๋ฅผ ์œ„ํ•œ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

8) ๋กœ๊น… ๋ฏธ๋“ค์›จ์–ด

// ๋กœ๊น… ๋ฏธ๋“ค์›จ์–ด
app.use((req, res, next) => {
    console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
    next();
});

์„ค๋ช…:

  • ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด ๋กœ๊ทธ๋ฅผ ๋‚จ๊น๋‹ˆ๋‹ค.
  • ์š”์ฒญ ์‹œ๊ฐ„, ๋ฐฉ๋ฒ•(GET, POST ๋“ฑ), URL์„ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.
  • ๋””๋ฒ„๊น…์— ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

4. ๋ผ์šฐํŠธ ์„ค์ •

1) ๋ผ์šฐํŠธ ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

// ๋ผ์šฐํŠธ ์„ค์ •
app.use('/api/games', require('./routes/games'));
app.use('/api/users', require('./routes/users'));
app.use('/api/statistics', require('./routes/statistics'));

์„ค๋ช…:

  • /api/games - ๊ฒŒ์ž„ ๊ด€๋ จ API
  • /api/users - ์‚ฌ์šฉ์ž ๊ด€๋ จ API
  • /api/statistics - ํ†ต๊ณ„ ๊ด€๋ จ API

2) ๋ฉ”์ธ ํŽ˜์ด์ง€ ๋ผ์šฐํŠธ

// ๋ฉ”์ธ ํŽ˜์ด์ง€
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

์„ค๋ช…:

  • ๋ฃจํŠธ ๊ฒฝ๋กœ(/ )๋กœ ์ ‘๊ทผํ•˜๋ฉด index.html ํŒŒ์ผ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ์›น์‚ฌ์ดํŠธ์˜ ์ฒซ ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.

5. ์—๋Ÿฌ ์ฒ˜๋ฆฌ

1) 404 ์—๋Ÿฌ ์ฒ˜๋ฆฌ

// 404 ์—๋Ÿฌ ์ฒ˜๋ฆฌ
app.use((req, res) => {
    res.status(404).json({ error: 'ํŽ˜์ด์ง€๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.' });
});

์„ค๋ช…:

  • ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•  ๋•Œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • 404 ์ƒํƒœ ์ฝ”๋“œ์™€ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

2) ์„œ๋ฒ„ ์—๋Ÿฌ ์ฒ˜๋ฆฌ

// ์—๋Ÿฌ ํ•ธ๋“ค๋ง ๋ฏธ๋“ค์›จ์–ด
app.use((err, req, res, next) => {
    console.error('์„œ๋ฒ„ ์—๋Ÿฌ:', err);
    res.status(500).json({ error: '์„œ๋ฒ„ ๋‚ด๋ถ€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.' });
});

์„ค๋ช…:

  • ์„œ๋ฒ„์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ชจ๋“  ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ์—๋Ÿฌ ๋กœ๊ทธ๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ๋Š” ์ผ๋ฐ˜์ ์ธ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

6. ๊ฒŒ์ž„ ๋ผ์šฐํŠธ ์˜ˆ์ œ

1) ๊ฒŒ์ž„ ๋ผ์šฐํŠธ ๊ธฐ๋ณธ ๊ตฌ์กฐ

const express = require('express');
const router = express.Router();
const BadukGameController = require('../controllers/BadukGameController');
const auth = require('../middleware/auth');

์„ค๋ช…:

  • express.Router() - ๋ผ์šฐํ„ฐ ๊ฐ์ฒด ์ƒ์„ฑ
  • BadukGameController - ๊ฒŒ์ž„ ๊ด€๋ จ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง
  • auth - ์ธ์ฆ ๋ฏธ๋“ค์›จ์–ด

2) ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ

// ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ
router.get('/', async (req, res) => {
    try {
        const games = await BadukGameController.getGameList(req.query);
        res.json({
            success: true,
            data: games,
            total: games.length
        });
    } catch (error) {
        res.status(500).json({
            success: false,
            error: error.message
        });
    }
});

์„ค๋ช…:

  • GET /api/games - ๋ชจ๋“  ๊ฒŒ์ž„ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
  • try-catch - ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ๊ตฌ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • ์„ฑ๊ณต ์‹œ ๊ฒŒ์ž„ ๋ชฉ๋ก๊ณผ ์ด ๊ฐœ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์‹คํŒจ ์‹œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

3) ์ƒˆ ๊ฒŒ์ž„ ์ƒ์„ฑ

// ์ƒˆ ๊ฒŒ์ž„ ์ƒ์„ฑ
router.post('/', auth, async (req, res) => {
    try {
        const { gameType, settings } = req.body;
        const game = await BadukGameController.createGame(req.user.id, gameType, settings);
 
        res.status(201).json({
            success: true,
            data: game
        });
    } catch (error) {
        res.status(400).json({
            success: false,
            error: error.message
        });
    }
});

์„ค๋ช…:

  • POST /api/games - ์ƒˆ๋กœ์šด ๊ฒŒ์ž„์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • auth - ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • req.body - ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ๋ฐ์ดํ„ฐ์ž…๋‹ˆ๋‹ค.
  • 201 - ์ƒ์„ฑ ์„ฑ๊ณต ์ƒํƒœ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

4) ํŠน์ • ๊ฒŒ์ž„ ์กฐํšŒ

// ํŠน์ • ๊ฒŒ์ž„ ์กฐํšŒ
router.get('/:gameId', async (req, res) => {
    try {
        const game = await BadukGameController.getGame(req.params.gameId);
 
        if (!game) {
            return res.status(404).json({
                success: false,
                error: '๊ฒŒ์ž„์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.'
            });
        }
 
        res.json({
            success: true,
            data: game
        });
    } catch (error) {
        res.status(500).json({
            success: false,
            error: error.message
        });
    }
});

์„ค๋ช…:

  • GET /api/games/:gameId - ํŠน์ • ๊ฒŒ์ž„ ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
  • req.params.gameId - URL์—์„œ ๊ฒŒ์ž„ ID๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒŒ์ž„์ด ์—†์œผ๋ฉด 404 ์—๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

5) ๊ฒŒ์ž„ ์ฐธ๊ฐ€

// ๊ฒŒ์ž„ ์ฐธ๊ฐ€
router.post('/:gameId/join', auth, async (req, res) => {
    try {
        const { gameId } = req.params;
        const { playerName } = req.body;
 
        const result = await BadukGameController.joinGame(gameId, req.user.id, playerName);
 
        res.json({
            success: true,
            data: result
        });
    } catch (error) {
        res.status(400).json({
            success: false,
            error: error.message
        });
    }
});

์„ค๋ช…:

  • POST /api/games/:gameId/join - ํŠน์ • ๊ฒŒ์ž„์— ์ฐธ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • req.params.gameId - URL์—์„œ ๊ฒŒ์ž„ ID๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  • req.body.playerName - ์š”์ฒญ ๋ณธ๋ฌธ์—์„œ ํ”Œ๋ ˆ์ด์–ด ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

6) ๊ฒŒ์ž„ ์ด๋™ ๊ธฐ๋ก

// ๊ฒŒ์ž„ ์ด๋™ ๊ธฐ๋ก
router.post('/:gameId/move', auth, async (req, res) => {
    try {
        const { gameId } = req.params;
        const { x, y, player } = req.body;
 
        const result = await BadukGameController.makeMove(gameId, req.user.id, x, y, player);
 
        res.json({
            success: true,
            data: result
        });
    } catch (error) {
        res.status(400).json({
            success: false,
            error: error.message
        });
    }
});

์„ค๋ช…:

  • POST /api/games/:gameId/move - ๊ฒŒ์ž„์—์„œ ๋Œ์„ ๋†“์Šต๋‹ˆ๋‹ค.
  • x, y - ๋ฐ”๋‘‘ํŒ์˜ ์ขŒํ‘œ์ž…๋‹ˆ๋‹ค.
  • player - ํ”Œ๋ ˆ์ด์–ด ์ •๋ณด์ž…๋‹ˆ๋‹ค.

7. ์„œ๋ฒ„ ์‹คํ–‰

1) ์„œ๋ฒ„ ์‹œ์ž‘

// ์„œ๋ฒ„ ์‹œ์ž‘
app.listen(PORT, () => {
    console.log(`์„œ๋ฒ„๊ฐ€ ํฌํŠธ ${PORT}์—์„œ ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค.`);
    console.log(`http://localhost:${PORT}์—์„œ ์ ‘์†ํ•˜์„ธ์š”.`);
});

์„ค๋ช…:

  • ์ง€์ •๋œ ํฌํŠธ์—์„œ ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • ์„œ๋ฒ„ ์‹œ์ž‘ ์‹œ ์ฝ˜์†”์— ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

2) ๋ชจ๋“ˆ ๋‚ด๋ณด๋‚ด๊ธฐ

module.exports = app;

์„ค๋ช…:

  • ๋‹ค๋ฅธ ํŒŒ์ผ์—์„œ ์ด ์•ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋‚ด๋ณด๋ƒ…๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ๋‚˜ ๋‹ค๋ฅธ ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉํ•  ๋•Œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

8. ์‹ค์Šต ์˜ˆ์ œ

1) ๊ฐ„๋‹จํ•œ Express ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ

1๋‹จ๊ณ„: ํ”„๋กœ์ ํŠธ ์ดˆ๊ธฐํ™”

npm init -y
npm install express

2๋‹จ๊ณ„: ๊ธฐ๋ณธ ์„œ๋ฒ„ ํŒŒ์ผ ์ƒ์„ฑ (app.js)

const express = require('express');
const app = express();
const PORT = 3000;
 
// JSON ํŒŒ์‹ฑ ๋ฏธ๋“ค์›จ์–ด
app.use(express.json());
 
// ๊ฐ„๋‹จํ•œ ๋ผ์šฐํŠธ
app.get('/', (req, res) => {
    res.json({ message: '์•ˆ๋…•ํ•˜์„ธ์š”! Express ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค.' });
});
 
app.get('/api/users', (req, res) => {
    res.json([
        { id: 1, name: '๊น€์ฒ ์ˆ˜' },
        { id: 2, name: '์ด์˜ํฌ' }
    ]);
});
 
// ์„œ๋ฒ„ ์‹œ์ž‘
app.listen(PORT, () => {
    console.log(`์„œ๋ฒ„๊ฐ€ ํฌํŠธ ${PORT}์—์„œ ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค.`);
});

3๋‹จ๊ณ„: ์„œ๋ฒ„ ์‹คํ–‰

node app.js

4๋‹จ๊ณ„: ํ…Œ์ŠคํŠธ


9. ์ฃผ์˜์‚ฌํ•ญ๊ณผ ํŒ

1) ๋ณด์•ˆ ์ฃผ์˜์‚ฌํ•ญ

  • ํ•ญ์ƒ helmet ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • ๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ๊ด€๋ฆฌํ•˜์„ธ์š”.
  • ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•˜์„ธ์š”.
  • HTTPS๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

2) ์„ฑ๋Šฅ ์ตœ์ ํ™”

  • compression ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • ์ •์  ํŒŒ์ผ ์บ์‹ฑ์„ ์„ค์ •ํ•˜์„ธ์š”.
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ํ’€์„ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • ๋ถˆํ•„์š”ํ•œ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ œ๊ฑฐํ•˜์„ธ์š”.

3) ๋””๋ฒ„๊น… ํŒ

  • ๋กœ๊น… ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ถ”๊ฐ€ํ•˜์„ธ์š”.
  • ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” ์ƒ์„ธํ•œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•˜์„ธ์š”.
  • ํ”„๋กœ๋•์…˜์—์„œ๋Š” ์ผ๋ฐ˜์ ์ธ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•˜์„ธ์š”.

10. ๋‹ค์Œ ๋‹จ๊ณ„

Express.js ๊ธฐ๋ณธ์„ ๋ฐฐ์› ๋‹ค๋ฉด ๋‹ค์Œ์„ ํ•™์Šตํ•ด๋ณด์„ธ์š”:

  • Socket.IO - ์‹ค์‹œ๊ฐ„ ํ†ต์‹  ๊ตฌํ˜„
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๋™ - MongoDB, MySQL ๋“ฑ
  • ์ธ์ฆ ์‹œ์Šคํ…œ - JWT, Passport.js ๋“ฑ
  • ํŒŒ์ผ ์—…๋กœ๋“œ - Multer ๋ฏธ๋“ค์›จ์–ด
  • API ๋ฌธ์„œํ™” - Swagger ๋“ฑ

์ถ”์ฒœ ํ•™์Šต ์ˆœ์„œ:

โ€” ์ด ํŽ˜์ด์ง€๋Š” ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. โ€”

wiki/it/dream_of_enc/metaverse/express.txt ยท ๋งˆ์ง€๋ง‰์œผ๋กœ ์ˆ˜์ •๋จ: ์ €์ž 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki