2025년 3월 11일

김동환·2025년 3월 11일

Today I Learned (TIL) - 마피아 게임에서 밤 행동 초기화 문제 해결

문제 상황

마피아 게임에서 밤 페이즈가 종료된 후, 새로운 밤이 시작될 때 이전 밤의 행동 데이터(마피아 공격, 경찰 조사, 의사 보호)가 초기화되지 않는 문제가 발생했다.

이로 인해, 이전 밤에 설정된 행동이 남아 있어 예상과 다르게 게임이 진행되었다.

원인 분석

  1. Redis 값 초기화 문제
    clearNightActions(roomId: string) 함수에서 redisClient.hdel()을 사용하여 nightAction:mafia, nightAction:police, nightAction:doctor를 삭제했지만, 실제로 Redis에서 값이 삭제되지 않고 남아 있었다.

  2. 비동기 처리의 문제 가능성
    Promise.all()을 사용하여 동시에 삭제했으나, 일부 키가 삭제되지 않는 현상이 발생했다.

  3. 삭제 후 값 검증 미흡
    삭제된 후 실제로 해당 키가 Redis에서 사라졌는지 검증하는 코드가 없었기 때문에, 값이 그대로 남아 있는지 확인하기 어려웠다.

해결 방법

  1. 삭제 후 값이 남아 있는지 검증하는 코드 추가

    • hdel 실행 후 hget을 사용하여 값이 삭제되었는지 확인했다.
  2. 단순 삭제에서 명시적인 초기화로 변경

    • hdel 대신 hset을 사용하여 값을 빈 문자열이나 false로 명시적으로 초기화했다.
  3. 디버깅 로그 추가

    • console.log()를 활용하여 삭제 과정과 결과를 명확하게 확인할 수 있도록 했다.

수정된 코드

// 밤 행동 상태를 초기화하는 메서드
async clearNightActions(roomId: string): Promise<void> {
  const gameId = await this.getCurrentGameId(roomId);
  if (!gameId) return;

  const redisKey = `room:${roomId}:game:${gameId}`;

  console.log(`초기화 전 상태 확인:`, await this.redisClient.hgetall(redisKey));

  // 기존 방식: hdel 사용 (비정상적인 삭제 문제 발생)
  // await Promise.all([
  //   this.redisClient.hdel(redisKey, 'nightAction:mafia'),
  //   this.redisClient.hdel(redisKey, 'nightAction:police'),
  //   this.redisClient.hdel(redisKey, 'nightAction:doctor'),
  // ]);

  // 새로운 방식: 값을 명시적으로 초기화 (삭제 대신 빈 값 저장)
  await Promise.all([
    this.redisClient.hset(redisKey, 'nightAction:mafia', 'false'),
    this.redisClient.hset(redisKey, 'nightAction:police', 'false'),
    this.redisClient.hset(redisKey, 'nightAction:doctor', 'false'),
  ]);

  // 삭제 후 값 확인
  const updatedValues = await this.redisClient.hgetall(redisKey);
  console.log(`초기화 후 상태 확인:`, updatedValues);

  console.log(`Room ${roomId}의 밤 행동 상태가 정상적으로 초기화되었습니다.`);
}

개선된 점

  1. 값이 실제로 초기화되었는지 확인 가능

    • console.log()를 통해 Redis 값이 변경되는 과정을 추적할 수 있도록 했다.
  2. 삭제 대신 명시적인 초기화 적용

    • hdel을 사용하여 삭제할 경우 삭제가 정상적으로 이루어지지 않을 가능성이 있었기 때문에, hset을 사용하여 값을 명확히 초기화했다.
  3. 비동기 실행 검증 추가

    • Promise.all()로 병렬 실행한 후, hgetall을 사용하여 데이터가 제대로 변경되었는지 확인했다.

결론

이제 밤이 끝날 때마다 마피아, 경찰, 의사의 행동이 정상적으로 초기화되어 새로운 밤이 예상대로 진행된다.

profile
Node.js 7기

0개의 댓글