Gate of Toon 제작기
성좌 관전 테마 AI 웹툰 추천 및 자이로스코프 패럴랙스 연출

성좌 상태창 콘셉트의 메인 진입 화면
게이트 오브 툰 (Gate of Toon) 제작기
판타지 성좌(Constellation) 테마의 인터랙티브 AI 웹툰 추천 서비스 및 모노레포 구축기
1. 문제 정의 및 기획 배경
기존의 웹툰/웹소설 추천 서비스들은 대부분 장르별 단순 나열식 필터링에 그쳐 독자들이 정말 몰입할 수 있는 맞춤형 작품을 추천받기 어려웠습니다. 그러던 중 스무고개 게임인 '아키네이터(Akinator)'를 보다가, 최근 급격히 발전한 생성형 AI를 결합하면 어떨까 하는 생각이 들었습니다. 매번 똑같이 고정된 정적 질문을 던질 필요 없이, AI가 실시간으로 이전 답변 내용에 맞춰 매번 완전히 새로운 최적의 질문을 동적으로 생성해 낸다면 어떨까요? 모든 사람들에게 본인의 성향에 딱 맞는 입체적이고 세밀한 질문과 웹툰 성향 분석이 가능할 것이라는 확신을 갖고, 퓨전 판타지 소설에 자주 등장하는 '성좌 상태창' 콘셉트를 융합해 이 프로젝트를 시작했습니다.
2. 핵심 사양 및 구현 목표
- 개인 맞춤형 실시간 질문 생성: Gemini 2.5 Flash를 활용하여 유저의 고유 맥락을 기억하고 매번 다른 최적의 심리 테스트형 질문 피드백.
- 초저비용 고효율 인프라 설계: 유료 API 호출을 최소화하는 캐시 및 세션 시스템 설계와 클라이언트-서버 분산 연산.
- 인터랙티브 웹 환경 연출: 모바일 자이로 센서 물리 연동을 통한 화려한 3D 은하수 공간 및 실시간 성좌 댓글 반응 시뮬레이션.
- 핵심 기술 스택:
- Frontend: Vite, React, TypeScript, Tailwind CSS, HTML5 Canvas, DeviceOrientation API
- Backend: Node.js, Express, TS-Node, Google Generative AI SDK (Gemini 2.5 Flash)
- Database: Google Firebase / Cloud Firestore (NoSQL)
- State & Session: InMemory Session Store & Background Batch Queue
3. 기술 검증 및 트러블슈팅
[1단계] 클라이언트 태그 기반 랭킹 최적화
모든 질문 교환 때마다 API를 호출하는 낭비를 방지하기 위해, 웹툰 메타데이터의 장르/스토리/분위기 가중치 연산을 100% 프론트엔드 자바스크립트로 우선 처리하여 후보군을 실시간 리랭킹 및 압축했습니다.
[2단계] Express 백엔드와 Gemini API 라우팅 설계
Express 백엔드 내에 인메모리 sessionStore를 구축하여 유저별 ChatSession 객체를 연속적으로 유지하고, 최종 추천 단계에서 단 1회의 LLM 호출을 수행하도록 통합했습니다.
[3단계] 백그라운드 청크 배치 시스템 연동
신규 웹툰 업로드 시 AI가 백그라운드 데몬으로 돌며 Firestore 데이터를 50개 단위 청크로 파싱해 가중치 표준화 태그를 자동 동기화하도록 구현했습니다.
R&D 및 트러블슈팅
1. 8초 분기 연출 애니메이션과 API 응답 시점 싱크 오류
- 문제: 질문 완료 후 우주 포털 및 성좌 리액션 댓글 피드가 흐르는 웅장한 애니메이션이 약 8초간 실행되는데, API 응답이 2~3초 만에 너무 일찍 오면 애니메이션 도중 카드가 튀면서 몰입이 깨지는 결함이 발생했습니다.
- 해결: 프론트엔드의 8초 연출 시나리오 타이밍을 강제 고정하기 위해, API 수신 여부와 무관하게 연출 타이밍 루프(
delay-sync)를 8초로 강제 고정하여 영화 같은 몰입감을 유지했습니다.
2. 모바일 브라우저의 DeviceOrientationPermission 보안 정책 충돌
- 문제: 스마트폰 자이로 센서를 사용한 은하수 입체 Parallax 효과가 최신 iOS Safari 및 모바일 크롬 환경에서 보안 권한 요구 정책으로 인해 기능이 차단되고 콘솔 에러가 대거 발생했습니다.
- 해결: 사용자 최초 진입 닉네임 입력 화면에서 센서 권한 허용 상호작용을 자연스럽게 유도하는
RequestPermission체인을 구성하고, 센서가 없는 PC 환경에서는 마우스 좌표(clientX,clientY)를 물리값으로 대입하는 하이브리드 Parallax 훅을 개발해 크로스 플랫폼을 완벽 보장했습니다.
4. 핵심 기능 및 구현 코드
- 아키네이터 기반 동적 실시간 리랭킹: 각 웹툰의 다중 가중치 태그를 기반으로 한 로컬 가중치 누적 필터링을 통해 연산 비용 0원으로 최적의 후보군 압축.
- 백그라운드 AI 청크 태깅 엔진 (
attachAiTagsAndCache): 관리자의 수동 입력 리소스 없이 신규 웹툰의 표준화 태그 주입 및 Firestore 자동 동기화. - 초저비용 캐시 아키텍처 및 세션 보존 (
sessionStore): 추천 조합 및 AI 성좌 페르소나의 답변 결과물을 Firestore 캐시 테이블에 TTL과 함께 캐싱하여 유료 API 호출 최소화.
핵심 코드 (Express Backend Entry & Background Daemon Trigger)
// server.ts - Express 엔트리 포인트 및 백그라운드 태거 실행 import express from 'express'; import cors from 'cors'; import { GoogleGenerativeAI, ChatSession } from '@google/generative-ai'; import { Firestore } from '@google-cloud/firestore'; import { getRecommendation, attachAiTagsAndCache } from './geminiService'; const app = express(); const port = process.env.PORT || 8080; app.use(cors({ origin: 'https://gate-of-toon.web.app', credentials: true })); app.use(express.json()); const FIRESTORE_DATABASE_ID = 'gateoftoon-datebase'; const GEMINI_KEY = process.env.GEMINI_API_KEY || ''; const genAI = new GoogleGenerativeAI(GEMINI_KEY); const db = new Firestore({ databaseId: FIRESTORE_DATABASE_ID }); // 사용자별 AI 채팅 세션을 보존하는 인메모리 세션 스토어 const sessionStore = new Map< string, { chat: ChatSession; filterRate: number; candidateIds: string[] } >(); // 웹툰 메타데이터 및 ID를 저장하는 로컬 캐시 레이어 const webtoonCache = { allWebtoonIds: [] as string[], webtoonMetadata: new Map<string, any>(), }; // 추천 분석 및 성좌 페르소나 피드백 API app.post('/api/recommend', async (req, res) => { const { sessionId, candidateIds, history, message } = req.body; if (!message) return res.status(400).send({ error: 'Message is required.' }); try { const resultObject = await getRecommendation( db, genAI, { sessionId, candidateIds, history: history || [], message }, sessionStore, webtoonCache ); res.status(200).json(resultObject); } catch (error) { console.error('Gemini API 추천 실패:', error); res.status(500).send({ error: 'Failed to process AI request.' }); } }); // 서버 기동 및 백그라운드 배치 큐 호출 app.listen(port, () => { console.log(`🚀 Server listening at http://localhost:${port}`); // 사용자 메인 스레드를 블로킹하지 않고 비동기로 메타데이터 자동 AI 태깅 기동 attachAiTagsAndCache(db, genAI, webtoonCache); });
5. 미래 확장성 및 고도화 계획
- 개인 선호 분석 보고서 소셜 미디어(SNS) 공유 카드 이미지 생성
- Gemini API 다중 챗 세션 만료 및 메모리 자동 GC(Garbage Collector) 튜닝