LLM 앱 프레임워크 5축 — 전체 10 도식v0.0.1 상세

코어 6 + 추가 4 · 각 도식마다 개념·컴포넌트·예시·함정·프레임워크 상세 설명 · 2026-09-21

📖 이 문서의 목적

LLM 앱 프레임워크를 고를 때 흔히 마주치는 혼란 — "LangChain vs LlamaIndex", "LangGraph vs AutoGen" 같은 비교는 프레임워크 카탈로그 수준에 머무름. 이 문서는 그보다 한 단계 위에서 "LLM 앱이 풀어야 할 5가지 문제"를 정의하고, 각 문제를 어떤 도식과 도구로 다루는지 보여주는 게 목표.

읽는 법: 처음이라면 1번(멘탈 모델) → 2번(전략 맵) → 3번(파이프라인) 순서로. 이미 LLM 앱을 만들고 있다면 4·5번(런타임/아키텍처)부터.

대상: LLM 앱을 처음 만드는 주니어, 또는 MLOps/DevOps 관점에서 LLM 파이프라인을 검토해야 하는 시니어.

📑 목차
  1. 큰 그림 mindmap
  2. 전략 맵 quadrantChart
  3. 데이터 흐름 flowchart
  4. 시간 순서 sequenceDiagram
  5. 내부 구조 flowchart subgraph
  6. 상태 전이 stateDiagram-v2
  7. 데이터 모델 classDiagram
  8. DB 스키마 erDiagram
  9. 사용자 여정 journey
  10. 구현 로드맵 gantt

1. 큰 그림 — 5축 멘탈 모델

LLM 앱 프레임워크가 풀어야 할 5가지 문제를 한 눈에 보여줘. 멘탈 모델을 먼저 잡고, 나머지 도식이 어디에 위치하는지 기준점을 만들어.

💡 핵심 개념: LLM은 텍스트를 입력받아 텍스트를 출력하는 함수에 불과. 실전 LLM 앱은 그 함수를 둘러싼 5가지 주변 문제(외부 지식, 도구 사용, 프롬프트 관리, 타입 안전성, 에이전트 흐름)를 풀어야 함. 이 5가지가 프레임워크 비교의 진짜 축.
mindmap root((LLM 앱
프레임워크)) RAG Pipeline 인덱싱 문서 로드 청크 분할 임베딩 검색·생성 벡터 검색 리랭킹 컨텍스트 주입 에이전트
오케스트레이션 ReAct 루프 Tool 호출 State 관리 Human-in-loop 프롬프트 최적화 시그니처 모듈 조립 컴파일러 평가 메트릭 타입 안정성 Pydantic Schema DI 모킹 시스템 통합

🔧 5가지 축의 의미

📋 구체적 예시: 사내 HR 정책 챗봇을 만든다고 치면 —
⚠️ 흔한 함정:
🛠️ 관련 프레임워크: 각 축의 1등 시민 — LlamaIndex/Haystack(RAG), LangGraph/AutoGen/CrewAI(Agent), DSPy(Prompt Opt), Pydantic AI/Instructor/Semantic Kernel(Type Safety).

2. 전략 맵 — 프레임워크 위치

각 프레임워크를 "단순↔복잡" × "오프라인/데이터↔온라인/추론" 2차원에 배치.

💡 핵심 개념: 프레임워크 선택은 기능 비교가 아니라 내 상황에 맞는 위치 매핑. x축은 "도구 사용 난이도", y축은 "데이터/추론 어느 쪽에 시간 들이는가".
quadrantChart title LLM 프레임워크 전략 맵 x-axis "단순한 사용성 --> 복잡한 워크플로우" y-axis "오프라인/데이터 --> 온라인/추론" quadrant-1 "복잡 에이전트 (오케스트레이션)" quadrant-2 "프롬프트·타입 (경량 추론)" quadrant-3 "데이터 중심 (RAG/ETL)" quadrant-4 "고급 데이터 파이프라인" LlamaIndex: [0.55, 0.50] Haystack: [0.65, 0.40] LangGraph: [0.85, 0.90] AutoGen: [0.75, 0.85] CrewAI: [0.65, 0.85] DSPy: [0.70, 0.75] Pydantic AI: [0.45, 0.80] Semantic Kernel: [0.80, 0.75] Instructor: [0.35, 0.70]

🔧 사분면별 해석

