협력 게임 WebSocket 명세서 설계 전, 내가 고민했던 것들

dobby·2026년 4월 26일

Let's git it BE

목록 보기
6/20

들어가며

SSAFY 프로젝트에서 협력 게임을 구현하기 위해 WebSocket 명세서를 작성하던 중, 몇 가지 설계 고민이 생겼다.
이 글은 그 고민과 결론을 정리한 글이다.


게임 구조 간단 요약

협력 게임의 핵심 흐름은 다음과 같다.

  1. 4명이 모두 접속해야 게임 시작 가능
  2. 명령어 4개를 3초 공개 → 카드 뒤집기 → 섞기 → 1인 1개 랜덤 배정
  3. 플레이어들은 기억한 순서대로 명령어를 순서에 맞게 입력
  4. 순서 오입력 시 사이렌 효과 + 해당 판 전체 리셋
  5. 20개 명령어(5세트 × 4개)를 모두 완료하면 게임 종료

고민 1. 게임 시작 시, 4명이 GAME_START를 받았는지 ACK로 확인해야 할까?

처음엔 방장이 게임 시작 요청을 보내면, 서버가 4명 모두에게 GAME_START를 broadcast하고 각 클라이언트가 ACK를 보내야 하는 게 아닐까 생각했다.

결론: 필요 없다

WebSocket은 TCP 기반이기 때문에, 연결이 살아있는 소켓에 메시지를 보내는 것 자체가 도달을 보장한다.
ACK 확인이 필요한 경우는 UDP 기반이거나, 클라이언트의 처리 완료 여부가 중요한 경우인데, 이 게임에서는 해당되지 않는다.

ACK 방식을 쓰면 오히려 문제가 생긴다

상황ACK 방식의 문제
한 명이 네트워크 지연전체 게임이 그 사람을 기다리며 블로킹
한 명이 튕김ACK가 영원히 안 옴 → 별도 타임아웃 로직 필요
복잡도명세서가 불필요하게 복잡해짐

대신 이렇게 설계한다

서버가 broadcast할 때 server_timestamp를 함께 전달하고, 클라이언트는 그 기준으로 남은 시간을 계산해 렌더링하면 된다.
ACK 없이도 모든 클라이언트가 동일한 기준 시간을 공유할 수 있다.

Server → ALL: GAME_START { commands: [...], server_timestamp: 1234567890 }
Server: 3초 타이머 시작 (ACK 기다리지 않음)
Server → ALL: CARD_FLIP

고민 2. 게임 시작 전, 예기치 않게 3명만 접속된 상태를 서버가 알 수 있을까?

4명이 필수인 게임인데, 방장이 시작 요청을 보내는 시점에 예기치 않게 한 명이 빠진 상태라면?

결론: 서버는 알 수 있다

WebSocket은 연결을 지속적으로 유지하기 때문에, 누군가 연결이 끊어지면 서버에 즉시 disconnect 이벤트가 발생한다.
즉, 서버는 항상 해당 방에 살아있는 소켓 수를 실시간으로 파악하고 있다.

플레이어 튕김 → disconnect 이벤트 발생 → 서버가 방 인원 업데이트
방장이 GAME_START 요청 → 서버가 현재 인원 체크 → 4명 미만이면 거절

명세서에 필요한 건 서버 validation 하나면 된다

상황서버 처리
방장이 start 요청, 4명 모두 연결GAME_START broadcast
방장이 start 요청, 4명 미만ERROR 응답 (start 거절)
게임 중 누군가 튕김disconnect 감지 → 게임 종료, 대기실 이동 broadcast

고민 3. 게임 중 플레이어가 튕기면 서버가 감지해서 게임을 종료시킬 수 있을까?

요구사항에 "게임 중 사용자가 튕긴 경우 → 게임 종료 → 대기실 이동"이 있었는데, 이게 실제로 구현 가능한가 고민했다.

결론: 가능하다, WebSocket이라서

흐름은 다음과 같다.

게임 중 누군가 튕김
    → 서버 disconnect 이벤트 발생
    → 해당 방이 게임 중인지 확인
    → 전체에게 GAME_OVER broadcast
    → 대기실로 이동

별도의 폴링이나 ACK 없이, disconnect 이벤트 하나로 처리된다.


이게 왜 WebSocket이라서 가능한가?

HTTP와 비교하면 차이가 명확하다.

항목HTTPWebSocket
연결 방식요청할 때만 연결, 응답 후 끊김연결을 계속 유지
서버가 클라이언트 상태 파악불가능실시간 가능
끊김 감지불가능 (다음 요청이 올 때까지 모름)disconnect 이벤트로 즉시 감지
서버 → 클라이언트 push불가능가능

HTTP였다면 클라이언트가 먼저 요청을 보내야만 서버가 응답할 수 있어서, 누군가 튕겨도 그 사람이 다음 요청을 보내기 전까지 서버는 알 수 없다.
폴링 같은 우회 방법이 필요하고 실시간성이 떨어진다.

WebSocket은 지속 연결을 유지하기 때문에, 연결이 끊어지는 순간 서버에 바로 이벤트가 발생한다.
이것이 실시간 멀티플레이 게임에 WebSocket을 쓰는 가장 핵심적인 이유다.


정리

고민결론
게임 시작 시 ACK 확인 필요?불필요. TCP 기반 WebSocket은 도달 보장. server_timestamp 동기화로 충분
예기치 않은 인원 부족을 서버가 알 수 있나?가능. disconnect 이벤트로 방 인원을 항상 실시간 파악
게임 중 튕김을 서버가 감지해 게임 종료 가능?가능. disconnect 이벤트 → GAME_OVER broadcast

결국 세 가지 고민 모두 WebSocket의 지속 연결 특성과 TCP의 도달 보장이 해결해준다.
명세서를 복잡하게 만들기 전에, WebSocket이 기본으로 제공하는 것이 무엇인지 먼저 파악하는 게 중요하다는 걸 느꼈다.

profile
느리게 한걸음

0개의 댓글