리스트
지난 글에서는 Stackspire의 핵심 자원인 Context, Focus, Tech Debt가 LLM과의 상호작용 속에서 어떻게 구체적인 시스템으로 구현되는지 살펴보았습니다. 플레이어의 상태가 실시간으로 프롬프트에 반영되어 LLM의 행동을 바꾸고, API의 비용 구조가 게임의 자원 시스템으로 치환되는 과정을 통해 우리는 살아있는 게임 시스템의 청사진을 그렸습니다.
하지만 개별 시스템들이 아무리 잘 설계되어도, 이들을 하나로 묶어 안정적으로 작동하게 하는 전체적인 구조가 없다면 모래 위에 성을 쌓는 것과 같습니다. 특히 LLM이라는 예측 불가능한 요소를 게임의 핵심 엔진으로 사용할 때는 더욱 그렇습니다.
이번 글에서는 한 걸음 물러나, 이 모든 시스템을 하나로 묶는 전체적인 게임 아키텍처와, LLM의 예측 불가능성을 제어하여 안정적인 게임 경험을 만들기 위한 필수적인 안전장치(Guardrails) 설계에 대해 이야기해보겠습니다.
1. Stackspire의 전체 아키텍처
Stackspire의 아키텍처는 게임의 핵심 로직과 LLM이라는 외부 지능을 명확하게 분리하는 것을 목표로 합니다. 각 컴포넌트는 자신의 역할에만 집중하며, 이를 통해 시스템의 복잡도를 관리하고 유지보수를 용이하게 만듭니다.
전체적인 데이터 흐름은 다음과 같습니다.
1.
게임 엔진 (Game Engine): 플레이어의 입력을 받고, UI를 렌더링하며, 게임의 모든 상태를 관리하는 '지휘관'입니다. 플레이어가 '지식 탐구의 방'에서 질문을 입력하면, 게임 엔진은 이 요청을 LLM 매니저에게 전달합니다.
2.
LLM 매니저 (LLM Manager): 게임 엔진 내부에 존재하는, 모든 LLM 상호작용을 전담하는 서비스 계층입니다. 이 매니저는 다음과 같은 핵심적인 역할을 수행합니다.
•
프롬프트 구성: 게임 엔진으로부터 현재 플레이어의 상태(Focus, Tech Debt 등)를 전달받아, 상황에 맞는 최종 프롬프트를 동적으로 조립합니다.
•
비동기 API 호출: 게임이 멈추지 않도록 LLM API를 비동기(Asynchronous) 방식으로 호출합니다.
•
응답 파싱 및 검증: LLM으로부터 받은 JSON 응답을 파싱하고, 미리 정의된 안전장치 규칙에 따라 유효성을 검사합니다.
3.
LLM API (External Service): OpenAI나 Anthropic 같은 외부 LLM 서비스입니다. 우리 아키텍처에서는 이 서비스를 오직 프롬프트를 입력받아 구조화된 텍스트(JSON)를 출력하는 '콘텐츠 생성기'로만 취급합니다.
4.
상태 업데이트: LLM 매니저가 검증을 마친 데이터를 다시 게임 엔진에 전달하면, 게임 엔진은 그 결과에 따라 플레이어의 자원을 업데이트하고 UI를 변경하여 플레이어에게 피드백을 줍니다.
이처럼 각자의 역할을 명확히 분리함으로써, 우리는 나중에 다른 LLM으로 교체하거나 게임 로직을 수정할 때 서로에게 미치는 영향을 최소화할 수 있습니다.
2. 예측 불가능성 제어하기: 안전장치(Guardrails)의 설계
LLM을 게임에 도입할 때 가장 큰 우려는 바로 예측 불가능성입니다. LLM은 때때로 엉뚱한 답변을 하거나, 이상한 형식으로 응답하거나, 심지어는 게임의 설정을 파괴하는 내용을 생성할 수도 있습니다. 안정적인 게임 경험을 위해서는 이러한 돌발 행동을 제어할 다층적인 안전장치가 반드시 필요합니다.
안전장치 1: 구조적 강제 (Structural Enforcement)
가장 기본적인 안전장치는 LLM이 반드시 우리가 원하는 형식, 즉 JSON으로만 응답하도록 강제하는 것입니다. 이는 프롬프트에 명시적인 규칙을 포함함으로써 구현할 수 있습니다.
System Prompt (일부): "당신은 게임 'Stackspire'의 퀴즈 출제자입니다. 당신의 응답은 반드시 다음 JSON 스키마를 따라야 합니다. 다른 설명이나 대화는 절대 포함하지 마십시오: {"question_text": "...", "choices": ["...", "...", "..."], "correct_answer_index": 0}"
또한, 최신 LLM API들이 제공하는 'JSON 모드'와 같은 기능을 활용하면 이 규칙을 더욱 확실하게 강제할 수 있습니다. LLM 매니저는 응답을 받았을 때 이 JSON 구조가 유효한지 먼저 파싱해보고, 만약 형식이 깨졌다면 게임을 중단시키는 대신 요청을 재시도하거나 미리 준비된 예비 질문을 사용하는 등의 예외 처리를 수행해야 합니다.
안전장치 2: 내용적 제어 (Content Control)
올바른 형식으로 응답하더라도, 그 내용이 게임의 맥락을 벗어날 수 있습니다. 예를 들어 SQL 퀴즈를 요청했는데 갑자기 파이썬(Python)에 대한 문제를 낼 수도 있습니다. 이는 시스템 프롬프트를 통해 제어합니다.
System Prompt (일부): "생성할 퀴즈는 반드시 'SQL의 JOIN 연산'과 관련된 내용이어야 합니다. 다른 주제에 대한 질문은 절대 생성하지 마십시오."
이러한 내용적 제약은 LLM이 허용된 범위 안에서만 창의성을 발휘하도록 하여, 게임의 몰입감과 주제의 일관성을 유지하는 역할을 합니다.
안전장치 3: 후처리 검증 (Post-Processing Validation)
프롬프트로 모든 것을 제어했다 하더라도, 우리는 LLM의 결과를 100% 신뢰해서는 안 됩니다. LLM 매니저는 파싱된 데이터를 게임 엔진에 전달하기 전에 마지막으로 논리적인 검증을 거쳐야 합니다.
•
검증 예시 1: LLM이 생성한 퀴즈 JSON에서 선택지(choices)는 3개인데 정답 인덱스(correct_answer_index)가 4로 되어 있는 경우. 이는 명백한 논리적 오류입니다.
•
검증 예시 2: 질문의 길이가 너무 길거나, 욕설과 같은 금지된 단어가 포함된 경우.
이러한 오류가 발견되면, LLM 매니저는 해당 응답을 폐기하고 대체 전략(Fallback Strategy)을 실행해야 합니다. 가장 간단한 방법은 몇 가지 고품질의 퀴즈를 미리 데이터베이스에 저장해두고, LLM 응답이 실패할 경우 이 예비 퀴즈 중 하나를 대신 사용하는 것입니다. 이를 통해 플레이어는 어떤 상황에서도 끊김 없는 게임 경험을 이어갈 수 있습니다.
마무리
이번 글에서는 Stackspire의 전체적인 아키텍처와 LLM의 예측 불가능성을 제어하기 위한 다층적인 안전장치 설계에 대해 알아보았습니다. 핵심은 관심사의 분리와 불신과 검증입니다. 게임 로직과 LLM 상호작용을 명확히 분리하고, LLM의 출력을 항상 검증하며, 모든 실패 상황에 대한 대체 전략을 마련해두는 것이 중요합니다.
다음 글에서는 이 모든 시스템을 바탕으로, 플레이어가 실패를 통해 성장하는 로그라이크의 핵심 재미, 즉 메타-프로그레션(Meta-Progression) 시스템을 어떻게 설계하고 구현할지 이야기해보겠습니다.