게임 디자인을 코드처럼 핫 리로드하기
대부분의 엔진은 불투명한 바이너리를 출시한다. RakuAI는 diff하고, 리뷰하고, 핫 리로드할 수 있는 텍스트를 출시한다 — AI 신경계가 바로 그 파일 안에서 주소 지정 가능한 채로. 그 선택이야말로 에이전트로 이루어진 팀 전체가 여러분과 함께 만들 수 있게 해주는 것이다.
파일 포맷 주말이다. 이 엔진에서 AI는 런타임 프리미티브이지, 그 옆에 덧붙인 기능이 아니다. 그것은 내가 전에 펼쳤던 아키텍처적 논지다. 이 글은 그것을 구체적으로 만드는 파일 포맷에 관한 것이다.
대부분의 엔진에서 게임을 만든다면, 여러분이 출시하는 산출물은 바이너리, 프로젝트 번들, 애셋 데이터베이스, 혹은 이 셋의 어떤 조합이다. 여러분이 작성하는 것은 독점 에디터 안에 산다. 여러분이 출시하는 것은 여러분의 팀이 이미 사용하는 도구들에게 불투명하다. 경험의 두 버전을 diff한다는 것은 같은 에디터를 두 번 실행해 변경 로그가 정직하기를 바라는 것을 의미한다.
우리는 다른 길을 택했다. RakuAI 경험은 .raku 파일이다. 그 파일은 JSON이다. 어떤 에디터에서든 열 수 있다. 어떤 코드 리뷰 도구에서든 두 버전을 diff할 수 있다. 스키마에 대해 검증할 수 있다. git에서 버전을 매길 수 있다. PR에서 리뷰할 수 있다. 핫 리로드할 수 있다. 원한다면 손으로 경험을 작성할 수도 있다.
이 파일 포맷은 화려하지 않다. 근간을 이룬다.
실제 .raku 파일이 어떻게 생겼나
이 글을 위해 다듬은, 실제 게임 정의가 여기 있다.
{
"schema_version": "1.0",
"game": {
"title": "My Space Shooter",
"genre": "space_shooter",
"template": "space_shooter",
"mode": "prototype",
"max_players": 1
},
"ai": {
"dda_enabled": true,
"target_flow_state": 0.7,
"profiler_mode": "active",
"emotional_tracking": true,
"adaptive_music": true
},
"entities": [
{
"type": "player_ship",
"health": 100,
"shield": 80,
"speed": 22.0,
"fire_rate": 0.09
},
{
"type": "enemy_wave",
"count": 8,
"health": 15,
"ai_behavior": "strafe",
"properties": { "enemy_id": "interceptor" }
},
{
"type": "boss",
"health": 500,
"ai_behavior": "boss_pattern"
}
]
}
이것이 경험의 대부분이다. 스키마 버전이 매겨진 헤더. 표면 메타데이터를 가진 game 블록. 런타임 AI 설정을 가진 ai 블록. 세계 안에 무엇이 있고 각 엔티티가 어떻게 행동하는지 설명하는 entities 배열.
몇 가지 짚어볼 만한 점이 있다.
ai 블록은 런타임 계약이다
이 부분을 다시 보라.
"ai": {
"dda_enabled": true,
"target_flow_state": 0.7,
"profiler_mode": "active",
"emotional_tracking": true,
"adaptive_music": true
}
여기가 파일이 “AI 신경계가 켜져 있다”고 말하는 곳이다. “GPT에게 레벨을 하나 써 달라고 요청하라”가 아니다. 켜짐. 런타임 레이어에서, 매 프레임, 플레이어가 플레이하는 동안.
dda_enabled는 동적 난이도 조절을 켠다. 런타임은 플레이어가 하는 일을 프로파일링하고 즉석에서 조우를 재구성한다. target_flow_state: 0.7은 런타임이 목표하는 난이도 대역이다. profiler_mode: "active"는 AI가 단지 플레이어의 행동을 샘플링만 하는 게 아니라 읽고 있다고 말한다. emotional_tracking과 adaptive_music은 다른 서브시스템에 적용된 같은 발상이다.
공장 패턴 엔진은 파일 층위에서 이런 손잡이들을 가질 수 없다. 파일이 주소 지정할 런타임 AI가 없기 때문이다. 우리 엔진에서는, 이 손잡이들이 작성자가 신경계에게 어떤 종류의 경험이 되어야 하는지 말하는 방법이다.
이 블록을 PR에서 리뷰할 수 있다. CI에서 두 값을 A/B 테스트할 수 있다. 에디터를 본 적 없는 프로듀서도 이것을 읽고 목표 플로우 상태가 무엇을 의미하는지에 대해 엔지니어링과 대화할 수 있다. 파일 포맷은 디자인 결정을 눈에 보이게 만든다.
엔티티별 AI 비헤이비어는 통합이 아니라 문자열이다
파일 안의 각 엔티티는 ai_behavior 필드를 가질 수 있다.
{
"type": "enemy_wave",
"count": 8,
"ai_behavior": "strafe"
}
"strafe"는 모델 호출이 아니다. 신경계 레이어가 구동하는, 런타임에 등록된 비헤이비어다. 같은 엔티티가 "patrol"이나 "boss_pattern"이나 런타임이 할 줄 아는 다른 무엇이든 될 수 있다. 파일은 모델을 임포트하지 않는다. 능력을 주소 지정한다.
이것이 파일 포맷을 특정 모델로부터 분리시키는 방법이다. 작성자는 의도를 쓴다. 런타임은 그 의도를 전달하기 위해 어느 모델, 어느 가중치, 어느 결정론적 폴백을 사용할지 결정한다. 다음 분기에 모델을 교체해도 .raku 파일은 바뀌지 않는다.
그 분리는 들리는 것보다 더 중요하다. 내가 이야기한 특정 LLM을 엔진에 억지로 끼워넣은 모든 팀은 모델 벤더가 움직였을 때 그 통합을 다시 해야 했다. 우리는 그러지 않는다.
왜 JSON인가
파일 포맷을 보여줄 때 가장 많이 받는 질문이다. 왜 수학 표현식, 인라인 스크립팅, 반응형 바인딩을 위한 더 나은 문법을 갖춘 커스텀 DSL이 아니라 JSON인가?
세 가지 이유다.
하나: 모든 도구가 이미 JSON을 말한다. 코드 리뷰. Diff 도구. 버전 관리. 린터. 스키마 검증기. CI 파이프라인. 정적 분석. 모든 플랫폼의 모든 에디터. 우리는 그중 어느 것도 만들 필요가 없었다. 공짜로 얻었다.
둘: 사람은 JSON을 충분히 잘 읽는다. 위의 파일은 예쁘지 않지만, 시니어 디자이너는 훈련 없이 그것을 읽을 수 있다. 누군가 PR을 리뷰할 수 있게 되기까지 배우는 데 일주일이 걸리는 DSL과 비교해 보라.
셋: AI 어시스턴트는 JSON을 극도로 잘 읽는다. 이것은 3년 전보다 2026년에 더 중요하다. 디자이너가 AI 어시스턴트에게 “보스가 더 무섭게 느껴지도록 조정해줘”라고 요청할 때, 어시스턴트는 파일을 읽고, diff를 제안할 수 있으며, 사람은 그 diff를 수락하거나 거부할 수 있다. 커스텀 DSL이라면 모든 어시스턴트에게 새로운 문법을 가르쳐야 할 것이다.
비용은 실재한다. JSON은 장황하다. 인라인 수학도, 주석도, 축약형도 없다. 우리는 도구의 보편성과 맞바꾸어 표현력을 포기한다. 지금까지 그 거래는 여러 번 그만한 값어치를 했다.
이것이 가능하게 하는 것
여러분의 경험이 텍스트가 되면 몇 가지가 바뀐다.
게임 디자인에 대한 PR 리뷰. 디자이너가 target_flow_state를 0.7에서 0.5로 바꾼다. 그 변경은 풀 리퀘스트 안에서 한 줄짜리 diff로 나타난다. 엔지니어링과 디자인이 함께 그 변경을 리뷰한다. PR 안의 대화는 경험이 왜 지금 방식대로 플레이되는지에 대한 기록이다. 6개월 후, 누군가 왜 난이도 곡선이 지금 느낌인지 물을 때, 답은 커밋 로그 안에 있다.
경험을 위한 CI. .raku 파일이 스키마 검증에 실패한다. 변경이 출시되기 전에 빌드가 실패한다. 여러분의 유닛 테스트를 실행하는 것과 같은 CI가 여러분의 경험 정의를 실행한다.
핫 리로드. 파일이 디스크에서 바뀐다. 런타임이 알아챈다. 세계가 재시작 없이 업데이트된다. 개발 루프는 초 단위로 조여진다.
롤백. 변경이 보스전을 망가뜨렸다. 커밋을 되돌린다. 경험이 되돌아간다. 에디터도, 애셋 재빌드도, 일주일짜리 왕복도 필요 없다.
AI에 의한 작성. 팀원이 자연어로 원하는 것을 설명한다. AI 어시스턴트가 .raku diff를 작성한다. 사람 리뷰어가 승인한다. 그 diff는 감사 가능하고, 버전 관리 가능하며, 다른 코드 변경과 같은 리뷰 규율 아래 놓인다.
이것들은 이국적인 능력이 아니다. 모든 현대 소프트웨어 팀이 코드베이스의 나머지에 대해 당연하게 여기는 것들이다. 우리는 그것들을 게임 디자인으로 확장했다.
어려운 점
정직한 비용들이다.
JSON에는 주석이 없다. 우리는 디자인 의도를 위한 사이드카 .md 파일과 서술적인 필드 이름으로 보완하지만, 실질적인 마찰이다.
스키마는 조심스럽게 진화해야 한다. 세계 생성이 원래 형태를 넘어섰을 때 한 번 schema_version: 1.0에서 2.0으로 올렸다. 이미 존재하는 모든 파일이 마이그레이션 경로를 필요로 했다. 그 작업은 일의 일부이며, 공짜가 아니다.
필드를 계속 추가하고 싶은 유혹이 있다. 우리는 들리는 것보다 더 세게 그것에 저항한다. 추가되는 모든 필드는 런타임이 영구히 준수해야 하는 계약이다. 편향은 파일을 작게 유지하고 복잡성을 파일이 아니라 런타임에 두는 것이다.
그리고 마지막으로: 텍스트 기반 경험 정의는 런타임이 실제로 그것들로 흥미로운 무언가를 할 때만 중요하다. 파일 포맷은 그 아래에 있는 아키텍처적 결정의 다운스트림이다. 엔진이 AI를 콘텐츠 공장으로 취급한다면, 파일은 그저 매니페스트일 뿐이다. 엔진이 AI를 런타임 프리미티브로 취급한다면, 파일은 악보다.
포맷을 처음부터 끝까지 읽고 싶다면, 스키마는 공개 문서 안에 살고 있고 샘플 파일은 저장소 안에 담겨 출시된다. 하나를 열어보라. 코드로서 읽어라. 실제로 그것이니까.
이틀 치 파일 포맷 작업이 은행에 쌓였다. 다음 주말 다시 엔진으로.
여러분의 AI가 읽고 쓸 수 있는 경험을 작성하라
RakuAI는 AI를 런타임 프리미티브로, 경험을 코드로 취급한다. .raku 포맷을 열고, diff하고, 핫 리로드하라 — 그리고 여러분의 어시스턴트가 현실 세계에서 여러분과 함께 만들게 하라.