뉴스 / ONI Games

Python 스크립트 하나로 16개 언어, 300페이지 게임 사이트를 만든 방법

CMS도 프레임워크도 없습니다. Python 파일 하나가 onirealms.com의 모든 페이지를 16개 언어로 만들고, 작은 Cloudflare Worker가 이를 제공합니다.

저희는 Android용 무료 게임을 만듭니다. 방치형 RPG 두 개, 블록 퍼즐 하나, 로봇 공장 경영 게임 하나입니다. 게임마다 전용 페이지가 필요했고, 모든 페이지는 게임을 플레이하는 모든 언어로 있어야 했습니다. 영어, 독일어, 스페인어(스페인과 중남미), 프랑스어, 크로아티아어, 인도네시아어, 이탈리아어, 일본어, 한국어, 포르투갈어(브라질과 포르투갈), 러시아어, 슬로베니아어, 튀르키예어, 번체 중국어까지 16개 버전입니다.

게임이 바뀔 때마다 바뀌는 사이트에 CMS는 너무 무거웠습니다. 그래서 onirealms.com 전체를 Python 스크립트 하나가 정적 파일로 만들고, 그 앞에 작은 Cloudflare Worker를 두었습니다.

전체 구조

스크립트 site.py는 약 3,200줄짜리 파일 하나입니다. 여기에는 게임마다 항목이 하나씩 있는 GAMES 딕셔너리가 있습니다. 패키지 이름, 테마, 키 아트, 섹션 사이의 아트 띠, 장르, 연령 등급, 출시 여부가 들어 있고, 나머지는 모두 여기서 파생됩니다.

텍스트는 언어별로 나뉜 평범한 Python 딕셔너리에 있으며, 영역마다 모듈이 하나씩 있습니다. 홈, 각 게임, FAQ, SEO 제목과 설명, 공략 가이드, 뉴스입니다. 게임 페이지는 게임과 언어를 받아 HTML을 돌려주는 함수입니다. 게임 4개를 16개 언어로, 여기에 홈, 뉴스, 가이드, 사이보그 도감, 개인정보처리방침, 보도자료 키트를 더하면 300페이지가 넘습니다. 전체 빌드는 약 26초가 걸립니다.

일본어, 독일어, 러시아어로 된 Block Brain 스토어 이미지.
일본어, 독일어, 러시아어로 된 Block Brain 스토어 이미지.

결국 생성기 자체보다 더 중요했던 것이 세 가지 있습니다.

1. hreflang은 빠짐없이 넣어야 의미가 있다

모든 페이지는 자기 자신을 포함한 모든 언어 버전과 x-default로 연결됩니다. 사이트맵도 같은 그룹을 반복합니다. 하나라도 빠지면 검색엔진은 그 페이지들을 서로 관련 없는 거의 중복된 페이지로 취급합니다. 스크립트는 페이지를 만들 때 쓰는 것과 같은 언어 목록으로 이 링크를 만들기 때문에 둘이 어긋날 수 없습니다.

2. 언어 리디렉션이 크롤러를 가두면 안 된다

Worker는 영어 페이지에 들어온 방문자를 브라우저 언어로 된 같은 페이지로 보냅니다. 플레이어에게는 좋지만 단순하게 구현하면 검색에는 치명적입니다. 크롤러에게는 리디렉션만 보이기 때문입니다. 그래서 봇은 리디렉션하지 않고, 사이트의 다른 페이지에서 온 방문자(일부러 영어를 고른 사람)도 리디렉션하지 않으며, 주소에 ?lang=이 있으면 끄고, 쿠키도 쓰지 않습니다. Vary: Accept-Language가 붙은 302이며, 절대 301이 아닙니다.

3. 변경 불가 에셋에는 새 파일 이름이 필요하다

/assets/ 아래의 모든 파일은 Cache-Control: max-age=31536000, immutable로 제공됩니다. 올바른 설정이지만, 이미지를 바꿔도 1년 동안 아무도 못 보는 문제가 생깁니다. 그래서 이미지 스크립트는 예전 파일을 덮어쓰지 않고 새 버전마다 새 파일 이름으로 저장합니다.

네 게임의 스토어 이미지: 한국어 Block Brain, 튀르키예어 Idle AI Factory, 영어 Idle Summoner와 Idle Ronin.
네 게임의 스토어 이미지: 한국어 Block Brain, 튀르키예어 Idle AI Factory, 영어 Idle Summoner와 Idle Ronin.

작지만 제 몫을 하는 기능들

  • 모든 게임 페이지의 QR 코드는 빌드할 때 만들어집니다. Worker의 짧은 링크 /go/<game>를 가리키고, 리퍼러 태그를 붙여 Google Play로 넘겨 주기 때문에 Play Console에서 유입 경로별 설치 수를 볼 수 있습니다.
  • 동의 기반 애널리틱스. 태그는 모든 저장소를 거부한 상태(consent mode v2)로 시작하고, 방문자가 쿠키 배너에서 동의한 뒤에야 켜집니다.
  • 배포할 때마다 IndexNow를 보내 Bing과 Yandex가 같은 날 변경 사항을 알 수 있게 합니다.
  • 언어별 RSS 피드로 피드 리더와 애그리게이터가 뉴스를 가져갑니다.
  • 보도자료 키트는 ZIP 파일이며, 스크립트가 게임 이미지로 묶어 줍니다.

다시 한다면 다르게 할 것

언어 목록과 텍스트 표를 HTML보다 먼저 만드는 것입니다. 영어를 전제로 한 마크업에 나중에 16개 언어를 넣는 일이 프로젝트 전체에서 가장 느린 작업이었습니다. 줄 길이, 일본어·한국어·중국어용 대체 글꼴, 러시아어용 키릴 문자 대체 글꼴이 각각 따로 손이 갔습니다.

게임은 Idle Ronin: Cyber RPG, Idle Summoner: Pixel RPG, Block Brain, Idle AI Factory: Robot Tycoon이며, 모두 Google Play에서 무료입니다.

전체 뉴스

전체 뉴스