본문 바로가기

블로그 / 기술

게임 네 개의 서버 지도: Workers, Durable Objects, 서울 VM을 어떻게 나눠 썼나

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

Salmonholic ·· 5분 읽기

Salmonholic과 AvoidNow의 타이틀 화면과 실제 플레이 화면을 네 칸으로 모은 이미지

지금 나는 게임 네 개를 동시에 굴린다. 웹 게임 셋(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 글에 자세히 적었다.

Salmonholic 온라인 경기 화면 왼쪽 위에 ONLINE 346 ms가 표시된 모습 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로 옮길 길은 남아 있다.

서로 건드리지 않게 정한 규칙

게임이 셋이 되니 서버끼리 부딪히는 일을 막는 게 중요해졌다. 저장소마다 문서 맨 위에 적어 둔 규칙은 이렇다.

  1. 게임마다 VM을 따로 둔다. Salmonholic이 CrazyGames에 올라가 운영을 시작한 뒤, AvoidNow 문서에 “SR VM은 절대 건드리지 않는다”를 넣었다. 랜선포차를 배포할 때도 AvoidNow VM에 같이 올리는 안, 새 VM을 만드는 안, Salmonholic VM에 얹는 안을 비교했다. 운영 중인 게임에 영향이 없는 새 nano VM을 골랐다.
  2. 서브도메인은 용도별로 셋. 웹, 한국 서버, 해외 서버를 다른 이름으로 둔다. Worker 커스텀 도메인이 잡힌 이름에는 A 레코드를 만들 수 없어서, 이름을 섞으면 배포가 실패한다.
  3. 설정 값은 코드에 둔다. 대시보드에서만 넣은 Worker 변수는 다음 배포 때 사라진다. Salmonholic을 만들며 확인한 뒤로 wrangler.jsonc의 vars에 적는다.
  4. 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 출시를 준비하고 있다.

#서버 구조#Cloudflare Workers#Durable Objects#Lightsail#1인 개발

함께 읽으면 좋은 글

전체 글 →