Socket IO를 이용한 타워디펜스 게임 만들기!
📂 src/
┣ 📂 init/
┃ ┣ 📜 assets.js
┃ ┣ 📜 redis.js
┃ ┣ 📜 socket.js
┣ 📂 handlers/
┃ ┣ 📜 game.handler.js
┃ ┣ 📜 tower.handler.js
┃ ┣ 📜 monster.handler.js
┃ ┣ 📜 stage.handler.js
┣ 📂 manager/
┃ ┣ 📜 monster.manager.js
┣ 📂 middlewares/
┃ ┣ 📜 auth.middleware.js
┃ ┣ 📜 error-handler.middleware.js
┣ 📂 models/
┃ ┣ 📜 tower.model.js
┃ ┣ 📜 monster.model.js
┣ 📂 routes/
┃ ┗ 📜 account.router.js
┣ 📂 utils/
┃ ┗ 📂 joi/
┃ ┗ 📜 valid.schema.js
타워 디펜스 프로젝트의 이벤트 핸들러 함수들을 다뤄보겠습니다. 이 함수들은 게임 내에서 플레이어와 서버 간의 상호작용을 관리하며, 타워 배치, 몬스터 소환, 스테이지 진행 등의 핵심 기능을 담당합니다. 제공된 파일에 맞추어 각 핸들러의 역할을 자세히 설명해드리겠습니다.
gameStart - 게임 시작gameStart 함수는 유저가 게임을 시작할 때 초기 게임 데이터를 설정하고, 클라이언트에 해당 데이터를 전달하는 역할을 합니다. 유저의 골드, 타워, 스테이지 정보 등을 Redis에 동기화하고, 몬스터 생성 작업을 처리합니다.
uuid: 유저의 고유 식별자.payload: 클라이언트로부터 받은 데이터로, 타임스탬프를 포함.socket: 클라이언트와 서버 간 실시간 통신을 위한 소켓 객체.게임 자산 및 유저 정보 조회
getGameAssets()를 호출해 초기 게임 데이터를 불러옵니다.getUserInfo(uuid)를 통해 유저 정보를 조회하고, 유저의 현재 골드, HP, 타워, 스테이지 정보를 불러옵니다.게임 시작 데이터 설정
타임스탬프 유효성 검사
payload.timeStamp가 없는 경우, 게임 초기 데이터 검증 실패 에러를 발생시킵니다.Redis 동기화 작업
syncTowersToRedis(socket)와 syncTowerStatsToRedis()를 통해 타워와 타워 스탯을 Redis에 동기화합니다.spawnMonsters(uuid)를 호출해 스테이지에 맞는 몬스터를 생성하고, 해당 데이터를 클라이언트에 전달합니다.syncStageToRedis()로 스테이지 정보를 Redis에 저장합니다.클라이언트로 게임 시작 이벤트 전송
{ status: 'success', message: '게임 시작!', ... }gameEnd - 게임 종료gameEnd 함수는 유저가 게임을 종료할 때 DB에 현재 스테이지와 골드 정보를 저장하고, 캐시에서 관련 데이터를 삭제하는 역할을 합니다.
uuid: 유저의 고유 식별자.payload: 클라이언트로부터 받은 데이터로 게임 종료 시 필요 정보 포함.초기 데이터 및 캐시에서 스테이지 정보 조회
getGameAssets()를 호출해 초기 데이터를 불러오고, 초기 골드 값을 설정합니다.RedisManager.getUserData(uuid)를 호출해 캐시에서 유저가 도달한 스테이지 정보를 가져옵니다.DB에 유저 데이터 저장
userDataClient.users.update()를 통해 유저의 골드와 스테이지 정보를 DB에 저장합니다.캐시 삭제
RedisManager.deleteCache()를 호출해 유저의 게임 정보 및 인벤토리 관련 캐시 데이터를 삭제합니다.{ status: 'success' }initTowerHandler - 타워 초기화타워를 초기화할 때 사용되는 함수로, 유저의 인벤토리에 새로운 타워 데이터를 설정합니다.
userId: 유저의 고유 식별자.payload: 클라이언트로부터 받은 데이터로 타워 인벤토리를 포함.getUserInfo(userId)를 통해 불러옵니다.payload.towerInven으로 갱신합니다.updateUserInventory(userId, user.inventory)를 호출해 갱신된 인벤토리를 저장합니다.{ status: 'success', message: '타워 초기화 성공', inventory: user.inventory }purchaseTowerHandler - 타워 구매유저가 타워를 구매할 때 골드를 차감하고 인벤토리에 해당 타워를 추가하는 함수입니다.
userId: 유저의 고유 식별자.payload: 클라이언트에서 전송된 데이터로, 타워 비용과 인벤토리 정보를 포함.getUserInfo(userId)로 불러옵니다.updateUserGold(userId, user.gold)로 유저의 골드 정보를 갱신합니다.updateUserInventory(userId, user.inventory)로 갱신된 인벤토리를 저장합니다.{status: 'success', message: '타워 구매 성공'}{status: 'fail', message: '골드가 부족합니다.'} 또는 {status: 'fail', message: '사용자 정보를 찾을 수 없습니다.'}upgradeTowerHandler - 타워 업그레이드유저가 보유한 타워를 업그레이드할 때 골드를 차감하고 인벤토리에 업그레이드된 타워 정보를 저장하는 함수입니다.
userId: 유저의 고유 식별자.payload: 클라이언트에서 전송된 데이터로, 업그레이드된 타워 인벤토리와 비용 정보를 포함.getUserInfo(userId)로 불러옵니다.payload.towerInven으로 갱신합니다.updateUserGold(userId, user.gold)로 갱신된 골드 정보를 저장합니다.updateUserInventory(userId, user.inventory)로 갱신된 인벤토리를 저장합니다.{status: 'success', message: '타워 업그레이드 성공'}killMonsterHandler 함수는 플레이어가 몬스터를 처치했을 때 서버와 클라이언트 간의 데이터를 처리하는 역할을 수행합니다. 이 함수는 서버에 저장된 몬스터 리스트에서 해당 몬스터를 제거하고, 유저에게 골드를 지급하는 등의 작업을 합니다.
uuid: 유저의 고유 식별자.payload: 클라이언트에서 전송된 데이터로, 몬스터 목록과 처치된 몬스터의 인덱스를 포함.socket: 클라이언트와 서버 간 실시간 통신을 위한 소켓 객체.서버의 몬스터 정보 및 유저 정보 조회
getMonsters(uuid)를 통해 Redis에 저장된 서버의 몬스터 목록을 불러옵니다.getUserInfo(uuid)를 호출해 유저의 현재 골드를 포함한 정보를 가져옵니다.몬스터 존재 여부 확인
payload.index로 받은 인덱스를 기준으로 해당 몬스터가 서버에 존재하는지 확인합니다.몬스터 제거
0을 삽입해 갱신합니다.골드 보상 지급
updateUserGold(uuid, newGold)로 유저 정보를 업데이트합니다.Redis에 갱신된 몬스터 리스트 저장
setMonsters(uuid, serverMonsters))클라이언트로 보상 이벤트 전송
socket.emit('getGold', { gold: newGold })로 클라이언트에 골드 획득 이벤트를 보냅니다.{ message: '몬스터 처치' }{ status: '몬스터 처치 처리 실패' }moveStageHandler 함수는 유저가 특정 스테이지에서 다음 스테이지로 이동할 때 처리하는 로직을 담당합니다. 스테이지 이동 시, 일정 시간 동안의 지연을 관리하고, 해당 스테이지에 등장할 몬스터를 생성하여 클라이언트에 전송합니다.
uuid: 유저의 고유 식별자.payload: 클라이언트로부터 받은 데이터로, 현재 스테이지와 이동할 스테이지 정보를 포함.socket: 클라이언트와의 실시간 통신을 위한 소켓 객체.유저 정보 및 스테이지 정보 확인
getUserInfo(uuid)를 호출해 유저 정보를 가져옵니다.payload에서 현재 스테이지(currentStage)와 이동할 스테이지(targetStage) 정보를 추출하여, 값이 없는 경우 실패 메시지를 반환합니다.스테이지 이동 시간 제한 확인
STAGE_MOVE_DELAY)보다 빠르게 요청이 들어올 경우 "Stage move action too fast" 메시지를 반환합니다.스테이지 이동 처리
updateStage(uuid, targetStage)를 호출해 유저의 스테이지 정보를 업데이트합니다.spawnMonsters(uuid)를 통해 새 스테이지에 맞는 몬스터를 생성합니다.클라이언트로 스테이지 이동 이벤트 전송
setTimeout 500ms), 소켓을 통해 클라이언트에 스테이지 이동 중 메시지와 몬스터 정보를 전송합니다.{ status: 'success', message: '스테이지 이동 완료' }{ status: 'fail', message: 'User Not Found' }, { status: 'fail', message: 'Not Exist Stage Info' }, 또는 { status: 'fail', message: 'Stage move action too fast' }