📋 구체적 예시: "내 팀은 FastAPI 백엔드에 RAG 붙이려 한다" → 좌상(Q2) + 좌하(Q3) 조합 추천: Pydantic AI로 타입 안전한 호출 + LlamaIndex로 인덱싱.
⚠️ 흔한 함정:
🛠️ 1줄 추천: 데이터 많음 → LlamaIndex. 백엔드 통합 → Pydantic AI. 에이전트 → LangGraph(명시적 그래프) or AutoGen(대화형).

3. 데이터 흐름 — RAG Pipeline

RAG Pipeline의 end-to-end 데이터 흐름. 인덱싱이 벡터 DB를 채우고, 검색·생성이 그걸 읽어 LLM으로 보냄.

💡 핵심 개념: RAG는 한 번에 끝나는 게 아니라 두 개의 시점(오프라인/온라인)으로 나뉨. 인덱싱은 배치로 천천히 돌고, 검색·생성은 사용자 요청마다 실시간. 둘을 잇는 게 벡터 DB.
flowchart LR subgraph OFF["📥 인덱싱 (오프라인·배치)"] D[문서]:::off C[청크]:::off E[임베딩]:::off D --> C --> E end VDB[("🗄️ 벡터 DB")]:::store subgraph ON["🔍 검색·생성 (온라인·추론)"] Q[질의]:::on R[검색·리랭킹]:::on G[컨텍스트 주입]:::on Q --> R --> G end LLM{{"🧠 LLM"}}:::llm A["📨 응답"]:::resp E ==>|"bulk upsert"| VDB VDB ==>|"top-k retrieve"| R G --> LLM --> A classDef off fill:#fef3c7,stroke:#f59e0b,color:#000 classDef on fill:#dbeafe,stroke:#3b82f6,color:#000 classDef store fill:#e5e7eb,stroke:#6b7280,color:#000 classDef llm fill:#f3e8ff,stroke:#a855f7,color:#000 classDef resp fill:#dcfce7,stroke:#10b981,color:#000

🔧 단계별 책임

📋 구체적 예시 (한국어 사내 문서 QA):
  1. Notion 페이지 1000개를 Loader로 추출 (PDF, HTML)
  2. Splitter로 페이지당 평균 800 토큰 청크
  3. 임베딩 모델은 text-embedding-3-small (저렴) 또는 text-embedding-3-large (정밀)
  4. Pinecone 서버리스에 upsert
  5. 사용자 "연차 정책" 검색 → top-10 chunk → rerank → top-3
  6. Prompt: "다음 문서 기반으로 답해. 문서: {chunk}. 질문: {query}"
⚠️ 흔한 함정:
🛠️ 관련 프레임워크: LlamaIndex(전체 파이프라인), Haystack(production DAG), LangChain(범용), Unstructured.io(Loader 전담).

4. 시간 순서 — 런타임 호출

사용자 질문이 들어와서 응답이 나가는 런타임 호출 시퀀스.

💡 핵심 개념: 데이터 흐름(3번)이 "데이터 어디로 가나"라면, 이 도식은 "누가 언제 누구를 부르나". API 서버·Retriever·LLM은 각각 다른 프로세스/스레드일 수 있어 호출 순서·latency 파악이 중요.
sequenceDiagram actor User as 👤 사용자 participant API as 🖥️ API participant R as 🔍 Retriever participant VDB as 🗄️ Vector DB participant L as 🧠 LLM User->>API: 질문 입력 activate API API->>R: 검색 요청 (질의) activate R R->>R: 질의 임베딩 R->>VDB: top-k 검색 activate VDB VDB-->>R: 관련 chunk들 deactivate VDB R-->>API: 리랭킹된 chunk들 deactivate R API->>L: 컨텍스트 + 질문 activate L L-->>API: 응답 생성 deactivate L API-->>User: 최종 응답 deactivate API

🔧 단계별 latency (typical)

📋 구체적 예시 (토스 FAQ 챗봇):
  1. 사용자 "적금 해지 어떻게 해?" 입력
  2. API 서버(FastAPI)가 인증·rate-limit 체크 → Retriever 호출
  3. Retriever가 질의 임베딩 + Qdrant 검색 (top-10)
  4. Cohere rerank로 top-3 압축
  5. Prompt 조립: "고객 상담사처럼 답해. 매뉴얼: {top3}. 질문: {q}"
  6. GPT-4o 응답 (streaming, 첫 토큰 800ms 후)
  7. SSE로 사용자에게 토큰 단위 전송
⚠️ 흔한 함정:
🛠️ 도식화 도구: sequenceDiagram(mermaid)이 이 패턴의 표준. PlantUML도 가능. 코드 추적은 OpenTelemetry(분산 trace).

