창조주의 교차점 제작기
온보딩 성향 추천 및 턴제 D&D 룰 전투 시뮬레이터

구글 AI 스튜디오 API 연동 및 캐릭터 커스터마이징 온보딩 인터페이스 화면
창조주의 교차점 (Creator's Intersection) 제작기
온디바이스 AI(WebLLM) 가상화 기술 및 IndexedDB 오프라인 미디어 분산 캐싱을 테스트하는 턴제 TRPG R&D 샌드박스
1. 문제 정의 및 기획 배경
본 프로젝트는 원래 '나만의 몬스터 생성기(MMM)'와 같은 대형 서비스를 개발하기 전, 브라우저 단독으로 작동하는 온디바이스 인공지능(On-Device AI) 제어 기술과 대용량 미디어의 오프라인 분산 캐싱 성능을 사전 검증하기 위한 R&D 실험작으로 출발했습니다. 초기에는 Google AI Studio API와 로컬 환경을 간단히 연동해보는 수준이었으나, 브라우저 LocalStorage의 5MB 용량 한계를 우회하는 데이터 적재 기법과 주사위 판정(d20 시스템)을 탑재한 턴제 시뮬레이션 메커니즘을 결합하면 훌륭한 독립 게임 엔진이 될 수 있겠다는 확신이 들었습니다. 유저의 기획 의도에 맞춰 동적으로 성향과 세부 설정이 파생된다는 매력을 강조하기 위해 '창조주의 교차점(Creator's Intersection)'이라는 타이틀을 명명하고, 핵심 기능인 AI 엔진 스위칭과 오프라인 데이터 유지 아키텍처를 구축해 고도화했습니다.
2. 핵심 사양 및 구현 목표
- Google AI Studio 기반 대화형 온보딩: 구글 AI 스튜디오 API를 통해 유저 성향과 가치관을 실시간 분석하고, 맞춤형 모험가 캐릭터 스펙 및 스토리를 빌드하는 동적 질문 알고리즘 구현.
- Vibe Coding 한계 극복 및 아키텍처 구조화: AI 응답을 단순 텍스트가 아닌 JSON 포맷 및 상태별 흐름으로 격리하여, 스파게티성 바이브 코딩에서 탈피하고 결합도를 낮추는 구조적 리팩터링 실행.
- API 호출 비효율 개선 및 캐싱: 불필요한 타이밍의 API 재호출을 차단하기 위한 상태 보존 로직과, 5MB 브라우저 한계를 넘는 고화질 아트워크 데이터 보존용 IndexedDB 분산 스토어 설계.
- 핵심 기술 스택:
- Frontend: React, TypeScript, Tailwind CSS
- AI Core: Google AI Studio API (Gemini 1.5/2.5 Pro & Flash)
- Database & Storage:
idb(IndexedDB Wrapper) - State Management: React State & Context Pattern
- Battle Engine: 제너레이터 기반 비동기 턴제 전투 모듈
3. 기술 검증 및 트러블슈팅
[1단계] Google AI Studio API 연동 및 프롬프트 제어
구글 AI 스튜디오 인스턴스를 수립하여, 프롬프트 엔지니어링을 통해 유저의 주관식 답변으로부터 정형화된 캐릭터 성향 스키마를 추출해내는 비동기 서비스 레이어를 구현했습니다.
[2단계] IndexedDB 분산 적재 및 LRU 만료 정책 수립
LocalStorage의 5MB 벽을 돌파하기 위해 IndexedDB 래퍼인 idb 라이브러리를 바인딩하고, 디스크 용량이 꽉 차면 가장 오래된 데이터를 밀어내는 LRU 캐시 모듈(imageStore.ts)을 완성했습니다.
[3단계] d20 정밀 주사위 전투 시스템 설계
공격의 명중률 및 회피율을 d20 주사위 난수와 연계 판독하고, 최소 대미지 1을 보장하는 대미지 가중 계산 공식을 이식했습니다.
R&D 및 트러블슈팅
1. 바이브 코딩의 구조적 한계와 비효율적인 API 과호출 결함
- 문제: Google AI Studio API를 처음 적용하는 과정에서 명확한 상태 제어와 모듈 분리 없이 코드를 즉흥적으로 구현(바이브 코딩)하다 보니, 기능 간의 결합도가 극도로 높아졌습니다. 이로 인해 컴포넌트 리렌더링이나 경미한 상태 변화 시에도 불필요하게 Gemini API를 과도하게 반복 호출하여 API 응답 지연과 비용 낭비가 초래되었습니다. 또한 초기 R&D 단계에서 완전한 클라이언트 단독 구동을 위해 온디바이스 LLM(WebLLM) 탑재를 검토 및 구현해보았으나, 한국어 시나리오 이해도가 크게 떨어지고 모바일 환경에서 논리적 판단 성능이 현격히 부족함을 실감하여 결국 최종 온디바이스 도입은 폐기하게 되었습니다.
- 해결:
- API 호출 레이어 격리 및 프록시 상태 캐싱: 온보딩 진입 상태와 응답 데이터를 React Context 및 커스텀 훅으로 안전하게 바인딩하여 데이터가 확정되기 전까지는 API 호출이 절대 중복 발생하지 않도록 차단 장치를 마련했습니다.
- 가상 시나리오 가중치 매핑 헬퍼(abilityGenerator.ts): 오프라인 상태나 API 한계치 도달 시의 대응을 위해, 유저가 입력한 이름/무기/성격 설정 가중치 매핑 행렬을 바탕으로 비용 0원으로 고유 등급(E~SS)과 시나리오 대사를 즉시 렌더링하는 가상 생성 엔진 구조를 대안으로 구축했습니다.
2. 전투 시뮬레이션의 비동기 속도 폭주 및 리액트 스레드 마비
- 문제: 전투 모의 루프가 지연 없이 연속으로 실행되면, 연산이 너무 빨라 유저가 전투 상황을 모니터링하기 어려웠고, 초당 수백 번의 상태 업데이트가 일어나 리액트 컴포넌트 렌더링 스레드가 통째로 멈춰 서는 문제가 발생했습니다.
- 해결: 제너레이터 함수(
function*) 패턴 and 비동기 딜레이 Promise를 적용하여 각 전투 턴 사이에 0.8초의 시각적 간격을 주입했습니다. 또한 전투 로그가 100줄을 넘어가면 큐(Queue) 구조로 오래된 로그를 메모리에서 순차 버리는 버퍼 제어 필터를 구현하여 렌더링 부하를 제로화했습니다.
4. 핵심 기능 및 구현 코드
- Google AI Studio 연동 및 가상 시나리오 엔진: 고해상도 질문 흐름을 통해 캐릭터를 정교히 생성하고, API 제한이나 오프라인 상태에서는 자체 매핑 알고리즘 기반의 가상 0원 생성 지원.
- IndexedDB 기반 이미지 분산 캐싱 레이어 (
imageStore.ts): 브라우저 LocalStorage 한계(5MB)를 우회하여 수백 장의 캐릭터 이미지를 인덱싱 및 적재 가능. - d20 정밀 물리 전투 시스템: 암호학적 난수 API(
crypto.getRandomValues)를 연계하여 주사위 눈의 편향 없는 공정한 확률 판정 구현.
핵심 코드 (IndexedDB Image Caching Layer)
// imageStore.ts - idb를 활용한 오프라인 이미지 캐싱 import { openDB, IDBPDatabase } from 'idb'; const DB_NAME = 'CreatorNexusDB'; const STORE_NAME = 'ImageStore'; const DB_VERSION = 1; let dbPromise: Promise<IDBPDatabase> | null = null; // 데이터베이스 초기화 및 업그레이드 const initDB = (): Promise<IDBPDatabase> => { if (dbPromise) return dbPromise; dbPromise = openDB(DB_NAME, DB_VERSION, { upgrade(db) { if (!db.objectStoreNames.contains(STORE_NAME)) { db.createObjectStore(STORE_NAME); } }, }); return dbPromise; }; // Base64 이미지 데이터 저장 export const setImage = async (key: string, value: string): Promise<void> => { const db = await initDB(); await db.put(STORE_NAME, value, key); }; // Base64 이미지 데이터 조회 export const getImage = async (key: string): Promise<string | undefined> => { const db = await initDB(); return await db.get(STORE_NAME, key); }; // 다중 이미지 데이터 삭제 (트랜잭션 관리) export const deleteImages = async (keys: string[]): Promise<void> => { if (keys.length === 0) return; const db = await initDB(); const tx = db.transaction(STORE_NAME, 'readwrite'); await Promise.all([...keys.map((key) => tx.store.delete(key)), tx.done]); };
5. 프로젝트 보관 사유 및 깨달은 점
본 프로젝트는 구글 AI 스튜디오 API 연동과 d20 주사위 룰 전투 시뮬레이션의 핵심 가능성을 검증했으나, 초기 아키텍처 설계의 한계로 인해 무리하게 확장을 이어가기보다 실험 보관(Archived) 상태로 전환했습니다.
- 바이브 코딩의 뼈아픈 한계: 체계적인 데이터 스키마 정의나 역할 분담 없이 "일단 작동만 하면 된다"는 식으로 즉흥적으로 개발(Vibe Coding)을 지속했을 때, 기능이 늘어날수록 코드 결합도가 극도로 치솟는 부채를 직접 경험했습니다. 특히 리액트 리렌더링 흐름과 연동되어 불필요한 Gemini API 호출이 반복적으로 발생하는 비효율을 겪으며, 비동기 데이터 통신과 클라이언트 상태를 선제적으로 설계하고 엄격히 통제하는 법을 배웠습니다.
- 서버 비용 제로를 위한 온디바이스 AI 시도와 타협: 초기 개발 시에는 API 비용 문제를 고려하지 않았으나, 프로젝트를 정식 서비스 수준으로 기획을 확장하면서 실시간 AI 호출에 따른 막대한 누적 비용 문제를 체감했습니다. 이를 해결하고자 프론트엔드 단독으로 구동되는 온디바이스 AI(WebLLM) 접목을 시도했으나, 모바일 브라우저의 가용 RAM 한계(OOM)와 당시 소형 LLM의 낮은 한국어 논리력 때문에 도입을 폐기했습니다. 이를 통해 무작정 비용 절감만을 쫓기보다 타겟 유저 디바이스의 하드웨어 제약과 언어 모델 성능 등 현실적 환경을 종합 판단하는 법을 배웠습니다.
- 안전한 보관과 차기 설계의 이정표: 꼬인 스파게티 코드 구조 위로 무리하게 3D 물리 캔버스나 심화 콘텐츠를 추가하기보다, R&D 마일스톤으로 가치를 보존한 채 보관을 결정했습니다. 이때 해결하고자 고민했던 IndexedDB 활용 대용량 파일 캐싱 기법, 비동기 전투 제어용 Generator 함수 패턴 등은 고스란히 차기작들의 든든한 기술적 초석이 되었습니다.