지난 글의 마지막에는 이런 질문을 남겼다.이 실험을 계속할 이유가 있는가?결론부터 말하면, 여기서 멈추기로 했다.더 해볼 방법이 없었던 것은 아니다.현재 CPU-only로 진행한 추론을 GPU에 offload할 수도 있었고, GPU를 전제로 더 큰 모델을 시험할 수도 있었다. Fine-tuning이나 여러 단계의 자기 수정, Cloud Model도 남아 있었다.방법은 많다.그런데 그 전에 다시 봐야 할 게 있었다.나는 원래 무엇을 확인하려고 이 게임을 만들기 시작했는가?목표는 ‘게임에서 LLM을 돌리는 것’이 아니었다UNSPECIFIED를 시작하면서 확인하고 싶었던 질문은 단순히“작은 Local LLM을 게임에서 실행할 수 있는가?”가 아니었다.Local Model을 실행하고, 요청을 보내고, 결과를 받아 게임에 연결하는 것 자체는 결국 엔지니어링 문제에 가깝다.실제로 이번 프로젝트에서도 그 부분은 동작했다.내가 확인하고 싶었던 건 그다음이었다.작은 Local LLM이 플레이어의 행동을 읽고, deterministic한 방식만으로는 쉽게 얻기 어려운 다양하고 납득 가능한 전투 능력을 만들어낼 수 있는가?그리고 그 차이가 Local LLM을 게임에 포함하는 비용을 감수할 정도로 큰가?즉 성공 기준은 “AI가 돌아갔다”가 아니었다.제품에 넣으려면 최소한 몇 가지 조건을 동시에 만족해야 했다.기준보고 싶었던 것실행 가능성실제 게임 규칙으로 컴파일하고 실행할 수 있는가다양성비슷한 결과 하나만 반복하지 않는가플레이 적합성실제 플레이어 행동에서 나온 결과처럼 느껴지는가납득 가능성결과를 보고 왜 나왔는지 이해할 수 있는가비용추론 시간과 Runtime 복잡성을 감수할 가치가 있는가하나만 만족해서는 부족했다.다양하지만 대부분 실행할 수 없다면 게임에 넣기 어렵다.잘 작동하지만 간단한 규칙 기반 방식과 별 차이가 없다면 굳이 모델을 함께 배포할 이유가 없다.그래서 마지막 판단 기준도 자연스럽게 바뀌었다.LLM을 사용할 수 있는가?가 아니라LLM을 사용해야 할 이유를 증명했는가?앞선 실험에서 확인한 두 가지지난 글에서 자세히 다뤘기 때문에 실험 과정 전체를 다시 반복하지는 않으려고 한다.결과를 요약하면 두 가지였다.먼저 모델에게 이미 검증된 스킬 중 하나를 선택하게 했을 때는 기술적으로 안정적으로 동작했다.구조화된 Ranking 결과가 정상적으로 돌아왔고, 그 결과로 선택된 기존 스킬을 실제 게임에 적용하는 흐름도 동작했다.하지만 작은 개발자 파일럿에서는 규칙 기반 시스템과 같은 선택이 나오는 경우가 많았고, Local Model의 추가 비용을 정당화할 만큼 뚜렷한 차이는 확인하지 못했다.그래서 모델의 역할을 넓혀 스킬 자체를 조합하게 했다.처음에는 내부 구조까지 직접 작성하게 했지만 결과가 너무 낮아, 혹시 실험 자체가 불공정한 것은 아닌지 다시 의심했다.결국 마지막에는 내부 배선을 전부 코드가 맡고, 모델은 행동 순서·대상 관계·공간 관계·효과 같은 의미 구조만 결정하도록 문제를 다시 단순화했다.그래도 핵심 문제는 남았다.마지막 실험 결과 요약최종 개발용 데이터셋은 24개의 고정된 상황으로 구성했다.20개는 실제 스킬 생성이 가능한 상황이었고, 4개는 행동 증거가 부족해 아무것도 만들지 않는 것이 정답인 상황이었다.생성 가능한 경우에는 시스템마다 서로 다른 후보 3개를 요구했기 때문에, 각 시스템은 총 60개의 후보를 만들었다.방식실행 가능한 후보 / 60중복 제거 후 후보하나라도 성공한 상황 / 20규칙 기반606020Qwen3 1.7B000Qwen3.5 2B644Granite 4.2 3B000여기서 실행 가능하다는 것은 재미있다는 뜻이 아니다.게임의 의미 규칙과 Compiler 검증을 통과해 실제 능력으로 실행할 수 있었다는 뜻이다.Local Model 중에서는 2B 모델만 일부 결과를 통과시켰고, 중복을 제거한 4개 역시 구조적으로는 한 종류로 수렴했다.세 모델 모두 한 상황에서 요구했던실행 가능하면서 서로 다른 세 가지 후보를 만든 경우는 없었다.그래서 마지막 Composition 단계는 추가 사람 평가로 넘어가지 않았다.사람에게 어떤 결과가 더 재미있는지 묻기 전에, 비교 가능한 후보 자체를 안정적으로 생성할 수 있어야 한다고 판단했기 때문이다. 성공한 몇 개만 골라 평가하면 실제 제품 성능보다 좋아 보일 가능성도 있었다.그리고 마지막 실패의 핵심은 단순한 JSON 형식 문제가 아니었다.세 Local Model이 만든 총 180개 후보 중 150개는 첫 번째 거절 사유가 행동·물체·대상 사이의 의미 관계 일관성 문제였다.예를 들어 물체 정보가 없는 행동을 선택한 뒤 “첫 번째 행동과 같은 물체”라는 조건을 붙이거나, 대상이 없는 행동에서 이전 공격 대상을 참조하는 식이었다.문법에 맞는 구조화된 출력을 만드는 것과, 여러 조건이 동시에 성립하는 게임 규칙을 만드는 것은 다른 문제였다.각각의 선택은 그럴듯해도, 스킬 전체의 관계를 끝까지 일관되게 유지하는 데서 문제가 생겼다.그런데 규칙 기반 시스템은 어디까지 갈 수 있었을까?여기서 비교를 위해 만든 deterministic Composer가 예상보다 중요한 결과를 하나 보여줬다.모든 관련 행동 증거가 충분히 강하게 존재한다고 가정한 개발용 테스트 공간에서,38,068개의 조합 표현을 검사했고, 구조 기준으로 6,434개의 서로 다른 유효 조합을 찾을 수 있었다.38,068개 검사 → 6,434개의 서로 다른 유효 구조이 숫자를“재미있는 스킬이 6,434개 생겼다.”라고 해석하면 안 된다.실제로 재미있는지, 밸런스가 맞는지, 플레이어에게 줄 가치가 있는지는 별개의 문제다.한 플레이어에게 이 모든 스킬이 동시에 유효하다는 뜻도 아니다.하지만 중요한 건 숫자의 크기 자체가 아니었다.현재 만든 Skill Grammar의 유효한 조합 공간을 deterministic code만으로도 상당 부분 탐색할 수 있었다는 것이었다.이 사실이 이후 판단에 꽤 큰 영향을 줬다.모델을 안전하게 만들수록, 생성의 핵심이 코드로 이동했다Local Model의 유효성을 올리는 방법은 분명히 있다.예를 들어 첫 번째 행동을 고른 뒤에는 그 행동과 실제로 연결 가능한 두 번째 조건만 모델에게 보여줄 수 있다.아예 가능한 구조들을 코드가 먼저 생성한 뒤 모델에게 그중 하나를 선택하게 할 수도 있다.잘못된 결과를 코드가 자동으로 수정할 수도 있다.단계별로 합법적인 선택지만 허용하는 식으로 더 강하게 제한할 수도 있다.이런 방식을 사용하면 실행 가능성은 분명 좋아질 수 있다.그런데 그럴수록 다른 문제가 생긴다.게임 코드가 이미무엇이 가능한 행동인지 계산하고어떤 관계가 합법적인지 판단하고유효한 조합을 찾아내고잘못된 조합을 수정한다면모델에게 남는 일은 점점 줄어든다.결국 다시“이미 안전한 후보 중 어떤 걸 선택할까?”라는 문제로 돌아간다.그리고 그 문제에서는 앞선 실험에서 규칙 기반 시스템보다 뚜렷한 추가 가치를 확인하지 못했다.특히 deterministic Composer만으로도 현재 Grammar의 유효 조합 공간을 상당히 탐색할 수 있다는 걸 확인한 뒤에는 이 문제가 더 선명해졌다.모델을 안전하게 만들기 위해 선택 공간을 코드가 더 많이 좁힐수록, 그 선택 공간 자체를 만드는 일도 코드가 하고 있었다.이게 더 진행하지 않기로 한 가장 큰 이유 중 하나였다.속도는 단독 실패 원인이 아니었다측정 환경: AMD Ryzen 9 9900X, CPU-only inference, 6 threads, Q4_K_M quantization, context 8192.Local Model의 추론 시간도 측정했다.Cold Load와 초기 Warm-up 시간은 제외한 값이다.이 수치는 모델 자체의 보편적인 성능 벤치마크가 아니라, 내가 사용한 개발 환경에서의 제품 판단용 측정값이다.모델최소중앙값최대Qwen3 1.7B13.93초14.32초15.96초Qwen3.5 2B17.76초20.37초22.26초Granite 4.2 3B33.27초38.46초40.35초규칙 기반 Composer는 같은 개발 환경에서 중앙값 약 2.53초였다.다만 이것 역시 현재 조합 공간을 폭넓게 탐색하는 개발용 구현이다.Shipping 최적화를 한 값은 아니고, 가능한 구조를 미리 계산하거나 캐시하면 더 줄일 수 있는 성격의 비용이다.그리고 14~20초대의 Local Model 추론 자체를 무조건 사용할 수 없는 시간이라고 생각한 것도 아니다.Adaptive Skill이 자주 등장하지 않는다면 전투 사이에서 비동기로 돌리고 다음 보상 시점까지 결과를 준비할 수도 있다.문제는 단순히 느렸다는 게 아니었다.그 시간을 기다릴 만큼 결과가 더 좋아지지 않았다.Local Model을 실제 제품에 포함하면 추론 시간 이외에도 모델 파일 배포, Worker 관리, Warm-up, 메모리 예산, Timeout, 오래된 응답 폐기, Fallback, 이후 기기별 검증 같은 비용이 추가된다.그 비용은 결과가 확실히 좋아진다면 감수할 수 있다.이번에는 그 근거를 얻지 못했다.“그럼 더 큰 모델을 쓰면 되지 않을까?”당연히 가능한 선택이다.이번 프로젝트는“LLM으로 게임 메커닉을 만드는 것은 불가능하다.”를 증명한 게 아니다.7B나 14B급 Local Model은 시험하지 않았다.Cloud Model도 시험하지 않았다.Fine-tuning이나 LoRA도 하지 않았다.GPU inference 역시 최종 제품 조건으로 비교하지 않았다.여러 번 생성하고 스스로 결과를 고치는 Agent 형태도 시험하지 않았다.더 많은 플레이 데이터를 모델에게 제공하는 방법도 남아 있다.따라서 이런 방법들이 실패한다고 말할 수는 없다.다만 여기서 중요하게 본 건 다른 질문이었다.더 좋은 모델이 존재할 수 있는가가 아니라, 내가 처음 세운 제품 제약 안에서 이 접근이 성립하는가?UNSPECIFIED에서 원했던 건 작은 Local Model이 상업 게임 안에서 실제로 돌아가면서 플레이어 행동을 읽고 새로운 전투 규칙을 만들어주는 것이었다.7B나 14B 모델이 필요하다면 그건 새로운 비용 구조를 가진 실험이다.Cloud API가 필요하다면 Local이라는 전제가 바뀐다.Fine-tuning이 필요하다면 별도의 데이터와 학습 프로젝트가 된다.여러 번의 Repair Pass가 필요하다면 Runtime 비용과 지연 역시 달라진다.모두 충분히 연구할 가치가 있을 수 있다.하지만 이번 가설을 살리기 위해 성공 조건을 계속 옮기는 것과는 구분하고 싶었다.실패할 때마다 조건을 바꾸면 가설은 절대 실패하지 않는다R&D를 계속할 수 있는 이유는 언제나 만들 수 있다.이번 모델이 작았다.입력 데이터가 부족했다.Prompt를 더 다듬을 수 있다.다음 모델은 더 좋을 것이다.Constrained Decoding을 붙이면 된다.Tool Use를 붙이면 된다.각각 맞는 말일 수 있다.그런데 실패가 나올 때마다 성공할 때까지 조건을 하나씩 바꾼다면,어느 순간부터는 처음 질문을 검증하는 것이 아니라AI를 성공시키기 위한 새로운 문제를 계속 만드는 것에 가까워진다.이번에는 그 선을 여기로 잡았다.최종적으로 내릴 수 있는 결론은 아주 제한적이다.현재 시험한 1.7B~3B급 Quantized Local Model과 현재의 Skill Grammar, Single-pass 실행 조건에서는 deterministic 방식보다 의미 있게 나은 Adaptive Skill 생성 가치를 확보하지 못했다.그 이상도, 그 이하도 아니다.하지만 이 정도면 다음 개발 비용을 결정하기에는 충분했다고 생각한다.불가능해서 멈춘 게 아니라, 현재 가설에 더 많은 개발 비용을 투자할 근거가 사라졌기 때문에 멈췄다.그래도 이 프로젝트에서 얻은 건 꽤 많았다Local LLM이라는 핵심 가설은 원하는 결과를 얻지 못했다.그렇다고 이번 개발 전체가 버려지는 건 아니다.오히려 가설을 제대로 검증하려다 보니 AI와 상관없이 재사용할 수 있는 시스템이 꽤 많이 남았다.Deterministic Combat대시와 피격, 동시에 발생한 공격, 투척과 피격처럼 순서가 민감한 전투 상황을 엔진 Callback 순서에 맡기지 않고 하나의 판정 흐름에서 처리하는 구조를 만들었다.Held Object Combat월드의 물체를 집고, 근접 공격에 사용하고, 던지고, 부수고, 튕기고, 다시 받아내는 흐름을 하나의 공통 전투 구조로 만들었다.Semantic Telemetry와 Motif단순히 버튼을 몇 번 눌렀는지가 아니라,플레이어가 실제로 확정한 행동과 그 행동 사이의 관계를 측정할 수 있게 됐다.Skill Grammar완성된 스킬을 하나씩 만드는 대신,행동·대상·기억·공간·효과를 조합해서 능력을 표현할 수 있는 작은 게임 언어를 만들었다.Skill Compiler와 실행 안전장치조합된 능력이 실제로 존재하는 기능만 사용하는지,입출력이 맞는지,상태의 수명이 정의돼 있는지,순환 실행이 없는지,파생 효과가 무한히 늘어나지 않는지를 검사할 수 있게 됐다.Presentation Pipeline실제 게임에서 실행되는 능력과 플레이어에게 보여주는 설명이 같은 검증된 의미 구조에서 나오도록 만들었다.Deterministic ComposerLLM 없이도 현재 Grammar의 가능한 조합을 탐색하고 비교할 수 있는 기준선이 생겼다.Local Model / Benchmark Infrastructure외부 Local Worker의 시작과 종료, Warm-up, Timeout, Crash, 늦은 응답, Fallback뿐 아니라 어떤 소스 상태에서 어떤 결과가 만들어졌는지도 추적할 수 있는 실험 구조를 만들었다.돌아보면 조금 재미있는 결과다.LLM을 검증하기 위해 만든 시스템 상당수가, LLM이 없어도 쓸 수 있는 자산으로 남았다.실패한 데이터도 같이 남기기로 했다코드만 보존할 생각은 없다.최종 Benchmark에 사용한 고정된 테스트 사례와 모델 결과, 실패 이유, 실행 시점의 Source 상태도 함께 보존하기로 했다.이유는 크게 세 가지다.1. 나중에 같은 실험을 다시 처음부터 하지 않기 위해몇 달이나 몇 년 뒤 훨씬 좋은 Small Local Model이 나온다면 다시 시험해볼 수 있다.그때 현재 테스트 데이터를 그대로 사용하면모델만 바뀌었을 때 실제로 얼마나 달라졌는가를 볼 수 있다.반대로 모델도 바꾸고, Prompt도 바꾸고, Grammar도 바꾸고, 입력 데이터도 바꾼다면 무엇 때문에 결과가 좋아졌는지 알기 어렵다.2. ‘안 됐다’가 아니라 ‘어디서 안 됐는지’를 남기기 위해시간이 지나면 실패 과정은 쉽게 압축된다.몇 달 뒤에는 아마“작은 모델로 해봤는데 잘 안 됐지.”정도로 기억하기 쉽다.하지만 실제로는 조금 더 구체적이었다.좁은 Ranking 역할에서는 모델의 추가 가치가 작았다.실제 Composition을 열자 실행 가능성이 무너졌다.내부 배선 부담을 없앤 뒤에도 의미 관계 일관성 문제가 남았다.그리고 마지막 180개 후보 중 150개는 첫 번째 거절 사유 기준으로 그 문제에서 탈락했다.이런 정보가 남아 있어야 다음 실험에서 똑같은 길을 다시 걷지 않는다.3. Negative Result도 다음 의사결정을 위한 데이터이기 때문에처음에는 나도 이런 기대가 있었다.Structured Output을 강하게 제한하고 뒤에 Compiler까지 붙이면, 작은 모델도 꽤 안정적으로 게임 메커닉을 만들 수 있지 않을까?그리고 2B가 부족하다면3B 정도면 꽤 좋아지지 않을까?라는 기대도 있었다.이번 조건에서는 둘 다 확인되지 않았다.이것 역시 결과다.성공한 실험만 남기고 실패한 결과를 지워버리면 다음에는 다시 같은 가정을 처음부터 검증해야 한다.그래서 이번 결과는 “버려진 프로토타입”보다는 다음 판단을 위한 기준점으로 남겨두려고 한다.이번 프로젝트에서 가장 크게 배운 것돌이켜보면 기술 자체보다 몇 가지 판단 기준을 더 많이 얻은 것 같다.Structured Output과 Semantic Validity는 다르다.JSON Schema를 만족시키는 것만으로 실제 실행 가능한 규칙이 되는 건 아니었다.국소적으로 그럴듯한 선택과 전체적으로 일관된 규칙도 다르다.행동 하나, 대상 하나를 고르는 건 잘해도 여러 단계의 제약을 동시에 유지하는 건 훨씬 어려웠다.AI의 자유도와 안전성은 공짜로 동시에 얻어지지 않았다.자유도를 늘리면 Invalid Space가 빠르게 커졌고, 안전성을 높이기 위해 제약을 강화하면 중요한 생성 로직이 Host 쪽으로 이동했다.그리고 무엇보다,Baseline을 만드는 일이 중요했다.규칙 기반 비교 대상이 없었다면 모델이 무언가를 생성했다는 사실 자체를 성공으로 착각했을 수도 있다.마지막으로 하나 더 있다.더 해볼 수 있다는 것과, 더 해야 한다는 것은 다르다.이번 프로젝트에서는 그 차이가 가장 중요한 결과였던 것 같다.UNSPECIFIED를 여기서 끝내며UNSPECIFIED는 처음부터 AI가 반드시 성공해야 하는 프로젝트로 만들고 싶지는 않았다.실제로 가능한지 알고 싶었다.그래서 AI를 넣기 전에 액션게임을 만들었고,플레이어 행동을 측정했고,그 행동을 능력으로 표현할 수 있는 언어를 만들었고,실행 가능한지 검증할 Compiler와 Runtime을 만들었고,마지막에는 규칙 기반 방식과 실제 Local Model을 같은 조건에서 비교했다.그리고 결과는 처음 기대했던 것과 달랐다.조금 아쉽기는 하다.하지만 가설이 마음에 든다는 이유로 계속 개발 비용을 쓰는 것보다는,처음 세운 질문에 지금까지 얻은 데이터가 어떤 답을 하고 있는지 따르는 편이 맞다고 생각한다.UNSPECIFIED는 내가 처음 기대했던 형태의 게임이 되지는 못했다.대신 “작은 Local LLM으로 실제 게임 규칙을 만들 수 있을까?”라는 질문에는, 적어도 내가 정한 조건 안에서 끝까지 답해볼 수 있었다.가설은 실패했고, 질문에는 답했다.