LLM 챗봇 NPC와 가상 사회 설계: 상호작용을 게임 시스템으로 만드는 법
LLM 챗봇 NPC가 반복 대화에 그치지 않고 관계, 평판, 경제, 퀘스트를 변화시키도록 설계하는 방법을 다룬다. 상태 모델·행동 선택·안전한 실행 계층·밸런싱 지표를 단계별로 정리한다.

핵심 요약
LLM 챗봇 NPC를 설득력 있게 만들려면 모델이 세계를 직접 바꾸게 해서는 안 된다. LLM은 대화 의도와 행동 후보를 생성하고 게임 시스템은 관계도·소문·재화·퀘스트 같은 검증 가능한 상태값을 갱신해야 한다. 이 분리를 지키면 즉흥적인 대화와 예측 가능한 밸런싱을 함께 얻을 수 있다.
LLM 챗봇 NPC는 왜 단순 대화 기능으로 끝나는가?
대화문만 생성하는 NPC는 플레이어가 여러 번 말을 걸어도 세계에 남는 결과가 없다. 반대로 LLM 출력에 재화 지급, 퀘스트 완료, 적대 전환 권한을 그대로 주면 프롬프트 오류나 문맥 오해가 게임 경제를 망가뜨릴 수 있다.
해결 원칙은 간단하다. 언어는 LLM이 처리하고 규칙과 결과는 게임이 처리한다.
| 계층 | 책임 | 예시 |
|---|---|---|
| 서사 계층 | 자연어 이해와 대사 생성 | 사과를 진심으로 받아들였는지 표현 |
| 의도 계층 | 제한된 행동 후보 선택 | offer_trade, spread_rumor, refuse_quest |
| 규칙 계층 | 조건 검증과 수치 변경 | 호감도 40 이상일 때 거래 할인 적용 |
| 세계 상태 계층 | 영속 데이터 저장 | 재화, 평판, 소문, 퀘스트 단계 |