5. 내부 구조 — 레이어드 아키텍처

시스템을 계층으로 분리. 어디에 어떤 컴포넌트가 사는 보여줌.

💡 핵심 개념: 좋은 아키텍처는 관심사 분리(SoC). "UI 코드"와 "DB 쿼리"가 한 함수에 섞이면 안 됨. LLM 앱에선 특히 프롬프트 조립을 도메인 로직에서 분리하는 게 핵심.
flowchart TB subgraph CL["🖥️ 클라이언트 레이어"] U[👤 사용자] end subgraph AL["🌐 API 레이어"] A["FastAPI 서버"] end subgraph RL["📦 RAG 레이어"] RP["RAG Pipeline"] RT["Retriever"] RD["Indexer"] end subgraph LL["🧠 LLM 레이어"] LP["LLM Provider"] end subgraph SL["💾 스토리지 레이어"] VDB[("Vector DB")] MDB[("Metadata DB")] end subgraph XL["🔁 횡단 관심사"] AG["🤖 Agent"] PO["✨ Prompt Opt"] TS["🛡️ Type Safety"] end U <--> A A --> RP RP --> RD RP --> RT RD --> VDB RT <--> VDB RT --> A A --> LP LP --> A RD <--> MDB AG -.도구.-> LP PO -.최적화.-> LP TS -.검증.-> A

🔧 레이어별 책임 + 추천 폴더 구조

📋 FastAPI 기준 폴더 예시:
app/
├── api/
│   ├── chat.py         # POST /chat 엔드포인트
│   └── admin.py        # 문서 업로드
├── rag/
│   ├── loader.py       # PDF/HTML → Document
│   ├── splitter.py     # Document → Chunk[]
│   ├── embedder.py     # Chunk → Embedding
│   ├── indexer.py      # Embedding → Vector DB
│   └── retriever.py    # Query → RetrievedChunk[]
├── llm/
│   ├── providers/
│   │   ├── openai.py
│   │   └── anthropic.py
│   └── prompts/        # prompt templates
├── core/
│   ├── agent.py        # Agent orchestration
│   ├── prompt_opt.py   # DSPy integration
│   └── types.py        # Pydantic models
└── db/
    ├── vector.py       # Pinecone client
    └── metadata.py     # Postgres session
      
⚠️ 흔한 함정:
🛠️ 아키텍처 지원: FastAPI(API), LangGraph(에이전트), Pydantic AI(타입), Prefect/Airflow(인덱싱 워크플로우).

6. 상태 전이 — 문서·질의 라이프사이클

문서 인덱싱(상)과 질의 처리(하)를 두 흐름으로 분리. 색상으로 흐름 구분(노랑=문서, 파랑=질의). "저장된 벡터로 검색" 화살표가 두 흐름을 잇는 핵심 연결.

💡 핵심 개념: 시스템 안의 객체는 시간이 지나며 상태가 바뀜. 같은 Document도 처음엔 raw, 나중엔 indexed. 상태 전이를 모르면 "이 객체 지금 어디까지 진행됐지?" 같은 디버깅이 안 됨.
stateDiagram-v2 direction LR state "📥 인덱싱 (오프라인)" as DocFlow { [*] --> D1 D1: 📄 원본 문서 D2: 📦 로드 완료 D3: ✂️ 청크 분할 D4: 🔢 임베딩 D5: 💾 벡터 DB 저장 D1 --> D2: Loader D2 --> D3: Splitter D3 --> D4: Embedder D4 --> D5: Indexer D5 --> [*] } state "🔍 검색·생성 (온라인)" as QueryFlow { [*] --> Q1 Q1: ❓ 사용자 질문 Q2: 🔢 질의 임베딩 Q3: 🔍 top-k 검색 Q4: 🧩 컨텍스트 구성 Q5: 💬 LLM 응답 Q1 --> Q2: Embedder Q2 --> Q3: Retriever Q3 --> Q4: Composer Q4 --> Q5: LLM Q5 --> [*] } D5 --> Q3: 저장된 벡터로 검색 classDef doc fill:#fef3c7,stroke:#f59e0b,color:#1f2937,stroke-width:2px classDef query fill:#dbeafe,stroke:#3b82f6,color:#1f2937,stroke-width:2px class D1,D2,D3,D4,D5 doc class Q1,Q2,Q3,Q4,Q5 query

🔧 각 상태의 invariant

