
서버/클라이언트 통신 선택: WebSocket vs gRPC vs UDP 기반 실시간 네트워크 비교
게임의 장르와 지연 시간 목표에 따라 WebSocket, gRPC, UDP 기반 네트워크의 역할은 달라진다. 세 방식의 특성과 한계를 비교하고 인디 팀이 현실적으로 선택할 수 있는 조합을 정리한다.
멀티플레이어 게임에서 통신 방식을 고를 때 가장 먼저 해야 할 일은 “무엇이 가장 빠른가”를 묻는 것이 아니다. 어떤 데이터가 얼마나 자주 오가며 늦거나 순서가 바뀌거나 일부가 유실됐을 때 게임이 어떻게 반응해야 하는지부터 정리해야 한다.
WebSocket, gRPC, UDP는 서로 완전히 대체하는 기술이 아니다. 로비와 매치메이킹, 인벤토리처럼 정확성이 중요한 기능에는 신뢰성 있는 통신이 알맞고 격투나 레이싱처럼 수십 밀리초의 차이가 체감되는 게임 플레이에는 지연을 제어하는 설계가 더 중요하다.
먼저 구분할 것: 프로토콜보다 전송 성질
세 기술을 비교할 때는 이름보다 다음 네 가지를 봐야 한다.
- 신뢰성: 보낸 데이터가 반드시 도착해야 하는가
- 순서 보장: 먼저 보낸 데이터가 먼저 처리되어야 하는가
- 지연 민감도: 오래된 데이터라도 반드시 받아야 하는가
- 개발·운영 비용: 클라이언트 환경, 서버 인프라, 디버깅 도구를 팀이 감당할 수 있는가
예를 들어 플레이어의 현재 입력은 다음 틱의 더 최신 입력이 곧 도착한다. 이전 입력 패킷을 재전송하느라 최신 입력까지 막는 것은 오히려 좋지 않을 수 있다. 반면 결제 결과나 아이템 지급은 한 번이라도 유실되면 안 된다.
flowchart TD
A[전송할 데이터] --> B{유실돼도 다음 값으로 복구 가능한가?}
B -- 아니오 --> C{웹 브라우저를 직접 지원해야 하는가?}
C -- 예 --> D[HTTPS, WebSocket 또는 gRPC-Web 계열]
C -- 아니오 --> E[gRPC 또는 신뢰성 있는 TCP 계열]
B -- 예 --> F{실시간 조작의 지연이 핵심인가?}
F -- 예 --> G[UDP 기반 게임 네트워크]
F -- 아니오 --> H[WebSocket 또는 신뢰성 채널]
WebSocket: 웹과 운영 도구에 강한 지속 연결
WebSocket은 HTTP 연결로 시작한 뒤 양방향 지속 연결로 전환하는 방식이다. 브라우저에서 기본적으로 지원하고 프록시와 방화벽 환경에서 비교적 다루기 쉬워 웹 게임과 운영용 대시보드에 특히 잘 맞는다.
기본적으로 TCP 위에서 동작하므로 데이터 유실과 순서 뒤바뀜을 애플리케이션이 직접 처리할 필요는 적다. 대신 앞선 데이터가 지연되거나 유실되어 재전송되는 동안 뒤의 데이터도 기다릴 수 있다. 이를 흔히 헤드 오브 라인 블로킹이라고 부른다.
WebSocket이 잘 맞는 기능
- 웹 기반 게임의 로비와 채팅
- 매치메이킹 상태 갱신
- 턴제 게임의 명령과 결과 전달
- 협동 게임의 방 상태, 준비 완료, 이모트
- 관리자 도구와 실시간 관전 정보
실시간 게임 플레이에 WebSocket을 쓸 수 없는 것은 아니다. 캐주얼 협동 게임이나 낮은 빈도의 상태 동기화에는 충분할 수 있다. 다만 빠른 액션 게임에서 매 프레임 전체 상태를 보낼 통로로 삼으면 지연이 누적되기 쉽다.

