LLM API + RAG 서빙 아키텍처

obok·2025년 6월 12일

DL

목록 보기
3/8

이 내용은 팀프로젝트 진행하는데 필요했던 내용을 스터디하면서 내가 한땀한땀 노션에 정리했던 자료로,
정리하게 된 배경은
팀원분이 FastAPI + SQLite 기반으로 구조를 제안하셨는데
우리가 하고자 하는 게 LLM 기반 서비스여서 내가 확장성과 검색 기능이 강화된 RAG 기반 구조를 제안했기 때문..
생각보다 의견 조율이 쉽지 않아서 각각이 어떤 것이고 왜 필요한지 이해를 돕고 설명을 하기 위함이라 다소 중복되는 내용이 있을 수 있다.

AI Serving

: FastAPI가 중심이 되어, 사용자 질문을 임베딩 + Weaviate로 의미 기반 검색 + LLM 답변 생성 + DB 저장, React 프론트와 통신하는 구조

개념 정리

1. LLM 작동의 4대 핵심 요소

LLM에서는 단순히 모델 구조뿐 아니라 "사용자 입력 → 내부 처리 → 출력 → 학습 데이터"가 유기적으로 설계되어야 함

단계구성 요소설명왜 중요한가
1단계사용자 입력
(User Prompt)사용자가 실제로 입력하는 문장이나 질문잘 설계되지 않으면 모델이 오작동하거나 의미를 제대로 이해 못 함
2단계내부 처리
(Internal Prompt Handling / Preprocessing)입력을 토큰화, 전처리하거나 시스템 프롬프트/컨텍스트를 설정하는 부분컨텍스트가 모델의 "생각 흐름"을 결정함
3단계출력 (Model Output)LLM이 생성한 응답, 요약, 분류 결과 등응답의 신뢰도와 일관성 확보가 필요
4단계학습 데이터
(Training/Fine-tuning Data)모델이 학습하거나 미세 조정할 때 사용한 데이터도메인 특화 성능은 여기에 달려 있음

2. 임베딩 모델이란?

"문장을 숫자로 바꿔주는 모델"

사용 예시)
"딸이 부모를 부양 안 하면 상속 못 받나요?"
→ 이 문장은 LLM이 쓰기엔 너무 추상적이니까
숫자 벡터(768차원짜리 벡터 등)로 바꿔서 Weaviate에 넣음
이렇게 바꾸는 일을 하는 모델이 바로 임베딩 모델

📌 HuggingFace에서는 sentence-transformers/paraphrase-MiniLM-L6-v2 같은 모델이 이 역할을 함

궁금했던 내용 Q&A

1. 학습 데이터 10만개는 적절한 수준인가?

사전 학습용, 즉 baseline 언어모델을 직접 처음부터 학습시키려면 수십억~수천억 토큰 단위의 데이터가 필요

Instruction Fine-tuning / Supervised Fine-tuning

: 이미 사전학습된 LLM (예: LLaMA, GPT2, Mistral 등)에 도메인 지식을 주입

데이터 양 (텍스트 쌍 기준)기대 수준
~1만 개소규모 실험용, 빠른 프로토타입 가능
1만~5만 개적응 시작, 특정 태스크 성능 향상
5만~10만 개도메인에 꽤 잘 적응, 실제 서비스 적용 가능
10만~50만 개일반적 파인튜닝 상한선, 고품질이면 LLM이 도메인 전문가처럼 동작함
100만 개 이상특수 대규모 서비스나 논문 연구 수준, 많은 비용/시간 필요

Classification / 감정 분석 / 요약 같은 Downstream Task Fine-tuning

ERT, RoBERTa, T5, KoBERT 등에 텍스트 분류, 요약, QA 태스크 적용

데이터 양기대 성능
5천 개 이하overfitting 주의, baseline 모델용
1만~5만 개꽤 괜찮은 성능, Kaggle 수준 대회 가능
5만~10만 개업계 실무 기준, 모델 안정성↑
10만 개 이상확실한 성능 확보, 다양한 조건 대응 가능

RAG 벡터 검색용 Knowledge Base 구축

문서를 임베딩해 검색 가능한 DB 구축 (예: 판례, 논문, 블로그 등)

중요한 건 데이터 “양”보다 “질” + 문서 길이와 다양성

예: 짧은 Q&A만 있는 10만 개보단, 풍부한 문맥을 담은 3만 개 판례

문서 수 (텍스트 단위)용도
1천~5천 개테스트 및 데모 수준
5천~2만 개소규모 서비스 가능
2만~10만 개일반적인 프로덕션 수준
10만~100만 개 이상대규모 서비스 또는 기업 내부 지식관리

GPT 추천 수준

상황적절한 데이터 양
시니어 법률 자문 서비스 Instruction 튜닝5만~10만 개 질문-답변 쌍 (도메인 맞춤형)
판례 벡터 DB 구축 (RAG용)2만~10만 개 판례 또는 문단 수준 문서
법률분야 분류 모델1만~5만 개 라벨링 텍스트

2. FastAPI + SQLite / FastAPI + REST + Weaviate + GraphQL + PostgreSQL 구조를 비교하면?

