Monster Arc를 웹에 올렸습니다. 파티 셋을 실시간으로 갈아타며 싸우는 쿼터뷰 액션 RPG입니다.

올리는 것 자체가 이번 작업의 대부분이었습니다. 게임 패키지가 137.3MB인데 호스팅의 파일당 한도가 25MiB입니다.

압축으로는 안 됐습니다

먼저 gzip을 걸었습니다. 137.3MB가 97.4MB가 됐습니다. 여전히 한도의 네 배입니다.

이 프로젝트의 자산은 이미 압축된 형식입니다. 텍스처와 메시가 대부분이고, 그런 것들은 한 번 더 압축해도 잘 안 줄어듭니다. 압축률 29%는 그 사실이 숫자로 나온 것이고, 여기서 방향을 바꿔야 한다는 신호였습니다.

엔진 실행 파일은 압축이 통했습니다

같은 방법이 다른 파일에는 통했습니다. 엔진 wasm은 37.7MB에서 9.8MB로 줄었습니다. 코드는 반복이 많아서 잘 줄어듭니다.

다만 여기에 함정이 하나 있습니다. gzip한 바이트를 그대로 보내면서 헤더에 "이건 gzip이다"라고 적으면 안 됩니다. 워커가 그 헤더를 떼어 버려서 브라우저가 압축된 바이트를 원본으로 알고 읽다가 실패합니다.

같은 문제를 예전에 다른 게임에서 겪었습니다. 그때 배운 대로, 워커가 직접 풀어서 평범한 바이트로 내보냅니다.

패키지는 잘랐습니다

압축이 안 되니 자르는 수밖에 없습니다. 20MiB짜리 조각 일곱 개로 나누고, 워커가 요청을 받으면 이어 붙여서 내보냅니다.

여기서 한 번 더 걸릴 뻔했습니다. 조각 일곱 개를 한꺼번에 요청해서 다 받은 뒤 합치면, 137MB어치 응답이 동시에 워커 메모리에 얹힙니다. 워커에는 그만한 여유가 없습니다.

한 조각씩 순서대로 받아서 그때그때 흘려보냅니다. 메모리에 남는 것은 조각 하나뿐입니다.

이름에 내용 해시를 넣었습니다

엔진 익스포트는 파일 이름이 고정입니다. 내용이 바뀌어도 이름이 같으니, 한 번 받아 간 브라우저는 새 파일을 받을 이유가 없습니다.

이름에 내용 해시를 넣어 내용이 바뀌면 이름도 바뀌게 했습니다. 이 사이트에서 이미 쓰고 있는 방법이고, 게임 쪽에도 같은 이유로 필요했습니다.

그런데 왜 고쳐졌는지 모릅니다

배포하고 나서도 웹에서 게임이 끝까지 안 돌았습니다. 두 판을 연달아 올리며 넷을 바꿨는데, 그중 어느 것이 고친 건지 지금도 모릅니다.

바뀐 넷은 이렇습니다. 소리 API 호출 하나, 화면 전환 전 한 프레임 양보, 로딩 문구 추가, 그리고 자산 해시가 바뀌면서 브라우저가 새로 받은 것.

가려내려고 해 봤습니다. 일부러 깨뜨려 익스포트해도 로그에 오류가 안 납니다. 컴파일된 스크립트의 문자열은 패키지에 평문으로 안 남아서 두 빌드를 문자열로 대조하는 방법도 못 씁니다 — 정상 빌드에서도 검출이 0이라 그 방법 자체가 무의미합니다.

그래서 "이게 고쳤다"고 적지 않았습니다. 캐시가 새로 받은 것만으로도 설명이 되는 상태이고, 그렇다면 나머지 셋은 아직 검증되지 않은 채로 들어가 있는 셈입니다.

기록에 그렇게 남겼습니다. 원인을 모르는 채로 고쳐진 것은, 고쳐졌다고만 적으면 다음에 같은 증상이 났을 때 아무 도움이 안 됩니다.

지금 상태

회색박스 전투장에서 시작해 스테이지와 보스, 캐릭터 생성기, 성장과 의상까지 붙였습니다. 캐릭터는 열두 명이 되었고 그중 셋을 골라 나갑니다. 지금은 그 열두 명을 양산하는 쪽에 시간을 쓰고 있습니다 — LOD 세 단계에 삼각형 예산을 걸고 자동으로 검증합니다.

안드로이드 빌드는 일부러 미루고 있습니다. 캐릭터 양산이 끝나기 전에 스토어 쪽 절차를 시작하면, 모델이 바뀔 때마다 그 절차를 다시 밟게 됩니다.