안녕하세요. 온라인 Snake 게임 개발 교육과정의 다섯 번째 시간입니다. 오늘은 Express.js를 이용한 서버 설정과 RESTful API 구현에 대해 알아보겠습니다.
1. Express.js 서버 설정
먼저 기본적인 Express.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);
const PORT = process.env.PORT || 3000;
app.use(express.static(path.join(__dirname, 'public')));
server.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
2. 게임 로직 모듈화
게임 로직을 별도의 모듈로 분리하여 관리합니다.
// gameLogic.js
const GRID_SIZE = 20;
const CANVAS_SIZE = 400;
class Game {
constructor() {
this.players = [];
this.foods = [];
this.gridSize = GRID_SIZE;
this.canvasSize = CANVAS_SIZE;
}
addPlayer(id) {
// 플레이어 추가 로직
}
removePlayer(id) {
// 플레이어 제거 로직
}
movePlayer(id, direction) {
// 플레이어 이동 로직
}
update() {
// 게임 상태 업데이트 로직
}
// 기타 필요한 메서드들...
}
module.exports = Game;
3. Socket.io 이벤트 핸들링
서버에서 Socket.io 이벤트를 처리합니다.
const Game = require('./gameLogic');
const games = new Map();
io.on('connection', (socket) => {
console.log('A user connected');
socket.on('createRoom', () => {
const roomCode = generateRoomCode();
games.set(roomCode, new Game());
socket.join(roomCode);
socket.emit('roomCreated', roomCode);
});
socket.on('joinRoom', (roomCode) => {
if (games.has(roomCode)) {
socket.join(roomCode);
const game = games.get(roomCode);
game.addPlayer(socket.id);
socket.emit('joinedRoom', roomCode);
io.to(roomCode).emit('playerJoined', game.players.length);
} else {
socket.emit('roomNotFound');
}
});
socket.on('startGame', (roomCode) => {
if (games.has(roomCode)) {
const game = games.get(roomCode);
game.start();
io.to(roomCode).emit('gameStarted', game.getState());
startGameLoop(roomCode);
}
});
socket.on('changeDirection', ({ roomCode, direction }) => {
if (games.has(roomCode)) {
const game = games.get(roomCode);
game.movePlayer(socket.id, direction);
}
});
socket.on('disconnect', () => {
console.log('A user disconnected');
// 플레이어 제거 및 게임 상태 업데이트 로직
});
});
4. 게임 루프 구현
서버에서 게임 루프를 실행하여 게임 상태를 주기적으로 업데이트합니다.
function startGameLoop(roomCode) {
const game = games.get(roomCode);
const interval = setInterval(() => {
game.update();
const gameState = game.getState();
io.to(roomCode).emit('gameState', gameState);
if (game.isOver()) {
clearInterval(interval);
io.to(roomCode).emit('gameOver', game.getWinners());
games.delete(roomCode);
}
}, 100); // 100ms 간격으로 업데이트
}
5. RESTful API 구현
게임 관련 정보를 조회할 수 있는 간단한 RESTful API를 구현합니다.
app.get('/api/rooms', (req, res) => {
const roomList = Array.from(games.keys());
res.json(roomList);
});
app.get('/api/room/:roomCode', (req, res) => {
const roomCode = req.params.roomCode;
if (games.has(roomCode)) {
const game = games.get(roomCode);
res.json(game.getState());
} else {
res.status(404).json({ error: 'Room not found' });
}
});
6. 에러 핸들링
서버에서 발생할 수 있는 에러를 적절히 처리합니다.
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Something went wrong!' });
});
process.on('uncaughtException', (err) => {
console.error('Uncaught Exception:', err);
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
process.exit(1);
});
7. 환경 변수 사용
보안과 유연성을 위해 환경 변수를 사용합니다.
require('dotenv').config();
const PORT = process.env.PORT || 3000;
const MAX_PLAYERS = process.env.MAX_PLAYERS || 4;
결론
이번 포스팅에서는 Express.js를 이용한 백엔드 서버 구축에 대해 알아보았습니다. 게임 로직의 모듈화, Socket.io를 이용한 실시간 통신, RESTful API 구현, 그리고 에러 핸들링 등 서버 개발의 주요 측면들을 다뤘습니다.
이러한 백엔드 구조는 게임의 안정성과 확장성을 보장하며, 클라이언트와 효율적으로 통신할 수 있는 기반을 제공합니다.
다음 포스팅에서는 게임 최적화와 버그 수정에 대해 다루겠습니다. 성능 개선 기법과 일반적인 게임 개발 관련 버그들을 어떻게 해결하는지 알아보겠습니다. 감사합니다!
관련 포스팅
결과물: 지렁이 게임 멀티 6인용(ver. 2.0) – CSAI
1. 프로젝트 개요 및 기획(지렁이 게임 온라인) – CSAI
2. 게임 로직 설계(지렁이 온라인 게임) – CSAI
3. 멀티플레이어 기능 구현(지렁이 온라인 게임) – CSAI
4. 프론트엔드 개발(지렁이 온라인 게임) – CSAI
I think this is one of the most vital info for me.And i am
glad reading your article. But want to remark on few
general things, The web site style is great,
the articles is rwally nice : D. Good job, cheers http://Boyarka-inform.com