"LLM은 게임을 못한다"는 말을 게임 개발자들 사이에서 자주 듣습니다. 같은 모델이 웹앱은 뚝딱 만들어내는데, 게임에서는 왜 무너질까요.
게임 개발자 Kyle Kukshtel은 9월 12일 Indie Rodeo(캘거리)에서 이 질문을 45분 발표로 다뤘고, 사람들의 요청에 따라 10월 10일 같은 내용을 글로 공개했습니다. 그의 결론은 단호합니다.
모델이 게임을 못 읽는 건 구조적 문제다.
게임은 코드만으로 이루어져 있지 않기 때문이다.
그리고 이건 정확히 말하면 모델 문제가 아니라 컨텍스트 문제다.
게임은 코드, 에셋(모델·사운드·텍스처), 데이터, 실행 상태가 뒤엉켜 있는 블랙박스입니다. 정적인 이미지와 텍스트를 배치하는 웹과 달리, 게임에는 코드로 온전히 표현되지 않는 것들이 쏟아집니다. 그래서 AI가 보는 것은 코드일 뿐, 게임이 아닙니다.
이 글은 Kukshtel의 발표를 따라가며, "게임을 AI가 다룰 수 있게 만드는 7가지 설계"를 정리합니다. 그리고 이 감각이 게임 밖(웹·앱)에서도 그대로 통한다는 것까지요.
왜 이런 일이 생기나: 컨텍스트의 문제
먼저 원인을 정확히 짚고 가겠습니다. 발표는 LLM 프롬프트의 기본 구조부터 설명합니다.
모든 LLM 호출은 세 부분으로 나뉜다
시스템 프롬프트 — 서비스가 공통으로 붙이는 텍스트
어시스턴트 프롬프트 — 모델의 응답 벡터를 잡아주는 영역
유저 프롬프트 — 실제 작업이 들어가는 곳
중요한 건 '세션'의 동작 방식이다.
한 세션에서 메시지를 보낼 때마다, 이전의 모든 메시지가
매번 다시 전송된다. (모든 참가자의 말을 매 턴 반복해서
읽는 놀이와 같다.)
여기서 두 가지가 따라옵니다. 첫째, 컨텍스트가 길어질수록 이전의 나쁜 정보도 계속 다시 들어가 "컨텍스트 오염(context rot)"이 생깁니다. 둘째, 게임처럼 코드가 아닌 것이 많을수록 모델이 보는 컨텍스트에는 정작 알아야 할 상태가 빠집니다. 그래서 Kukshtel은 말합니다. "게임과 LLM을 잘 붙이는 것은 게임이나 LLM의 본질 문제가 아니라, 컨텍스트 엔지니어링 문제다."
7가지 설계: 게임을 AI에게 설명 가능하게 만들기
발표의 핵심입니다. 하나씩 보면 전부 게임 개발 일반에도 도움이 되는 원칙들이고, AI와 붙였을 때 그 가치가 증폭되는 것들입니다.
① 고정 랜덤 시드: 재현의 출발점
게임 시작 시 하나의 '시드된' 난수 소스를 만들고,
비결정적 호출을 전부 이 소스로 통일한다.
→ 같은 시드로 게임은 거의 모든 상태를 결정적으로 재현할 수 있다
→ 에이전트가 "같은 출발점"에서 여러 번 시도할 수 있게 된다
에이전트가 어떤 수정을 여러 번 반복 검증하려면, 매번 같은 상태에 도달할 수 있어야 합니다. 재현이 안 되면 수정이 도움이 되는지 자체를 알 수 없습니다.
② 스크린샷과 이미지 diff: 진행도를 정량화하기
- 스크린샷 API를 쓴다 (UI 레이어 토글로 노이즈 줄이기)
- 전/후 스크린샷을 도구로 'diff'한다 — 예: odiff
→ "85% 유사" 같은 정량 수치가 나온다
- 에이전트는 이 수치를 목표로 삼아 반복 개선한다
(이미지 자체를 이해시키는 것보다 숫자를 읽히는 게 훨씬 안정적)
클로드 같은 멀티모달 모델에게 전/후 이미지를 그냥 던지면 "무엇이 바뀌었는지" 판단하기 어렵습니다. 이미지 전체가 컨텍스트 노이즈이기 때문입니다. 이미지 diff 도구를 붙여 숫자로 바꾸면, 그 루프가 안정적인 평가 지표가 됩니다.
③ 결정적 상태: 세이브/로드를 첫날부터
- 세이브/로드는 마지막에 붙이는 '기능'이 아니라,
개발의 슈퍼파워다. 첫날부터 설계한다
- 'Thing-driven' 개발:
모든 객체를 사실상 같은 타입(Thing)으로 다룬다
(나무도 개도 — 메시, 콜라이더, 상태값의 조합일 뿐이다)
- 객체 타입이 하나면 직렬화 경로도 하나다.
"어떤 클래스를 확장하지?" 고민 없이, AI는 어디를 고칠지 안다
이 대목이 발표에서 가장 실전적입니다. 100개의 클래스 계층이 있으면 AI는 그 전부를 이해해야 합니다. 단일 오브젝트 타입(fat struct)이면 저장·로드도 한 경로, 수정 지점도 한 곳입니다. "AI가 정말 좋아하는 구조"라고 Kukshtel은 표현합니다.
④ 커맨드 패턴: 컴파일 없이 상태를 다루기
상태 변경을 함수 호출이 아니라 (직렬화 가능한) '커맨드 객체'로 표현한다.
[시작 상태] + [커맨드 재생] = [버그가 난 종료 상태]
- 버그 재현: 플레이어에게 물어보는 대신 커맨드를 그대로 재생
- 커맨드는 텍스트 파일이라 게임 밖에서도 작성 가능
→ AI가 커맨드를 써서 게임을 '조종'할 수 있다
→ 어떤 시도에도 컴파일·빌드가 필요 없어진다
에이전트 루프에서 컴파일 대기는 사이클을 죽이는 병목입니다. 커맨드 재생 구조가 있으면 "시도 → 확인"이 초 단위로 줄어듭니다.
⑤ 데이터는 게임 밖에: 빌드 없이 바꾸기
타입·공격력·이동속도 같은 데이터를 코드가 아니라
게임 외부의 데이터 소스에 둔다. 로딩 시 역직렬화해서 반영.
- Cantata 사례: 비프로그래머 팀원 ~7명이 Depot으로 데이터를 고치고,
게임 빌드는 그 변경을 로드해서 반영 — 개발자 빌드 대기 불필요
- AI 에이전트도 같은 도구를 배워서, 팀원처럼 빌드 없이 반복한다
"데이터 변경에 빌드가 필요하다"는 규칙이 하나 사라지면, 그만큼 에이전트가 더 자주 실험하고 더 빨리 배웁니다.
⑥ 시뮬레이션 분리: 엔진 밖으로 꺼내기
게임의 '시뮬레이션'을 엔진과 분리해 별도 라이브러리(DLL)로 만든다.
[엔진/비주얼] ←→ 커맨드/상태 ←→ [시뮬레이션 코어]
- 엔진은 커맨드를 보내고, 돌아온 상태를 그대로 반영하는 '순한' 쪽
- 시뮬레이션은 진실의 원천. "시뮬레이션이 움직였다면, 움직인 것"
- 이득 1: 네트워크·테스트·LLM 등 어떤 소스가 커맨드를 보내도 동작
- 이득 2: 엔진 없이 순수 코드로 시뮬레이션 테스트가 가능
→ 에이전트가 게임 전체를 띄우지 않고도 검증한다
⑦ 임팩트 평가: 에이전트가 읽는 프로파일링
성능 도구는 보통 '사람'을 위해 만들어졌다 — 그래프와 콜스택을 눈으로 본다.
에이전트에게는 텍스트가 더 잘 맞는다. 캡처를 텍스트로 뱉는 도구를 쓴다.
예: samply — 프로파일 캡처를 이식성 있는 형식으로 덤프
→ 에이전트가 자기 변경의 성능 영향을 스스로 읽고 재평가한다
여기까지 연결하면 이런 플라이휠이 됩니다.
[결정적 상태 재현] → [커맨드로 수정] → [컴파일 없이 실행]
→ [이미지 diff + 텍스트 프로파일로 평가] → [다음 턴]
이 루프를 한 번에 몇 초 안에 돌릴 수 있게 되면,
'중요한 변경'에만 돌리던 검증을 '모든 변경'에 돌릴 수 있다.
더 나아가기: 게임이 곧 하네스다
발표의 제목이 여기서 완성됩니다. 각종 AI 하네스(Claude Code 같은 코딩 에이전트부터)는 "무엇을 만들고 있는지 더 잘 이해하고, 그 과정을 안내"하는 장치입니다. 그런데 어떤 하네스도 "당신의 게임"과 대화하지는 못합니다.
게임을 legible(읽히는 것)하게 만들면,
그 게임 자체가 에이전트의 하네스가 된다.
어떤 게임이든 이 원칙을 적용할 수 있다.
전: 한계와 반박
Kukshtel 본인도 글 끝(Postscript)에서 균형을 잡습니다.
- 이 설계들은 '큰 프로젝트'를 위한 이야기다.
본인이 지금 출시 준비 중인 작은 프로젝트에는 이것들 없이 개발했다
- 초기 비용이 있다. 결정성·저장 구조는 프로젝트 막바지에
도입하면 사실상 불가능하다. 첫 줄부터 깔아야 한다
- 모든 프로젝트에 필요한 건 아니다. 규모와 수명이 기준이다
그런데 이 원칙들, 웹·앱으로 번역해도 그대로 통합니다.
| 게임에서의 설계 | 웹·앱으로 번역 |
|---|---|
| 고정 시드 난수 | 시드 있는 테스트 픽스처, 고정된 가짜 데이터 |
| 스크린샷 + 이미지 diff | 스냅샷/시각 회귀 테스트 (예: Playwright) |
| 세이브/로드 = 단일 상태 | 직렬화 가능한 단일 상태 저장소 |
| 커맨드 재생 | 이벤트 로그 리플레이, 녹화된 API 시퀀스 |
| 시뮬레이션 분리(블랙박스) | UI에서 분리된 순수 도메인 모듈 |
| 텍스트 프로파일링 | CI에 남는 성능 리포트·벤치마크 출력 |
CodeBridge Mini Lab: 작은 프로젝트에 검증 루프 붙이기
브리핑의 액션을 그대로 실험으로 옮기면 이렇습니다.
작은 UI 프로젝트 하나를 골라 3가지를 차례로 붙인다:
① 상태 재현
[ ] 시드 기반 테스트 데이터로 어떤 화면 상태든 명령 하나로 복원
② 스크린샷 비교
[ ] 기준 스크린샷 저장 → 변경 후 자동 비교 → 차이 리포트
③ 자동 회귀 테스트
[ ] 핵심 시나리오 몇 개를 자동 실행, 깨지면 에이전트가 먼저 보게
그다음 AI 에이전트에게 "이 화면의 간격을 고쳐줘"를 맡겨 보라.
검증 루프가 있으면 답이 달라진다 — 에이전트가 스스로 확인하고,
고치고, 다시 확인한다.
결론: 생산성은 앱의 '설명 가능성'에서 나온다
AI 에이전트의 생산성은 모델 성능만이 아니라,
애플리케이션의 테스트 가능성과 관측 가능성에 달려 있다.
게임을 게임 자체의 하네스로 만드는 발상은 결국 자기 코드를 AI가 읽을 수 있게 쓰는 일입니다. 그 설계는 어디서나 통합니다.
함께 읽으면 좋은 글
- 하네스 엔지니어링이란? AI 에이전트를 '잘 쓰는 것' 다음에 필요한 것
- 말로 게임을 만든다고? Google Playground × Unity Spark 뜯어보기
- AI 코딩은 모델만 바꾸면 좋아질까? 모델보다 Harness가 결과를 바꾸는 순간
참고 자료
- Kyle Kukshtel: Your Game Is A Harness (Oct 10, 2026)
- Indie Rodeo — Calgary
- odiff: 빠른 이미지 diff CLI
- samply: 이식 가능한 프로파일러
이 주제를 직접 따라가며 배우고 싶다면
"게임을 AI가 이해할 수 있게 만드는 설계"는 게임을 직접 만들어 볼 때 가장 빨리 체감됩니다. Gemini와 Flutter로 작은 게임을 만들며 상태·재현·검증이 어떻게 얽히는지 경험해 보세요.