I Built an AI Game That Wants You to Go Outside
밖으로 나가게 하는 AI 게임을 만들었습니다
Side Quest는 Google의 Gemma를 활용해 주변 환경에 맞는 야외 퀘스트를 만들고, 사진으로 완료 여부를 판정하는 오픈소스 게임입니다. 휴대폰에서 모델을 돌리는 대신 데스크톱 브라우저에서 로컬 추론을 실행하고, 휴대폰은 가벼운 인터페이스로 연결하는 구조를 소개합니다.
- 주제
AI 요약
Side Quest는 산책이나 야외 탐험에 작은 목표를 더하는 게임입니다. 사용자가 장소와 날씨, 계절, 시간대를 입력하면 Google의 Gemma가 주변 환경에 어울리는 퀘스트를 만듭니다. 플레이어는 밖에서 대상을 찾아 사진을 찍고, Gemma가 사진을 살펴 퀘스트 완료 여부를 판정합니다. 완료하면 발견한 대상의 특징을 바탕으로 만든 작은 생물을 얻습니다.
사진에서 생물까지
생물을 미리 만든 목록에서 무작위로 지급하지 않습니다. Gemma가 사진에서 생물에 쓸 특징을 설명하면 앱이 그 정보를 바탕으로 SVG 캐릭터를 직접 그립니다. 이미지 생성 API를 따로 호출하지 않으며, 사진에서 일관된 시드를 만들어 같은 이미지를 제출하면 같은 생물이 나오게 했습니다. 수집함에는 생물과 원본 사진을 함께 보관해 자연 관찰 기록처럼 살펴볼 수 있습니다.
일반 퀘스트 외에 여러 대상을 한 번에 찾는 Scavenger Hunt 모드도 제공합니다. Gemma가 찾을 항목 목록을 만들고, 사용자는 사진을 모아 한꺼번에 판정을 요청합니다. 퀘스트 판정에서 사진이 거절되면 다시 시도해야 하며, 현재는 결과를 직접 덮어쓰는 기능이 없습니다.
브라우저에서 실행하는 Gemma
AI 기능에는 Google의 오픈 웨이트 멀티모달 모델 Gemma 4 E2B를 사용합니다. Transformers.js와 WebGPU로 4비트 ONNX 모델인 onnx-community/gemma-4-E2B-it-ONNX를 실행하고, 모델은 웹 워커에 올려 메인 UI를 막지 않게 했습니다. 퀘스트 생성, 사진 판정, 생물 특징 생성, 수집형 사냥의 항목 생성과 판정을 모두 맡깁니다.
데스크톱에서 처음 실행할 때 모델을 내려받아야 하며, 크기는 약 3.4GB입니다. 최신 Chrome이나 Edge에서 WebGPU를 지원해야 합니다. 내려받은 모델은 브라우저에 캐시됩니다. 단독 플레이는 계정이나 외부 AI API 없이 브라우저에서 실행하고, 게임 데이터와 사진도 로컬 저장소에 둡니다. React 19, TypeScript, Vite 8, Tailwind CSS 4를 사용했고, IndexedDB에는 퀘스트와 사진, 완료한 항목, 생물을 저장합니다.
데스크톱 모델과 휴대폰 연결
개발자는 iPhone 12에서 모델을 실행하려 했지만, 모델을 약 500MB 내려받은 뒤 브라우저 탭이 종료됐습니다. 그래서 데스크톱이 Gemma를 실행하는 홈 베이스가 되고, 휴대폰은 퀘스트와 촬영, 수집을 담당하는 구조를 만들었습니다. 휴대폰에서 사진을 제출하면 데스크톱으로 보내 Gemma가 판정과 생물 특징 생성을 처리하고, 결과를 다시 휴대폰으로 돌려줍니다. 휴대폰은 인터넷이 끊긴 동안 사진을 IndexedDB 대기열에 보관하고 연결이 복구되면 다시 전송합니다. 홈 베이스는 미리 퀘스트와 사냥 목록을 생성해 대기 시간을 줄이며, 주변 조건이 바뀌면 기존 목록을 버리고 새로 만듭니다.
처음에는 로컬 Node 서버와 임시 Cloudflare 터널을 이용했습니다. 이 방식을 원하면 npm run home으로 실행할 수 있습니다. 더 간단한 체험을 위해 호스팅 구성도 추가했습니다. Cloudflare Worker가 휴대폰과 데스크톱 사이 메시지를 전달하고, D1은 계정과 퀘스트 데이터를, R2는 사진을 저장합니다. GitHub로 데스크톱에 로그인한 뒤 임시 QR 코드를 휴대폰으로 스캔해 연결합니다. 생물 수집함은 로그인한 기기 사이에서 동기화됩니다. 이 구성에서도 AI 추론은 클라우드가 아니라 데스크톱 브라우저에서 실행됩니다.
데이터 처리 방식은 실행 모드에 따라 다릅니다. 단독 모드에서는 사진과 게임 데이터가 브라우저 로컬 저장소에 남습니다. 호스팅 모드에서는 사진이 Cloudflare Worker를 거쳐 R2에 저장되며, 계정을 삭제하면 관련 사진과 기록도 삭제할 수 있습니다. 비공개 홈 베이스 모드에서는 사진을 사용자 컴퓨터에 보관합니다. 게임은 GPS 좌표를 추적하지 않으며, 사용자가 입력한 장소 이름은 퀘스트 문맥에만 씁니다.
개발 중 맞닥뜨린 문제
개발자는 AI가 문장을 생성하는 부분보다 기기 사이 상태 동기화, 요청 대기열, 연결 처리, 오프라인 상황 대응에 더 많은 시간을 썼다고 설명합니다. Cloudflare Worker 테스트에서는 통과하던 요청이 Vite 개발 프록시를 거치면 403으로 거부되는 문제도 있었습니다. 테스트 하네스와 개발 프록시가 서로 다른 요청 URL과 Origin 헤더 조합을 보낸 탓이었습니다. 요청 호스트나 명시적으로 설정한 애플리케이션 Origin을 고려하고, 테스트 하네스뿐 아니라 실제 개발 프록시를 거쳐 확인하도록 수정했습니다. 테스트가 통과해도 실제 브라우저 환경에서 동작한다고 단정할 수 없다는 사례입니다. Vitest와 Wrangler 테스트 하네스를 사용해 로컬 D1, R2 바인딩도 검사합니다.
소스와 실행
프로젝트는 Apache 2.0 라이선스로 공개했습니다. 저장소에는 React 프런트엔드, Gemma 추론 워커, 퀘스트와 생물 로직, Cloudflare Worker 백엔드, 선택형 비공개 홈 베이스 서버, 테스트가 포함됩니다. 기본 단독 버전은 npm install과 npm run dev로 실행한 뒤 WebGPU를 지원하는 데스크톱 브라우저에서 localhost:5173을 열면 됩니다.
dev.to 반응
- @technogamerz — 행운을 빕니다.
- @sizzlebop — 감사합니다!
- @wrobeltomasz — 사용자가 난이도나 테마, 프롬프트 문구 같은 퀘스트 생성 설정을 바꿔 야외 도전을 맞춤화할 수 있나요?
- @sizzlebop — 아직 직접 난이도나 테마, 프롬프트 문구를 바꾸는 기능은 없습니다. 지금은 공원인지 도시인지, 날씨와 계절, 시간대, 원한다면 장소 이름까지 입력하는 방식으로 조정합니다. Gemma가 그 문맥에 맞춰 퀘스트를 만듭니다. 난이도를 낮추거나 더 기묘하고 구체적으로, 혹은 특정 테마에 맞게 만드는 기능도 다음 단계로 재미있을 것 같습니다.
- @rinrinrinrin — 긴 글이었지만 정말 만족스럽게 읽었습니다. 해커톤에 처음 참여하고 싶은 사람이 두려움을 이겨내고 직접 만들어 보려면 어떤 해커톤을 추천하시나요?
- @sizzlebop — 감사합니다! DEV의 주말 챌린지를 추천합니다. 제 첫 해커톤은 아니었지만, 더 적극적으로 참여하고 계속 만들고 공유하도록 동기를 준 행사입니다. 대체로 참여하기 어렵지 않고, 재미있는 주제와 마감일이 일단 만들어 보게 해줍니다. 커뮤니티도 정말 친절하고 응원해줘서 결과물을 공개하는 부담이 줄어듭니다. 완벽한 결과물을 걱정하지 말고 참여해서 즐겨보세요!
- @rinrinrinrin — 정말 감사합니다! 그렇게 해볼게요! <3
- @edo_rolan — 모델을 화면에서 보내는 시간을 줄이는 데 쓰는 구도가 좋습니다. 한 가지 예외 상황이 궁금합니다. 플레이어가 맞는 대상을 찾았는데 Gemma가 사진을 거절하면 판정을 직접 무시할 수 있나요, 아니면 다시 시도하는 방식이 게임의 일부인가요?
- @sizzlebop — 감사합니다! 지금은 다시 시도하는 방식입니다. Gemma가 사진을 거절하면 플레이어가 한 번 더 시도할 수 있고, 판정을 덮어쓰지는 못합니다. 그 약간의 불확실성이 게임처럼 느껴져 좋기도 하지만, 실제로 맞는 대상을 찾았을 때 좌절스럽지 않도록 조심해야 합니다. 나중에 판정 무시나 ‘이 정도면 됨’ 옵션을 추가하면 덜 엄격하게 느껴질 수도 있습니다.
- @sinarezaei — 모델 출력을 결정적인 결과로 바꾸는 부분이 흥미롭습니다. 사진에서 생물 특징을 생성하고 SVG로 그리면 이미지 생성 호출을 추가하지 않아도 되지만, 모델 출력과 렌더링 로직 사이의 경계가 중요해집니다. 특징 스키마를 제한하고 색상, 크기, 형태 매개변수를 렌더링 전에 검증하면 좋겠습니다. 예상 밖의 모델 응답이 생물 생성기를 망가뜨리지 않으면서 같은 입력의 결과도 일관되게 유지할 수 있습니다. 창작 부분은 Gemma에 맡기고 실제 렌더링은 직접 제어하는 설계가 좋습니다.
- @xupershydra — 흥미로운 아이디어입니다! AI를 활용해 화면을 덜 보게 하는 접근이 신선합니다. 모바일 제약을 데스크톱에서 Gemma를 실행하고 휴대폰은 가벼운 인터페이스로 쓰는 방식으로 해결한 점이 눈에 띄었습니다. 오프라인 사진 대기열도 연결이 불안정한 곳을 탐험하는 사용자에게 유용한 기능입니다. 저희 MXL TV는 Android 앱 가이드와 호환성, 문제 해결을 다루기 때문에 모바일 성능과 사용성의 균형을 맞추는 과제가 특히 흥미롭습니다. 데스크톱 연결이 끊겨도 탐험을 계속할 수 있도록 가벼운 오프라인 퀘스트 모드를 추가할 생각이 있나요?
원문: dev.to / 번역·요약: Trawling