WebSocket 메시지는 작게 유지하는 편이 좋다. JSON은 디버깅하기 편하지만 자주 오가는 플레이 입력에는 크기와 파싱 비용이 부담이 될 수 있다. 메시지 종류만큼은 명확히 구분하고 빈도가 높은 경로에는 바이너리 직렬화를 검토할 만하다.
// 클라이언트: WebSocket 메시지의 최소 형태 예시
socket.send(JSON.stringify({
type: "ready",
matchId: "m_42"
}));
socket.addEventListener("message", (event) => {
const message = JSON.parse(event.data);
if (message.type === "match-found") {
connectToGame(message.endpoint);
}
});
gRPC: 서비스 간 계약과 내부 API에 강한 선택
gRPC는 보통 Protocol Buffers로 인터페이스를 정의하고 생성된 코드로 원격 호출을 수행하는 RPC 프레임워크다. 메시지 구조와 API 계약을 명시적으로 관리할 수 있고 단항 호출뿐 아니라 스트리밍도 지원한다.
게임 백엔드에서는 특히 서비스 간 통신에 장점이 크다. 계정, 친구, 인벤토리, 랭킹, 분석, 매치메이킹처럼 여러 서비스가 나뉜 구조에서 타입이 있는 계약과 코드 생성은 변경 실수를 줄이는 데 도움이 된다.
gRPC의 강점과 주의점
gRPC는 HTTP/2를 기반으로 하므로 다중 요청과 스트리밍을 깔끔하게 다룰 수 있다. 하지만 일반적인 네이티브 gRPC는 브라우저에서 그대로 쓸 수 있는 전제가 아니다. 웹 클라이언트에서는 gRPC-Web 호환 계층이나 프록시 구성이 필요하며 지원 기능과 스트리밍 제약도 구현체별로 확인해야 한다.
또한 gRPC 역시 신뢰성 있는 전송을 바탕으로 한다. 따라서 프레임 단위 입력 동기화처럼 최신성이 신뢰성보다 중요한 구간의 만능 해법은 아니다.
syntax = "proto3";
service Matchmaking {
rpc FindMatch(FindMatchRequest) returns (FindMatchResponse);
}
message FindMatchRequest {
string player_id = 1;
string region = 2;
}
message FindMatchResponse {
string match_id = 1;
string game_endpoint = 2;
}
인디 팀이라면 처음부터 모든 서버를 마이크로서비스로 분리할 이유는 없다. 단일 서버 구조에서도 내부 모듈 경계를 잘 잡고 외부 API 계약이 복잡해지는 시점에 gRPC를 도입하는 편이 운영 부담을 낮출 수 있다.
UDP 기반 네트워크: 빠른 조작감에 집중하는 도구
UDP는 연결 상태, 재전송, 순서 보장 같은 기능을 거의 제공하지 않는 데이터그램 전송 방식이다. 그만큼 애플리케이션이 필요한 성질만 골라 구현할 수 있다. 빠른 액션 게임이 UDP 또는 UDP 기반 네트워크 라이브러리를 검토하는 이유다.
핵심은 UDP 자체가 자동으로 빠르게 만들어 주지 않는다는 점이다. 유실, 순서 변경, 중복 도착, 네트워크 주소 변환, 악의적인 패킷까지 고려해야 한다. 실시간 게임 서버는 보통 입력 시퀀스 번호, 서버 틱, 스냅샷, 보간, 예측, 필요한 데이터만의 재전송 같은 규칙을 함께 설계한다.
전형적인 입력 전송 방식
클라이언트는 자신의 입력을 번호와 함께 자주 전송하고 서버는 마지막으로 처리한 번호를 응답에 포함한다. 클라이언트는 서버가 이미 반영한 입력을 버리고 아직 반영되지 않은 입력만 다시 적용해 화면을 보정할 수 있다.
입력 패킷: { sequence: 381, tick: 9201, moveX: 1, jump: false }
서버 응답: { serverTick: 9204, ackSequence: 381, players: [...] }
여기서 중요한 것은 오래된 상태를 무조건 재전송하지 않는 것이다. 위치나 조준 방향처럼 곧 새 값으로 대체되는 정보는 최신 패킷이 더 가치 있다. 반대로 라운드 시작, 탄환 발사, 아이템 획득처럼 한 번의 사건이 중요한 데이터는 별도의 신뢰성 규칙을 적용해야 한다.

