■ 시작: "한 판만 더"가 나오는 1분짜리 게임

목표는 명확했다. 토스 미니게임처럼 누구나 30초 만에 배우고, 한 판이 1분 안에 끝나며, 끝나는 순간 "한 판만 더"가 나오는 캐주얼 운전 게임. 컨셉은 보험사 긴급출동 서비스다. 배터리 방전, 타이어 펑크로 발이 묶인 고객을 최대한 빨리 구조하러 달리는 것. 레퍼런스는 한 시대를 풍미한 "다함께 차차차" — 세로 화면, 자동 전진, 좌우 차선 변경이라는 검증된 뼈대를 가져오되, 이름과 아트, 세부 메커닉은 전부 새로 만들었다.

■ 기술 선택: 엔진 없이 캔버스로

유니티도 페이저도 쓰지 않았다. HTML5 캔버스 + 바닐라 자바스크립트(ES 모듈) 약 2,600줄. 이유는 셋이다. 첫째, 웹 미니게임은 로딩이 생명인데 엔진 런타임만 수 MB다. 둘째, 60FPS 목표에서 2D 캔버스는 충분히 빠르다. 셋째, 의존성이 없으면 유지보수가 단순해진다. 오브젝트 풀링으로 장애물·파티클을 재사용하고, deltaTime 기반 물리에 프레임 클램프를 걸어 저사양에서도 게임 속도가 변하지 않게 했다. 결과물의 총 다운로드 용량은 약 1MB, 초기 로드는 0.5MB 수준이다.

■ AI 에셋 파이프라인: 그릴 것과 생성할 것을 나누다

처음엔 차량 스프라이트도 AI로 만들려 했지만 곧 접었다. 탑다운 차량은 방향·색·크기 일관성이 생명인데 생성 이미지는 그걸 보장하지 못한다. 그래서 원칙을 세웠다. "빠르게 움직이는 것은 코드로 그리고, 감정을 전달하는 것은 AI로 생성한다." 차량·도로·이펙트는 전부 절차적 벡터 드로잉으로, 엔딩에서 인사하는 고객 캐릭터는 Replicate의 recraft-v3로 생성했다.

캐릭터는 시행착오가 많았다. 첫 배치는 낙서풍이라 폐기했고, 두 번째는 한국적 정서를 담으라는 피드백에 따라 "세미 리얼 한국 웹툰풍"으로 프롬프트를 다시 설계했다. 최종적으로 직장인, 신랑신부, 임산부 부부, 휴가 나온 군인까지 16종을 한 배치로 생성해 스타일을 통일했다. 배경 제거 모델을 체이닝하고, 가장자리 잘림을 검사하는 QA 스크립트를 게이트로 걸었다. 원본 15MB짜리 PNG들은 알파 크롭 + 480px 리사이즈 + WebP 변환으로 643KB까지 줄였다. 96% 절감이다.

■ 게임성의 전환점: 거리 목표에서 택시 루프로

초기 버전은 "3km 앞 목적지에 도착하라"였다. 돌려보니 밋밋했다. 그래서 차차차의 본질인 운행 루프를 이식했다. 한 판(40초) 안에서 고객을 태우고 → 목적지까지 달리고 → 요금을 받고 → 즉시 다음 고객. 이송할수록 시간이 조금씩 연장되니 실력이 곧 플레이타임이 된다. 여기에 하트 3개(충돌 3번이면 사고 종료), 지역·날씨별 조작 변화(눈길 미끄러짐, 터널 시야 제한, 해안 횡풍), 희귀도 있는 고객 도감을 얹었다.

■ 밸런싱: 감이 아니라 봇으로

제일 재미있었던 부분이다. 자동 주행 봇(완벽/보통/허술 3단계)을 만들어 수십 판을 시뮬레이션하고 지표를 뽑았다. 그러자 문제가 숫자로 드러났다. 별점이 3~4개에 몰려 5성이 수학적으로 불가능했고, 부스터는 판당 1개밖에 안 나왔으며, 충돌해도 사실상 페널티가 없어 긴장감이 없었다. 별점 공식을 재설계하고, 부스터를 플레이어 차선 쪽에 스폰하고, 하트 시스템을 넣은 뒤 다시 시뮬레이션을 돌려 별점 분포가 1~5성에 고르게 퍼지는 것을 확인했다. "재미없다"는 느낌을 "별점 분포 히스토그램"으로 바꾸면 고칠 수 있는 문제가 된다.

니어미스 판정도 데이터로 잡았다. 처음 판정 폭 88px는 옆 차선 중심 거리(77px)보다 넓어서, 그냥 지나가기만 해도 니어미스가 됐다. 스릴의 화폐가 인플레이션에 빠진 셈이다. "최근 0.45초 안에 차선을 바꿔서 피했을 때만 인정"으로 바꾸니 판당 니어미스가 20회에서 5~7회로 줄면서 비로소 희소한 보상이 됐다.

■ 멀티 에이전트 코드 리뷰: 내가 못 본 것들

배포 전 리뷰 단계에서는 관점을 나눈 리뷰 에이전트 15개를 병렬로 돌렸다. 라인 단위 스캔, 삭제된 불변식 추적, 크로스 파일 콜 트레이싱, JS 함정 전문, 성능 프로파일링… 결과는 뼈아팠다. 테마별 길가 배경을 그리는 48줄짜리 함수가 어디서도 호출되지 않는 죽은 코드였고(8개 테마의 비주얼 정체성이 통째로 잠자고 있었다), 일시정지에서 "그만두기"를 눌러도 완주와 똑같이 보상과 축하 폭죽이 나왔으며, 20fps 저사양에서는 정면충돌이 판정 틈새로 빠져 오히려 니어미스 보너스를 받는 버그가 있었다. 전부 수치와 재현 시나리오가 붙은 리포트로 나왔고, 하나씩 수정한 뒤 재검증했다.

■ 상용화 마감: 이모지를 버리다

상용성 감사에서 가장 큰 지적은 의외로 이모지였다. 부스터 아이콘을 🚀 같은 이모지로 그리면 삼성·애플·구글에서 다 다르게 보이고, 일부 웹뷰에선 두부(□)가 된다. 인게임 이모지를 전부 벡터 글리프로 교체하고, 버튼에는 그라디언트·베벨·눌림 상태를 넣고, 차량은 바퀴가 보이는 테이퍼 보디로 리터치했다. 마지막으로 영어를 기본으로 한 2개 국어(EN/KO 자동 감지)를 붙이고, CrazyGames SDK 이벤트를 연동하고, 외부 링크 정책에 맞춰 공유 기능을 손봐 제출 패키지(zip + 커버 + 영문 메타데이터)까지 만들었다.

■ 배운 것

1) AI 에셋은 "어디에 쓸지"가 "얼마나 잘 뽑을지"보다 중요하다. 일관성이 필요한 곳엔 코드가, 감성이 필요한 곳엔 생성 모델이 맞다.
2) 밸런스는 취향 논쟁이 아니라 측정 문제다. 봇 시뮬레이션 30판이면 어떤 직감보다 정확하다.
3) 리뷰는 관점의 수가 품질이다. 혼자서는 죽은 코드 48줄을 끝까지 못 봤을 것이다.
4) 재미의 화폐(니어미스, 별점, 부스터)는 희소해야 가치가 있다. 남발되는 보상은 보상이 아니다.

게임은 여기서 플레이할 수 있다: 
https://blog.midnightai.net/play/rescue-rush/

(모바일 권장, 데스크톱은 방향키/A·D)