티스토리 뷰
LLM 실전 활용 2: 임베딩과 벡터 데이터베이스 — RAG 성능의 80%는 여기서 결정된다
RAG를 처음 만들었을 때,
“어? 답은 나오네?” 싶다가
며칠 지나면 꼭 이런 말이 나온다.“근데 왜 중요한 문서를 못 찾지?”
“비슷한 질문인데 결과가 들쭉날쭉해…”이때 대부분의 문제가
👉 모델이 아니라 임베딩과 벡터 검색에서 발생한다.솔직히 말하면,
RAG의 성능 80%는 ‘임베딩 + 벡터 DB 설계’에서 갈린다.
이번 글은
- 임베딩이 정확히 무엇인지
- 벡터 검색이 왜 키워드 검색과 다른지
- 문서를 어떻게 쪼개야 하는지
- 벡터 DB를 어떻게 선택해야 하는지
를 실무 기준 + 시행착오 중심으로 정리한다.
1. 임베딩(Embedding)을 한 문장으로 정의하면
“텍스트의 ‘의미’를 숫자 좌표로 바꾼 것”
LLM은 글자를 그대로 이해하지 않는다.
모든 텍스트는 결국 고차원 벡터 공간의 점이다.
- 비슷한 의미 → 가까운 위치
- 다른 의미 → 먼 위치
이게 가능해지면,
“단어가 달라도 의미가 비슷하면 찾는다”가 된다.
2. 키워드 검색 vs 벡터 검색 (실무 차이)
질문
“휴가 규정 알려줘”
문서
“연차 사용 기준은 근속 연수에 따라 다르다”
키워드 검색
- 휴가 ≠ 연차
- ❌ 매칭 실패
벡터 검색
- 휴가 ≈ 연차
- ⭕ 의미 기반 매칭 성공
👉 RAG에서 키워드 검색은 거의 의미가 없다.
3. 임베딩 모델이 하는 일 (중요)
임베딩 모델은 다음을 학습했다:
- 단어 간 의미 관계
- 문장 구조
- 문맥 패턴
그래서 이런 게 가능하다:
- “연봉” ↔ “급여”
- “해지” ↔ “계약 종료”
- “환불” ↔ “반품”
RAG에서 임베딩 모델은
‘의미 변환기’ 라고 생각하면 된다.
4. 문서를 그냥 넣으면 RAG는 망한다
이건 진짜 많이 겪는 실수다.
❌ “PDF 하나 통째로 임베딩하면 되겠지?”
안 된다. 이유는 단순하다.
이유 1: 임베딩은 평균을 낸다
- 문서가 길수록
- 의미가 섞여서 애매한 벡터가 된다
이유 2: 검색 정확도 급락
- 질문은 보통 한 문장
- 문서는 수십 페이지
→ 거리 계산이 왜곡된다
그래서 반드시 필요한 개념이 있다.
5. Chunking — 문서를 쪼개는 기술
“RAG는 문서를 ‘어떻게 쪼갰는가’로 평가된다.”
기본 원칙
- 한 chunk = 하나의 의미 단위
- 너무 길면 ❌
- 너무 짧아도 ❌
실무에서 많이 쓰는 기준
- 300~500 tokens
- 문단 단위 우선
- 제목/조항 기준 분리
예:
[제5조 연차 규정]
연차는 근속 연수에 따라…
👉 제목 + 내용은 반드시 같이 간다.
(제목 없는 chunk는 검색에서 약하다)
6. Chunk Size, 감으로 정하면 안 된다
너무 작으면?
- 문맥 부족
- 답변이 단편적
너무 크면?
- 검색 정확도 하락
- 불필요한 정보 포함
권장 전략
- 기본: 400 tokens
- Overlap: 50~100 tokens
Overlap은:
- 문맥 끊김 방지
- 문단 경계 문제 해결
7. 벡터 데이터베이스(Vector DB)의 역할
벡터 DB는 단순 저장소가 아니다.
“수십만 개의 고차원 벡터 중
가장 가까운 것들을 빠르게 찾는 엔진”
필요한 기능:
- 빠른 근사 최근접 탐색(ANN)
- 메타데이터 필터링
- 스케일 확장
8. 대표적인 벡터 DB, 언제 뭘 쓰나?
FAISS
- 로컬/서버 내장형
- 빠름, 가벼움
- 운영 편의성 ❌
👉 PoC, 실험, 내부 도구
Chroma
- 개발 친화적
- RAG 튜토리얼 최강자
- 대규모 트래픽엔 한계
👉 초기 서비스, MVP
Pinecone / Weaviate / Qdrant
- 클라우드 기반
- 확장성, 안정성
- 비용 발생
👉 상용 서비스
9. 임베딩 + 벡터 DB 기본 파이프라인
문서 수집
→ Chunking
→ Embedding 생성
→ Vector DB 저장
→ 질문 임베딩
→ Top-K 검색
→ Context 구성
→ LLM 호출
이 중에서
- Chunking
- Embedding 품질
- Top-K 설정
이 세 개가 성능 체감의 핵심이다.
10. 실제로 많이 하는 실수 TOP 5
1️⃣ 문서 통째로 임베딩
2️⃣ Chunk에 제목 없음
3️⃣ Top-K 너무 작음 (1~2개)
4️⃣ 임베딩 모델 아무거나 선택
5️⃣ 검색 결과 검증 안 함
RAG는 “붙이면 끝”이 아니다.
검색 품질 튜닝이 전부다.
11. 최소 임베딩 + 벡터 검색 코드 (실행 가능)
from sentence_transformers import SentenceTransformer
import numpy as np
docs = [
"연차는 근속 연수에 따라 최대 25일까지 부여됩니다.",
"병가는 연 10일까지 사용할 수 있습니다.",
"재택근무는 팀장 승인 하에 가능합니다."
]
model = SentenceTransformer("all-MiniLM-L6-v2")
doc_vecs = model.encode(docs)
query = "휴가 규정 알려줘"
query_vec = model.encode([query])[0]
def cos_sim(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
scores = [cos_sim(query_vec, v) for v in doc_vecs]
top_idx = np.argmax(scores)
print("검색 결과:", docs[top_idx])
✔ 실제 RAG 검색의 핵심 구조
✔ 그대로 실행 가능
12. 이 글의 진짜 메시지
RAG는 LLM 기술이 아니라
검색 시스템 설계 문제다.
- 모델 바꾸기 전에
- 프롬프트 바꾸기 전에
- 임베딩과 문서 구조부터 의심하자
LLM,RAG,임베딩,벡터데이터베이스,VectorDB,FAISS,Chroma,AI서비스,LLM실무,검색증강생성
'study > ML' 카테고리의 다른 글
- Total
- Today
- Yesterday
- 웹개발
- Python
- 압박면접
- nextJS
- 개발블로그
- NestJS
- JAX
- Express
- Next.js
- REACT
- PostgreSQL
- llm
- DevOps
- Redis
- 백엔드개발
- rag
- seo 최적화 10개
- ai철학
- fastapi
- Docker
- Prisma
- SEO최적화
- node.js
- kotlin
- flax
- CI/CD
- LangChain
- 딥러닝
- 쿠버네티스
- JWT
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
