LLM 앱 프레임워크가 풀어야 할 문제를 6개 축으로 보여줘. 멘탈 모델을 먼저 잡고, 나머지 도식이 어디에 위치하는지 기준점을 만들어. 관측·평가 축은 최근 1년 사이에 모든 프레임워크에서 빠지지 않는 필수 항목이 됨.
왜 필요한가: 큰 그림 없이 세부 도식을 보면 길을 잃음.
mindmap
root((LLM 앱 프레임워크))
RAG Pipeline
인덱싱
문서 로드
청크 분할
임베딩
메타 추출
검색·생성
벡터 검색
리랭킹
컨텍스트 주입
인용 추적
에이전트 오케스트레이션
ReAct 루프
Tool 호출
State 관리
Human-in-loop
멀티에이전트
프롬프트 최적화
시그니처
모듈 조립
컴파일러
평가 메트릭
타입 안정성
Pydantic Schema
DI
모킹
시스템 통합
스트리밍·UX
토큰 스트리밍
SSE / WebSocket
취소·타임아웃
관측·평가
트레이스
토큰·비용
품질 평가
회귀 테스트
📐 설계 노트
관련 프레임워크: 관측은 Langfuse/LangSmith, 평가는 Ragas/Deepeval, 스트리밍은 모든 프레임워크가 1급 지원.
트레이드오프: 6축 모두 만족하는 프레임워크는 없음. LangGraph + Langfuse + Ragas 조합이 가장 균형.
프롬프트 최적화·타입 안정성·관측은 코드 레벨 작업, RAG·에이전트·스트리밍은 런타임 동작.
2전략 맵 — 프레임워크 위치
🎯 positioning9 프레임워크
각 프레임워크를 "단순↔복잡" × "오프라인/데이터↔온라인/추론" 2차원에 배치. 점수가 높을수록 더 복잡하거나 추론 중심.
좌측 하단(Q3) 추천: RAG 1차 구현은 LlamaIndex 또는 Haystack. 둘 다 문서 로더·청커·인덱서가 성숙.
우측 상단(Q1) 추천: 에이전트 워크플로우는 LangGraph (제어 흐름 명시적) 또는 CrewAI (역할 기반, 빠른 시작).
트레이드오프:AutoGen는 멀티에이전트 강력하지만 디버깅 어려움. Semantic Kernel는 .NET 통합 강점.
축 위치는 정답이 아닌 2026-09 시점의 주류 평가. 프로젝트 특성·팀 역량에 따라 다름.
3데이터 흐름 — RAG Pipeline
🔌 pipeline오프라인·온라인 + 캐시 + 재시도
RAG Pipeline의 end-to-end 데이터 흐름. 인덱싱이 벡터 DB를 채우고, 검색·생성이 그걸 읽어 LLM으로 보냄. 응답 캐시·재시도·에러 분기 추가.
왜 필요한가: "데이터가 어디서 어디로 가는지" 한 장으로 보여줘야 구현할 때 헤매지 않음.
flowchart LR
subgraph OFF["📥 인덱싱 (오프라인·배치)"]
D[문서]:::off
L[로더]:::off
C[청크]:::off
E[임베딩]:::off
M[메타 추출]:::off
D --> L --> C --> M
M --> E
end
VDB[("🗄️ 벡터 DB")]:::store
META[("🗃️ 메타 DB")]:::store
CACHE[("⚡ 응답 캐시")]:::store
subgraph ON["🔍 검색·생성 (온라인·추론)"]
Q[질의]:::on
EMB[질의 임베딩]:::on
R[검색·리랭킹]:::on
G[컨텍스트 주입]:::on
Q --> EMB --> R
end
LLM{{"🧠 LLM"}}:::llm
A["📨 응답"]:::resp
ERR["❌ 에러/재시도"]:::err
E ==>|"bulk upsert"| VDB
M -->|"tag"| META
VDB ==>|"top-k retrieve"| R
R --> G
G -->|"cache hit?"| CACHE
CACHE -->|"hit"| A
CACHE -->|"miss"| LLM
LLM -->|"ok"| A
LLM -->|"timeout/5xx"| ERR
ERR -.재시도.-> LLM
ERR -->|"3회 실패"| 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
classDef err fill:#fee2e2,stroke:#ef4444,color:#000
📐 설계 노트
캐시 키:hash(prompt_template + top_k_chunks + model). 동일 입력에 LLM 호출 안 하도록.
사용자 질문이 들어와서 응답이 나가는 런타임 호출 시퀀스. 스트리밍 응답·타임아웃·부분 실패 경로 포함.
왜 필요한가: "이 함수가 언제 실행돼?" 디버깅의 기준점.
sequenceDiagram
actor User as 👤 사용자
participant API as 🖥️ API
participant Cache as ⚡ Cache
participant R as 🔍 Retriever
participant VDB as 🗄️ Vector DB
participant L as 🧠 LLM
participant Obs as 📊 Observability
User->>API: 질문 입력
activate API
API->>Obs: trace 시작 (trace_id)
API->>Cache: 캐시 조회
alt cache hit
Cache-->>API: cached answer
API-->>User: 즉시 응답 (스트리밍)
else cache miss
API->>R: 검색 요청 (질의)
activate R
R->>R: 질의 임베딩
R->>VDB: top-k 검색 (ANN)
activate VDB
VDB-->>R: 관련 chunk들
deactivate VDB
R-->>R: 리랭킹 (cross-encoder)
R-->>API: top-k chunks
deactivate R
API->>L: 컨텍스트 + 질문 (스트림)
activate L
loop token 스트리밍
L-->>API: token delta
API-->>User: SSE event
end
alt 정상 완료
L-->>API: done + usage
deactivate L
API->>Cache: 캐시 저장
API->>Obs: trace 끝 (usage, latency)
else 타임아웃/에러
L--xAPI: timeout (30s)
API->>Obs: trace 끝 (error)
API-->>User: 504 + 재시도 안내
end
end
deactivate API
📐 설계 노트
스트리밍: SSE가 가장 단순. WebSocket은 양방향 필요할 때만.
타임아웃: LLM 호출은 30s, 검색은 2s로 분리. 임베딩은 1s.
트레이드오프: 캐시 hit이면 빠르지만 환각(hallucination) 재사용 위험. 답변 변동 필요 시 TTL 짧게.
trace_id를 User 요청부터 LLM 응답까지贯穿해 로그·메트릭·평가 연결.
5내부 구조 — 레이어드 아키텍처
🏛 architecture8개 레이어 + 횡단 관심사
시스템을 8개 레이어로 분리. 캐시·큐·평가·설정 레이어 추가, 횡단 관심사는 점선으로 표시.
왜 필요한가: "내 코드는 어디 폴더에 둬야 하지?" 구성 질문의 답.
flowchart TB
subgraph CL["🖥️ 클라이언트 레이어"]
U[👤 사용자]
UI[Web/Mobile UI]
end
subgraph AL["🌐 API 레이어"]
A[FastAPI 서버]
AUTH[인증·인가]
end
subgraph QL["📬 큐 레이어"]
QJ[작업 큐 Celery/RQ]
end
subgraph RL["📦 RAG 레이어"]
RP[RAG Pipeline]
RT[Retriever]
RD[Indexer]
RERANK[Re-ranker]
end
subgraph LL["🧠 LLM 레이어"]
LP[LLM Provider OpenAI/Anthropic]
EMB[Embedding API]
end
subgraph SL["💾 스토리지 레이어"]
VDB[(Vector DB)]
MDB[(Metadata DB)]
CACHE[(응답 캐시)]
OBJ[(문서 원본 S3/MinIO)]
end
subgraph EL["📊 평가 레이어"]
EVAL[오프라인 평가 Ragas/Deepeval]
OBS[관측 Langfuse]
end
subgraph XL["🔁 횡단 관심사"]
AG[🤖 Agent]
PO[✨ Prompt Opt]
TS[🛡️ Type Safety Pydantic]
CFG[⚙️ Config Hydra/pydantic-settings]
end
U <--> UI
UI <--> A
A --> AUTH
A --> RP
A --> QJ
QJ --> RD
RP --> RD
RP --> RT
RP --> RERANK
RD --> OBJ
RD --> VDB
RD --> MDB
RT --> VDB
RT --> CACHE
RT --> A
A --> LP
A --> EMB
LP --> A
RD --> EMB
AG -.도구.-> LP
PO -.최적화.-> LP
TS -.검증.-> A
TS -.검증.-> RP
CFG -.설정.-> A
CFG -.설정.-> RP
OBS -.트레이스.-> A
OBS -.트레이스.-> LP
EVAL -.품질.-> RP
왜 필요한가: "DB 스키마는 어떻게 짜?" "메타데이터는 어디 저장하지?" 설계 단계의 답.
erDiagram
DOCUMENT ||--o{ CHUNK : contains
DOCUMENT ||--o{ DOCUMENT_VERSION : has
CHUNK ||--|| EMBEDDING : has
EMBEDDING }o--|| VECTOR_INDEX : stored_in
USER ||--o{ QUERY : submits
USER ||--o{ FEEDBACK : provides
QUERY ||--|| RESPONSE : produces
RESPONSE }o--o{ CHUNK : cites
RESPONSE ||--o{ EVAL_RESULT : scored_by
RESPONSE ||--o{ FEEDBACK : receives
DOCUMENT {
string id PK
string title
string source_uri
datetime created_at
jsonb metadata
string owner_id FK
}
DOCUMENT_VERSION {
string id PK
string document_id FK
int version
text content_hash
datetime created_at
}
CHUNK {
string id PK
string doc_id FK
int position
text content
int token_count
index idx_doc_position (doc_id, position)
}
EMBEDDING {
string chunk_id PK,FK
string model
int dimensions
vector vector
index idx_vector_hnsw (vector HNSW)
}
VECTOR_INDEX {
string name PK
string embedding_model
int dimensions
string distance_metric
string algorithm
}
USER {
string id PK
string email
datetime created_at
}
QUERY {
string id PK
string user_id FK
text question
datetime created_at
index idx_user_created (user_id, created_at)
}
RESPONSE {
string id PK
string query_id FK
text answer
jsonb metadata
int input_tokens
int output_tokens
float latency_ms
datetime generated_at
}
FEEDBACK {
string id PK
string response_id FK
string user_id FK
int rating
text comment
datetime created_at
}
EVAL_RESULT {
string id PK
string response_id FK
float faithfulness
float relevancy
string grader_model
datetime evaluated_at
}
📐 설계 노트
벡터 인덱스: pgvector HNSW는 m=16, ef_construction=64가 시작점. 정확도 vs 메모리 트레이드오프.
버전 관리:DOCUMENT_VERSION으로 청킹·임베딩 모델 변경 시 재처리 추적.
트레이드오프: 메타데이터를 jsonb로 두면 유연하지만 쿼리·인덱싱 어려움. 자주 쓰는 키는 컬럼화.
RESPONSE에 input_tokens/output_tokens/latency_ms 저장 → 비용 분석·품질 회귀의 1차 데이터.
9사용자 여정 — UX 흐름 추가
🧑💻 journey12단계 · 만족도 1~5
RAG 시스템에서 사용자가 어떤 경험을 하는지 단계별로. 만족도가 낮은 구간이 마찰 지점 — 그 구간을 우선 개선.
왜 필요한가: "내 사용자는 어디서 막히지?" UX 관점에서 시스템 평가.
journey
title RAG 시스템 사용자 여정
section 진입
서비스 접속: 5: User
첫 화면 로드: 4: User
section 의도 파악
질문 입력: 5: User
예시 클릭: 4: User
section 검색·생성
벡터 검색 실행: 4: System
관련 문서 추출: 4: System
컨텍스트 구성: 3: System
LLM 스트리밍 시작: 5: System, User
section 검증·반복
답변 확인: 4: User
출처 인용 클릭: 5: User
후속 질문: 3: User
section 종료·피드백
👍/👎 피드백: 4: User
만족/이탈: 4: User
📐 설계 노트
저점 구간: 컨텍스트 구성(3), 후속 질문(3) — 이 구간이 시스템 병목 또는 UX 마찰.
gantt
title LLM 앱 프레임워크 학습·구현 로드맵 (예시)
dateFormat YYYY-MM-DD
axisFormat %m/%d
section 기초 이해
LLM API 이해 :a1, 2026-09-21, 7d
프롬프트 작성 :a2, after a1, 5d
기초 마일스톤 :milestone, m1, after a2, 0d
section RAG Pipeline
인덱싱 파이프라인 :b1, after a2, 7d
검색·생성 파이프라인 :b2, after b1, 7d
평가 메트릭 설계 :b3, after b2, 5d
RAG 마일스톤 :milestone, m2, after b3, 0d
section 에이전트
LangGraph 기초 :c1, after b3, 7d
멀티에이전트 :c2, after c1, 7d
Tool·MCP 통합 :c3, after c2, 5d
에이전트 마일스톤 :milestone, m3, after c3, 0d
section 프로덕션화
타입 안정성 적용 :d1, after c3, 5d
관측·로깅 구축 :d2, after d1, 5d
회귀 평가 자동화 :d3, after d2, 7d
프로덕션 마일스톤 :milestone, m4, after d3, 0d
📐 설계 노트
병렬화 가능:a2와 b1은 부분 병렬 — 프롬프트 학습하면서 인덱싱 데이터셋 만들기 가능.
마일스톤: 각 단계 끝에 동작하는 데모를 만들어야 함. 코드만 있는 단계는 헛도.
트레이드오프: 평가 메트릭을 빨리 잡으면 좋지만, 도메인 특화 메트릭은 데이터가 쌓여야 정교해짐. M2에서 1차, M4에서 2차.
관측·로깅을 d2에서 넣지 말고 b1부터 넣을 것. 인덱싱 단계에서 토큰 사용량 보면서 시작.