웹소켓 서버에서 handlerMapping과 PacketType을 사용하여 클라이언트와 서버 간의 패킷 교환을 구현하는 방법을 설명하겠습니다. 이 예제에서는 클라이언트가 서버로 다양한 유형의 요청을 보내고, 서버가 이를 처리하여 응답을 보내는 흐름을 다룹니다.
주요 구성 요소
- PacketType: 각 패킷의 유형을 정의하는 상수 모음입니다. 이를 통해 서버는 수신한 패킷의 유형을 식별할 수 있습니다.
- handlerMapping: 각 패킷 유형에 대응하는 핸들러 함수를 매핑하는 객체입니다. 패킷 유형에 따라 적절한 핸들러가 호출됩니다.
- 핸들러 함수: 각각의 패킷 유형에 대한 구체적인 처리 로직을 포함합니다.
- WebSocket 서버: 클라이언트로부터 메시지를 수신하고 적절한 핸들러 함수를 호출합니다.
구현 예시
1. PacketType 정의
먼저 패킷 유형을 정의합니다. 예를 들어, 클라이언트에서 서버로 로그인 요청, 게임 종료 요청, 게임 동기화 요청, 서버에서 클라이언트로 게임 종료 알림을 보낼 수 있다고 가정합니다.
// constants.js
const PacketType = {
C2S_LOGIN_REQUEST: 'C2S_LOGIN_REQUEST',
C2S_GAME_END_REQUEST: 'C2S_GAME_END_REQUEST',
C2S_GAMESYNC_REQUEST: 'C2S_GAMESYNC_REQUEST',
S2C_GAME_OVER_NOTIFICATION: 'S2C_GAME_OVER_NOTIFICATION'
};
module.exports = { PacketType };
2. 핸들러 함수 정의
각 패킷 유형에 대응하는 핸들러 함수를 정의합니다.
//import { getUsers, removeUser } from '../models/user.model.js';
import { CLIENT_VERSION } from '../constants.js';
import handlerMappings from './handlerMapping.js';
export const handleDisconnect = (socket, uuid) => {
//removeUser(socket.id); // 사용자 삭제
console.log(`User disconnected: ${socket.id}`);
//console.log('Current users:', getUsers());
};
export const handleConnection = async (socket, userUUID) => {
console.log(`New user connected: ${userUUID} with socket ID ${socket.id}`);
//console.log('Current users:', getUsers());
socket.emit('connection', { uuid: userUUID, highScore: highScore });
};
export const handleEvent = async (io, socket, data) => {
if (!CLIENT_VERSION.includes(data.clientVersion)) {
// 만약 일치하는 버전이 없다면 response 이벤트로 fail 결과를 전송합니다.
socket.emit('response', { status: 'fail', message: 'Client version mismatch' });
return;
}
const handler = handlerMappings[data.handlerId];
if (!handler) {
socket.emit('response', { status: 'fail', message: 'Handler not found' });
return;
}
// 적절한 핸들러에 userID 와 payload를 전달하고 결과를 받습니다.
const response = await handler(data.userId, data.payload);
// 만약 결과에 broadcast (모든 유저에게 전달)이 있다면 broadcast 합니다.
if (response.broadcast) {
io.emit('response', response);
return;
}
// 해당 유저에게 적절한 response를 전달합니다.
socket.emit('response', response);
};
3. 핸들러 매핑
핸들러 함수를 패킷 유형에 매핑합니다.
// handlerMapping.js
const { PacketType } = require('../constants');
const { handleLogin, handleGameEnd, handleGameSync, handleGameOver } = require('./handlers');
const handlerMapping = {
[PacketType.C2S_LOGIN_REQUEST]: handleLogin,
[PacketType.C2S_GAME_END_REQUEST]: handleGameEnd,
[PacketType.C2S_GAMESYNC_REQUEST]: handleGameSync,
[PacketType.S2C_GAME_OVER_NOTIFICATION]: handleGameOver
// 추가 핸들러 매핑
};
module.exports = handlerMapping;
요약
- PacketType 정의: 패킷 유형을 정의하여 요청과 응답을 식별합니다.
- 핸들러 함수 작성: 각 패킷 유형에 대응하는 핸들러 함수를 작성합니다.
- 핸들러 매핑: 패킷 유형과 핸들러 함수를 매핑하여 요청에 대응하는 함수를 호출할 수 있게 합니다.
- WebSocket 서버 설정: 서버에서 메시지를 수신하고 적절한 핸들러를 호출하는 로직을 작성합니다.
- 클라이언트 구현: 클라이언트에서 서버로 요청을 보내고 응답을 처리합니다.
이를 통해 클라이언트와 서버는 다양한 유형의 요청과 응답을 처리할 수 있으며, 서버는 클라이언트의 요청에 따라 적절한 동작을 수행할 수 있습니다.
'[웹 소켓]' 카테고리의 다른 글
handler를 활용한 타워 디펜스 개발 (0) | 2024.06.18 |
---|