구성 비교

구성FastAPI + SQLite 구조제안하는 구조
API 서버FastAPI 단독FastAPI (역할 분리)
DBSQLiteSupabase(PostgreSQL) + Weaviate
AI 모델FastAPI에서 로딩HuggingFace LLM + 벡터 검색(RAG)
문서 검색❌ 불가✅ Weaviate (의미기반 검색)
정형 정보 조회SQL 직접 쿼리✅ GraphQL API로 빠르게 조회
히스토리 저장SQLite 파일✅ 실시간 저장 + 조회 (Supabase)

제안하는 이유

문서 의미 검색불가Weaviate로 RAG 구현
AI 모델 추론로딩 가능하나 컨텍스트 제한문서 + 질문 기반 고도화
데이터 저장단일 파일, 병렬 처리 어려움Supabase로 실시간 + 안정 저장
사용자 경험직접 SQL만 가능GraphQL + React 최적화
확장성단일 개발/로컬 테스트용팀 개발, MVP, 서비스 확장까지 가능

상세 구조

[사용자 화면]
   ↓ 질문 입력

[React + TypeScript + Docker] 프론트
   ↓ FastAPI 백엔드에 요청 (REST 스타일) (: `/recommend`, `/history`, `/query`)

────────────────────────────────────
[FastAPI 백엔드 서버]
├─ `/recommend`LLM 기반 판례 추천 : [FastAPI → Weaviate + LLM → 답변 생성]
│   ├─ HuggingFace sentence-transformers → 질문 임베딩
│   ├─ Weaviate 벡터 DB → 유사 판례 문서 검색
│   ├─ HuggingFace LLM → 검색 문서 + 질문으로 답변 생성
│   ├─ Supabase PostgreSQL → 질문/답변 기록 저장
│   └─ 결과 응답 → 프론트로 반환

├─ `/history`  → 사용자 히스토리 불러오기 : [FastAPI → Supabase → 기록 조회]
│   └─ Supabase PostgreSQL에서 사용자 질문/답변 이력 조회

├─ `/query`  → 판례 목록 등 정형 정보 요청 : [프론트 or FastAPI → Supabase GraphQL → PostgreSQL]
│   └─ Supabase GraphQL API 호출 → 판례 제목, 날짜 등 조건 필터 조회

────────────────────────────────────
[외부 구성 요소]
├─ HuggingFace 모델
│   ├─ 문장 임베딩 모델 (: `sentence-transformers`)
│   └─ LLM 모델 (: GPT2, Mistral, Falcon 등)

├─ Weaviate (벡터 DB)
│   └─ 임베딩된 문서 저장 + 의미기반 검색

├─ Supabase (PostgreSQL)
│   └─ 사용자, 질문, 답변, 히스토리 저장

├─ Supabase GraphQL API
│   └─ 판례 제목, 날짜 등 정형 데이터 조회용 API

총정리

  1. 사용자가 입력한 질문은 React 프론트에서

    REST API를 통해 FastAPI 서버로 전달

  2. FastAPI는 그 질문을 먼저 문장 임베딩 모델(HuggingFace)에 넣어서

    숫자 벡터로 바꿈

  3. 그 벡터를 가지고 Weaviate(벡터 DB)에 요청을 보냄

  4. Weaviate가 관련 문서 여러 개를 찾아서 FastAPI에 넘김

  5. FastAPI는

    • 질문
    • 검색된 문서 이 두 가지를 LLM 모델(HuggingFace LLM)에게 전달
  6. 모델은 “문서들을 참고해서 질문에 대한 답변”을 생성

  7. FastAPI는 이 답변을 다시 React 프론트에 보냠

  8. 동시에 사용자의 질문/답변/시간 같은 기록을

    Supabase(PostgreSQL)에 저장

  9. 프론트는 그 답변을 사용자한테 보여줌

구성 요소정확한 정체역할 설명비유 (쉽게 풀어 쓴 표현)
FastAPI백엔드 서버 프레임워크REST API 서버. 프론트 요청을 받아 LLM 호출, DB 저장 등 모든 처리 담당손님 요청을 받고 주방(모델/DB)과 연결해주는 종업원
HuggingFace 임베딩문장 임베딩 모델질문을 벡터로 변환하여 Weaviate에서 의미기반 검색할 수 있게 처리질문을 수치화해 검색할 수 있도록 가공하는 벡터 번역기
Weaviate벡터 DB 시스템의미기반 문서 검색. 질문과 유사한 판례를 벡터 공간에서 찾아 반환AI 전용 검색 창고
HuggingFace LLMAI 답변 생성기 (LLM)질문 + 유사 문서를 받아 자연어 답변 생성 (GPT2, Mistral 등 사용)문서들을 읽고 답장을 써주는 AI 작가
PostgreSQL관계형 데이터베이스사용자 정보, 질문/답변 히스토리 등 정형 데이터를 저장칸칸이 잘 정리된 엑셀 표 창고
SupabasePostgreSQL 관리 플랫폼PostgreSQL을 쉽게 쓰게 해주는 도구. 인증, GraphQL API, 실시간 기능까지 포함DB, 로그인, API까지 관리해주는 올인원 매니저
GraphQL API데이터 통신 방식 (API 스타일)프론트에서 원하는 필드만 요청 가능. 판례 제목, 날짜, 카테고리 등 정형 데이터 조회용“이름만 주세요!” 하고 정확한 항목만 뽑아주는 스마트 요청 창구
React + TypeScript프론트엔드 (사용자 인터페이스)사용자 입력을 받고, FastAPI 또는 GraphQL로 요청 후 응답을 화면에 출력사용자가 직접 만지는 화면, 버튼, 입력창 등

