LLM/MLLM 종합 가이드¶
이 문서의 목적¶
이론 교과서보다는, LLM/MLLM 프로젝트에서 설계 판단이 필요할 때 참고하는 실용 가이드.
읽는 방법: - 각 섹션의 "설계 판단 요약" 박스만 먼저 훑어보면 빠르게 파악할 수 있 - 세부 이론은 필요할 때 선택적으로 찾아보면 됩니다 - "버려도 되는 선택지"와 "쓰지 말아야 할 조건"이 실무에서 더 도움이 됩니다
핵심 원칙: - 복잡한 기법이 항상 좋은 건 아닙니다 - 되돌릴 수 있는 선택을 먼저 고려하는 게 좋 - 90%의 프로젝트는 단순한 방법으로도 충분합니다
목차¶
- LLM 기본 아키텍처 - API 사용자는 1.5, 1.6만 확인
- MLLM 아키텍처 - OCR+LLM으로 안 되는지 먼저 검토
- LLMOps 파이프라인 - RAG vs Fine-tuning 판단 핵심
- 실무 적용 패턴 - RAG 실패 케이스 꼭 읽어보세요
- 주요 구현 사례
- 데이터베이스 인프라
- 워크플로우 오케스트레이션
- 클라우드 AI 서비스
- 기업 실무 통합 스택
주요 다이어그램¶
LLMOps 기술 스택¶
LLM 모델 생태계¶
RAG 파이프라인¶
1. LLM 기본 아키텍처¶
이 섹션은 참조용. API로 LLM을 사용하는 경우, Attention/PE 세부 구조를 몰라도 됩니다. 설계 판단이 목적이라면 1.5 아키텍처 유형 비교와 1.6 모델 스펙 해석만 확인하고, 나머지는 필요할 때 검색으로 확인하면 됨.
1.1 Transformer 개요 (참조용)¶
Transformer는 현대 LLM의 기반 아키텍처. 2017년 Google의 "Attention Is All You Need"에서 제안.
설계에 영향을 주는 핵심 특성: - 병렬 처리 가능 → GPU 활용에 유리 - Context length에 quadratic한 비용 → 긴 문서 처리 시 비용 폭발 - 확장성 우수 → 모델 크기와 성능이 비례 (일정 범위 내)
1.2 Self-Attention (참조용)¶
설계에 미치는 영향: - Context 길이 N에 대해 O(N^2) 메모리/연산 → 긴 context = 비용 급증 - 모든 토큰이 서로 참조 → 순서 정보 없음 (별도 위치 인코딩 필요)
수식 자체를 이해할 필요는 없음. "context 길이가 늘면 비용이 제곱으로 증가함"만 기억하세요.
1.3 Multi-Head Attention / MQA / GQA (참조용)¶
대부분의 실무자가 신경 쓸 필요 없는 내용. 기성 모델(GPT-4, Claude, LLaMA 등)을 API나 배포된 형태로 사용한다면, 이 부분은 이미 모델 제작사가 결정한 것.
신경 써야 하는 경우: 직접 모델을 학습하거나, Self-hosted LLM의 KV cache 메모리를 최적화할 때.
설계 판단에 영향을 주는 것: - GQA/MQA 모델은 KV cache가 작음 → 같은 GPU에서 더 긴 context 또는 더 많은 동시 요청 처리 가능 - LLaMA 3, Mistral 등 최신 오픈소스 모델은 대부분 GQA 채택
버려도 되는 지식: - Head 역할 분화 (Syntactic/Semantic Head 등) - 연구용 - Head Collapse 문제 - 모델 학습할 때만 관련 - Head 수 결정 공식 - 기성 모델은 이미 결정됨
[설계 판단 요약]
- 이 개념이 필요한 경우: Self-hosted LLM 배포 시 메모리 최적화
- 굳이 몰라도 되는 경우: API 사용, 기성 모델 그대로 사용
- 흔히 하는 잘못된 선택: Attention 구조를 이해해야 LLM을 잘 쓴다고 생각하는 것
1.4 Positional Encoding (참조용)¶
대부분의 실무자가 신경 쓸 필요 없는 내용. 기성 모델은 이미 RoPE 또는 ALiBi가 적용되어 있음. 우리가 신경 쓸 건 context length와 비용뿐.
설계에 영향을 주는 핵심만:
| 모델의 PE 방식 | 설계 시 고려사항 |
|---|---|
| RoPE (LLaMA, Qwen, Mistral) | Long-context 확장 기법(YaRN 등) 적용 가능 |
| ALiBi (BLOOM, Falcon) | 외삽 성능 좋으나 GQA와 호환성 이슈 |
Long-Context가 필요할 때만 알면 되는 것: - 학습된 context 이상으로 확장하려면 → YaRN, NTK-aware 등 적용 필요 - 대부분의 경우 → 모델 제공자가 이미 확장해둠 (LLaMA 3: 128K)
[설계 판단 요약]
- 이 개념이 필요한 경우: Self-hosted LLM의 context 확장, 커스텀 모델 학습
- 굳이 몰라도 되는 경우: API 사용, 기성 모델 그대로 배포
- 흔히 하는 잘못된 선택: RoPE 수식을 이해해야 한다고 생각하는 것
- 실제로 신경 쓸 것: "이 모델의 실제 usable context는 몇 K인가?"
1.5 아키텍처 유형 비교 (설계 판단용)¶
| 유형 | 대표 모델 | 언제 선택하나 |
|---|---|---|
| Encoder-Decoder | T5, BART | 번역, 입력-출력 길이가 다른 변환 작업 |
| Encoder-only | BERT, RoBERTa | 분류, NER, 임베딩 추출 |
| Decoder-only | GPT, LLaMA, Claude | 대부분의 생성 태스크 (현재 표준) |
실무 선택: - 2024년 이후 새 프로젝트 → Decoder-only 모델 사용 (생태계, 성능 우위) - 분류/NER 전용 → BERT 계열도 여전히 유효 (더 작고 빠름) - 번역 → T5 또는 Decoder-only 둘 다 가능
[설계 판단 요약]
- 이 개념이 필요한 경우: 모델 선택 시 기본 이해
- 굳이 몰라도 되는 경우: API만 사용하면 자동으로 Decoder-only
- 흔히 하는 잘못된 선택: 분류에 GPT-4를 쓰는 것 (BERT가 더 빠르고 쌈)
1.6 주요 LLM 모델 스펙¶
| 모델 | 파라미터 | Context | 아키텍처 특징 |
|---|---|---|---|
| GPT-4 | ~1.8T (추정) | 128K | MoE, 비공개 |
| Claude 3.5 Sonnet | 비공개 | 200K | Constitutional AI |
| LLaMA 3.1 405B | 405B | 128K | GQA, RoPE |
| Qwen 2.5 72B | 72B | 128K | GQA, SwiGLU |
| DeepSeek V3 | 671B (37B active) | 128K | MoE, MLA |
| Gemini 1.5 Pro | 비공개 | 1M | MoE, 멀티모달 |
1.6.1 MoE (Mixture of Experts) 이해하기¶
MoE는 모델 파라미터를 크게 늘리면서도 추론 비용을 억제하는 핵심 기술.
기본 원리:
기존 FFN: x -> FFN(x) -> output
모든 파라미터가 항상 활성화
MoE FFN: x -> Router(x) -> Top-K Experts 선택 -> 가중 합산 -> output
선택된 Expert만 활성화 (Sparse Activation)
구조:
Input x
|
v
+------+------+
| Router | (Gating Network)
| (Linear) |
+------+------+
|
Softmax + Top-K Selection
|
+-------+-------+-------+-------+
| | | | |
v v v v v
Expert1 Expert2 Expert3 Expert4 Expert5 ...
(FFN) (FFN) (FFN) (FFN) (FFN)
| | | | |
+-------+-------+-------+-------+
|
Weighted Sum (by router scores)
|
v
Output
Total Params vs Active Params:
| 모델 | Total Params | Active Params | Expert 구성 | 압축률 |
|---|---|---|---|---|
| Mixtral 8x7B | 46.7B | 12.9B | 8 experts, Top-2 | 72% |
| DeepSeek V2 | 236B | 21B | 160 experts, Top-6 | 91% |
| DeepSeek V3 | 671B | 37B | 256 experts, Top-8 | 94% |
| Grok-1 | 314B | ~78B | 8 experts, Top-2 | 75% |
실무적 의미: - 학습 비용: Total Params에 비례 (모든 Expert 학습) - 추론 비용: Active Params에 비례 (선택된 Expert만 실행) - 메모리 요구량: Total Params 전체 로드 필요 (Expert는 GPU 메모리에 상주) - 처리량: Active Params 기준, Dense 모델 대비 유리
MoE 선택 시 고려사항:
| 상황 | 권장 | 이유 |
|---|---|---|
| GPU 메모리 제한적 | Dense 모델 | MoE는 전체 파라미터 로드 필요 |
| 처리량 최대화 | MoE | Active params 기준 효율적 |
| 배치 크기 큰 환경 | MoE | Expert 병렬화 효과 |
| 단일 추론 지연 중요 | Dense 모델 | Expert 선택 오버헤드 |
1.6.2 Context 길이 스펙 해석 시 주의점¶
"Context 128K"가 항상 같은 의미가 아님:
| 고려 사항 | 설명 | 실무 영향 |
|---|---|---|
| Sliding Window | 일부 모델은 전체가 아닌 윈도우 내에서만 full attention | Mistral: 4K window + 128K sparse |
| 실제 Usable Context | 입력 + 출력 합산, 시스템 프롬프트 포함 | 128K 중 실제 사용 가능 100K 이하 |
| 성능 저하 구간 | 긴 context에서 "Lost in the Middle" 현상 | 중간 위치 정보 검색 정확도 하락 |
| KV Cache 비용 | Context 길이에 비례하여 메모리 증가 | 128K context = 수십 GB KV cache |
KV Cache 메모리 계산:
KV Cache Size = 2 * num_layers * num_kv_heads * head_dim * seq_len * batch_size * dtype_bytes
예시 (LLaMA 3 8B, 128K context, FP16):
= 2 * 32 * 8 * 128 * 131072 * 1 * 2 bytes
= ~17 GB (단일 요청)
숫자가 크다고 좋은 게 아닌 이유: 1. 비용: 긴 context = 높은 토큰 비용 + GPU 메모리 2. 지연: Context 길이에 quadratic하게 증가 (standard attention) 3. 정확도: 매우 긴 context에서 검색 정확도 저하 4. 실용성: 대부분의 실제 use case는 8-32K로 충분
실무 권장: - 필요한 context 길이를 먼저 분석 - RAG로 관련 정보만 추출하여 context 효율화 - Long-context는 요약, 전체 문서 분석 등 특수 케이스에만
1.7 효율적 Attention 변형 (참조용)¶
| 기법 | 복잡도 | 설명 |
|---|---|---|
| Flash Attention | O(n^2) | IO-aware, 메모리 효율적 구현 |
| Multi-Query Attention (MQA) | O(n^2) | K, V를 헤드 간 공유 |
| Grouped-Query Attention (GQA) | O(n^2) | MQA와 MHA의 중간 |
| Sliding Window Attention | O(n*w) | 고정 윈도우 내 어텐션 |
| Linear Attention | O(n) | 커널 근사 기반 |
| Multi-Latent Attention (MLA) | O(n^2) | KV 압축 (DeepSeek V2/V3) |
1.7.1 Attention 변형 상세 비교¶
MHA vs MQA vs GQA 메모리 비교:
모델: 32 heads, d_head=128, seq_len=8192, batch=1, FP16
MHA (Multi-Head Attention):
KV Cache = 2 * 32 * 128 * 8192 * 2 bytes = 128 MB
MQA (Multi-Query Attention):
KV Cache = 2 * 1 * 128 * 8192 * 2 bytes = 4 MB (32x 절감)
GQA (8 groups):
KV Cache = 2 * 8 * 128 * 8192 * 2 bytes = 32 MB (4x 절감)
Flash Attention이 중요한 이유:
| 기존 Attention | Flash Attention |
|---|---|
| HBM ↔ SRAM 왕복 많음 | Tiling으로 SRAM 내 처리 |
| 메모리 O(n^2) | 메모리 O(n) |
| GPU 메모리 병목 | Compute-bound로 전환 |
실무 조합:
최신 LLM 표준 조합:
- GQA (메모리 효율) + Flash Attention (속도) + RoPE (위치)
예: LLaMA 3.1
- GQA: 32 query heads, 8 KV heads
- Flash Attention 2
- RoPE with 8K base, 128K extended
MLA (Multi-Latent Attention) - DeepSeek의 혁신:
기존 GQA: K, V를 그룹화하여 공유
MLA: K, V를 저차원 latent로 압축 후 복원
KV Cache = d_latent * seq_len (d_latent << d_model)
장점: 극단적 KV cache 압축 (DeepSeek V3: 93% 감소)
단점: 추가 projection 연산, 학습 복잡도
이 섹션 전체의 설계 판단: Attention 변형은 모델 제작사가 이미 결정한 것. Self-hosted 배포 시 메모리 최적화 참조용. 그 외에는 무관.
2. MLLM 아키텍처¶
이 섹션을 읽기 전에 먼저 확인해 보세요:
"OCR + LLM"으로 충분한가? - 문서/이미지에서 텍스트만 추출하면 되는 경우 → MLLM 불필요 - 표, 차트의 구조까지 이해해야 하는 경우 → MLLM 또는 Document AI - 이미지 내용 자체를 이해해야 하는 경우 → MLLM 필요
90% 프로젝트에서 MLLM이 과잉인 이유: - OCR (Tesseract, Google Vision) + GPT-4로 대부분 해결 - MLLM은 비용이 높고, Self-hosted 시 GPU 요구량 큼 - 이미지 "설명"이 아닌 "텍스트 추출"이면 OCR이 더 정확
[MLLM 도입 전 체크리스트]
[ ] OCR + LLM으로 해결 안 되는지 먼저 테스트했는가?
[ ] 이미지의 "의미"를 이해해야 하는가? (단순 텍스트 추출 아님)
[ ] 비용/지연 증가를 감당할 수 있는가?
[ ] GPT-4V, Claude Vision API로 충분하지 않은가?
2.1 MLLM이 정말 필요한 경우¶
| 필요한 경우 | 불필요한 경우 (OCR+LLM으로 충분) |
|---|---|
| 이미지 내 객체 관계 이해 | 문서에서 텍스트 추출 |
| 차트/그래프 해석 및 추론 | 영수증, 명함 OCR |
| 이미지 기반 Q&A | PDF에서 정보 추출 |
| 의료 영상, 위성 사진 분석 | 표 구조가 단순한 문서 |
| 실시간 비디오 이해 | 스캔된 계약서 처리 |
2.2 MLLM 아키텍처 분류 (참조용)¶
아키텍처 분류는 모델 선택 시 참조용. API 사용자는 무관.
| Type | 대표 모델 | 특징 |
|---|---|---|
| Type-A | Flamingo, IDEFICS | Cross-Attention 기반, LLM 내부 수정 |
| Type-B/C | LLaVA, Qwen-VL, InternVL | 가장 흔함, MLP 프로젝터 |
| Type-D | Gemini, GPT-4V | 네이티브 멀티모달, 비공개 |
2.3 Type-C 아키텍처 상세 (가장 널리 사용)¶
Type-C는 Encoder-Projector-LLM 3단계 구조로, 현재 가장 널리 사용되는 MLLM 아키텍처.
구조 다이어그램:
+------------------------------------------------------------------+
| MLLM (Type-C) |
+------------------------------------------------------------------+
| |
| [Image] [Audio] [Video] [Text] |
| | | | | |
| v v v | |
| +-------+ +---------+ +----------+ | |
| | ViT / | | Whisper | | Video | | |
| | CLIP | | Encoder | | Encoder | | |
| +---+---+ +----+----+ +-----+----+ | |
| | | | | |
| v v v | |
| +-------+ +---------+ +----------+ | |
| | MLP | | MLP | | MLP | | |
| |Project| | Project | | Project | | |
| +---+---+ +----+----+ +-----+----+ | |
| | | | | |
| +----------------+------------------+ | |
| | | |
| v v |
| +--------+--------+ +--------+ |
| | Visual/Audio | | Text | |
| | Tokens | | Tokens | |
| +--------+--------+ +----+---+ |
| | | |
| +-------------+-------------+ |
| | |
| +---------v---------+ |
| | | |
| | LLM Decoder | |
| | (Autoregressive)| |
| | | |
| +---------+---------+ |
| | |
| v |
| [Generated Text] |
| |
+------------------------------------------------------------------+
핵심 구성 요소:
| 구성 요소 | 역할 | 대표 구현체 |
|---|---|---|
| Vision Encoder | 이미지 특징 추출 | ViT, CLIP, EVA-CLIP, SigLIP |
| Audio Encoder | 오디오 특징 추출 | Whisper, HuBERT |
| Projector | 모달리티 정렬 | MLP, Q-Former, Perceiver |
| LLM Backbone | 텍스트 이해/생성 | LLaMA, Vicuna, Qwen |
2.4 Connector/Projector 유형¶
| 유형 | 설명 | 복잡도 | 대표 모델 |
|---|---|---|---|
| Linear | 단순 선형 변환 | 낮음 | LLaVA 1.0 |
| MLP | 다층 퍼셉트론 | 중간 | LLaVA 1.5, Qwen-VL |
| Q-Former | 학습된 쿼리로 추출 | 높음 | BLIP-2, InstructBLIP |
| Perceiver | Cross-attention 기반 | 높음 | Flamingo |
| Resampler | 고정 토큰 수 출력 | 중간 | IDEFICS |
2.4.1 Token Fusion 방식 비교 (실무 선택 기준)¶
Vision과 Language 토큰을 어떻게 융합할지는 MLLM 설계의 핵심 결정 사항.
Fusion 방식 분류:
| 방식 | 구현 | 장점 | 단점 |
|---|---|---|---|
| Concatenation | Vision + Text 토큰 단순 연결 | 구현 간단, LLM 수정 불필요 | 토큰 수 증가, 계산량 증가 |
| Cross-Attention | LLM 내부에 Cross-attn 레이어 삽입 | 토큰 수 제어 가능 | LLM 구조 수정 필요, 학습 복잡 |
| Gated Fusion | 학습 가능한 gate로 가중 합산 | 적응적 융합, 노이즈 억제 | 추가 파라미터, 학습 불안정 가능 |
상세 비교:
주요 MLLM별 Fusion 전략:
| 모델 | Fusion 방식 | Connector | 토큰 수 | 특징 |
|---|---|---|---|---|
| LLaVA 1.5 | Concat | 2-layer MLP | 576/img | 단순, 효과적 |
| LLaVA-NeXT | Concat | MLP + AnyRes | 가변 | 고해상도 지원 |
| Qwen-VL 2 | Concat | MLP | 256/img | 동적 해상도 |
| Qwen2-VL | Concat | MLP + MRope | 가변 | 3D RoPE로 위치 인코딩 |
| InternVL 2 | Concat | MLP | 256-1024 | PixelShuffle 압축 |
| Flamingo | Cross-Attn | Perceiver Resampler | 64/img | 토큰 효율적 |
| BLIP-2 | Cross-Attn | Q-Former | 32/img | 극단적 압축 |
| Idefics 2 | Concat + Perceiver | Perceiver | 64/img | 토큰 절약 |
Fusion 방식 선택 기준:
| 상황 | 권장 방식 | 이유 |
|---|---|---|
| 빠른 프로토타이핑 | Concatenation + MLP | LLM 변경 없이 즉시 사용 |
| 긴 문서 + 다수 이미지 | Cross-Attention | 토큰 수 제어 가능 |
| 단일 고해상도 이미지 | Concat + Dynamic Resolution | AnyRes 등으로 품질 유지 |
| 비디오 입력 | Cross-Attention 또는 압축 | 프레임당 토큰 최소화 필수 |
| 기존 LLM 체크포인트 활용 | Concatenation | 구조 변경 없음 |
토큰 수 vs 성능 트레이드오프:
[설계 판단 요약 - MLLM Token Fusion]
- 이 개념이 필요한 경우: 커스텀 MLLM 학습, Self-hosted MLLM 최적화
- 굳이 몰라도 되는 경우: GPT-4V, Claude Vision API 사용 (이미 최적화됨)
- 흔히 하는 잘못된 선택: Token fusion 구조를 고민하는 것 (API 사용 시 무의미)
- 버려도 되는 선택지: Cross-Attention 직접 구현 (기존 MLP 방식이 더 쉽고 효과적)
2.5 주요 MLLM 모델 비교 (API 사용자용)¶
| 모델 | Vision Encoder | Connector | LLM | 해상도 |
|---|---|---|---|---|
| GPT-4V | 비공개 | 비공개 | GPT-4 | 다양 |
| Claude 3 Vision | 비공개 | 비공개 | Claude 3 | 다양 |
| Gemini 1.5 Pro | 내장 | 내장 | Gemini | 다양 |
| LLaVA 1.6 | CLIP ViT-L/14 | MLP | Vicuna/LLaMA | 336-672 |
| Qwen-VL 2 | SigLIP | MLP | Qwen2 | 동적 |
| InternVL 2.5 | InternViT-6B | MLP | InternLM2 | 448-4K |
2.6 MLLM 학습 파이프라인¶
Phase 1: Pre-training (Alignment)
+------------------+ +------------------+
| Image-Text Pairs | --> | Vision-Language |
| (Large Scale) | | Alignment |
+------------------+ +------------------+
|
v
Only Projector Trained
LLM & Encoder Frozen
Phase 2: Instruction Tuning
+------------------+ +------------------+
| Instruction Data | --> | Full Model |
| (Curated) | | Fine-tuning |
+------------------+ +------------------+
|
v
All Components Trained
(or LoRA Applied)
[설계 판단 요약 - MLLM 전체]
- 이 개념이 필요한 경우: 이미지/비디오의 "의미"를 이해해야 할 때
- 굳이 몰라도 되는 경우: 텍스트 추출만 필요 (OCR + LLM)
- 흔히 하는 잘못된 선택: 모든 이미지 처리에 MLLM 사용 (비용 폭발)
- 버려도 되는 선택지: 커스텀 MLLM 학습 (GPT-4V/Claude Vision이 대부분 커버)
- 쓰지 말아야 할 조건: 단순 문서 OCR, 텍스트만 있는 이미지
3. LLMOps 파이프라인¶
이 섹션은 운영 관점에서 가장 중요함. RAG vs Fine-tuning 판단, 장애 대응, 되돌릴 수 있는/없는 선택을 다룬다.
3.1 LLMOps 개요¶
LLMOps는 대규모 언어 모델의 전체 라이프사이클을 관리하는 운영 체계다.
LLMOps vs MLOps:
| 항목 | MLOps | LLMOps |
|---|---|---|
| 모델 크기 | MB~GB | GB~TB |
| 학습 방식 | Full Training | Pre-train + Fine-tune |
| 입력 | 구조화 데이터 | 자연어 + 멀티모달 |
| 버전 관리 | 모델 가중치 | 모델 + 프롬프트 + RAG |
| 평가 | 정량 메트릭 | 정량 + 정성 + 안전성 |
| 추론 비용 | 낮음 | 높음 (토큰 기반) |
3.2 LLMOps 아키텍처 전체 구조¶
+===========================================================================+
| LLMOps Architecture |
+===========================================================================+
| |
| +-------------------------+ +-------------------------+ |
| | DATA LAYER | | MODEL LAYER | |
| +-------------------------+ +-------------------------+ |
| | | | | |
| | [Raw Data Sources] | | [Base Models] | |
| | - Public Corpora | | - GPT-4 | |
| | - Internal Docs | | - Claude | |
| | - User Feedback | | - LLaMA | |
| | | | - Qwen | |
| | | | | | | |
| | v | | v | |
| | [Data Processing] | | [Model Customization] | |
| | - Cleaning | | - Fine-tuning | |
| | - Chunking | | - LoRA/PEFT | |
| | - Embedding | | - Instruction Tuning | |
| | | | | |
| | | | | | | |
| | v | | v | |
| | [Vector Database] | | [Context-Specific LLM] | |
| | - Pinecone | | - Domain Adapted | |
| | - Weaviate | | - Task Specific | |
| | - Qdrant | | | |
| +------------+------------+ +------------+------------+ |
| | | |
| +---------------+--------------+ |
| | |
| +---------------v---------------+ |
| | LLM GATEWAY | |
| +-------------------------------+ |
| | - Unified API Interface | |
| | - Authentication & RBAC | |
| | - Rate Limiting | |
| | - Request Routing | |
| | - Prompt Template Mgmt | |
| | - A/B Testing | |
| | - Fallback Handling | |
| +---------------+---------------+ |
| | |
| +---------------v---------------+ |
| | INFERENCE LAYER | |
| +-------------------------------+ |
| | - Model Serving (vLLM, TGI) | |
| | - Batching & Streaming | |
| | - GPU Orchestration | |
| | - KV Cache Management | |
| | - Quantization | |
| +---------------+---------------+ |
| | |
| +----------------------+----------------------+ |
| | | | |
| v v v |
| +-----------+ +-----------+ +-----------+ |
| | Web App | | Mobile App| | API | |
| +-----------+ +-----------+ +-----------+ |
| | | | |
| +----------------------+----------------------+ |
| | |
| +---------------v---------------+ |
| | OBSERVABILITY LAYER | |
| +-------------------------------+ |
| | - Logging & Tracing | |
| | - Cost Monitoring | |
| | - Latency Metrics | |
| | - Quality Evaluation | |
| | - Hallucination Detection | |
| | - User Feedback Collection | |
| +---------------+---------------+ |
| | |
| v |
| +-------------------------------+ |
| | CONTINUOUS IMPROVEMENT | |
| +-------------------------------+ |
| | - RLHF Pipeline | |
| | - Model Versioning | |
| | - A/B Testing Analysis | |
| | - Retraining Triggers | |
| +-------------------------------+ |
| |
+===========================================================================+
3.3 핵심 구성 요소¶
3.3.1 Data Management¶
| 구성 요소 | 역할 | 도구 예시 |
|---|---|---|
| Data Ingestion | 다양한 소스에서 데이터 수집 | Airbyte, Fivetran |
| Data Processing | 정제, 청킹, 변환 | Spark, Pandas |
| Embedding | 텍스트를 벡터로 변환 | OpenAI Ada, Sentence-BERT |
| Vector Store | 임베딩 저장 및 검색 | Pinecone, Weaviate, Qdrant |
청킹 전략:
| 전략 | 설명 | 적합한 경우 |
|---|---|---|
| Fixed Size | 고정 문자/토큰 수로 분할 | 일반적인 문서 |
| Sentence | 문장 단위 분할 | Q&A, FAQ |
| Recursive | 구분자 기반 재귀 분할 | 구조화된 문서 |
| Semantic | 의미 기반 분할 | 복잡한 문서 |
3.3.2 Model Development¶
| 접근 방식 | 설명 | 리소스 요구량 |
|---|---|---|
| Prompt Engineering | 프롬프트만 수정 | 최소 |
| RAG | 외부 지식 검색 + 생성 | 낮음~중간 |
| Fine-tuning (Full) | 전체 가중치 업데이트 | 매우 높음 |
| Fine-tuning (PEFT) | 일부 파라미터만 업데이트 | 중간 |
| Pre-training | 처음부터 학습 | 극히 높음 |
RAG vs Fine-tuning: 역할 구분과 선택 기준¶
근본적인 차이:
| 측면 | RAG | Fine-tuning |
|---|---|---|
| 지식 주입 시점 | Inference-time (실시간) | Training-time (사전) |
| 지식 위치 | 외부 DB (모델 외부) | 모델 가중치 (모델 내부) |
| 업데이트 | DB만 갱신, 즉시 반영 | 재학습 필요 |
| 변경 대상 | "모델이 참조하는 정보" | "모델의 행동/스타일" |
RAG가 적합한 경우:
| 상황 | 이유 |
|---|---|
| 자주 변경되는 정보 (가격, 재고, 뉴스) | DB 업데이트만으로 반영 |
| 사실 기반 Q&A | 출처 명시 가능, 환각 감소 |
| 대규모 지식 베이스 (수만 문서) | 모델에 다 넣을 수 없음 |
| 개인화/사용자별 정보 | 사용자별 context 구성 |
| 빠른 프로토타이핑 | 학습 없이 즉시 시작 |
Fine-tuning이 적합한 경우:
| 상황 | 이유 |
|---|---|
| 특정 문체/톤 학습 (법률, 의료) | 행동 패턴은 가중치에 저장 |
| 도메인 전문 용어/약어 | 토큰화 수준에서 이해 필요 |
| 특정 포맷 출력 (JSON, 표) | 구조적 패턴 학습 |
| 추론 방식 변경 | Chain-of-thought 스타일 등 |
| 응답 속도 최적화 | RAG 검색 지연 제거 |
조합 전략 (RAG + Fine-tuning):
시나리오: 금융 고객 상담 봇
1. Fine-tuning으로:
- 금융 용어, 약어 이해 (예: "신용한도", "연체이자")
- 정중한 상담원 톤
- 민감 정보 처리 거부 패턴
2. RAG로:
- 최신 상품 정보, 이자율
- 고객별 계좌 정보
- FAQ, 정책 문서
결과: 도메인 전문가처럼 말하면서 + 최신/정확한 정보 제공
비용/효과 트레이드오프:
| 항목 | RAG | Fine-tuning | RAG + Fine-tuning |
|---|---|---|---|
| 초기 비용 | 낮음 (인프라 구축) | 높음 (GPU, 데이터 준비) | 높음 |
| 운영 비용 | 중간 (검색 비용) | 낮음 (추론만) | 중간 |
| 정확도 (사실) | 높음 | 중간 (환각 가능) | 높음 |
| 정확도 (스타일) | 낮음 (프롬프트 의존) | 높음 | 높음 |
| 유지보수 | 쉬움 (DB 업데이트) | 어려움 (재학습) | 중간 |
| 시작 시간 | 수일 | 수주 | 수주 |
의사결정 플로우:
실무에서 버려야 하는 것: - "Fine-tuning하면 모든 지식을 기억함" - 환각 발생 - "RAG만 쓰면 된다" - 스타일/행동 변경 불가 - "둘 중 하나만 선택해야 한다" - 조합이 최선인 경우 많음
3.3.3 Inference & Deployment¶
추론 최적화 기법:
| 기법 | 설명 | 효과 |
|---|---|---|
| Quantization | 가중치 정밀도 감소 (INT8, INT4) | 메모리 50-75% 절감 |
| KV Cache | 이전 토큰의 K,V 재사용 | 추론 속도 향상 |
| Continuous Batching | 동적 배치 처리 | 처리량 2-4배 증가 |
| Speculative Decoding | 작은 모델로 예측 후 검증 | 지연 시간 감소 |
| Tensor Parallelism | GPU간 레이어 분산 | 대형 모델 지원 |
3.3.4 Monitoring & Governance¶
모니터링 메트릭:
| 카테고리 | 메트릭 | 설명 |
|---|---|---|
| 성능 | Latency (TTFT, TPS) | Time-to-First-Token, Tokens/Second |
| 비용 | Token Usage | 입력/출력 토큰 사용량 |
| 품질 | Relevance Score | 응답 관련성 점수 |
| 안전성 | Hallucination Rate | 환각 발생 비율 |
| 사용자 | Feedback Score | 사용자 피드백 |
3.4 운영 관점: 장애 대응과 되돌릴 수 있는 선택¶
이 섹션은 프로덕션 운영 시 필수로 읽어야 함.
3.4.1 장애 났을 때 어디가 망가지나?¶
| 장애 지점 | 증상 | 진단 방법 | 복구 시간 |
|---|---|---|---|
| LLM API | 응답 없음, 5xx 에러 | API 상태 페이지 확인 | 제공자 의존 (수분~수시간) |
| Vector DB | 검색 결과 없음/오류 | 쿼리 테스트, 인덱스 상태 | 재시작: 수분, 재색인: 수시간 |
| Embedding 서비스 | 새 문서 색인 불가 | Embedding API 테스트 | 서비스 의존 |
| LLM Gateway | 라우팅 실패 | 로그 확인 | 수분 |
| 프롬프트 템플릿 | 응답 품질 저하 | A/B 테스트 비교 | 즉시 (롤백) |
장애 대응 우선순위: 1. Fallback 모델 준비: 주 모델 (GPT-4) 장애 시 → Claude/LLaMA로 전환 2. 캐시 활용: 자주 묻는 질문은 캐시로 응답 3. Graceful degradation: RAG 실패 시 → LLM만으로 응답 (품질 저하 고지)
3.4.2 되돌릴 수 있는 선택 vs 없는 선택¶
| 선택 | 되돌리기 | 비용 | 권장 |
|---|---|---|---|
| 프롬프트 변경 | 즉시 가능 | 없음 | 자유롭게 실험 |
| Top-K, Temperature 조정 | 즉시 가능 | 없음 | 자유롭게 실험 |
| Vector DB 데이터 추가 | 삭제로 복구 | 낮음 | 점진적 추가 |
| Chunk 크기 변경 | 재색인 필요 | 중간 | 신중하게 결정 |
| Embedding 모델 변경 | 전체 재색인 | 높음 | 처음에 신중히 선택 |
| Vector DB 교체 | 전체 마이그레이션 | 높음 | 처음에 신중히 선택 |
| Fine-tuned 모델 배포 | 롤백 가능하나 복잡 | 중간 | 버전 관리 필수 |
| Base 모델 변경 | 프롬프트 전체 재검토 | 높음 | 충분한 테스트 후 |
3.4.3 임베딩 모델 변경의 실제 비용¶
임베딩 모델을 바꾸면:
1. 기존 모든 벡터가 무효화됨 (차원, 의미 공간 다름)
2. 전체 문서 재임베딩 필요
3. 재색인 시간: 100K 문서 기준 수시간~하루
4. 비용: API 호출 비용 + 컴퓨팅 비용
예시: 10만 문서, 평균 1000 토큰/문서
- OpenAI text-embedding-3-small: ~$2
- OpenAI text-embedding-3-large: ~$13
- 시간: 병렬 처리로 1-2시간
임베딩 모델 선택 시 고려: - 처음에 충분히 좋은 모델 선택 (text-embedding-3-large 권장) - 나중에 더 좋은 모델 나와도 쉽게 바꾸기 어려움 - 비용보다 품질 우선 (재색인 비용이 더 큼)
3.4.4 Vector DB 교체 가능성¶
| Vector DB | 마이그레이션 용이성 | 고려사항 |
|---|---|---|
| pgvector | 쉬움 (SQL 덤프) | PostgreSQL 생태계 |
| Qdrant | 중간 (API 기반 추출) | 자체 포맷 |
| Pinecone | 어려움 (벤더 락인) | API로만 접근 |
| Weaviate | 중간 | GraphQL 인터페이스 |
| Chroma | 쉬움 (로컬 파일) | 소규모 전용 |
벤더 락인 최소화 전략: 1. 원본 문서와 메타데이터를 별도 저장소에 보관 2. 임베딩은 언제든 재생성 가능하게 파이프라인 구축 3. Vector DB 추상화 레이어 사용 (LangChain 등)
4. 실무 적용 패턴¶
4.1 RAG (Retrieval-Augmented Generation)¶
RAG는 외부 지식을 검색하여 LLM의 응답을 보강하는 패턴.
4.1.1 기본 RAG 아키텍처¶
+-----------------------------------------------------------------------+
| Basic RAG Pipeline |
+-----------------------------------------------------------------------+
| |
| [User Query] |
| | |
| v |
| +----+----+ |
| | Embedding| +------------------+ |
| | Model |--->| Query Vector | |
| +----------+ +--------+---------+ |
| | |
| v |
| +--------+---------+ |
| | Vector Database | |
| | (Similarity | |
| | Search) | |
| +--------+---------+ |
| | |
| v |
| +--------+---------+ |
| | Top-K Documents | |
| | (Retrieved) | |
| +--------+---------+ |
| | |
| v |
| +----------+ +--------+---------+ |
| | User | | Context | |
| | Query |--->| Construction | |
| +----------+ | (Query + Docs) | |
| +--------+---------+ |
| | |
| v |
| +--------+---------+ |
| | LLM | |
| | (Generation) | |
| +--------+---------+ |
| | |
| v |
| [Generated Response] |
| |
+-----------------------------------------------------------------------+
4.1.2 Advanced RAG 기법¶
| 기법 | 설명 | 해결하는 문제 |
|---|---|---|
| Long RAG | 긴 청크 단위 검색 | 컨텍스트 손실, 고비용 |
| Self-RAG | 검색 필요성 자체 판단 | 불필요한 검색, 정확도 |
| Corrective RAG | 검색 결과 평가 및 수정 | 오검색, 할루시네이션 |
| Graph RAG | 지식 그래프 기반 검색 | 관계 정보 손실 |
| Adaptive RAG | 쿼리 복잡도별 전략 | 일률적 처리 비효율 |
| Golden-Retriever | 도메인 용어 명확화 | 전문 용어 오해 |
Graph RAG: 언제 필요한가?¶
경고: 90% 프로젝트에 Graph RAG는 필요 없음.
Graph RAG 도입 전 확인: - Vector RAG로 정말 안 되는지 먼저 충분히 테스트했는가? - "관계 기반 질문"이 전체 쿼리의 20% 이상인가? - Knowledge Graph 구축/유지보수 리소스가 있는가? - 도입 실패 시 Vector RAG로 롤백할 수 있는가?
흔히 하는 잘못된 선택: "관계가 중요할 것 같으니 Graph RAG로 시작하자" → Vector RAG로 80% 해결 가능, 나머지 20%는 프롬프트 엔지니어링으로 커버
Graph RAG가 적합한 상황:
| 상황 | 이유 | 예시 |
|---|---|---|
| 엔티티 간 관계 중요 | Vector 검색은 관계 무시 | "A 회사의 CEO가 B 회사와 어떤 관계?" |
| Multi-hop 추론 | 여러 문서 연결 필요 | "X 약물의 부작용이 Y 질환에 미치는 영향" |
| 네트워크 구조 | 조직도, 계보, 의존성 | "이 라이브러리의 모든 의존성 패키지" |
| 시간순 이벤트 | 인과관계, 순서 | "이 사건 이후 어떤 결정이 내려졌나" |
Graph RAG 구현 개요:
Vector RAG vs Graph RAG:
| 측면 | Vector RAG | Graph RAG |
|---|---|---|
| 검색 대상 | 텍스트 청크 | 엔티티, 관계, 서브그래프 |
| 강점 | 의미적 유사성 | 구조적 관계 |
| 구축 비용 | 낮음 (임베딩만) | 높음 (KG 구축) |
| 유지보수 | 쉬움 | 어려움 (스키마 변경) |
| 적합한 질문 | "~란 무엇인가" | "A와 B의 관계는?" |
실무 권장: - 대부분의 경우 Vector RAG로 시작 - 관계 기반 질문이 20% 이상이면 Graph RAG 고려 - Hybrid 접근: Vector + Graph 결합
Adaptive RAG: 쿼리 분류 기준¶
경고: Adaptive RAG는 도입 비용과 실패 확률이 높음.
문제점: - Query Classifier가 틀리면 전체 파이프라인 실패 - 분류 기준 설계/튜닝에 많은 시간 소요 - 디버깅 복잡도 증가 (어느 단계에서 실패했는지 추적 어려움) - 단순 RAG 대비 지연 시간 2-3배 증가
먼저 시도할 것: 단순 RAG + 좋은 프롬프트로 90% 커버 가능한지 확인 Adaptive RAG가 정당화되는 경우: 쿼리 유형이 명확히 다르고, 각 유형별 최적 전략이 확실히 다를 때
Adaptive RAG 흐름:
Query Classifier 설계:
class QueryClassifier:
"""쿼리 복잡도에 따른 RAG 전략 분류"""
STRATEGIES = {
"no_retrieval": "LLM만으로 답변 가능",
"single_retrieval": "단순 검색 1회",
"iterative_retrieval": "여러 번 검색 필요",
"decomposition": "질문 분해 후 각각 검색"
}
def classify(self, query):
# 방법 1: 규칙 기반
if is_factual_knowledge(query): # "수도는?", "정의는?"
return "no_retrieval"
if has_single_entity(query): # "X에 대해 알려줘"
return "single_retrieval"
if has_comparison(query): # "A와 B 비교"
return "decomposition"
if is_complex_reasoning(query): # "왜 X가 Y에 영향을?"
return "iterative_retrieval"
# 방법 2: LLM 기반 분류
return self.llm_classify(query)
분류 기준 상세:
| 쿼리 유형 | 특징 | 전략 | 예시 |
|---|---|---|---|
| 일반 지식 | 모델이 이미 알 것 | No Retrieval | "파이썬이란?" |
| 단순 사실 | 단일 문서로 답변 | Single Retrieval | "2024 매출은?" |
| 비교/분석 | 여러 항목 필요 | Decomposition | "A vs B 장단점" |
| 복잡 추론 | 여러 단계 검색 | Iterative | "X의 원인과 해결책" |
| 범위 외 | DB에 없는 정보 | Fallback | "내일 날씨" |
Fallback 전략:
def adaptive_rag_with_fallback(query, max_retries=2):
strategy = classifier.classify(query)
for attempt in range(max_retries):
result = execute_strategy(strategy, query)
# 결과 품질 검증
if verify_answer_quality(result, query):
return result
# Fallback: 더 강력한 전략으로 업그레이드
strategy = upgrade_strategy(strategy)
# 최종 Fallback: 정직한 "모름" 응답
return generate_graceful_fallback(query)
def upgrade_strategy(current):
"""전략 업그레이드 순서"""
upgrade_path = {
"no_retrieval": "single_retrieval",
"single_retrieval": "iterative_retrieval",
"iterative_retrieval": "decomposition",
"decomposition": "web_search" # 외부 검색
}
return upgrade_path.get(current, "human_handoff")
비용/지연 관리:
| 전략 | 검색 횟수 | LLM 호출 | 예상 지연 | 비용 |
|---|---|---|---|---|
| No Retrieval | 0 | 1 | ~1s | 최저 |
| Single Retrieval | 1 | 1 | ~2s | 낮음 |
| Iterative (3회) | 3 | 3-4 | ~6s | 중간 |
| Decomposition | N (하위 질문 수) | N+1 | ~10s | 높음 |
실무에서 버려야 하는 것: - "모든 쿼리에 같은 파이프라인" - 비효율적 - "항상 가장 강력한 전략" - 비용/지연 폭발 - "Fallback 없이 실패 허용" - 사용자 경험 저하
4.1.3 RAG 구현 모범 사례 (실무 전략)¶
Chunk Size 트레이드오프¶
| Chunk Size | 장점 | 단점 | 적합한 경우 |
|---|---|---|---|
| 작음 (256-512) | 정확한 검색, 노이즈 적음 | Context 단편화, 의미 손실 | FAQ, 정의형 질문 |
| 중간 (512-1024) | 균형 잡힌 성능 | - | 일반적인 문서 Q&A |
| 큼 (1024-2048) | 풍부한 context, 연속성 | 검색 정확도 하락 | 서사형 콘텐츠, 요약 |
Chunk Size 결정 기준:
# 경험적 가이드
chunk_size = min(
avg_question_length * 3, # 질문의 3배 정도
model_context_limit / expected_top_k, # LLM context 고려
semantic_unit_size # 의미 단위 (단락, 섹션)
)
Overlap 전략:
# 일반적인 overlap: chunk_size의 10-20%
overlap = int(chunk_size * 0.15)
# 주의: overlap이 너무 크면
# - 중복 검색 증가
# - 스토리지 낭비
# - 같은 내용 반복 제공
# Overlap 대신 고려할 대안:
# 1. Sentence-aware splitting (문장 경계 존중)
# 2. Parent-child chunking (작은 chunk 검색, 큰 chunk 반환)
1. 청킹 최적화:
# 예시: Recursive Character Text Splitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
separators=["\n\n", "\n", ".", "!", "?", ",", " "]
)
# 더 나은 접근: Semantic Chunking
from langchain_experimental.text_splitter import SemanticChunker
semantic_splitter = SemanticChunker(
embeddings=embedding_model,
breakpoint_threshold_type="percentile",
breakpoint_threshold_amount=90
)
Metadata Filtering 전략¶
검색 전에 메타데이터로 후보를 줄여서 정확도와 속도 향상:
# 메타데이터 설계 예시
document_metadata = {
"source": "product_manual",
"category": "installation",
"product_id": "PRD-12345",
"date": "2024-01-15",
"language": "ko",
"version": "2.1"
}
# 검색 시 필터링
results = vector_store.similarity_search(
query=user_question,
filter={
"product_id": {"$eq": current_product},
"date": {"$gte": "2024-01-01"}
},
k=10
)
Metadata 활용 패턴:
| 패턴 | 용도 | 예시 |
|---|---|---|
| 범위 필터링 | 날짜, 버전 | date >= 2024-01 |
| 정확 매칭 | 카테고리, ID | category == "FAQ" |
| 권한 필터링 | 사용자 접근 제어 | access_level in user.permissions |
| 언어 필터링 | 다국어 지원 | language == user.locale |
2. Hybrid Search (키워드 + 시맨틱):
# 예시: BM25 + Vector Search 결합
from rank_bm25 import BM25Okapi
def hybrid_search(query, documents, embeddings, alpha=0.5):
# BM25 점수 (키워드 매칭)
bm25 = BM25Okapi(documents)
bm25_scores = bm25.get_scores(query.split())
# Vector 유사도 (의미 매칭)
query_embedding = get_embedding(query)
vector_scores = cosine_similarity(query_embedding, embeddings)
# 결합 (Reciprocal Rank Fusion 권장)
final_scores = alpha * normalize(bm25_scores) + (1-alpha) * vector_scores
return final_scores
# 더 나은 결합: Reciprocal Rank Fusion (RRF)
def rrf_fusion(rankings_list, k=60):
"""여러 ranking 결과를 RRF로 결합"""
scores = defaultdict(float)
for rankings in rankings_list:
for rank, doc_id in enumerate(rankings):
scores[doc_id] += 1.0 / (k + rank + 1)
return sorted(scores.items(), key=lambda x: x[1], reverse=True)
Hybrid Search가 필요한 경우:
| 쿼리 유형 | Vector Only | BM25 Only | Hybrid |
|---|---|---|---|
| "비밀번호 재설정 방법" | O | O | O |
| "PRD-12345 오류 코드" | X (의미 모호) | O | O |
| "부드러운 느낌의 소파" | O | X (키워드 없음) | O |
| "2024년 1월 매출 보고서" | X | O | O |
3. Re-ranking (Cross-Encoder):
# 예시: Cross-encoder 재순위화
from sentence_transformers import CrossEncoder
reranker = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
# 2단계 검색 파이프라인
def two_stage_retrieval(query, k_initial=50, k_final=5):
# Stage 1: 빠른 초기 검색 (Bi-encoder)
candidates = vector_store.similarity_search(query, k=k_initial)
# Stage 2: 정밀 재순위화 (Cross-encoder)
pairs = [[query, doc.page_content] for doc in candidates]
scores = reranker.predict(pairs)
# 상위 k_final 반환
reranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
return [doc for doc, score in reranked[:k_final]]
Reranker 비용/효과:
| 모델 | 속도 | 정확도 | 적합한 경우 |
|---|---|---|---|
| 없음 | 최고 | 낮음 | 낮은 지연 필수, 정확도 덜 중요 |
| ms-marco-MiniLM-L-6-v2 | 빠름 | 중간 | 일반적인 검색 |
| bge-reranker-large | 중간 | 높음 | 정확도 중요 |
| Cohere Rerank | API 의존 | 최고 | 상용 서비스, 비용 허용 |
RAG 실패 케이스와 대응 (꼭 읽어보세요)¶
이 섹션은 RAG 운영 시 가장 중요함. RAG가 실패하는 원인을 모르면 디버깅에 수일을 낭비함.
1. Chunking 잘못하면 생기는 문제:
| 잘못된 Chunking | 증상 | 진단 | 해결 |
|---|---|---|---|
| Chunk 너무 작음 | 답변이 단편적, 맥락 없음 | 검색된 chunk 확인 | Chunk 크기 증가, overlap 추가 |
| Chunk 너무 큼 | 관련 없는 내용 포함, 검색 정확도 하락 | Top-1 chunk의 관련성 확인 | Chunk 크기 감소 |
| 문장 중간에서 자름 | 의미 손실, 문법 오류 | Chunk 내용 직접 확인 | Sentence-aware splitting |
| 표/코드 블록 분리 | 구조 정보 손실 | 특수 포맷 chunk 확인 | 구조 인식 splitter 사용 |
2. Recall 낮을 때 원인 구분법:
def diagnose_low_recall(query, expected_doc, retrieved_docs):
"""Recall이 낮은 이유 진단"""
# 1. 쿼리 임베딩과 문서 임베딩 직접 비교
query_emb = embed(query)
doc_emb = embed(expected_doc)
similarity = cosine_similarity(query_emb, doc_emb)
if similarity < 0.5:
return "임베딩 미스매치: 쿼리와 문서의 어휘/표현이 다름 → HyDE 또는 Query Expansion"
# 2. Top-K에 포함되는지 확인
if expected_doc in retrieved_docs[:50]:
return "Top-K 너무 작음: K 증가 또는 Reranker 추가"
# 3. 메타데이터 필터 확인
if metadata_filter_applied:
return "메타데이터 필터가 문서를 제외함 → 필터 조건 완화"
# 4. 문서가 DB에 있는지 확인
if expected_doc not in vector_db:
return "문서가 색인되지 않음 → 색인 파이프라인 확인"
return "Embedding 모델 품질 문제 → 더 좋은 모델로 교체"
3. Top-K 늘릴수록 성능 떨어지는 지점:
4. RAG가 Hallucination을 못 줄이는 경우:
| 상황 | 왜 RAG가 실패하나 | 해결 |
|---|---|---|
| 검색 결과에 오류 정보 | RAG는 검색된 것을 신뢰함 | 문서 품질 관리, 최신화 |
| 질문이 문서 범위 밖 | 관련 없는 문서로 답변 생성 | Out-of-scope 감지 + 거부 |
| 여러 문서의 정보 혼합 | LLM이 잘못 조합 | 단일 소스 응답 강제 |
| 추론이 필요한 질문 | 문서에 직접적 답 없음 | Fine-tuning 또는 CoT 프롬프트 |
| 숫자/날짜 처리 | LLM 고유의 수학 약점 | 후처리로 검증, 도구 사용 |
RAG가 Hallucination을 줄이지 못하는 본질적 이유: - RAG는 "참조할 정보 제공"일 뿐, LLM이 그 정보를 정확히 사용하는지는 보장 안 함 - 출처 명시를 강제해도 LLM이 "인용하며 거짓말"할 수 있음 - 해결: 답변 후 검증 단계 추가 (NLI 기반, 또는 다른 LLM으로 검증)
5. 요약: RAG 실패 유형별 대응
| 실패 유형 | 증상 | 원인 | 대응 |
|---|---|---|---|
| 검색 실패 | 관련 문서 못 찾음 | 임베딩 미스매치, 쿼리 너무 짧음 | Query expansion, HyDE |
| Context 과다 | 너무 많은 정보로 혼란 | Top-K 과다, 중복 chunk | Reranking, K 줄이기 |
| Lost in Middle | 중간 정보 무시 | LLM 특성 | 중요 정보 앞뒤 배치 |
| 환각 | 없는 정보 생성 | Grounding 실패 | 출처 명시 강제, 검증 단계 |
| Out-of-scope | 질문이 DB 범위 밖 | 해당 문서 없음 | Fallback 응답, 범위 안내 |
| 오래된 정보 | 과거 정보로 답변 | DB 미갱신 | 정기 갱신 파이프라인 |
| 모호한 답변 | 여러 문서 정보 혼합 | Context 충돌 | 단일 소스 선호, 명확화 요청 |
[설계 판단 요약 - RAG 실패 대응]
- 먼저 확인할 것: 검색 결과 직접 확인 (LLM 문제인지 검색 문제인지 구분)
- 흔히 하는 잘못된 선택: "RAG 추가하면 hallucination 해결된다"
- 버려도 되는 선택지: 복잡한 파이프라인 (단순 RAG + 검증이 더 효과적)
- 쓰지 말아야 할 조건: 문서 품질이 낮을 때 RAG 도입 (garbage in, garbage out)
Query Expansion (HyDE) 예시:
def hypothetical_document_embedding(query, llm):
"""쿼리로 가상의 답변 문서를 생성하여 검색"""
prompt = f"다음 질문에 대한 답변을 작성하세요:\n질문: {query}\n답변:"
hypothetical_answer = llm.generate(prompt)
# 가상 답변을 임베딩하여 검색 (실제 답변과 유사한 문서 찾기)
return embedding_model.embed(hypothetical_answer)
4.2 Fine-tuning¶
4.2.1 Fine-tuning 접근 방식 비교¶
| 방식 | 학습 파라미터 | GPU 요구량 | 적합한 경우 |
|---|---|---|---|
| Full Fine-tuning | 전체 (100%) | 매우 높음 | 충분한 리소스, 대규모 데이터 |
| LoRA | 0.1-1% | 낮음 | 제한된 리소스 |
| QLoRA | 0.1-1% (양자화) | 매우 낮음 | 소비자 GPU |
| Prefix Tuning | ~0.1% | 낮음 | 빠른 적응 |
| Adapter | ~1-5% | 낮음 | 멀티태스크 |
4.2.2 LoRA (Low-Rank Adaptation)¶
LoRA는 가중치 행렬을 저차원 행렬의 곱으로 근사하여 효율적으로 파인튜닝하는 기법.
원리:
W' = W + Delta_W
Delta_W = A * B
where:
- W: 원본 가중치 (d x k)
- A: (d x r) 행렬
- B: (r x k) 행렬
- r: rank (r << min(d, k))
LoRA 적용 위치:
LoRA 코드 예시:
from peft import LoraConfig, get_peft_model
# LoRA 설정
lora_config = LoraConfig(
r=8, # rank
lora_alpha=32, # 스케일링 팩터
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
# 모델에 LoRA 적용
model = get_peft_model(base_model, lora_config)
# 학습 가능한 파라미터 확인
model.print_trainable_parameters()
# Output: trainable params: 4,194,304 || all params: 6,742,609,920 || trainable%: 0.06%
4.2.3 QLoRA (Quantized LoRA)¶
QLoRA는 베이스 모델을 4비트로 양자화하고 LoRA를 적용하여 메모리를 극적으로 절감함.
메모리 비교 (7B 모델 기준):
| 방식 | GPU 메모리 | 학습 가능 |
|---|---|---|
| Full FP32 | ~28GB | A100 (40GB) |
| Full FP16 | ~14GB | A100 (40GB) |
| LoRA FP16 | ~14GB | RTX 4090 (24GB) |
| QLoRA 4-bit | ~4GB | RTX 3090 (24GB) |
QLoRA 코드 예시:
from transformers import BitsAndBytesConfig
import torch
# 4비트 양자화 설정
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True
)
# 양자화된 모델 로드
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
quantization_config=bnb_config,
device_map="auto"
)
# LoRA 적용
model = get_peft_model(model, lora_config)
4.3 LLM Serving¶
4.3.1 Serving 엔진 비교¶
| 엔진 | 개발사 | 특징 | 최적 사용 케이스 |
|---|---|---|---|
| vLLM | UC Berkeley | PagedAttention, 고처리량 | 프로덕션 API 서빙 |
| TensorRT-LLM | NVIDIA | NVIDIA 최적화, 저지연 | NVIDIA GPU 환경 |
| TGI | HuggingFace | 쉬운 사용, 토큰 스트리밍 | 빠른 프로토타이핑 |
| llama.cpp | ggerganov | CPU/Edge 최적화 | 로컬/엣지 배포 |
| Ollama | Ollama | 로컬 실행 간편화 | 개발/테스트 |
| SGLang | Stanford | 구조화된 출력, 고속 | 복잡한 프롬프트 |
4.3.2 vLLM 핵심 기술¶
PagedAttention:
Traditional KV Cache:
+-----------------------------------+
| [ Token 1 KV ][ Token 2 KV ]...[ Token N KV ]
+-----------------------------------+
Contiguous Memory (Fragmentation Issue)
PagedAttention:
+--------+ +--------+ +--------+
| Page 1 | | Page 2 | | Page 3 | ...
| Token | | Token | | Token |
| 1-4 KV | | 5-8 KV | | 9-12 |
+--------+ +--------+ +--------+
Non-contiguous (Memory Efficient)
장점: - 메모리 단편화 해결 - 동적 메모리 할당 - 높은 배치 처리량
vLLM 배포 예시:
# OpenAI 호환 API 서버 실행
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-2-7b-chat-hf \
--tensor-parallel-size 2 \
--max-model-len 4096 \
--gpu-memory-utilization 0.9
4.3.3 Serving 최적화 체크리스트¶
| 항목 | 설명 | 권장값 |
|---|---|---|
| Batch Size | 동시 처리 요청 수 | 동적 (Continuous Batching) |
| Max Tokens | 최대 출력 토큰 | 태스크에 따라 조정 |
| Temperature | 생성 다양성 | 0.0-0.7 (태스크별) |
| GPU Memory | GPU 메모리 활용률 | 85-95% |
| Quantization | 양자화 수준 | INT8/INT4 (품질 허용시) |
4.4 Monitoring & Evaluation¶
4.4.1 LLM 평가 메트릭¶
자동 평가:
| 메트릭 | 측정 대상 | 적합한 태스크 |
|---|---|---|
| BLEU | n-gram 일치 | 번역 |
| ROUGE | 요약 품질 | 요약 |
| Perplexity | 모델 확신도 | 일반 |
| F1/Accuracy | 정확도 | 분류, QA |
| BERTScore | 의미적 유사도 | 생성 전반 |
LLM-as-Judge:
+------------------+ +------------------+
| Generated | | Reference/ |
| Response | --> | Criteria |
+------------------+ +------------------+
|
v
+------------------+
| Evaluator LLM |
| (GPT-4, Claude) |
+------------------+
|
v
+------------------+
| Score + Reason |
| (1-5 scale) |
+------------------+
4.4.2 Hallucination Detection¶
접근 방식:
| 방식 | 설명 | 구현 복잡도 |
|---|---|---|
| Self-Consistency | 여러 번 생성 후 일관성 확인 | 낮음 |
| RAG Grounding | 소스 문서와 대조 | 중간 |
| NLI-based | 함의 관계 검증 | 중간 |
| LLM-as-Judge | 다른 LLM으로 검증 | 높음 |
| Knowledge Graph | KG와 대조 검증 | 높음 |
Self-Consistency 예시:
def check_consistency(question, model, n_samples=5, temperature=0.7):
responses = []
for _ in range(n_samples):
response = model.generate(question, temperature=temperature)
responses.append(response)
# 응답 간 유사도 계산
embeddings = [get_embedding(r) for r in responses]
avg_similarity = compute_pairwise_similarity(embeddings)
# 낮은 유사도 = 높은 불확실성 (잠재적 환각)
return avg_similarity, responses
4.4.3 Observability 스택¶
+-----------------------------------------------------------------------+
| LLM Observability Stack |
+-----------------------------------------------------------------------+
| |
| +------------------+ +------------------+ +------------------+ |
| | Logging | | Tracing | | Metrics | |
| +------------------+ +------------------+ +------------------+ |
| | - Prompt/Response| | - Request Flow | | - Latency | |
| | - Token Counts | | - RAG Pipeline | | - Throughput | |
| | - Timestamps | | - LLM Calls | | - Error Rate | |
| | - User ID | | - Span Duration | | - Token Usage | |
| +--------+---------+ +--------+---------+ +--------+---------+ |
| | | | |
| +---------------------+---------------------+ |
| | |
| +------------v------------+ |
| | Observability Platform | |
| | (Langfuse, Arize, | |
| | Phoenix, Weights&Biases)| |
| +------------+-------------+ |
| | |
| +---------------------+---------------------+ |
| | | | |
| +--------v---------+ +--------v---------+ +--------v---------+ |
| | Dashboards | | Alerts | | Analysis | |
| +------------------+ +------------------+ +------------------+ |
| | - Cost Tracking | | - Latency Spike | | - A/B Testing | |
| | - Usage Trends | | - Error Surge | | - Prompt Optim | |
| | - Quality Scores | | - Cost Overflow | | - Drift Detect | |
| +------------------+ +------------------+ +------------------+ |
| |
+-----------------------------------------------------------------------+
5. 주요 구현 사례¶
이 섹션은 도구 선택 시 참조용. 모든 도구를 알 필요 없음. 필요할 때 검색하면 됨.
[설계 판단 요약 - 도구 선택]
- 시작할 때: LangChain + Chroma + OpenAI API (가장 빠른 시작)
- 프로덕션: vLLM + Qdrant/Pinecone + Langfuse
- 흔히 하는 잘못된 선택: 모든 도구를 직접 운영하려는 것
- 버려도 되는 선택지: "최신 도구"를 쫓는 것 (안정성 > 신규 기능)
5.1 오픈소스 프레임워크¶
5.1.1 LLM 프레임워크¶
| 프레임워크 | 주요 기능 | GitHub Stars | 특징 |
|---|---|---|---|
| LangChain | 체이닝, 에이전트 | 95k+ | 가장 범용적 |
| LlamaIndex | 데이터 연결, RAG | 35k+ | RAG 특화 |
| Haystack | 파이프라인, RAG | 17k+ | 프로덕션 중심 |
| DSPy | 프로그래밍적 프롬프트 | 18k+ | 최적화 중심 |
| Semantic Kernel | MS 에이전트 프레임워크 | 22k+ | 엔터프라이즈 |
5.1.2 Vector Database¶
| DB | 특징 | 호스팅 | 최대 벡터 |
|---|---|---|---|
| Pinecone | 완전 관리형, 고성능 | 클라우드 | 무제한 |
| Weaviate | GraphQL, 하이브리드 | 둘 다 | 수십억 |
| Qdrant | Rust 기반, 고성능 | 둘 다 | 수십억 |
| Milvus | 분산, 대규모 | 둘 다 | 수십억 |
| Chroma | 경량, 로컬 우선 | 둘 다 | 수백만 |
| pgvector | PostgreSQL 확장 | Self | 수백만 |
5.1.3 Serving & Inference¶
| 도구 | 개발사 | 오픈소스 | 주요 특징 |
|---|---|---|---|
| vLLM | UC Berkeley | Yes | PagedAttention, 고처리량 |
| TensorRT-LLM | NVIDIA | Yes | NVIDIA 최적화 |
| TGI | HuggingFace | Yes | 쉬운 사용 |
| llama.cpp | Community | Yes | CPU/Edge |
| Triton | NVIDIA | Yes | 멀티모델 서빙 |
5.1.4 Observability¶
| 도구 | 유형 | 주요 기능 |
|---|---|---|
| Langfuse | 오픈소스 | 트레이싱, 프롬프트 관리 |
| Phoenix | 오픈소스 | 드리프트 감지, 평가 |
| Weights & Biases | 상용 (무료 티어) | 실험 추적, 평가 |
| Arize AI | 상용 | 프로덕션 모니터링 |
| Helicone | 상용 (무료 티어) | 로깅, 비용 추적 |
5.2 기업 사례¶
5.2.1 주요 기업 LLMOps 사례¶
| 기업 | 사용 사례 | 기술 스택 | 규모 |
|---|---|---|---|
| Netflix | 콘텐츠 추천, 검색 | 자체 인프라 + OpenAI | 2억+ 사용자 |
| Spotify | 음악/팟캐스트 추천 | GCP + 자체 모델 | 6억+ 사용자 |
| Stripe | 문서 검색, 지원 | GPT-4 + RAG | 수백만 API 호출/일 |
| Notion | AI 글쓰기 어시스턴트 | Claude + 자체 인프라 | 3천만+ 사용자 |
| GitHub | Copilot | OpenAI Codex | 수백만 개발자 |
5.2.2 아키텍처 사례: RAG 기반 고객 지원¶
+-----------------------------------------------------------------------+
| Enterprise RAG Customer Support System |
+-----------------------------------------------------------------------+
| |
| [Customer Query via Chat/Email/Phone] |
| | |
| v |
| +----+----+ |
| | Intent | |
| | Router | |
| +----+----+ |
| | |
| +------------+------------+------------+ |
| | | | | |
| v v v v |
| [FAQ Search] [Doc Search] [Ticket History] [Product DB] |
| | | | | |
| +------------+------------+------------+ |
| | |
| v |
| +--------+--------+ |
| | Context Ranking | |
| | & Selection | |
| +--------+--------+ |
| | |
| v |
| +--------+--------+ |
| | Response LLM | |
| | (Claude/GPT-4) | |
| +--------+--------+ |
| | |
| v |
| +--------+--------+ |
| | Safety Filter | |
| | & Hallucination | |
| | Check | |
| +--------+--------+ |
| | |
| +------------+------------+ |
| | | |
| v v |
| [Confident] [Uncertain] |
| | | |
| v v |
| [Auto Response] [Human Handoff] |
| |
+-----------------------------------------------------------------------+
5.3 기술 스택 선택 가이드¶
5.3.1 규모별 권장 스택¶
소규모 (MVP/스타트업):
| 레이어 | 권장 도구 | 비용 |
|---|---|---|
| LLM | OpenAI API / Claude API | 사용량 기반 |
| Vector DB | Chroma / pgvector | 무료 |
| Framework | LangChain / LlamaIndex | 무료 |
| Serving | 직접 API 호출 | N/A |
| Monitoring | Langfuse (self-hosted) | 무료 |
중규모 (성장 기업):
| 레이어 | 권장 도구 | 비용 |
|---|---|---|
| LLM | OpenAI + 오픈소스 (Llama 3) | 혼합 |
| Vector DB | Qdrant Cloud / Pinecone | 월 $100-1K |
| Framework | LangChain + LangSmith | 월 $100+ |
| Serving | vLLM on Cloud GPU | 월 $500-5K |
| Monitoring | Langfuse Cloud / Arize | 월 $200+ |
대규모 (엔터프라이즈):
| 레이어 | 권장 도구 | 비용 |
|---|---|---|
| LLM | 자체 Fine-tuned + API 혼합 | 월 $10K+ |
| Vector DB | Milvus / Weaviate (자체 운영) | 인프라 |
| Framework | 자체 오케스트레이션 | 개발 비용 |
| Serving | TensorRT-LLM on H100 클러스터 | 월 $50K+ |
| Monitoring | 자체 구축 + 상용 도구 | 월 $5K+ |
6. 데이터베이스 인프라¶
이 섹션은 인프라 선택 시 참조용. 처음 시작할 때는 pgvector + PostgreSQL로 충분함.
[설계 판단 요약 - 데이터베이스]
- 시작할 때: pgvector (PostgreSQL 이미 있으면) 또는 Chroma (로컬)
- 프로덕션: Qdrant (Self-hosted) 또는 Pinecone (관리형)
- 흔히 하는 잘못된 선택: "Vector DB는 전용 솔루션이 필요하다" (pgvector로 100만 벡터까지 충분)
- 쓰지 말아야 할 조건: 벤더 락인이 문제될 때 Pinecone 선택
- 되돌리기 어려운 결정: Vector DB 종류 (마이그레이션 비용 높음)
6.1 Vector Database¶
벡터 임베딩을 저장하고 유사도 검색을 수행하는 특화된 데이터베이스.
6.1.1 주요 Vector DB 비교¶
| DB | 개발사 | 호스팅 | 특징 | GitHub Stars |
|---|---|---|---|---|
| Pinecone | Pinecone | 클라우드 전용 | 완전 관리형, 서버리스, 고성능 | N/A (상용) |
| Milvus | Zilliz | 둘 다 | 분산 처리, 대규모 지원, GPU 가속 | 30k+ |
| Weaviate | Weaviate | 둘 다 | GraphQL API, 하이브리드 검색, 모듈식 | 12k+ |
| Qdrant | Qdrant | 둘 다 | Rust 기반, 고성능, 필터링 강점 | 20k+ |
| Chroma | Chroma | 둘 다 | 경량, 로컬 우선, 개발 친화적 | 15k+ |
| pgvector | Supabase | Self | PostgreSQL 확장, 기존 인프라 활용 | 12k+ |
| FAISS | Meta | Self | 라이브러리, 연구/프로토타입용 | 30k+ |
| LanceDB | LanceDB | 둘 다 | 서버리스, 멀티모달, 빠른 시작 | 5k+ |
6.1.2 Vector DB 선택 가이드¶
+------------------+ +------------------+ +------------------+
| 규모/요구사항 | | 권장 DB | | 이유 |
+------------------+ +------------------+ +------------------+
| | | | | |
| 프로토타입/로컬 | --> | Chroma, LanceDB | --> | 설치 간편, 무료 |
| | | | | |
| PostgreSQL 환경 | --> | pgvector | --> | 기존 인프라 활용 |
| | | | | |
| 완전 관리형 SaaS | --> | Pinecone | --> | 운영 부담 최소화 |
| | | | | |
| 대규모 (10억+) | --> | Milvus | --> | 분산 처리 지원 |
| | | | | |
| 고성능 필터링 | --> | Qdrant | --> | 필터 + 벡터 최적 |
| | | | | |
| 하이브리드 검색 | --> | Weaviate | --> | BM25 + 벡터 통합 |
| | | | | |
+------------------+ +------------------+ +------------------+
6.1.3 Vector DB 성능 비교¶
| DB | QPS (1M 벡터) | 지연시간 (p99) | 메모리 효율 | 인덱스 타입 |
|---|---|---|---|---|
| Pinecone | 1000+ | <50ms | 높음 | 독자 |
| Milvus | 2000+ | <100ms | 중간 | IVF, HNSW, DiskANN |
| Qdrant | 1500+ | <30ms | 높음 | HNSW |
| Weaviate | 1000+ | <50ms | 중간 | HNSW |
| pgvector | 500+ | <100ms | 낮음 | IVF, HNSW |
6.2 전통적 데이터베이스¶
LLM 애플리케이션의 메타데이터, 사용자 정보, 설정 등을 저장함.
6.2.1 관계형 데이터베이스 (RDBMS)¶
| DB | 특징 | 적합한 용도 | 라이선스 |
|---|---|---|---|
| PostgreSQL | 확장성, JSON 지원, pgvector | 범용, 벡터 통합 | Open Source |
| MySQL | 성숙도, 광범위한 지원 | 웹 애플리케이션 | Open Source |
| Oracle | 엔터프라이즈, 고가용성 | 대기업, 금융 | Commercial |
| SQL Server | MS 생태계 통합 | Windows 환경 | Commercial |
| CockroachDB | 분산 SQL, 글로벌 | 멀티리전 | Open Core |
| TiDB | MySQL 호환, 분산 | 하이브리드 워크로드 | Open Source |
6.2.2 NoSQL 데이터베이스¶
| DB | 유형 | 특징 | 적합한 용도 |
|---|---|---|---|
| MongoDB | Document | 유연한 스키마, JSON | 로그, 채팅 기록 |
| DynamoDB | Key-Value | 서버리스, 자동 스케일링 | AWS 환경, 세션 |
| Cassandra | Wide Column | 고가용성, 쓰기 최적화 | 시계열, 로그 |
| ScyllaDB | Wide Column | Cassandra 호환, 고성능 | 고처리량 워크로드 |
| Neo4j | Graph | 관계 쿼리 최적화 | 지식 그래프, RAG |
| Firebase | Document | 실시간 동기화 | 모바일 앱 |
6.3 캐시 및 메시지 큐¶
6.3.1 캐시 시스템¶
| 시스템 | 특징 | LLM 용도 |
|---|---|---|
| Redis | 인메모리, 다양한 자료구조 | KV 캐시, 세션, Rate Limiting |
| Redis Stack | Redis + 벡터 검색 | 벡터 캐시 + 유사도 검색 |
| Memcached | 단순 KV, 멀티스레드 | 단순 캐시 |
| KeyDB | Redis 호환, 멀티스레드 | 고성능 캐시 |
| Dragonfly | Redis 호환, 고효율 | 대규모 캐시 |
LLM 캐시 전략:
+-----------------------------------------------------------------------+
| LLM Response Caching Strategy |
+-----------------------------------------------------------------------+
| |
| [User Query] |
| | |
| v |
| +----+----+ |
| | Hash | Query Normalization |
| | Query | (lowcase, trim, dedupe) |
| +----+----+ |
| | |
| v |
| +----+----+ +------------------+ |
| | Redis | --> | Cache Hit? | |
| | Lookup | +--------+---------+ |
| +----+----+ | |
| | Yes | No |
| +<------------------+ |
| | | |
| v v |
| [Return +-----+-----+ |
| Cached] | LLM Call | |
| +-----+-----+ |
| | |
| v |
| +-----+-----+ |
| | Cache | TTL: 1h ~ 24h |
| | Response | Key: hash(prompt + model + params) |
| +-----------+ |
| |
+-----------------------------------------------------------------------+
6.3.2 메시지 큐 / 스트리밍¶
| 시스템 | 특징 | LLM 용도 |
|---|---|---|
| Kafka | 분산 스트리밍, 고처리량 | 이벤트 로깅, 실시간 분석 |
| RabbitMQ | AMQP, 라우팅 유연 | 작업 큐, 비동기 처리 |
| Redis Streams | 경량 스트리밍 | 간단한 이벤트 처리 |
| Amazon SQS | 서버리스, AWS 통합 | 비동기 추론 요청 |
| Pulsar | 멀티테넌트, 지오복제 | 대규모 분산 환경 |
6.4 검색 엔진¶
키워드 검색과 하이브리드 검색을 위한 인프라.
| 엔진 | 특징 | 벡터 검색 지원 | 적합한 용도 |
|---|---|---|---|
| Elasticsearch | 분산, 실시간, 성숙도 | kNN (8.0+) | 로그 분석, 전문 검색 |
| OpenSearch | ES 포크, AWS 통합 | kNN | AWS 환경, 오픈소스 |
| Typesense | 경량, 빠른 시작 | 지원 | 소규모 검색 |
| Meilisearch | 간단, 오타 허용 | 미지원 | 프로토타입 |
| Algolia | SaaS, 고성능 | AI 검색 | 이커머스, 검색 UX |
하이브리드 검색 아키텍처:
[User Query]
|
+------------------+------------------+
| | |
v v v
+----------+ +----------+ +----------+
| Keyword | | Semantic | | Sparse |
| (BM25) | | (Dense) | | (SPLADE) |
+----+-----+ +----+-----+ +----+-----+
| | |
v v v
+----+-----+ +----+-----+ +----+-----+
|Elastic | |Vector DB | |Vector DB |
|Search | |(Dense) | |(Sparse) |
+----+-----+ +----+-----+ +----+-----+
| | |
+--------+--------+--------+--------+
|
v
+--------+--------+
| Reciprocal Rank |
| Fusion (RRF) |
+--------+--------+
|
v
[Re-ranked Results]
7. 워크플로우 오케스트레이션¶
이 섹션은 참조용. 대부분의 LLM 프로젝트는 단순한 스크립트로 시작해도 됨. 오케스트레이터는 파이프라인이 복잡해진 후에 도입해도 늦지 않다.
[설계 판단 요약 - 오케스트레이션]
- 시작할 때: 단순 Python 스크립트 + cron
- 복잡해지면: Prefect (Pythonic) 또는 Airflow (표준)
- 흔히 하는 잘못된 선택: MVP 단계에서 Airflow 도입 (오버엔지니어링)
- 버려도 되는 선택지: 모든 LLM 호출을 DAG로 관리하는 것
7.1 데이터/ML 파이프라인 오케스트레이터¶
7.1.1 주요 오케스트레이터 비교¶
| 도구 | 개발사 | 패러다임 | 학습 곡선 | 적합한 용도 |
|---|---|---|---|---|
| Apache Airflow | Airbnb/Apache | DAG-as-code (Python) | 높음 | 복잡한 데이터 파이프라인 |
| Prefect | Prefect | 함수 데코레이터 | 중간 | Pythonic 워크플로우 |
| Dagster | Dagster | 자산 중심 (Asset) | 중간 | 데이터 품질, 관측성 |
| n8n | n8n.io | 비주얼 노드 | 낮음 | 노코드/로우코드 자동화 |
| Temporal | Temporal | 코드 기반, 내구성 | 중간 | 장기 실행 워크플로우 |
| Temporal | Temporal | 워크플로우-as-code | 높음 | 분산 시스템, 내구성 |
| Argo Workflows | CNCF | K8s 네이티브 (YAML) | 높음 | Kubernetes 환경 |
| Luigi | Spotify | Task 기반 | 낮음 | 배치 처리 |
| Mage | Mage | 하이브리드 (GUI+코드) | 낮음 | 빠른 프로토타이핑 |
7.1.2 상세 비교¶
Apache Airflow:
# Airflow DAG 예시
from airflow import DAG
from airflow.operators.python import PythonOperator
from datetime import datetime
def extract_data():
# 데이터 추출 로직
pass
def process_with_llm():
# LLM 처리 로직
pass
with DAG(
'llm_pipeline',
start_date=datetime(2024, 1, 1),
schedule_interval='@daily'
) as dag:
extract = PythonOperator(
task_id='extract',
python_callable=extract_data
)
process = PythonOperator(
task_id='process_llm',
python_callable=process_with_llm
)
extract >> process
Prefect:
# Prefect Flow 예시
from prefect import flow, task
from prefect.tasks import task_input_hash
from datetime import timedelta
@task(cache_key_fn=task_input_hash, cache_expiration=timedelta(hours=1))
def fetch_documents(source: str):
# 문서 가져오기
pass
@task(retries=3, retry_delay_seconds=10)
def embed_documents(docs: list):
# 임베딩 생성
pass
@task
def store_vectors(embeddings: list):
# 벡터 DB 저장
pass
@flow(name="RAG Indexing Pipeline")
def rag_indexing_flow(source: str):
docs = fetch_documents(source)
embeddings = embed_documents(docs)
store_vectors(embeddings)
return {"status": "success", "count": len(docs)}
Dagster:
# Dagster Asset 예시
from dagster import asset, AssetExecutionContext
import pandas as pd
@asset(
group_name="llm_data",
metadata={"description": "Raw documents for RAG"}
)
def raw_documents(context: AssetExecutionContext):
# 문서 로드
docs = load_documents()
context.log.info(f"Loaded {len(docs)} documents")
return docs
@asset(
group_name="llm_data",
deps=[raw_documents]
)
def document_embeddings(raw_documents):
# 임베딩 생성
embeddings = embed(raw_documents)
return embeddings
@asset(
group_name="llm_data",
deps=[document_embeddings]
)
def vector_index(document_embeddings):
# 벡터 인덱스 구축
index = build_index(document_embeddings)
return index
7.1.3 오케스트레이터 선택 가이드¶
| 상황 | 권장 도구 | 이유 |
|---|---|---|
| 대규모 데이터 파이프라인 | Airflow | 성숙도, 커뮤니티, 확장성 |
| Python 중심 팀 | Prefect | Pythonic API, 쉬운 시작 |
| 데이터 품질/관측성 중시 | Dagster | Asset 기반, 메타데이터 |
| Kubernetes 환경 | Argo Workflows | K8s 네이티브 |
| 분산 트랜잭션 | Temporal | 내구성, 복구 |
| 빠른 프로토타입 | Mage, Luigi | 낮은 진입 장벽 |
7.2 Low-Code/No-Code 자동화¶
비개발자도 사용 가능한 워크플로우 자동화 도구.
| 도구 | 유형 | LLM 통합 | 가격 | 적합한 용도 |
|---|---|---|---|---|
| n8n | Self-hosted/Cloud | OpenAI, Claude 노드 | 무료/유료 | 범용 자동화 |
| Zapier | Cloud | AI Actions | 유료 | 비즈니스 자동화 |
| Make (Integromat) | Cloud | OpenAI 모듈 | 유료 | 복잡한 시나리오 |
| Activepieces | Self-hosted | AI 피스 | 오픈소스 | Zapier 대안 |
| Windmill | Self-hosted | 스크립트 기반 | 오픈소스 | 개발자 친화적 |
n8n LLM 워크플로우 예시:
+----------+ +-----------+ +----------+ +----------+
| Webhook | --> | OpenAI | --> | Postgres | --> | Slack |
| Trigger | | Chat | | Insert | | Message |
+----------+ +-----------+ +----------+ +----------+
| | | |
v v v v
HTTP POST GPT-4 분석 결과 저장 알림 전송
7.3 LLM 특화 오케스트레이션¶
| 프레임워크 | 특징 | 주요 기능 |
|---|---|---|
| LangChain | 범용 LLM 프레임워크 | 체인, 에이전트, 메모리 |
| LangGraph | 그래프 기반 에이전트 | 상태 머신, 멀티에이전트 |
| LlamaIndex | 데이터 연결 특화 | RAG, 인덱싱, 쿼리 |
| Haystack | 프로덕션 중심 | 파이프라인, 평가 |
| CrewAI | 멀티에이전트 | 역할 기반 협업 |
| AutoGen | MS 에이전트 프레임워크 | 대화형 에이전트 |
8. 클라우드 AI 서비스¶
이 섹션은 클라우드 선택 시 참조용. 특정 클라우드에 종속되어 있지 않다면, 직접 API 호출이 더 유연함.
[설계 판단 요약 - 클라우드 AI]
- AWS 환경: Bedrock (Claude 사용 가능, 관리 편함)
- Azure 환경: Azure OpenAI (GPT-4 사용, 규정준수 용이)
- GCP 환경: Vertex AI (Gemini 사용)
- 클라우드 무관: OpenAI/Anthropic 직접 API (가장 유연)
- 흔히 하는 잘못된 선택: 클라우드 AI 서비스가 항상 더 좋다고 생각
- 쓰지 말아야 할 조건: 멀티클라우드 전략일 때 특정 클라우드 AI에 종속
8.1 AWS AI 서비스¶
| 서비스 | 용도 | 지원 모델 |
|---|---|---|
| Amazon Bedrock | 관리형 LLM API | Claude, Llama, Titan, Mistral |
| SageMaker | ML 플랫폼 | 커스텀 모델, HuggingFace |
| SageMaker JumpStart | 사전 학습 모델 | Llama, Falcon, Stability |
| Kendra | 엔터프라이즈 검색 | RAG 통합 |
| Q Business | 비즈니스 AI 어시스턴트 | 문서 Q&A |
Bedrock 아키텍처:
+-----------------------------------------------------------------------+
| AWS Bedrock Architecture |
+-----------------------------------------------------------------------+
| |
| +------------------+ |
| | Application | |
| | (Lambda/EC2) | |
| +--------+---------+ |
| | |
| v |
| +--------+---------+ +------------------+ |
| | Bedrock API | --> | Model Selection | |
| | (invoke_model) | | Claude/Llama/etc | |
| +--------+---------+ +--------+---------+ |
| | | |
| +------------------------+ |
| | |
| +--------v---------+ +------------------+ |
| | Knowledge Bases | <-> | OpenSearch | |
| | (RAG) | | Serverless | |
| +--------+---------+ +------------------+ |
| | |
| v |
| +--------+---------+ +------------------+ |
| | Guardrails | --> | Content Filter | |
| | (Safety) | | PII Detection | |
| +------------------+ +------------------+ |
| |
+-----------------------------------------------------------------------+
8.2 Azure AI 서비스¶
| 서비스 | 용도 | 지원 모델 |
|---|---|---|
| Azure OpenAI | OpenAI 모델 호스팅 | GPT-4, GPT-3.5, Embeddings |
| Azure AI Studio | 통합 AI 개발 환경 | 다양한 모델 |
| Azure ML | ML 플랫폼 | 커스텀 모델 |
| Cognitive Search | 엔터프라이즈 검색 | 벡터 + 키워드 |
| Copilot Studio | 챗봇 빌더 | 커스텀 코파일럿 |
Azure OpenAI 통합:
# Azure OpenAI 사용 예시
from openai import AzureOpenAI
client = AzureOpenAI(
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
api_version="2024-02-15-preview",
azure_endpoint="https://<resource>.openai.azure.com"
)
response = client.chat.completions.create(
model="gpt-4", # deployment name
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
]
)
8.3 Google Cloud AI 서비스¶
| 서비스 | 용도 | 지원 모델 |
|---|---|---|
| Vertex AI | 통합 ML 플랫폼 | Gemini, PaLM, Claude |
| Vertex AI Search | 엔터프라이즈 검색 | RAG, 문서 검색 |
| Model Garden | 모델 카탈로그 | 오픈소스 + 독점 |
| Gemini API | Gemini 모델 API | Gemini Pro/Flash |
| Document AI | 문서 처리 | OCR, 추출 |
8.4 클라우드 AI 서비스 비교¶
| 항목 | AWS Bedrock | Azure OpenAI | Vertex AI |
|---|---|---|---|
| 강점 | 다양한 모델 선택 | OpenAI 독점, 엔터프라이즈 | Google 모델, 통합 |
| 모델 | Claude, Llama, Titan | GPT-4, GPT-3.5 | Gemini, Claude |
| RAG | Knowledge Bases | AI Search | Vertex Search |
| 파인튜닝 | 일부 모델 | GPT-3.5/4 | Gemini |
| 가격 | 토큰 기반 | 토큰 기반 | 토큰 기반 |
| 리전 | 제한적 | 글로벌 | 글로벌 |
| 규정준수 | SOC2, HIPAA | SOC2, HIPAA, FedRAMP | SOC2, HIPAA |
9. 기업 실무 통합 스택¶
이 섹션은 엔터프라이즈 환경 참조용. 스타트업/MVP는 이 복잡한 스택이 필요 없음.
[설계 판단 요약 - 기업 스택]
- 스타트업: OpenAI API + Supabase (pgvector) + Vercel
- 중견기업: 자체 호스팅 고려, 규정준수 확인
- 대기업: 이 섹션의 레퍼런스 아키텍처 참조
- 흔히 하는 잘못된 선택: 스타트업이 엔터프라이즈 스택을 따라하는 것
- 버려도 되는 선택지: "확장성"을 위해 처음부터 복잡한 구조 (YAGNI)
9.1 산업별 레퍼런스 아키텍처¶
9.1.1 금융 서비스 (규제 중심)¶
+-----------------------------------------------------------------------+
| Financial Services LLM Stack |
+-----------------------------------------------------------------------+
| |
| [Compliance Layer] |
| +------------------+ +------------------+ +------------------+ |
| | PII Detection | | Content Filter | | Audit Logging | |
| | (Presidio) | | (Guardrails) | | (Splunk) | |
| +------------------+ +------------------+ +------------------+ |
| |
| [LLM Layer] |
| +------------------+ +------------------+ |
| | Azure OpenAI | | Self-hosted | |
| | (GPT-4) | | (Llama 3, vLLM) | |
| +------------------+ +------------------+ |
| |
| [Data Layer] |
| +------------------+ +------------------+ +------------------+ |
| | PostgreSQL | | Elasticsearch | | Pinecone | |
| | (Metadata) | | (Search) | | (Vector) | |
| +------------------+ +------------------+ +------------------+ |
| |
| [Orchestration] |
| +------------------+ +------------------+ |
| | Airflow | | LangChain | |
| | (Batch) | | (Real-time) | |
| +------------------+ +------------------+ |
| |
+-----------------------------------------------------------------------+
특징:
- Private VPC 배포
- 데이터 레지던시 준수
- 감사 로그 필수
- 모델 버전 관리
9.1.2 이커머스 (확장성 중심)¶
+-----------------------------------------------------------------------+
| E-commerce LLM Stack |
+-----------------------------------------------------------------------+
| |
| [Frontend] |
| +------------------+ +------------------+ +------------------+ |
| | Search Bar | | Chatbot | | Recommendations | |
| | (Hybrid Search) | | (Customer Svc) | | (Personalization)| |
| +------------------+ +------------------+ +------------------+ |
| |
| [API Gateway] |
| +------------------+ |
| | Kong / AWS API | Rate Limiting, Caching, Auth |
| | Gateway | |
| +------------------+ |
| |
| [LLM Layer] |
| +------------------+ +------------------+ +------------------+ |
| | Claude API | | vLLM Cluster | | Embedding Svc | |
| | (Complex Query) | | (High Volume) | | (Product Search) | |
| +------------------+ +------------------+ +------------------+ |
| |
| [Data Layer] |
| +------------------+ +------------------+ +------------------+ |
| | MongoDB | | Redis Cluster | | Qdrant | |
| | (Products) | | (Cache) | | (Embeddings) | |
| +------------------+ +------------------+ +------------------+ |
| |
| [Streaming] |
| +------------------+ +------------------+ |
| | Kafka | | Flink | |
| | (Events) | | (Real-time ML) | |
| +------------------+ +------------------+ |
| |
+-----------------------------------------------------------------------+
특징:
- 글로벌 CDN
- Auto-scaling
- 실시간 개인화
- A/B 테스트
9.1.3 스타트업 (비용 효율 중심)¶
+-----------------------------------------------------------------------+
| Startup LLM Stack (Cost-Efficient) |
+-----------------------------------------------------------------------+
| |
| [API Layer] |
| +------------------+ |
| | FastAPI | Simple, Python-native |
| | + Uvicorn | |
| +------------------+ |
| |
| [LLM Layer] |
| +------------------+ +------------------+ |
| | OpenAI API | | Ollama (Local) | |
| | (Production) | | (Development) | |
| +------------------+ +------------------+ |
| |
| [Data Layer] |
| +------------------+ +------------------+ |
| | Supabase | | Chroma | |
| | (PostgreSQL + | | (Vector DB) | |
| | pgvector) | | | |
| +------------------+ +------------------+ |
| |
| [Orchestration] |
| +------------------+ +------------------+ |
| | LangChain | | Prefect (Free) | |
| +------------------+ +------------------+ |
| |
| [Monitoring] |
| +------------------+ |
| | Langfuse | Self-hosted, Open Source |
| | (Self-hosted) | |
| +------------------+ |
| |
+-----------------------------------------------------------------------+
예상 비용: $100-500/월 (트래픽에 따라)
9.2 기업별 실제 사용 스택 (공개 정보 기반)¶
| 기업 | LLM | Vector DB | Orchestration | Monitoring |
|---|---|---|---|---|
| Notion | Claude | 자체 | 자체 | 자체 |
| Duolingo | GPT-4 | 비공개 | 자체 | DataDog |
| Stripe | GPT-4 | Pinecone | 자체 | 자체 |
| Shopify | 다양 | 자체 | 자체 | DataDog |
| Airbnb | GPT-4 | 자체 | Airflow | 자체 |
| 다양 | 자체 | 자체 | 자체 | |
| Canva | Claude/GPT | 비공개 | 자체 | 자체 |
9.3 기술 스택 선택 체크리스트¶
+-----------------------------------------------------------------------+
| Tech Stack Selection Checklist |
+-----------------------------------------------------------------------+
[1. 팀 역량]
[ ] Python 숙련도: _______
[ ] DevOps 경험: _______
[ ] ML/AI 경험: _______
[2. 규모 및 요구사항]
[ ] 예상 QPS: _______
[ ] 데이터 볼륨: _______
[ ] 지연시간 요구: _______
[3. 규정 준수]
[ ] GDPR: [ ]Yes [ ]No
[ ] HIPAA: [ ]Yes [ ]No
[ ] SOC2: [ ]Yes [ ]No
[ ] 데이터 레지던시: _______
[4. 예산]
[ ] 월간 인프라 예산: $_______
[ ] 월간 API 비용 예산: $_______
[5. 기존 인프라]
[ ] 클라우드: [ ]AWS [ ]Azure [ ]GCP [ ]기타
[ ] 컨테이너: [ ]K8s [ ]ECS [ ]없음
[ ] 기존 DB: _______
[6. 권장 스택]
예산 < $500/월:
- LLM: OpenAI API / Claude API
- Vector DB: Chroma / pgvector
- Orchestration: LangChain
- Monitoring: Langfuse (self-hosted)
예산 $500-5000/월:
- LLM: OpenAI API + vLLM (오픈소스)
- Vector DB: Qdrant / Weaviate
- Orchestration: Prefect / Dagster
- Monitoring: Langfuse Cloud / Helicone
예산 > $5000/월:
- LLM: Multi-model (API + Self-hosted)
- Vector DB: Pinecone / Milvus
- Orchestration: Airflow / Temporal
- Monitoring: 상용 솔루션 (Arize, DataDog)
+-----------------------------------------------------------------------+
9.4 통합 아키텍처 다이어그램¶
+===========================================================================+
| Enterprise LLM Platform Architecture |
+===========================================================================+
| |
| +---------------------+ +---------------------+ +---------------------+ |
| | DATA SOURCES | | PROCESSING | | STORAGE | |
| +---------------------+ +---------------------+ +---------------------+ |
| | | | | | | |
| | - Internal Docs | | - Document Parser | | - PostgreSQL | |
| | - CRM (Salesforce) | | (Unstructured) | | (Metadata) | |
| | - Confluence | | - Chunking | | | |
| | - Slack History | | (LangChain) | | - Elasticsearch | |
| | - Email Archives | | - Embedding | | (Full-text) | |
| | - Product DB | | (OpenAI/Cohere) | | | |
| | | | | | - Qdrant | |
| +----------+----------+ +----------+----------+ | (Vector) | |
| | | | | |
| v v | - Redis | |
| +----------+------------------------+----------+ | (Cache) | |
| | Workflow Orchestration | | | |
| | (Airflow / Prefect / Dagster) | | - S3/GCS | |
| +---------------------------------------------+ | (Documents) | |
| +---------------------+ |
| |
| +---------------------------------------------------------------------+ |
| | API GATEWAY LAYER | |
| +---------------------------------------------------------------------+ |
| | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | Authentication | | Rate Limiting | | Load Balancing | | |
| | | (OAuth/JWT) | | (Redis) | | (nginx/HAProxy) | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | |
| +---------------------------------------------------------------------+ |
| |
| +---------------------------------------------------------------------+ |
| | LLM SERVING LAYER | |
| +---------------------------------------------------------------------+ |
| | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | External APIs | | Self-Hosted | | Specialized | | |
| | | | | | | | | |
| | | - OpenAI GPT-4 | | - vLLM Cluster | | - Embedding Svc | | |
| | | - Anthropic | | (Llama 3) | | (text-embed) | | |
| | | Claude | | - TGI | | | | |
| | | - Azure OpenAI | | (Mistral) | | - Reranker Svc | | |
| | | | | | | (cross-enc) | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | |
| +---------------------------------------------------------------------+ |
| |
| +---------------------------------------------------------------------+ |
| | APPLICATION LAYER | |
| +---------------------------------------------------------------------+ |
| | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | RAG Pipeline | | Agent Framework | | Evaluation | | |
| | | (LlamaIndex) | | (LangGraph) | | (RAGAS) | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | Chatbot Service | | Search Service | | Analysis Service | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | |
| +---------------------------------------------------------------------+ |
| |
| +---------------------------------------------------------------------+ |
| | OBSERVABILITY LAYER | |
| +---------------------------------------------------------------------+ |
| | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | Tracing | | Metrics | | Logging | | |
| | | (Langfuse) | | (Prometheus) | | (Loki/ELK) | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | Dashboards | | Alerting | | Cost Tracking | | |
| | | (Grafana) | | (PagerDuty) | | (Custom) | | |
| | +------------------+ +------------------+ +------------------+ | |
| | | |
| +---------------------------------------------------------------------+ |
| |
+===========================================================================+
참고 자료¶
논문¶
- Vaswani, A., et al. (2017). "Attention Is All You Need." NeurIPS 2017.
-
arXiv: https://arxiv.org/abs/1706.03762
-
Hu, E.J., et al. (2021). "LoRA: Low-Rank Adaptation of Large Language Models."
-
arXiv: https://arxiv.org/abs/2106.09685
-
Lewis, P., et al. (2020). "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks."
-
arXiv: https://arxiv.org/abs/2005.11401
-
Yin, S., et al. (2024). "A Survey on Multimodal Large Language Models."
-
arXiv: https://arxiv.org/abs/2306.13549
-
Wadekar, S., et al. (2024). "The Evolution of Multimodal Model Architectures."
-
arXiv: https://arxiv.org/abs/2405.17927
-
Kwon, W., et al. (2023). "Efficient Memory Management for Large Language Model Serving with PagedAttention."
- SOSP 2023
온라인 자료¶
- TrueFoundry LLMOps Architecture: https://www.truefoundry.com/blog/llmops-architecture
- vLLM Documentation: https://docs.vllm.ai/
- LangChain Documentation: https://docs.langchain.com/
- HuggingFace PEFT: https://github.com/huggingface/peft
Last Updated: 2025-07