📋 디버깅 시나리오: "어느 chunk가 왜 잘못 검색됐지?" 추적 →
  1. D1(원본) → D2(로드) → D3(청크) → D4(임베딩) → D5(저장) 각 단계 로그 확인
  2. 어느 단계에서 끊겼는지 보면 "청크가 너무 작아서 의미 손실" 같은 원인 파악
⚠️ 흔한 함정:
🛠️ 상태 추적: LangSmith, W&B Weave, OpenTelemetry, 또는 자체 DB에 document_status 컬럼 추가.

7. 데이터 모델 — 클래스 관계 추가

시스템을 흐르는 핵심 객체들의 구조와 관계. Document → Chunk → Embedding → VectorIndex, Query → Prompt → Response.

💡 핵심 개념: LLM 앱의 객체 모델은 일반 웹 앱과 거의 같음. 차이는 Embedding(float 배열)이라는 비정형 객체와 VectorIndex(검색 인터페이스) 정도. 나머지는 평범한 도메인 모델.
classDiagram class Document { +String id +String title +String source +DateTime createdAt +Metadata metadata } class Chunk { +String id +String docId +String text +Int position +Int tokenCount } class Embedding { +String chunkId +String model +Float[] vector +Int dimensions } class VectorIndex { +String id +String name +Int dimensions +DistanceMetric metric +upsert(Embedding) +query(Float[]) Chunk[] } class Query { +String text +Float[] embedding +Int topK } class RetrievedChunk { +String chunkId +Float score +String text } class Prompt { +String systemMsg +String userMsg +Chunk[] context } class Response { +String answer +RetrievedChunk[] sources +DateTime generatedAt } Document "1" --> "*" Chunk : splits into Chunk "1" --> "1" Embedding : has Embedding "*" --> "1" VectorIndex : stored in Query --> VectorIndex : searches VectorIndex --> RetrievedChunk : returns RetrievedChunk --> Prompt : context for Prompt --> Response : input to Response --> Query : answers

🔧 필드별 의미

📋 Pydantic 구현 예시:
from pydantic import BaseModel, Field
from datetime import datetime
from typing import Literal

class Document(BaseModel):
    id: str
    title: str
    source: str  # 'notion://page/123' or 's3://bucket/key'
    created_at: datetime
    metadata: dict = Field(default_factory=dict)

class Chunk(BaseModel):
    id: str
    doc_id: str
    text: str
    position: int
    token_count: int

class Embedding(BaseModel):
    chunk_id: str
    model: str  # 'text-embedding-3-small'
    vector: list[float]
    dimensions: int
      
⚠️ 흔한 함정:
🛠️ 구현: Python Pydantic, TypeScript Zod, Go struct + validator. LangChain은 자체 Document 클래스 제공하지만 커스텀 권장.

8. DB 스키마 — ER 다이어그램 추가

PostgreSQL 같은 RDB에 저장되는 테이블 관계. 벡터는 VECTOR 타입 (pgvector) 또는 별도 Vector DB 참조.

