목차

🟢 Node.js 백엔드 설정

Phaser Baduk Metaverse 프로젝트의 Node.js 백엔드 설정과 구성에 대해 자세히 설명합니다.


1. Node.js란 무엇인가요?

Node.jsJavaScript를 서버에서 실행할 수 있게 해주는 런타임 환경입니다. 웹 브라우저에서만 실행되던 JavaScript를 서버에서도 실행할 수 있게 해줍니다.

주요 특징:


2. 프로젝트 개요

이 프로젝트는 Node.js를 기반으로 하며, 웹 페이지를 서버에서 렌더링하고 클라이언트와의 실시간 통신 기능을 제공합니다.

주요 기술 스택:


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');     // 파일 경로 처리 유틸리티

각 모듈의 역할:

2) 애플리케이션 인스턴스 생성

const app = express(); // Express 애플리케이션 생성
const server = http.createServer(app); // HTTP 서버 생성 (Express 앱을 기반으로)
const io = socketIo(server); // 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'));
});

설명:

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);
    });
});

설명:

5) 서버 포트 설정 및 실행

환경 변수에서 포트 번호를 가져오거나 기본값(3000)을 사용하여 서버를 지정된 포트에서 실행합니다.

// 환경 변수에서 PORT를 가져오거나 기본값 3000 사용
const PORT = process.env.PORT || 3000;
 
// 서버를 지정된 포트에서 실행하고, 성공 시 콘솔에 메시지 출력
server.listen(PORT, () => {
    console.log(`서버가 포트 ${PORT}에서 실행 중입니다.`);
    console.log(`http://localhost:${PORT}에서 접속하세요.`);
});

설명:


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

주요 환경 변수:

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;

설명:


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

각 폴더의 역할:


7. 개발 환경 설정

1) Node.js 설치

Windows에서 Node.js 설치:

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

설명:

2) 프로덕션 모드로 서버 실행

npm start

설명:

3) 서버 테스트

브라우저에서 테스트:

터미널에서 테스트:

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에서 디버깅:


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 기본을 배웠다면 다음을 학습해보세요:

추천 학습 순서:

이 페이지는 자동으로 생성되었습니다.