2025년 2월 20일

김동환·6일 전
0

Today I Learned (TIL) - 마피아 게임 웹소켓 시스템 개선

오늘 한 일

오늘은 마피아 게임의 웹소켓 시스템을 개선하기 위해 NightResultService를 새롭게 정리하고 확장했다. 이 서비스는 밤 동안의 결과 발표, 낮 시작 알림, 역할별 행동 공지, 게임 시작 및 종료 알림 등을 웹소켓을 통해 방 내 플레이어들에게 전달하는 역할을 한다.

주요 개선 사항

  1. 코드 정리 및 일관성 유지

    • announceSystemMessage 메서드를 추가하여 일반적인 시스템 메시지를 전송하는 로직을 통합했다.
    • announceJoinRoom, announceLeaveRoom, announceRoomFull 등 방 관련 공지에서도 이 함수를 활용하도록 수정했다.
  2. 새로운 알림 기능 추가

    • 경찰, 의사, 마피아의 액션을 명확하게 알릴 수 있는 메서드를 추가했다.
    • 밤이 끝난 후의 아침 알림(announceMorning)을 추가하여 게임 흐름을 더욱 직관적으로 만들었다.
  3. 게임 흐름 제어 기능 강화

    • 게임이 다시 시작될 때의 공지(announceGameRestart)를 추가하여 재시작 시 혼란을 방지했다.
    • 게임 시작 타이머가 취소될 경우를 대비하여 announceCancelTimer 기능을 구현했다.

오늘의 인사이트

  • 웹소켓을 활용한 공지 기능이 많아질수록 중복되는 코드가 많아질 수 있는데, 이를 적절히 추상화하는 것이 중요하다는 점을 다시 한번 깨달았다.
  • RoomGateway와의 의존성을 관리하면서도 서비스가 지나치게 비대해지지 않도록 단순한 역할을 유지하는 것이 중요하다.

내일 할 일

  • 게임 로직과의 연동을 고려하여 각 액션별 이벤트 트리거를 개선할 예정.
  • RoomGateway에서 알림을 보낼 때 메시지 포맷을 통합하고, 클라이언트와의 일관된 프로토콜 설계 검토.
  • 전체적인 테스트 코드 작성 및 리팩토링 진행.

import { Injectable } from '@nestjs/common';
import { RoomGateway } from './../room/room.gateway';

@Injectable()
export class NightResultService {
  constructor(private readonly roomGateway: RoomGateway) {}

  // 기본 시스템 공지 함수
  announceSystemMessage(
    roomId: string,
    message: string,
    additionalData?: Record<string, any>,
  ): void {
    this.roomGateway.broadcastNotice(
      roomId,
      'system_message',
      message,
      additionalData,
    );
  }

  announceNightResult(
    roomId: string,
    nightNumber: number,
    result: { killedUserId: string | null; details: string },
  ): void {
    const message = `밤 동안의 사건 결과: ${result.details}`;
    this.roomGateway.broadcastNotice(roomId, 'night_result', message, {
      nightNumber,
      result,
    });
  }

  announceDayStart(roomId: string, dayNumber: number): void {
    const message = `낮이 되었습니다. ${dayNumber}번째 낮`;
    this.roomGateway.broadcastNotice(roomId, 'day_start', message, {
      dayNumber,
    });
  }

  announceGameRestart(roomId: string): void {
    const message = '다시 시작되었습니다.';
    this.roomGateway.broadcastNotice(roomId, 'game_restart', message);
  }

  announcePoliceAction(roomId: string, userId: string): void {
    const message = `경찰이 능력을 사용했습니다: ${userId}`;
    this.roomGateway.broadcastNotice(roomId, 'police_action', message, {
      userId,
    });
  }

  announceDoctorAction(roomId: string, savedUserId: string): void {
    const message = `의사가 플레이어를 살렸습니다: ${savedUserId}`;
    this.roomGateway.broadcastNotice(roomId, 'doctor_action', message, {
      savedUserId,
    });
  }

  announceMafiaAction(roomId: string, targetUserId: string): void {
    const message = `마피아가 플레이어를 죽였습니다: ${targetUserId}`;
    this.roomGateway.broadcastNotice(roomId, 'mafia_action', message, {
      targetUserId,
    });
  }

  announceMorning(roomId: string, morningNumber: number): void {
    const message = `${morningNumber}번째 아침이 시작됩니다.`;
    this.roomGateway.broadcastNotice(roomId, 'morning_start', message, {
      morningNumber,
    });
  }

  // 추가된 시스템 공지 함수들
  announceJoinRoom(roomId: string, userId: number): void {
    const message = `${userId}번 유저가 ${roomId}번 방에 접속하였습니다.`;
    this.announceSystemMessage(roomId, message);
  }

  announceRoomFull(roomId: string): void {
    const message = '방이 꽉 찼습니다. 10초 후 게임이 시작됩니다.';
    this.announceSystemMessage(roomId, message);
  }

  announceLeaveRoom(roomId: string, userId: number): void {
    const message = `${userId}번 유저가 ${roomId}번 방에서 나갔습니다.`;
    this.announceSystemMessage(roomId, message);
  }

  announceCancelTimer(roomId: string): void {
    const message = '인원이 줄어들어 게임 시작 타이머가 취소되었습니다.';
    this.announceSystemMessage(roomId, message);
  }
}
profile
Node.js 7기

0개의 댓글

관련 채용 정보