PostgreSQL + pgvector: 실전에서 ORM과 벡터 검색 붙이기
Prisma의 driver adapter, NestJS의 모듈 구조, pgvector의 하이브리드 시맨틱 검색을 한 스택에 얹어본 기록. migrate dev 가 HNSW 인덱스를 지워 온 이유, 감쇠를 SQL 밖으로 뺀 이유, PostgreSQL 18 에서 기대와 실제가 갈린 지점을 정리했다.
개발 경험과 인사이트를 공유합니다
Prisma의 driver adapter, NestJS의 모듈 구조, pgvector의 하이브리드 시맨틱 검색을 한 스택에 얹어본 기록. migrate dev 가 HNSW 인덱스를 지워 온 이유, 감쇠를 SQL 밖으로 뺀 이유, PostgreSQL 18 에서 기대와 실제가 갈린 지점을 정리했다.
브라우저 EventSource는 GET밖에 못 보낸다. 이 제약을 fetch + ReadableStream으로 우회하고, Zustand 스토어를 비즈니스 로직과 UI 상태로 쪼갠 뒤 TanStack Query와 붙인 실시간 AI 채팅 프론트엔드 이야기다.
플릿 초기(2026년 3월)의 3모드 설계 기록이다. 감독형(스토리), 목적형(토크룸), 관계형(캐릭터 챗) AI 의 프롬프트 빌더 분기, 캐릭터 독립 엔티티 설계, 모드별 메모리 전략을 다룬다. 현재 플릿은 1:1 캐릭터 챗 하나로 운영한다.
1:1 AI 캐릭터 채팅 플랫폼의 전체 아키텍처를 설계하며 내린 판단들을 정리했다. NestJS 11 + Next.js 16 pnpm 워크스페이스 모노레포와 @plit/shared 공유 패키지, Render + Vercel + Upstash + Clerk + R2 로 짠 관리형 인프라 조합, 캐릭터를 독립 엔티티로 두고 관계를 (user_id, character_id)에 거는 스키마, 그리고 운영 가능성을 기준으로 삼은 트레이드오프를 다룬다.
LLM의 컨텍스트 윈도우를 넘어서는 장기 기억을 어떻게 만들었나. 사용자×캐릭터 단위로 5건마다 시도하는 AI 요약과 Gemini 768차원 임베딩, pgvector 코사인 유사도와 tsvector 키워드 검색을 대화 순번 감쇠로 재랭킹해 RRF로 병합하고, 중요도 예약 슬롯과 함께 최대 12개를 주입하는 설계를 정리했다.
한국어에는 자모 분리, 공백 삽입, 유니코드 정규화 차이처럼 이 언어에만 열려 있는 우회 경로가 있고, 공백을 지우면 멀쩡한 문장이 금지어처럼 보이는 오탐도 생긴다. 4단계 정규화와 자모 조합 알고리즘, 어절 경계 검사로 키워드를 맞추고, 문맥을 못 보는 키워드 대신 LLM 심사기가 판정하도록 입력과 출력을 설계한 과정을 적었다.
AI 캐릭터의 한마디는 어떻게 만들어지는가. 컨텍스트 빌드, 응답 생성, 턴 마무리 3단계 파이프라인부터 생성과 병렬로 도는 입력 안전 심사, 스트리밍 JSON 추출, POST-based SSE, 용도별 모델 배정, 화면 도달량 기준 환불까지 1:1 캐릭터 챗 대화 엔진의 설계를 기록했다.
Google Safe Browsing이 도메인 전체에 경고를 붙인 인시던트. 악성 단축 URL 즉시 차단, Safe Browsing API 사전 검증 연동, DB 트리거 기반 영구 차단까지 방어를 3단계로 쌓은 과정을 적었다.