가상 사회의 최소 상태 모델은 어떻게 설계할까?
처음부터 모든 NPC의 감정과 기억을 문장으로 저장할 필요는 없다. NPC별로 게임플레이에 영향을 주는 수치와 짧은 사실 목록만 유지하는 편이 훨씬 안정적이다.
NPC별 상태
type NpcState = {
id: string;
faction: "guild" | "merchant" | "guard";
trust: number; // -100 ~ 100
fear: number; // 0 ~ 100
wealth: number; // 보유 재화
needs: string[]; // "food", "protection" 등
memories: string[]; // 검증된 사건 요약, 최대 10개
};
type SocialEvent = {
actorId: string;
targetId?: string;
type: "trade" | "gift" | "insult" | "rumor" | "crime";
magnitude: number;
day: number;
};
memories에는 대화 원문 대신 플레이어가 경비대장에게 약초를 선물함처럼 판정이 끝난 사건만 넣는다. 프롬프트 토큰 비용을 줄이고 NPC가 사실과 다른 기억을 확정하는 문제도 막는다.
관계도는 감정이 아니라 의사결정 변수다
호감도 하나만으로 모든 관계를 표현하면 상인이 무서워서 할인하는지 좋아해서 할인하는지 구분할 수 없다. 최소한 신뢰와 공포는 분리하는 편이 좋다.
NPC A가 NPC B를 대하는 관계 점수는 다음처럼 계산할 수 있다.
- : 신뢰도
- : 공포도
- : 길드·가문·진영의 이해관계 점수. 이 예시에서는 신뢰·공포와 같은
-100~100범위로 정규화한다.
계수와 범위는 밸런스 설계 예시이지 검증된 표준값이 아니다. 신뢰와 공포를 다른 범위로 저장한다면 먼저 같은 척도로 정규화하고, 결과 점수를 행동별로 별도 튜닝한다.
이 점수는 대사의 감정이 아니라 거래 수락, 도움 요청, 소문 확산, 공격 회피 같은 행동 가중치에 사용한다.
LLM NPC 간 상호작용을 어떻게 구현할까?
모든 NPC 대화를 실시간 LLM 호출로 처리하면 비용과 지연 시간이 빠르게 커진다. 플레이어와 직접 대화하는 핵심 NPC만 실시간 호출하고 NPC끼리의 상호작용은 이벤트 시뮬레이션과 요약 호출로 처리하는 것이 실용적이다.
1. 게임 규칙으로 행동 후보를 만든다
먼저 현재 상태에서 가능한 행동만 추린다. 예를 들어 상인은 재고가 있고 신뢰도가 일정 수준 이상일 때만 거래를 제안할 수 있다.
const actions = [
{ type: "offer_trade", requires: npc.wealth > 20 && playerTrust >= 20 },
{ type: "spread_rumor", requires: npcMemories.includes("player_committed_crime") },
{ type: "refuse_quest", requires: npc.fear >= 70 },
].filter((action) => action.requires);
2. LLM에는 선택권과 말투만 맡긴다
프롬프트에는 세계 요약, NPC 성향, 현재 사건, 허용된 행동 목록을 넣는다. 반드시 JSON 형식으로 응답하게 하고 서버에서 스키마를 검증한다.
{
"dialogue": "경비대가 당신을 좋게 보지는 않을 겁니다.",
"action": "spread_rumor",
"target": "market_district",
"reason": "범죄 목격 사실을 주변 상인에게 알린다"
}
LLM이 목록에 없는 행동을 반환하면 기본 행동인 idle 또는 continue_dialogue로 대체한다. 자연어 생성 실패가 게임 상태 손상으로 이어지지 않게 하는 안전장치다.
3. 규칙 엔진이 결과를 확정한다
spread_rumor가 선택되어도 즉시 모든 주민에게 적용하지 않는다. 발신 NPC의 신뢰도, 지역 전파율, 대상 진영의 성향으로 확률을 계산한다.
이 예시에서 T_speaker는 -100~100, 지역 전파 계수 I_region은 0~1로 둔다. 범위를 바꾸면 계수도 다시 조정해야 한다.
성공한 사건만 사회 이벤트 로그에 기록하고 다음 날 또는 구역 재진입 시 영향을 갱신한다. 플레이어는 대화의 결과를 상점 가격, 경비 반응, 새 퀘스트처럼 관찰 가능한 변화로 이해한다.
flowchart LR
A[플레이어 또는 NPC 사건] --> B[규칙 기반 행동 후보]
B --> C[LLM: 대사와 행동 선택]
C --> D[JSON 스키마·권한 검증]
D --> E[사회 규칙 엔진]
E --> F[관계·경제·퀘스트 상태 갱신]
F --> G[기억 요약과 다음 상호작용]
가상 사회 경제와 퀘스트를 어떻게 연결할까?
사회 시뮬레이션의 목표는 NPC가 스스로 문학적인 삶을 사는 것이 아니라 플레이어가 읽을 수 있는 선택지를 만드는 데 있다. 따라서 각 사회 변화는 적어도 하나의 게임 시스템에 연결해야 한다.
| 사회 사건 | 시스템 결과 | 플레이어가 체감하는 변화 |
|---|---|---|
| 광산 파업 | 광석 공급 감소 | 무기 가격 상승, 중재 퀘스트 생성 |
| 경비대장 신뢰 하락 | 치안 서비스 제한 | 통행 검사, 현상금 증가 |
| 상인 길드 호감 상승 | 거래 조건 개선 | 할인, 희귀 재료 정보 획득 |
| 소문 확산 | 지역 평판 변경 | NPC 대사와 퀘스트 접근 조건 변화 |
경제 수치는 무작위 대사보다 보수적으로 다뤄야 한다. 가격은 기준 가격에 공급·수요·평판 보정만 곱하는 정도로 시작할 수 있다.
이 예시에서 Demand와 Supply는 게임에서 정한 기준에 따라 정규화한 값이다. ReputationModifier를 0.6~1.4로 제한하고 최종 가격에도 게임의 최소·최대 범위를 적용한다. 수식과 한도는 설계 출발점이며 경제 시뮬레이션과 플레이 테스트로 조정해야 한다.
NPC 사회가 플레이어를 배제하지 않게 하려면?
NPC끼리만 사건을 만들면 플레이어는 이미 결정된 세계를 구경하게 된다. 사회 시뮬레이션은 플레이어가 개입할 수 있는 갈림길을 만들 때만 실행 가치가 있다.
- 사건이 발생하면 해결, 편들기, 방관 중 하나 이상의 선택지를 제공한다.
- 플레이어가 개입하지 않은 사건은 작은 수치 변화로 끝내고 핵심 퀘스트를 자동 실패시키지 않는다.
- 소문과 관계 변화는 지도, 일지, 대사 중 하나로 알려 준다. 보이지 않는 시스템은 플레이어에게 존재하지 않는 시스템과 같다.
- 중요한 결정은 LLM의 자유 생성이 아니라 명시적인 퀘스트 상태 전이로 처리한다.
밸런싱은 어떤 지표로 확인해야 할까?
LLM NPC 시스템은 대사가 자연스러운지만 보면 실패하기 쉽다. 테스트 로그에서 다음 지표를 확인한다.
| 지표 | 확인할 문제 | 권장 대응 |
|---|---|---|
| 행동 거부율 | 허용 행동이 너무 적거나 조건이 과도함 | 후보 조건 완화 또는 기본 행동 추가 |
| 무효 행동률 | LLM 선택이 규칙에서 자주 거부됨 | 프롬프트의 행동 설명과 JSON 검증 정렬 |
| 경제 변동폭 | 가격이 짧은 기간에 급등락함 | 공급·수요 계수와 상한 조정 |
| 퀘스트 도달률 | 사회 사건 때문에 핵심 진행이 막힘 | 필수 경로에 대체 조건 추가 |
| NPC 기억 토큰 수 | 호출 비용과 문맥 품질 저하 | 사건 요약 수 제한, 오래된 기억 압축 |
자주 묻는 질문 (FAQ)
LLM이 NPC의 모든 결정을 내려도 될까?
아니다. LLM은 대사와 제한된 행동 후보 선택에 쓰고 재화·전투·퀘스트·영구 평판 변경은 규칙 엔진이 확정해야 한다.
NPC마다 긴 대화 기록을 저장해야 할까?
아니다. 원문 대신 검증된 사건 요약과 핵심 관계 수치를 저장하면 비용, 모순, 개인정보성 텍스트 노출 위험을 줄일 수 있다.
작은 게임에도 가상 사회 시뮬레이션이 필요한가?
필요한 것은 완전한 시뮬레이션이 아니라 결과가 남는 상호작용이다. 핵심 NPC 3~5명과 하나의 지역 경제, 두세 개의 관계 이벤트만으로도 충분하다.
정리
LLM 챗봇 NPC의 가치는 끝없이 대화하는 데 있지 않다. 대화가 규칙을 거쳐 관계, 경제, 퀘스트에 작은 흔적을 남길 때 가상 사회가 된다. 처음에는 제한된 행동 집합과 작은 지역 하나로 시작하고 로그에서 플레이어가 실제로 읽고 활용한 변화를 확인한 뒤 확장하자.



