
게임 서버 통신: WebSocket vs gRPC 실무 선택 기준
WebSocket과 gRPC는 경쟁 관계라기보다 맡기기 좋은 일이 다른 도구다. 클라이언트 종류, 동기화 빈도, 운영 환경을 기준으로 게임 서버 통신 방식을 고르는 방법을 정리한다.
먼저 결론: 실시간 플레이 경로와 서비스 경로를 나눠 본다
게임에서 중요한 질문은 “어느 쪽이 더 빠른가”가 아니다. 어떤 메시지가 누구에게 얼마나 자주 전달되며 실패했을 때 어떻게 복구해야 하는지를 먼저 정해야 한다.
- WebSocket은 브라우저와 게임 클라이언트가 서버로 이벤트를 계속 주고받는 실시간 세션에 잘 맞는다.
- gRPC는 내부 서비스 간 호출, 운영 도구, 계정·매치메이킹·인벤토리 같은 명확한 요청·응답 API에 특히 강하다.
- 프레임 단위의 매우 민감한 대전 액션이나 슈팅 게임이라면 둘 다 TCP 기반이라는 점을 고려해야 한다. 이 경우 UDP 계열 전송이나 별도 실시간 전송 설계가 더 적합할 수 있다.
선택 흐름
flowchart TD
A[통신 요구사항 확인] --> B{브라우저 클라이언트가\n직접 연결하는가?}
B -->|예| C{지속적인 양방향\n이벤트가 필요한가?}
C -->|예| D[WebSocket 우선 검토]
C -->|아니오| E[HTTP API 또는 gRPC-Web 검토]
B -->|아니오| F{내부 서비스 또는\n관리 도구 통신인가?}
F -->|예| G[gRPC 우선 검토]
F -->|아니오| H{지연 민감도가\n프레임 단위인가?}
H -->|예| I[UDP 또는 전용 실시간 전송 검토]
H -->|아니오| D
WebSocket이 맞는 경우
WebSocket은 연결을 한 번 맺은 뒤 양방향으로 메시지를 주고받는다. 채팅, 로비 알림, 방 상태 변화, 협동 게임의 비교적 느린 상태 동기화처럼 서버가 먼저 이벤트를 밀어 보내야 하는 기능에 자연스럽다.
장점
- 브라우저에 표준 API가 있어 웹 게임에서 바로 사용할 수 있다.
- 연결 하나로 클라이언트 이벤트와 서버 푸시를 처리하기 쉽다.
- JSON으로 빠르게 시작할 수 있고 필요해지면 바이너리 프레임과 MessagePack·Protocol Buffers 같은 직렬화 형식으로 전환할 수 있다.
- 세션 기반 게임 서버의 접속·재접속 흐름을 모델링하기 편하다.
주의할 점
WebSocket은 메시지 형식, 버전 관리, 오류 코드, 재시도 정책을 팀이 직접 정해야 한다. 서버가 메시지를 너무 빨리 보내면 느린 클라이언트의 송신 버퍼가 쌓일 수 있으므로 큐 상한과 메시지 병합 정책이 필요하다.
예를 들어 위치 패킷은 오래된 값이 새 값보다 중요하지 않다. 큐에 모두 쌓기보다 마지막 위치만 남기는 편이 낫다.
// 위치 갱신은 연결별로 최신 값 하나만 보관한다.
type Position = { x: number; y: number; tick: number };
const pendingPosition = new Map<string, Position>();
function onPosition(clientId: string, position: Position) {
pendingPosition.set(clientId, position);
}
function flushPositions() {
for (const [clientId, position] of pendingPosition) {
broadcast({ type: "position", clientId, position });
}
pendingPosition.clear();
}
gRPC가 맞는 경우
gRPC는 Protocol Buffers로 계약을 정의하고 코드 생성으로 클라이언트와 서버의 타입을 맞춘다. 서비스가 여러 개로 나뉘는 팀일수록 API 계약과 변경 이력을 관리하기 좋다.
대표적인 활용처는 다음과 같다.
- 게임 서버가 계정, 결제 검증, 인벤토리, 랭킹 서비스에 요청할 때
- 매치메이킹 결과를 저장하거나 게임 결과를 정산할 때
- GM 도구나 배치 작업이 백엔드 서비스를 호출할 때
- 네이티브 게임 클라이언트가 비교적 명확한 요청·응답 API를 사용할 때
syntax = "proto3";
package game.matchmaking.v1;
service MatchmakingService {
rpc FindMatch(FindMatchRequest) returns (FindMatchResponse);
}
message FindMatchRequest {
string player_id = 1;
string region = 2;
uint32 rating = 3;
}
message FindMatchResponse {
string match_id = 1;
repeated string player_ids = 2;
string game_server_endpoint = 3;
}
장점
.proto파일이 API 계약의 기준점이 된다.- 요청과 응답의 타입이 명확해 실수를 일찍 발견하기 쉽다.
- 데드라인, 상태 코드, 인증 메타데이터 같은 호출 규칙을 일관되게 적용할 수 있다.
- 서버 간 통신에서 HTTP/2 기반 다중화와 스트리밍을 활용할 수 있다.
주의할 점
일반 브라우저는 네이티브 gRPC를 그대로 지원하지 않는다. 웹 클라이언트에서는 gRPC-Web과 프록시 구성이 필요하며 네이티브 gRPC와 스트리밍 기능이 완전히 동일하지 않을 수 있다. 브라우저 게임의 지속적 양방향 이벤트 채널을 만들려는 목적이라면 WebSocket이 보통 더 단순하다.
또한 gRPC 스트리밍이 있다고 해서 곧바로 게임 플레이 동기화의 정답이 되는 것은 아니다. 메시지 빈도와 패킷 손실보다 TCP의 순서 보장으로 인해 앞선 데이터가 지연될 때 뒤 데이터도 기다리는 특성이 플레이 감각에 더 큰 영향을 줄 수 있다.
비교표
| 기준 | WebSocket | gRPC |
|---|---|---|
| 브라우저 직접 지원 | 좋음 | gRPC-Web 등 추가 구성이 필요함 |
| 양방향 실시간 이벤트 | 매우 적합 | 서버 간 스트리밍에는 적합하나 웹 환경은 제약 확인 필요 |
| API 계약과 코드 생성 | 직접 설계해야 함 | Protocol Buffers와 코드 생성이 강점 |
| 메시지 형식 | JSON·바이너리 등 자유로움 | Protocol Buffers 중심 |
| 내부 마이크로서비스 | 가능하지만 규칙을 별도로 마련해야 함 | 매우 적합 |
| 초저지연 프레임 동기화 | TCP 특성을 검토해야 함 | TCP 특성을 검토해야 함 |
실무에서 자주 쓰는 조합
가장 현실적인 구성은 하나만 고집하지 않는 방식이다.
- 웹·모바일·PC 클라이언트와 게임 세션 서버 사이에는 WebSocket을 둔다.
- 게임 세션 서버와 계정·인벤토리·랭킹·매치메이킹 서비스 사이에는 gRPC를 둔다.
- 결과 저장, 로그 수집, 보상 지급처럼 즉시 응답이 꼭 필요하지 않은 작업은 메시지 브로커나 작업 큐로 분리한다.
이렇게 나누면 플레이어 연결 관리와 서비스 API 관리의 관심사가 섞이지 않는다. 특히 게임 세션 서버가 외부 서비스의 느린 응답을 기다리느라 틱 처리를 멈추지 않도록 호출 데드라인과 실패 시 대체 동작을 명확히 정해 두는 것이 중요하다.
대역폭과 전송 주기 계산
상태 동기화 비용은 대략 다음처럼 볼 수 있다.
예를 들어 한 플레이어의 상태 갱신이 평균 120바이트이고 초당 20회 전송되며 이를 30명에게 전달한다면 헤더와 암호화 오버헤드를 제외한 값만으로도 초당 약 72KB가 된다. 실제 설계에서는 수신 범위에 따라 대상을 줄이는 관심 영역 관리와 메시지 압축 여부를 함께 검토해야 한다.
도입 전 체크리스트
WebSocket을 고른다면
- 연결 끊김, 재접속, 중복 접속의 서버 정책을 정한다.
- 메시지 타입과 스키마 버전을 정의한다.
- 클라이언트별 송신 큐의 최대 크기와 초과 시 처리 방식을 정한다.
- 인증 갱신과 권한 검사를 연결 수명 전체에 걸쳐 설계한다.
gRPC를 고른다면
.proto변경의 호환성 규칙을 정한다. 기존 필드 번호를 재사용하지 않는 원칙이 대표적이다.- 모든 원격 호출에 적절한 데드라인을 둔다.
- 재시도 가능한 요청과 중복 실행되면 안 되는 요청을 구분한다.
- 브라우저 지원이 필요하면 gRPC-Web의 프록시, 스트리밍 제약, 관측 도구를 초기부터 검증한다.
마무리
WebSocket은 플레이어와 지속적으로 대화하는 채널에 gRPC는 서비스 사이의 명확한 계약이 필요한 호출에 강점이 있다. 먼저 게임의 실시간성 요구와 클라이언트 플랫폼을 분리해 보면 선택이 쉬워진다. 한 가지 프로토콜로 모든 문제를 해결하려 하기보다 플레이 경로와 백엔드 업무 경로에 각각 맞는 통신 방식을 배치하는 편이 운영과 확장 모두에서 유리하다.


