RAG 기반 AI 서비스는 어떻게 도는가
모델 API는 어디서 호출되고, DB는 어떻게 구성되며, 각 역할이 어떻게 맞물려 도는지 — 실제 배포된 서비스들의 요청 생명주기 전체를 한 장에.
OpenAI·Claude·ElevenLabs 호출은 전부 Vercel 함수(/api/*) 안에서만. 키는 브라우저에 절대 안 감.
질문을 임베딩→유사도 검색으로 '근거'를 찾고, 그 근거를 프롬프트에 넣어 LLM이 답하게 한다.
지식(벡터 스토어) + 운영 데이터(대화로그·인텔·FAQ). Supabase Postgres에 RLS로 안전하게.
📐 한눈에 보는 구조 모형도
① 입력부터 ⑩ 응답까지 — 모델 API·DB가 어디서 붙는지 한 장(PPT 형식)으로.

요청 생명주기 — 단계별 상세
사용자가 질문하면 → 아래로 흐릅니다. 오른쪽은 그 단계가 부르는 모델 API · DB.
텍스트 · 🎙 음성 · 📍 위치(GPS) 입력. React(Next.js) 화면. — 키는 절대 여기 없음.
오케스트레이터 라우트. 여기서부터 서버(비공개). 모든 모델 API 호출은 이 안에서만 일어남(키 노출 0).
녹음 오디오(Blob)를 텍스트로 변환.
질문 문장을 1536차원 벡터로 변환 — 의미 검색의 좌표.
질문 벡터와 문서 벡터의 코사인 유사도로 관련 청크 K개 + 출처를 뽑음.
시스템 프롬프트 + 검색된 컨텍스트(근거) + 대화 history를 하나로 합침. — RAG의 'R'과 'G'를 잇는 지점.
근거를 바탕으로 답 생성. 필요 시 실시간 웹검색, 2차 자기검증(리플렉션)으로 사실성 강화.
근거 밖 주장 억제, 모르면 모른다고. 검색 청크의 출처(코드/문서)를 답에 함께 노출.
답변을 복제된 목소리(Hans17 voice)로 음성 합성.
텍스트 답변(+출처) + 오디오를 클라이언트로 스트리밍/반환. 대화 로그는 DB에 적재.
지식 인제스션 (임베딩 파이프라인)
검색이 되려면, 먼저 문서를 벡터로 만들어 저장해 둬야 합니다. 이건 요청과 별개로 미리 1회.
DB는 어떻게 구성되나
DB는 두 역할 — 지식(벡터) 과 운영 데이터. 접근은 RLS로 통제.
service_role 키로만같은 뼈대, 3가지 Type
위 파이프라인은 공통. 벡터를 어디에 두느냐 / 입력이 무엇이냐에 따라 세 갈래로 나뉩니다.
빌드 타임에 문서를 임베딩해 embeddings.json으로 번들. 런타임엔 메모리에서 코사인 유사도 계산. 별도 벡터 인프라·종속 없음.
소~중규모 지식(강의노트·가이드). 배포 초간단, 이식 쉬움.
임베딩을 Supabase Postgres의 pgvector에 저장(ivfflat 인덱스). 런타임엔 SQL 벡터 검색으로 Top-k. 대용량·증분 업데이트에 강함.
대규모 코퍼스, 계속 늘어나는 지식, 다중 사용자.
이미지를 Vision 모델로 분석해 구조화 텍스트로 변환 → 그 결과를 텍스트 RAG 파이프라인(4~8단계)에 그대로 태움.
사진·실측 등 비텍스트 입력이 핵심인 현장 서비스.
역할 · API · 키 한눈에
| 구성요소 | 역할 | 호출 위치 | 키(env) |
|---|---|---|---|
| OpenAI Embeddings | 질문·문서를 벡터로 | 서버(/api) | OPENAI_API_KEY |
| Anthropic Claude | 답변 생성 · 웹검색 · 리플렉션 | 서버(/api) | ANTHROPIC_API_KEY |
| ElevenLabs | STT(듣기) · TTS(내 목소리) | 서버(/api) | ELEVENLABS_API_KEY |
| Supabase Postgres | 벡터 스토어(pgvector) + 운영 데이터 | 서버(/api) | SUPABASE_* (service_role) |
| Vercel Function | 오케스트레이터 · 모든 API 중계 | Vercel(Fluid) | — |
| 브라우저 | 입력·재생 · GPS/날씨 직호출 | 클라이언트 | 키 없음 |
핵심: 모델 API·DB 접근은 전부 서버(Vercel 함수)에서. 브라우저는 키를 모르고, 오직 결과만 받습니다.