3. GraphQL API랑 FastAPI를 다 사용하는 이유는?

FastAPI는 LLM 추론, Weaviate 검색, 히스토리 저장 같은 비정형 고처리 로직을 맡고, Supabase의 GraphQL API는 단순한 정형 정보(판례 목록 등)를 가볍게 조회할 수 있게 분리한 구조

실제로 이 구조를 많이 사용한다고 함

[React]
├─ /recommend 요청 → [FastAPI → Weaviate + LLM → 답변]
├─ /history 요청 → [FastAPI → Supabase → 기록 조회]
└─ GraphQL 요청 → [Supabase GraphQL 엔진 → 판례 목록/필터링]

4. Weaviate + LLM은 RAG 구조?

  • 정확함
    • 질문을 벡터로 바꾼 뒤 → 유사 문서를 Weaviate에서 검색
    • 검색된 문서와 질문을 LLM에게 주고 → 답 생성
    • 이게 바로 Retrieval-Augmented Generation (RAG) 구조

5. 왜 벡터 DB가 필요한가?

Weaviate는 언제 필요해지냐

사용자의 질문에 대해

“내가 미리 저장해둔 문서 중에서 관련된 걸 먼저 검색하고” →
“그걸 참고해서 LLM이 답변하도록 만들고 싶을 때”

즉, RAG 구조일 때 필요


6. RAG(Retrieval-Augmented Generation) 구조란?

사용자가 “상속세율”이라고 물었을 때

→ 모델이 직접 생성하는 게 아니라,

→ “내가 저장한 법률 문서 중에서 ‘상속세율’ 관련 내용을 먼저 검색”

→ 그걸 컨텍스트로 모델에 넣고

→ 모델이 그걸 바탕으로 답변 생성

이 구조를 가능하게 해주는 게 바로 Weaviate (벡터 DB)

항목Weaviate (벡터 DB)PostgreSQL (일반 DB)
목적"비슷한 의미" 찾기"정확한 조건"으로 찾기
저장하는 것임베딩된 숫자 벡터 (ex: 문장의 의미)테이블/행/열로 구성된 일반 데이터
예시 질문“이와 비슷한 판례는 뭐야?”“2023년 이후 민법 판례 중 상속 관련된 것만 줘”
사용 위치RAG 검색 (GPT가 참고할 자료)일반 정보/조건 조회 (목록, 히스토리 등)
검색 방식의미 기반 근접 검색 (semantic search)SQL 조건 검색 (WHERE절)
연동 방식REST API / GraphQL (Weaviate 자체 API)GraphQL API (Supabase 또는 Hasura)

Weaviate (벡터 DB)

  • 판례 원문이나 법률 문장을 숫자 벡터로 변환해서 저장
  • 예:

    "딸이 부모 부양을 안 하면 상속 못 받나요?"

    → 이 문장을 벡터화해서, 유사한 판례 문장을 의미기반으로 검색

  • GPT가 참조해서 더 똑똑한 답변을 생성하도록 도와줌 (RAG 구조)

PostgreSQL (일반 DB)

  • 정형 정보 저장:
    • 사용자의 이름/이메일
    • 질문 히스토리
    • 판례의 제목, 분류, 날짜 등 "정리된 표 형태 정보"
  • 예:
    • SELECT * FROM 판례 WHERE category='상속' AND year >= 2020
  • 프론트에서 목록 보여주기, 기록 보기 할 때 사용

이건 그냥 참고용

Weaviate 도입 제안 이유 (벡터 검색 가능)

기능WeaviateSQLite
의미 기반 검색내장 벡터 검색 (HNSW)없음
문서 분류 없이 유사도 검색지원불가능
RAG 필수 요소HuggingFace와 연동 쉬움구조 자체가 안 맞음

GraphQL 도입 제안 이유

특징GraphQLSQL 직접 호출 (SQLite 등)
필요한 필드만 조회지원전부 조회 후 필터링
조건별 조합 쿼리유연함직접 JOIN, WHERE 처리 필요
프론트와 연동React + Apollo 등과 궁합 좋음REST만 가능
실시간 구독가능 (Supabase)안됨

Supabase(PostgreSQL) 도입 제안 이유

특징GraphQLSQL 직접 호출 (SQLite 등)
필요한 필드만 조회지원전부 조회 후 필터링
조건별 조합 쿼리유연함직접 JOIN, WHERE 처리 필요
프론트와 연동React + Apollo 등과 궁합 좋음REST만 가능
실시간 구독가능 (Supabase)안됨

0개의 댓글