아시아의 실시간 서비스: WebSocket 서버의 위치가 중요한 이유
· Hibira
거리가 실시간 통신 지연의 하한을 정하는 이유, 홍콩에서 아시아 각지까지의 하한, 그리고 내 사용자의 왕복 시간을 재는 방법.

채팅 메시지, 시세 변동, "입력 중" 표시는 대략 0.1초 안에 도착하면 즉각적으로 느껴집니다. 그 시간의 대부분은 네트워크에서 쓰이고, 네트워크 시간의 대부분은 여러분이 고르는 한 가지, 즉 WebSocket 서버를 어디에 두느냐로 정해집니다.
거리가 하한을 정한다
광섬유 속의 빛은 1밀리초에 약 200km를 갑니다. 진공에서의 광속의 약 3분의 2입니다. 그래서 1,000km 떨어진 서버까지 왕복하는 데는 라우팅, 대기, 처리를 빼고도 최소 10ms가 걸립니다. 실제 해저 케이블은 대권 경로를 따르지 않고 라우터도 지연을 더하므로, 실측 왕복 시간은 흔히 이 하한의 2~4배가 됩니다. 홍콩에서 타이베이까지 실측은 약 30ms였고, 하한은 8ms입니다.
Hibira가 현재 운영되는 홍콩(AWS ap-east-1)에서 아시아 각 도시까지의 하한은 다음과 같습니다.
| 홍콩에서 | 대권 거리 | 최소 왕복 시간 |
|---|---|---|
| 타이베이 | 810km | 8ms |
| 마닐라 | 1,120km | 11ms |
| 방콕 | 1,730km | 17ms |
| 서울 | 2,090km | 21ms |
| 싱가포르 | 2,590km | 26ms |
| 도쿄 | 2,880km | 29ms |
| 자카르타 | 3,270km | 33ms |
| 미국 버지니아주 애슈번(미국 동부) | 13,090km | 131ms |
이것은 벤치마크가 아니라 물리 법칙입니다. 어떤 네트워크도 이보다 빠를 수 없고, 실제 수치는 더 느립니다. 마지막 줄은 비교를 위한 것입니다. 많은 미국 서비스가 실시간 인프라를 미국 동부에 두고 있고, Pusher의 기본 클러스터 mt1도 그곳에 있습니다. Pusher에도 아시아 클러스터가 있으니, Pusher를 쓰고 있다면 앱이 어느 클러스터에 만들어졌는지 확인해 보세요.
실시간 기능이 웹 페이지보다 지연에 민감한 이유
웹 페이지는 로드할 때 몇 번 왕복할 뿐입니다. 실시간 기능은 상호작용할 때마다 왕복합니다.
- 입력 중 표시와 커서는 1초에 여러 번 클라이언트 이벤트를 보냅니다. 왕복이 느리면 사용자의 움직임을 따라가지 못합니다.
- 채팅은 한 사용자에서 여러분의 서버, WebSocket 서비스를 거쳐 다른 모든 사람에게 갑니다. 구간마다 거리가 더해집니다.
- 프레즌스(누가 온라인인지)는 멤버가 들어오고 나갈 때 갱신됩니다. 갱신이 느리면 이미 나간 사람이 여전히 온라인으로 보입니다.
- 재연결은 휴대폰이 네트워크를 바꿀 때 일어나며, TLS 핸드셰이크와 재구독으로 여러 번 연속 왕복합니다.
모든 구간을 세기
백엔드가 이벤트를 발행하면 이벤트는 다음 구간을 지납니다.
- 사용자의 동작에서 여러분의 백엔드까지
- 백엔드에서 WebSocket 서비스의 HTTP API까지
- WebSocket 서비스에서 구독 중인 모든 클라이언트까지
1구간과 3구간은 사용자의 위치에, 2구간은 백엔드의 위치에 달려 있습니다. 도쿄의 백엔드가 버지니아의 WebSocket 서비스를 통해 발행하면, 타이베이에 있는 두 사용자 사이의 이벤트가 태평양을 두 번 건넙니다. WebSocket 서비스는 사용자 가까이에 두고, 가능하면 백엔드도 그 가까이에 두세요.
직접 측정하기
이 테스트의 측정 범위: pusher:ping/pusher:pong은 이미 연결된 WebSocket과 실시간 서비스 사이의 왕복 시간만 측정합니다. 백엔드 발행부터 구독자 수신까지의 지연, 최초 연결, 팬아웃, 브라우저 렌더링 시간은 포함되지 않습니다. 실제 사용자의 네트워크(모바일 포함)에서 여러 번 측정해 중앙값과 p95를 비교하세요. DNS, TLS, 경로 및 혼잡도 결과에 영향을 줍니다.
표는 출발점일 뿐이고, 중요한 것은 사용자의 네트워크입니다. Pusher 프로토콜에는 서버가 즉시 응답하는 ping 메시지가 있어서, 아무것도 발행하지 않고 왕복 시간을 잴 수 있습니다. 다음을 ping.mjs로 저장하고 WebSocket이 내장된 Node.js 22 이상에서 실행하세요.
// node ping.mjs YOUR_APP_KEY [host]
const [key, host = 'ws.hibira.io'] = process.argv.slice(2);
const ws = new WebSocket(`wss://${host}/app/${key}?protocol=7&client=js&version=8.4.0`);
const times = [];
let sent = 0;
const ping = () => {
sent = performance.now();
ws.send(JSON.stringify({ event: 'pusher:ping', data: {} }));
};
ws.onmessage = (msg) => {
const { event } = JSON.parse(msg.data);
if (event === 'pusher:pong') times.push(performance.now() - sent);
if (event !== 'pusher:connection_established' && event !== 'pusher:pong') return;
if (times.length < 20) return void setTimeout(ping, 250);
times.sort((a, b) => a - b);
console.log(`best ${times[0].toFixed(1)} ms, median ${((times[9] + times[10]) / 2).toFixed(1)} ms`);
ws.close();
};사용자가 있는 곳에서 실행하세요. 서비스하는 나라마다 클라우드 서버를 하나씩 띄우거나, 집 인터넷에 연결한 동료의 노트북에서 돌려 보면 됩니다. 비교할 숫자는 중앙값이고, 최솟값은 경로가 하한에 얼마나 가까운지를 보여 줍니다. 모바일 네트워크는 지연을 더하므로 휴대폰 핫스팟으로도 테스트해 보세요.
실제 사용자의 수치를 보려면 pusher-js가 connecting에서 connected가 될 때까지 걸린 시간을 재서 사용자의 국가와 함께 분석 도구로 보내세요.
저희의 계획
Hibira가 지금 홍콩에서 운영되는 이유는 홍콩이 동아시아와 동남아시아의 거의 한가운데에 있기 때문입니다. 다음으로 준비 중인 리전은 도쿄, 그다음은 싱가포르입니다. 앱은 하나의 리전에 고정되므로, 사용자 대부분과 가장 가까운 리전을 고르면 됩니다.
전환하기 전에 내 사용자의 수치를 먼저 보고 싶다면, 무료 플랜으로 위 스크립트를 내 앱에 대해 실행할 수 있습니다.