게임 네 개의 서버 지도: Workers, Durable Objects, 서울 VM을 어떻게 나눠 썼나
Salmonholic, AvoidNow, 랜선포차, PallMark가 각각 어떤 서버 위에서 도는지 한 장으로 정리했다. 같은 부품을 골라 쓰면서도 게임마다 구성이 달라진 이유와, 서로 건드리지 않게 정한 분리 규칙을 적었다.

지금 나는 게임 네 개를 동시에 굴린다. 웹 게임 셋(Salmonholic, AvoidNow, 랜선포차)과 Steam으로 낼 PC 게임 하나(PallMark)다. 웹 게임 셋은 모두 온라인 멀티플레이가 있어서 서버가 필요하다. 처음에는 “같은 구조를 세 번 복사하면 되겠지”라고 생각했다. 실제로는 부품은 같은데 조합이 게임마다 달라졌다. 이 글은 그 조합을 한 장으로 정리한 지도다.
한 장으로 보는 구성
| 게임 | 웹 페이지 | 해외 접속자 | 한국 접속자 | 저장소 |
|---|---|---|---|---|
| Salmonholic | Cloudflare Worker + 정적 파일 | Durable Objects (대륙별 풀 4개) | 서울 Lightsail VM | KV(통계), DO |
| AvoidNow | Cloudflare Worker + 정적 파일 | Durable Objects | 서울 Lightsail VM (전용) | D1(랭킹), KV(통계) |
| 랜선포차 | Cloudflare Worker (정적 파일만) | 서울 VM 하나로 전부 | 서울 Lightsail VM (전용) | VM 안의 SQLite |
| PallMark | 없음 (Steam 빌드) | 없음 | 없음 | 로컬 저장 |
부품은 네 가지뿐이다. 웹 페이지는 Cloudflare Workers의 정적 에셋으로 내보낸다. 방 하나를 Durable Object(DO) 하나로 돌리는 서버는 해외 접속자를 받는다. 한국 접속자는 서울에 둔 월 5달러짜리 Lightsail VM이 받는다. 기록은 게임에 따라 KV, D1, SQLite 중 하나에 둔다.
PallMark는 서버가 없다. Steam으로 파는 싱글 PC 게임이라 저장소에는 빌드를 올리는 스크립트만 있다. 그래서 이 지도에서 PallMark 칸은 비어 있다.
왜 한국만 따로 VM을 두나
Cloudflare 한 곳에서 전 세계 방을 다 받으면 제일 간단하다. 그런데 한국에서 DO에 붙으면 요청이 LA를 거쳐 가서 왕복 지연이 약 324ms였다. Enterprise가 아닌 플랜에서는 한국 트래픽이 이렇게 돈다. 서울 VM으로 옮기자 약 14ms가 됐다. 그 과정은 324ms → 14ms 글에 자세히 적었다.
9월 21일 브라우저 호환성 점검 때 Cloudflare 쪽 방 서버에 붙은 화면. 한국에서 접속했는데 지연이 346ms로 찍혔다
그래서 구조가 두 갈래가 됐다. 클라이언트가 두 서버에 핑을 재서 빠른 쪽에 붙는다. AvoidNow는 /health를 세 번씩 재고, 한국 서버에 30ms를 우대한다. 한국 서버가 가득 차서 입장이 503으로 막히면 해외 서버로 한 번 넘어간다. Salmonholic도 같은 방식이고, 9월 27일 커밋 83283e9에서 입장 전 예약 단계까지 “세 번 재서 고르는” 정책을 맞췄다.
같은 부품, 다른 조합
Salmonholic은 원조다. 방 서버 로직을 DO용으로 먼저 짰고, Node 서버가 그 파일을 가져다 쓰는 식으로 서울 VM을 붙였다. DO는 유럽, 북미, 남미, 아시아 네 풀로 나눴다. DO 쪽 설계와 비용 계산은 Durable Objects 룸 서버 글에 있다.
AvoidNow는 Salmonholic 구조를 복사해 고쳤다. 달라진 점은 공유 코드를 처음부터 shared/ 패키지로 뺀 것이다. 방 로직은 한 번만 쓰고, Node 서버와 DO 워커는 전송만 맡는 얇은 어댑터로 뒀다. 랭킹은 D1에 저장하고, 기록은 클라이언트가 아니라 게임 서버가 제출한 것만 받는다.
랜선포차는 DO를 아예 뺐다. 9월 26일에 DO 연결층을 만들었다가(0e4ab37) 같은 날 밤 지웠다(e9b33c5). 커밋 메시지에는 “요청은 DO와 같은 언어로 호환성 유지였는데 DO 연결층까지 구현한 것은 범위를 넘었다”고 적었다. 랜선포차는 한국어로만 하는 파티 게임이다. 서울 VM 하나에 Node와 SQLite만 두는 편이 운영할 게 적다고 봤다. 대신 게임 코어는 런타임과 분리해 뒀다. 나중에 DO로 옮길 길은 남아 있다.
서로 건드리지 않게 정한 규칙
게임이 셋이 되니 서버끼리 부딪히는 일을 막는 게 중요해졌다. 저장소마다 문서 맨 위에 적어 둔 규칙은 이렇다.
- 게임마다 VM을 따로 둔다. Salmonholic이 CrazyGames에 올라가 운영을 시작한 뒤, AvoidNow 문서에 “SR VM은 절대 건드리지 않는다”를 넣었다. 랜선포차를 배포할 때도 AvoidNow VM에 같이 올리는 안, 새 VM을 만드는 안, Salmonholic VM에 얹는 안을 비교했다. 운영 중인 게임에 영향이 없는 새 nano VM을 골랐다.
- 서브도메인은 용도별로 셋. 웹, 한국 서버, 해외 서버를 다른 이름으로 둔다. Worker 커스텀 도메인이 잡힌 이름에는 A 레코드를 만들 수 없어서, 이름을 섞으면 배포가 실패한다.
- 설정 값은 코드에 둔다. 대시보드에서만 넣은 Worker 변수는 다음 배포 때 사라진다. Salmonholic을 만들며 확인한 뒤로
wrangler.jsonc의vars에 적는다. - VM은 멈춰도 돈이 나간다. Lightsail은 정지 상태에도 과금되고, 떼어 놓은 고정 IP도 과금된다. 안 쓰면 지워야 한다.
고정비는 문서에 적힌 만큼
비용 문서에 적힌 단가는 이렇다. Workers 유료 플랜은 계정당 월 5달러다. Lightsail nano VM은 월 5달러에 전송량 1TB가 들어 있다. DO는 월 40만 GB-s까지 기본 포함이다. 만들기 전에는 한 판을 8분으로 가정해 월 약 6,000판으로 계산했는데, 운영 뒤 실제 경기 길이(약 340초)로 다시 잡으니 한 판이 42.5 GB-s, 월 약 9,400판까지 추가 요금이 없었다. 한국 접속자는 VM이 받으니 DO 비용에 거의 잡히지 않는다.
결국 매달 고정으로 나가는 건 VM 세 대와 Workers 기본료다. 한 대에 몇 명까지 받을 수 있는지는 AvoidNow 부하 테스트 글에 측정값으로 남겼다. 배포 절차는 웹 게임 배포 파이프라인에서 이어서 정리한다.
세 게임은 각각 Salmonholic, AvoidNow, 랜선포차 페이지에서 해 볼 수 있다. 서버가 없는 PallMark는 Steam 출시를 준비하고 있다.