UDP를 직접 다룰 때는 다음 항목을 초기에 정해야 한다.
- 패킷 크기 상한과 메시지 분할 정책
- 시퀀스 번호와 중복 패킷 처리 방식
- 중요한 이벤트의 선택적 재전송 방식
- 서버 권위 판정과 클라이언트 예측 범위
- 지연, 지터, 패킷 유실을 재현하는 테스트 환경
- 암호화와 인증, 패킷 위조 방지 전략
브라우저 게임은 표준 웹 API로 임의의 UDP 소켓을 직접 열 수 없다. 따라서 브라우저와 네이티브 클라이언트를 함께 지원한다면 WebSocket을 별도 경로로 두거나 WebRTC 데이터 채널처럼 브라우저가 제공하는 실시간 전송 수단을 검토해야 한다. 이때도 데이터 채널의 신뢰성과 순서 설정, 중계 서버 구성은 별도로 검토해야 한다.
한눈에 보는 선택 기준
| 관점 | WebSocket | gRPC | UDP 기반 네트워크 |
|---|---|---|---|
| 기본 전송 성질 | 신뢰성·순서 보장 | 신뢰성·순서 보장 | 유실·순서 변경 가능 |
| 브라우저 직접 지원 | 좋음 | 별도 웹 호환 계층이 필요한 경우가 많음 | 직접 지원 불가 |
| 실시간 액션 적합성 | 제한적 | 제한적 | 높음. 구현 품질에 좌우됨 |
| API 계약 관리 | 직접 설계 | 매우 좋음 | 직접 설계 |
| 개발 난이도 | 낮음~중간 | 중간 | 높음 |
| 대표 용도 | 로비, 채팅, 턴제 | 내부 서비스 API, 계정·인벤토리 | 슈팅, 격투, 레이싱 |
현실적인 권장 조합
대부분의 게임은 하나만 고르기보다 통신 경로를 나눠 쓴다. 예를 들어 웹 기반 협동 게임은 HTTPS와 WebSocket으로 인증, 로비, 채팅, 매치 상태를 처리하고 플레이 중에는 게임 규모에 따라 WebSocket 상태 동기화 또는 별도 실시간 전송 계층을 둔다. 네이티브 경쟁 액션 게임은 로비와 상거래에는 HTTPS나 gRPC를 사용하고 실제 플레이 입력과 상태 스냅샷에는 UDP 기반 채널을 두는 구성이 자연스럽다.
작은 팀이라면 다음 순서가 안전하다.
- 게임 장르별 목표 지연 시간과 동시 접속 규모를 문서화한다.
- 로비와 플레이 서버의 책임을 분리한다.
- 처음에는 검증하기 쉬운 신뢰성 채널로 수직 슬라이스를 만든다.
- 실제 지연과 유실을 측정한 뒤 병목인 플레이 구간만 UDP 기반 설계로 옮긴다.
- 네트워크 전환보다 서버 권위와 치트 방지 규칙을 먼저 점검한다.
통신 기술은 게임의 재미를 대신 만들어 주지 않는다. 하지만 데이터의 중요도와 최신성을 구분해 설계하면 같은 서버 비용 안에서도 더 안정적이고 반응 좋은 멀티플레이 경험을 만들 수 있다.


