플릿(Plit) - AI 캐릭터 채팅 플랫폼
링크
스크린샷
플릿 메인 화면
프로젝트 개요
플릿(Plit)은 사용자가 캐릭터를 골라 1:1로 대화하는 AI 캐릭터 채팅 플랫폼입니다. 남성 캐릭터 중심의 여성향은 10~30대 여성(웹소설·오토메 독자, 연애 리얼리티 시청자)을, 여성 캐릭터 중심의 남성향은 10~30대 남성(웹소설·웹툰 독자, 서브컬처·수집형 게임 이용자)을 타겟으로 하며, 성향은 이용자가 직접 고릅니다.
호감도 6단계와 케미 스킬 해금, 대화 세션을 넘어 유저×캐릭터 단위로 이어지는 장기 기억, 답이 끊기면 캐릭터가 먼저 말을 거는 넛지를 제공합니다.
용도별 LLM 배정 파이프라인(Gemini 중심, 무배포 교체), pgvector RRF 하이브리드 기억 검색, 젬 단일 재화와 TossPayments 결제, LLM 판정 중심의 한국어 콘텐츠 안전 정책, POST-based SSE 스트리밍을 서비스 기획부터 인프라·운영까지 1인 풀스택으로 구축·운영 중입니다.
담당 역할
풀스택 개발 (서비스 기획 → 시스템 아키텍처 설계 → DB 모델링 → AI 파이프라인 구현 → 프론트엔드/백엔드 구현 → 인프라 구성 → 운영)
주요 기능
- 1:1 캐릭터 챗 아키텍처 (세션은 유저×캐릭터 대화방에만 귀속, 그룹챗은 예정)
- 캐릭터 독립 엔티티 설계 (원본은 characters, 유저별 관계·호감도·기억은 유저×캐릭터 키 테이블로 분리, 작품과 N:M)
- 여성향·남성향 성향 축 (캐릭터마다 성향을 지정하고, 첫 방문 시 고른 성향으로 홈·탐색 노출을 가름)
- 용도별 모델 배정 AI 파이프라인 (입력 안전 판정 → 응답 스트리밍 생성 → 상태 갱신, 모델은 llm_task_assignments 로 배포 없이 교체)
- POST-based SSE 실시간 스트리밍 (JSON 항목 점진적 파싱, 나레이션·대사·호감도 변동을 청크 단위 즉시 전달)
- pgvector + Gemini 임베딩 기반 장기 기억 (벡터·전문 검색 RRF 병합, 유저×캐릭터 단위 유지, 턴당 최대 12개 주입 중 고중요도 2슬롯 예약)
- 호감도 6단계 시스템 (-1~5, 0 없음, 레벨별 케미 스킬 해금, AI 평가 기반 점수 산정)
- 호감도 변동 제어 (레벨별 승수·하드캡, 부정 이벤트 후 회복 곡선, 깊은 음수 소프트 플로어, affinitySnapshot 기반 되감기 복원)
- 콘텐츠 안전 시스템 (카테고리별 3단계 위험도, 판정은 LLM 평가 한 곳에서 결정, 키워드는 검토 큐와 턴 보류만, 제재는 관리자 수동)
- 젬 단일 재화(로트 원장) + TossPayments 결제 (선차감-환불 패턴, 소비 거래 ID 기반 멱등 환불, 서버 측 결제 승인 → 젬 자동 충전)
- Plit+ 구독 시스템 구현 (월간/연간 플랜, 월간 젬 자동 충전, 구독 만료 cron 처리. 출시 전)
- Redis 락 기반 기억 생성 중복 방지 (인스턴스 간 단일 실행 보장)
- 콘텐츠 관리 어드민 (캐릭터·작품·시작 지점·이미지 CRUD, 모델 배정·재화 단가 무배포 변경, 감사 로그)
- 2단계 Rate Limiting (IP 미들웨어 전역 300req/60s + 엔드포인트별 4-tier 사용자 제한)
- PWA + Web Push 알림 (커스텀 Service Worker, 오프라인 폴백, 미응답 세션 자동 넛지: 세션당 횟수·쿨다운 제어)
- Cloudflare R2 이미지 스토리지 (캐릭터 WebP 이미지 업로드·서빙, 개발/프로덕션 버킷 분리)
- 관리자에서 버튼 한 번으로 캐릭터·이미지 자동 생성 (캐릭터 설정 JSON 과 고유 스킬을 LLM 이 생성, 외모 설명을 번역해 이미지 생성 후 WebP 로 R2 업로드)
- 무응답 사용자에게 캐릭터가 먼저 말 거는 자동 알림 (2분 주기 cron, 3분 이상 무응답 대상, 하루 2회 제한)
기술 스택
기술적 의사결정
- AI 파이프라인 설계: 입력 안전 판정 → 응답 JSON 스트리밍 → 상태 갱신(호감도 평가·기억 생성)으로 구성하고, 실패 시 턴 단위 멱등 환불로 복구를 구조화함
- 한국어 키워드 탐지: NFC 정규화·분리 자모 결합·공백 제거 비교로 우회를 잡되, 키워드 단독으로는 막지 않고 LLM 문맥 판정이 나올 때까지 턴을 보류함
- 장기 대화 맥락 유지: pgvector + Gemini 임베딩 + RRF 하이브리드 검색으로 유저×캐릭터 기억 중 관련 항목만 주입하고, 고중요도 기억 2슬롯을 검색과 무관하게 예약함
- 젬 트랜잭션 정합성: 선차감 → 응답 생성 → 실패 시 소비 거래 ID 기반 멱등 환불로 재화 손실 없는 과금 구조를 구현함
- 모델 비용 최적화: 응답 생성은 Flash, 평가·기억·안전 판정은 Flash Lite 로 용도별 배정하고, 배정 테이블로 배포 없이 교체함
- 호감도 인플레이션 방지: 레벨별 승수·하드캡과 회복 곡선으로 상승을 제어하고, affinitySnapshot 으로 되감기 시 호감도를 복원함
관련 글
- AI 채팅 플랫폼 풀스택 아키텍처 설계: NestJS + Next.js 모노레포와 인프라 전략
1:1 AI 캐릭터 채팅 플랫폼의 전체 아키텍처를 설계하며 내린 판단들을 정리했다. NestJS 11 + Next.js 16 pnpm 워크스페이스 모노레포와 @plit/shared 공유 패키지, Render + Vercel + Upstash + Clerk + R2 로 짠 관리형 인프라 조합, 캐릭터를 독립 엔티티로 두고 관계를 (user_id, character_id)에 거는 스키마, 그리고 운영 가능성을 기준으로 삼은 트레이드오프를 다룬다.
- AI 캐릭터 플랫폼의 3모드 아키텍처: 감독형·목적형·관계형 AI
플릿 초기(2026년 3월)의 3모드 설계 기록이다. 감독형(스토리), 목적형(토크룸), 관계형(캐릭터 챗) AI 의 프롬프트 빌더 분기, 캐릭터 독립 엔티티 설계, 모드별 메모리 전략을 다룬다. 현재 플릿은 1:1 캐릭터 챗 하나로 운영한다.
- AI 캐릭터 대화 엔진 설계: 3단계 파이프라인과 실시간 스트리밍
AI 캐릭터의 한마디는 어떻게 만들어지는가. 컨텍스트 빌드, 응답 생성, 턴 마무리 3단계 파이프라인부터 생성과 병렬로 도는 입력 안전 심사, 스트리밍 JSON 추출, POST-based SSE, 용도별 모델 배정, 화면 도달량 기준 환불까지 1:1 캐릭터 챗 대화 엔진의 설계를 기록했다.
- pgvector 하이브리드 검색과 RRF 로 만든 AI 캐릭터 장기 기억
LLM의 컨텍스트 윈도우를 넘어서는 장기 기억을 어떻게 만들었나. 사용자×캐릭터 단위로 5건마다 시도하는 AI 요약과 Gemini 768차원 임베딩, pgvector 코사인 유사도와 tsvector 키워드 검색을 대화 순번 감쇠로 재랭킹해 RRF로 병합하고, 중요도 예약 슬롯과 함께 최대 12개를 주입하는 설계를 정리했다.
- 한국어 AI 콘텐츠 안전 필터링: 유니코드 정규화부터 키워드와 LLM 심사의 두 겹 판정까지
한국어에는 자모 분리, 공백 삽입, 유니코드 정규화 차이처럼 이 언어에만 열려 있는 우회 경로가 있고, 공백을 지우면 멀쩡한 문장이 금지어처럼 보이는 오탐도 생긴다. 4단계 정규화와 자모 조합 알고리즘, 어절 경계 검사로 키워드를 맞추고, 문맥을 못 보는 키워드 대신 LLM 심사기가 판정하도록 입력과 출력을 설계한 과정을 적었다.
- POST로 SSE를 받고 Zustand를 둘로 나눈 실시간 채팅 구조
브라우저 EventSource는 GET밖에 못 보낸다. 이 제약을 fetch + ReadableStream으로 우회하고, Zustand 스토어를 비즈니스 로직과 UI 상태로 쪼갠 뒤 TanStack Query와 붙인 실시간 AI 채팅 프론트엔드 이야기다.
- PostgreSQL + pgvector: 실전에서 ORM과 벡터 검색 붙이기
Prisma의 driver adapter, NestJS의 모듈 구조, pgvector의 하이브리드 시맨틱 검색을 한 스택에 얹어본 기록. migrate dev 가 HNSW 인덱스를 지워 온 이유, 감쇠를 SQL 밖으로 뺀 이유, PostgreSQL 18 에서 기대와 실제가 갈린 지점을 정리했다.