Skip to content

게임 방에서 새로고침 또는 브라우저 탭을 닫을 때의 예외 처리

simjaesung edited this page Dec 1, 2024 · 1 revision

문제

다음과 같이 게임 방에서 새로고침을 하거나 브라우저 탭을 닫을 때 게임 방에서 퇴장하지 못하는 문제가 발생하였습니다.

image

환경

운영체제, 브라우저, 의존성 목록 등

  • Windows 11
  • Chrome
  • Next.js v15.0.2

설명

게임 방에서 나가기 버튼을 누르면 정상적으로 게임 방 퇴장이 이루어지지만, 게임 방 페이지에서 새로고침을 하거나 브라우저 탭을 닫는 경우 게임 방 퇴장이 이루어지지 못하는 문제가 발생하였습니다. 해당 문제가 발생하면서 실제 존재하지 않는 플레이어가 방의 참여 인원으로 존재하게 되므로 다른 플레이어의 방 입장이나 게임 진행에 큰 문제가 발생할 수 밖에 없었습니다.


해결 과정

원래 기존의 게임 방 퇴장 기능은 다음과 같이 useEffectclean-up 을 통해 이루어졌습니다.

useEffect(() => {
    // 웹 사이트를 새로고침하거나 주소창 입력으로 게임 방에 접속하려는 경우 로비 페이지로 강제 이동
    if (!socket) {
      router.replace('/lobby');
      return;
    }

    // 방 입장
    socket?.emit('enter-room', { roomId });

    return () => {
      socket?.emit('leave-room', { roomId });
    };
  }, [roomId, router, socket]);

하지만 useEffectclean-up 은 컴포넌트가 unmount될 때만 동작하고 웹 페이지를 새로고침하거나 아예 브라우저 탭을 닫을 때에는 동작하지 못합니다. 따라서 새로고침을 하거나 브라우저 탭을 닫는 경우 게임 방에서 퇴장하지 못했습니다.


해결

다음과 같이 beforeunload 이벤트를 통해 사용자가 새로고침을 하거나 브라우저 탭을 닫으려고 할 때 자동으로 방 퇴장 이벤트를 서버로 전송하여 문제를 해결하였습니다. 여기서 beforeunload 이벤트는 window, 문서(document) 및 해당 리소스가 언로드(unload) 되려고 할 때 시작되는 이벤트입니다.

useEffect(() => {
    // 웹 사이트를 새로고침하거나 주소창 입력으로 게임 방에 접속하려는 경우 로비 페이지로 강제 이동
    if (!socket) {
      router.replace('/lobby');
      return;
    }

    // 방 입장
    socket?.emit('enter-room', { roomId });

    **const handleBeforeUnload = () => {
      socket?.emit('leave-room', { roomId });
    };

    window.addEventListener('beforeunload', handleBeforeUnload);**

    return () => {
      **window.removeEventListener('beforeunload', handleBeforeUnload);**
      socket?.emit('leave-room', { roomId });
    };
  }, [roomId, router, socket]);

참고

[Window: beforeunload 이벤트 - Web API | MDN](https://developer.mozilla.org/ko/docs/Web/API/Window/beforeunload_event)

MafiaCamp

📔소개
🎯프로젝트 규칙
💻프로젝트 기획
🍀기술 스택
📚그룹 회고
🌈개발 일지
🍀문제 해결 경험
🔧트러블 슈팅
Clone this wiki locally