💡 핵심 개념: 벡터는 두 가지 저장 옵션. (1) Postgres + pgvector 확장 — 한 DB로 통합, transactional 보장. (2) Pinecone/Qdrant 같은 전용 Vector DB — 성능/스케일 유리, sync 부담. 트레이드오프 있음.
erDiagram DOCUMENT ||--o{ CHUNK : contains CHUNK ||--|| EMBEDDING : has EMBEDDING }o--|| VECTOR_INDEX : stored_in USER ||--o{ QUERY : submits QUERY ||--|| RESPONSE : produces RESPONSE }o--o{ CHUNK : cites DOCUMENT { string id PK string title string source_uri datetime created_at jsonb metadata } CHUNK { string id PK string doc_id FK int position text content int token_count } EMBEDDING { string chunk_id PK,FK string model int dimensions vector vector } VECTOR_INDEX { string name PK string embedding_model int dimensions string distance_metric } USER { string id PK string email } QUERY { string id PK string user_id FK text question datetime created_at } RESPONSE { string id PK string query_id FK text answer jsonb metadata datetime generated_at }

🔧 인덱스 전략

📋 pgvector 통합 예시:
-- pgvector 활성화
CREATE EXTENSION IF NOT EXISTS vector;

-- 테이블
CREATE TABLE chunk (
  id UUID PRIMARY KEY,
  doc_id UUID REFERENCES document(id),
  position INT,
  content TEXT,
  token_count INT
);

CREATE TABLE embedding (
  chunk_id UUID PRIMARY KEY REFERENCES chunk(id),
  model VARCHAR(64),
  dimensions INT,
  vector VECTOR(1536)  -- OpenAI text-embedding-3-small
);

-- HNSW 인덱스 (코사인 유사도)
CREATE INDEX embedding_vector_idx
  ON embedding USING hnsw (vector vector_cosine_ops);

-- 검색
SELECT c.content, e.vector <=> $1 AS distance
FROM embedding e JOIN chunk c ON c.id = e.chunk_id
ORDER BY distance
LIMIT 5;
      
⚠️ 흔한 함정:
🛠️ 옵션: pgvector(Postgres 통합), Pinecone(관리형), Qdrant(오픈소스), Weaviate(GraphQL 친화).

9. 사용자 여정 — UX 흐름 추가

RAG 시스템에서 사용자가 어떤 경험을 하는지. 만족도 스코어(1~5)와 함께 표현.

💡 핵심 개념: 시스템 아키텍처가 아무리 좋아도 사용자가 답을 못 얻으면 실패. "답 정확도"만 보지 말고 "답까지 걸리는 시간", "출처 표시", "재질문 흐름" 같은 UX 지표도 봐야 함.
journey title RAG 시스템 사용자 여정 section 문제 인식 정보 부족 인식: 3: User 시스템 접속: 5: User section 검색 시도 질문 입력: 5: User, System 벡터 검색 실행: 4: System 관련 문서 추출: 4: System section 답변 생성 컨텍스트 구성: 3: System LLM 응답 생성: 5: System 출처 인용 표시: 4: System section 검증 답변 확인: 4: User 후속 질문: 3: User 만족/피드백: 4: User

🔧 단계별 UX metric

📋 만족 여정 vs 좌절 여정 비교:
시나리오만족 여정좌절 여정
질문 입력자동완성, 예시 질문빈 입력란, "뭘 물어봐야 할지" 모름
응답2초 내 streaming + 출처10초 대기 + 출처 없음
후속"더 자세히", "예시 보여줘" 버튼새 질문 처음부터 다시
피드백👍/👎 1클릭 + 코멘트피드백 없음, 개선 불가
⚠️ 흔한 함정:
🛠️ UX 도구: Streamlit/Gradio(프로토타입), Next.js + Vercel AI SDK(프로덕션), LangSmith(trace/feedback 수집).

10. 구현 로드맵 — Gantt 추가

LLM 앱을 처음부터 만들어갈 때의 단계별 일정 (예시). 기초 → RAG → 에이전트 → 프로덕션화 순서.

💡 핵심 개념: LLM 앱 학습은 단계적이 가장 빠름. 처음부터 멀티에이전트 만들려 하면 디버깅 지옥. "Hello LLM → RAG → 평가 → Agent → 프로덕션화" 순서가 검증된 학습 경로.
gantt title LLM 앱 프레임워크 학습·구현 로드맵 (예시) dateFormat YYYY-MM-DD axisFormat %m/%d section 기초 이해 LLM API 이해 :a1, 2026-09-21, 7d 프롬프트 작성 :a2, after a1, 5d section RAG Pipeline 인덱싱 파이프라인 :b1, after a2, 7d 검색·생성 파이프라인 :b2, after b1, 7d 평가 메트릭 설계 :b3, after b2, 5d section 에이전트 LangGraph 기초 :c1, after b3, 7d 멀티에이전트 :c2, after c1, 7d section 프로덕션화 타입 안정성 적용 :d1, after c2, 5d 모니터링·로깅 :d2, after d1, 5d

🔧 단계별 산출물 + 검증 방법

📋 단계별 skip-or-go 결정:
상황추천
내부 PoC, 사용자 10명 이하a→b까지만. c·d 생략 OK
외부 서비스, SLA 필요전체 진행. 특히 d2 모니터링 필수
단순 Q&A 봇, 외부 tool 없음c(에이전트) 스킵. RAG + prompt로 충분
코드 실행·API 호출 필요c1(LangGraph) 필수. d1(타입)도
⚠️ 흔한 함정:
🛠️ 일정 관리: Linear/Notion에 단계별 이슈로 분리. LangSmith로 각 단계 자동 trace.

🚀 다음 단계 추천

방금 막 시작했다면: 1번(멘탈 모델) → 10번(로드맵) → a1·b1 구현. 작은 RAG부터.

이미 RAG 있다: 4번(런타임) + 5번(아키텍처) 점검. latency·에러 처리·모니터링 확인.

프로덕션 운영 중: 9번(UX) 점검. 출처 표시·피드백 루프·hallucination rate.

학습 더 하고 싶다면: learning-plan.md 같은 체크리스트로 a~d 단계별 진행 상황 추적 권장.