SSAFY 프로젝트에서 협력 게임을 구현하기 위해 WebSocket 명세서를 작성하던 중, 몇 가지 설계 고민이 생겼다.
이 글은 그 고민과 결론을 정리한 글이다.
협력 게임의 핵심 흐름은 다음과 같다.
처음엔 방장이 게임 시작 요청을 보내면, 서버가 4명 모두에게 GAME_START를 broadcast하고 각 클라이언트가 ACK를 보내야 하는 게 아닐까 생각했다.
WebSocket은 TCP 기반이기 때문에, 연결이 살아있는 소켓에 메시지를 보내는 것 자체가 도달을 보장한다.
ACK 확인이 필요한 경우는 UDP 기반이거나, 클라이언트의 처리 완료 여부가 중요한 경우인데, 이 게임에서는 해당되지 않는다.
| 상황 | ACK 방식의 문제 |
|---|---|
| 한 명이 네트워크 지연 | 전체 게임이 그 사람을 기다리며 블로킹 |
| 한 명이 튕김 | ACK가 영원히 안 옴 → 별도 타임아웃 로직 필요 |
| 복잡도 | 명세서가 불필요하게 복잡해짐 |
서버가 broadcast할 때 server_timestamp를 함께 전달하고, 클라이언트는 그 기준으로 남은 시간을 계산해 렌더링하면 된다.
ACK 없이도 모든 클라이언트가 동일한 기준 시간을 공유할 수 있다.
Server → ALL: GAME_START { commands: [...], server_timestamp: 1234567890 }
Server: 3초 타이머 시작 (ACK 기다리지 않음)
Server → ALL: CARD_FLIP
4명이 필수인 게임인데, 방장이 시작 요청을 보내는 시점에 예기치 않게 한 명이 빠진 상태라면?
WebSocket은 연결을 지속적으로 유지하기 때문에, 누군가 연결이 끊어지면 서버에 즉시 disconnect 이벤트가 발생한다.
즉, 서버는 항상 해당 방에 살아있는 소켓 수를 실시간으로 파악하고 있다.
플레이어 튕김 → disconnect 이벤트 발생 → 서버가 방 인원 업데이트
방장이 GAME_START 요청 → 서버가 현재 인원 체크 → 4명 미만이면 거절
| 상황 | 서버 처리 |
|---|---|
| 방장이 start 요청, 4명 모두 연결 | GAME_START broadcast |
| 방장이 start 요청, 4명 미만 | ERROR 응답 (start 거절) |
| 게임 중 누군가 튕김 | disconnect 감지 → 게임 종료, 대기실 이동 broadcast |
요구사항에 "게임 중 사용자가 튕긴 경우 → 게임 종료 → 대기실 이동"이 있었는데, 이게 실제로 구현 가능한가 고민했다.
흐름은 다음과 같다.
게임 중 누군가 튕김
→ 서버 disconnect 이벤트 발생
→ 해당 방이 게임 중인지 확인
→ 전체에게 GAME_OVER broadcast
→ 대기실로 이동
별도의 폴링이나 ACK 없이, disconnect 이벤트 하나로 처리된다.
HTTP와 비교하면 차이가 명확하다.
| 항목 | HTTP | WebSocket |
|---|---|---|
| 연결 방식 | 요청할 때만 연결, 응답 후 끊김 | 연결을 계속 유지 |
| 서버가 클라이언트 상태 파악 | 불가능 | 실시간 가능 |
| 끊김 감지 | 불가능 (다음 요청이 올 때까지 모름) | disconnect 이벤트로 즉시 감지 |
| 서버 → 클라이언트 push | 불가능 | 가능 |
HTTP였다면 클라이언트가 먼저 요청을 보내야만 서버가 응답할 수 있어서, 누군가 튕겨도 그 사람이 다음 요청을 보내기 전까지 서버는 알 수 없다.
폴링 같은 우회 방법이 필요하고 실시간성이 떨어진다.
WebSocket은 지속 연결을 유지하기 때문에, 연결이 끊어지는 순간 서버에 바로 이벤트가 발생한다.
이것이 실시간 멀티플레이 게임에 WebSocket을 쓰는 가장 핵심적인 이유다.
| 고민 | 결론 |
|---|---|
| 게임 시작 시 ACK 확인 필요? | 불필요. TCP 기반 WebSocket은 도달 보장. server_timestamp 동기화로 충분 |
| 예기치 않은 인원 부족을 서버가 알 수 있나? | 가능. disconnect 이벤트로 방 인원을 항상 실시간 파악 |
| 게임 중 튕김을 서버가 감지해 게임 종료 가능? | 가능. disconnect 이벤트 → GAME_OVER broadcast |
결국 세 가지 고민 모두 WebSocket의 지속 연결 특성과 TCP의 도달 보장이 해결해준다.
명세서를 복잡하게 만들기 전에, WebSocket이 기본으로 제공하는 것이 무엇인지 먼저 파악하는 게 중요하다는 걸 느꼈다.