13장. 임베딩과 벡터 검색 이해하기
1. RAG의 핵심은 “관련 문서를 잘 찾는 것”이다
12장에서 RAG는 검색과 생성을 결합한 구조라고 설명했다.
사용자 질문
→ 관련 문서 검색
→ 검색된 문서를 AI에게 전달
→ AI가 문서를 근거로 답변 생성
이 흐름에서 가장 중요한 단계 중 하나가 관련 문서 검색이다.
AI가 아무리 답변을 잘 만들어도, 검색된 문서가 엉뚱하면 좋은 답변이 나올 수 없다.
예를 들어 사용자가 이렇게 물었다고 해보자.
하트를 충전했는데 반영이 안 됐다고 하면 어떻게 처리해?
이 질문에 대해 RAG가 다음 문서를 찾았다면 좋은 답변을 만들 수 있다.
결제 실패 및 하트 미반영 처리 매뉴얼
하지만 다음 문서를 찾았다면 답변 품질이 떨어진다.
방송 입장 장애 대응 문서
회원 탈퇴 정책 문서
채팅 금칙어 운영 기준
검색 단계에서 이미 잘못된 문서를 가져왔기 때문이다.
RAG에서 LLM은 검색된 문서를 보고 답한다.
따라서 검색 결과가 좋지 않으면 AI는 잘못된 근거를 바탕으로 답하거나, 문서에 없는 내용을 추측할 가능성이 커진다.
그래서 RAG를 제대로 만들려면 먼저 이 질문을 이해해야 한다.
“사용자 질문과 의미가 비슷한 문서를 어떻게 찾을 것인가?”
이때 필요한 개념이 임베딩과 벡터 검색이다.
임베딩은 문장이나 문서를 숫자 배열로 바꾸는 방식이다.
벡터 검색은 그 숫자 배열을 비교해서 의미가 비슷한 문서를 찾는 방식이다.
2. 일반 검색과 벡터 검색은 다르다
기존 검색은 주로 키워드 중심으로 동작한다.
예를 들어 문서 안에 “하트 충전”이라는 단어가 있으면,
사용자가 “하트 충전”이라고 검색했을 때 그 문서를 찾을 수 있다.
사용자 검색어:
하트 충전
문서 내용:
하트 충전 후 반영되지 않는 경우 PG 승인 여부를 확인한다.
이 경우는 잘 찾는다.
하지만 사용자가 다르게 표현하면 어떨까?
사용자 검색어:
결제했는데 재화가 안 들어왔어요.
문서에는 “하트 충전”이라고 되어 있고,
사용자는 “결제”, “재화”라고 표현했다.
키워드 검색만 사용하면 이 문서를 놓칠 수 있다.
사람이 보면 두 문장은 비슷한 의미다.
하트 충전 후 반영되지 않음
결제했는데 재화가 안 들어옴
하지만 단어가 다르기 때문에 단순 키워드 검색은 잘 찾지 못할 수 있다.
이런 문제를 해결하기 위해 벡터 검색을 사용한다.
벡터 검색은 단어가 정확히 일치하는지만 보는 것이 아니라,
문장 전체의 의미가 얼마나 비슷한지를 비교한다.
키워드 검색:
같은 단어가 있는지 찾는다.
벡터 검색:
의미가 비슷한지 찾는다.
예를 들어 다음 문장들은 표현은 다르지만 비슷한 의미다.
하트를 충전했는데 반영이 안 됐어요.
결제 후 재화가 지급되지 않았습니다.
충전은 됐는데 잔액이 늘지 않았어요.
카드 결제는 됐는데 하트가 안 들어왔습니다.
벡터 검색은 이런 문장들을 비슷한 것으로 찾는 데 강하다.
그래서 RAG에서는 벡터 검색이 자주 사용된다.
3. 컴퓨터는 문장의 의미를 그대로 이해하지 못한다
사람은 문장을 읽고 의미를 이해한다.
하트를 충전했는데 반영이 안 됐어요.
사람은 이 문장을 보고 다음 의미를 이해할 수 있다.
사용자가 결제 또는 충전은 했지만,
서비스 내 재화가 지급되지 않은 상황
하지만 컴퓨터는 문장을 그대로 의미로 이해하지 못한다.
컴퓨터가 비교하고 계산하려면 문장을 숫자로 바꿔야 한다.
예를 들어 문장을 다음과 같은 숫자 배열로 바꿀 수 있다.
하트를 충전했는데 반영이 안 됐어요.
→ [0.12, -0.45, 0.87, 0.03, ...]
이 숫자 배열을 벡터라고 부른다.
문장을 벡터로 바꾸면 컴퓨터는 두 문장이 얼마나 비슷한지 계산할 수 있다.
예를 들어 다음 두 문장이 있다고 해보자.
문장 A:
하트를 충전했는데 반영이 안 됐어요.
문장 B:
결제 후 재화가 지급되지 않았습니다.
이 두 문장을 각각 벡터로 바꾼다.
문장 A → [0.12, -0.45, 0.87, 0.03, ...]
문장 B → [0.10, -0.43, 0.82, 0.05, ...]
두 벡터가 비슷하면 의미도 비슷하다고 판단할 수 있다.
반대로 전혀 다른 문장은 벡터도 멀어진다.
문장 C:
비밀번호를 잊어버렸어요.
문장 C → [-0.72, 0.11, -0.09, 0.64, ...]
A와 B는 가까운 벡터가 되고,
A와 C는 먼 벡터가 되는 식이다.
이것이 임베딩의 기본 개념이다.
벡터는 여러 숫자로 이루어진 배열이다.
AI에서는 문장, 이미지, 문서 같은 데이터를 숫자 배열로 표현할 때 사용한다.
4. 임베딩은 의미를 숫자로 바꾸는 과정이다
임베딩은 텍스트를 의미가 담긴 숫자 벡터로 바꾸는 과정이다.
조금 더 쉽게 말하면,
문장을 컴퓨터가 비교할 수 있는 좌표로 바꾸는 것이다.
예를 들어 지도를 생각해보자.
서울, 부산, 대구 같은 도시는 지도 위의 좌표로 표현할 수 있다.
서울 → 위도, 경도
부산 → 위도, 경도
대구 → 위도, 경도
좌표가 있으면 두 도시가 얼마나 가까운지 계산할 수 있다.
임베딩도 비슷하다.
문장을 의미 공간 안의 좌표로 바꾼다고 생각하면 된다.
하트 충전 실패 문의 → 의미 공간의 한 지점
결제 후 재화 미반영 문의 → 가까운 지점
비밀번호 찾기 문의 → 다른 방향의 지점
방송 끊김 문의 → 또 다른 지점
의미가 비슷한 문장들은 가까운 위치에 놓인다.
의미가 다른 문장들은 멀리 떨어진다.
가까운 문장:
- 하트를 충전했는데 반영이 안 됐어요.
- 결제했는데 재화가 안 들어왔어요.
- 카드 승인은 됐는데 하트가 없습니다.
먼 문장:
- 비밀번호를 잊어버렸어요.
- 방송이 자꾸 끊겨요.
- 닉네임을 변경하고 싶어요.
임베딩 모델은 이런 변환을 담당한다.
문장
→ 임베딩 모델
→ 벡터
RAG에서는 문서 조각도 임베딩하고, 사용자 질문도 임베딩한다.
그다음 두 벡터가 얼마나 가까운지 비교해서 관련 문서를 찾는다.
5. 임베딩은 왜 RAG에 필요한가
RAG에서는 사용자의 질문과 관련 있는 문서를 찾아야 한다.
문제는 사용자가 문서와 같은 표현을 쓰지 않는다는 점이다.
문서에는 이렇게 적혀 있을 수 있다.
PG 승인 완료 후 재화 지급 이력이 없는 경우 충전 처리 로그를 확인한다.
하지만 사용자는 이렇게 묻는다.
하트 결제했는데 안 들어왔어요. 뭐 확인해야 해요?
키워드만 보면 겹치는 단어가 많지 않을 수 있다.
문서에는 “PG”, “재화 지급”, “충전 처리 로그”가 있고,
질문에는 “하트”, “결제”, “안 들어옴”이 있다.
하지만 의미는 관련 있다.
임베딩을 사용하면 이런 의미적 관련성을 찾을 수 있다.
사용자 질문:
하트 결제했는데 안 들어왔어요.
의미:
결제는 되었지만 재화 지급이 되지 않은 상황
관련 문서:
PG 승인 후 재화 지급 이력 확인 절차
즉, 임베딩은 사용자의 자연스러운 표현과 문서의 공식적인 표현 사이를 연결해준다.
RAG에서 임베딩이 필요한 이유는 다음과 같다.
- 질문과 문서의 표현이 달라도 의미로 찾을 수 있다.
- 긴 문서 중 관련 부분만 찾을 수 있다.
- 내부 용어와 사용자 표현을 연결할 수 있다.
- 키워드 검색이 놓치는 문서를 찾을 수 있다.
예를 들어 방송 플랫폼에서는 같은 의미를 여러 방식으로 표현할 수 있다.
사용자 표현:
방이 안 들어가져요.
운영팀 표현:
방송방 입장 실패
개발 문서 표현:
stream room join API timeout
장애 보고서 표현:
방송 입장 요청 지연
이 표현들은 단어는 다르지만 관련성이 높다.
임베딩과 벡터 검색은 이런 차이를 줄여준다.
6. 문서도 임베딩하고 질문도 임베딩한다
RAG에서 임베딩은 두 곳에 사용된다.
1. 문서를 저장할 때
2. 사용자가 질문할 때
먼저 문서를 저장할 때다.
사내 문서나 운영 매뉴얼을 작은 조각으로 나누고,
각 조각을 임베딩한다.
문서 조각 A:
하트 충전 후 미반영 시 PG 승인 여부를 확인한다.
→ 벡터 A
문서 조각 B:
비밀번호 재설정은 이메일 인증 후 가능하다.
→ 벡터 B
문서 조각 C:
방송방 입장 실패 시 Redis와 WebSocket 상태를 확인한다.
→ 벡터 C
이 벡터들을 벡터DB에 저장한다.
벡터DB:
- 벡터 A + 문서 내용 + 문서 제목
- 벡터 B + 문서 내용 + 문서 제목
- 벡터 C + 문서 내용 + 문서 제목
그다음 사용자가 질문할 때도 질문을 임베딩한다.
사용자 질문:
하트 결제했는데 안 들어왔어요.
→ 질문 벡터 Q
이제 질문 벡터 Q와 문서 벡터들을 비교한다.
질문 벡터 Q와 가까운 문서:
1. 문서 조각 A
2. 문서 조각 C
3. 문서 조각 B
가장 가까운 문서 조각을 검색 결과로 가져온다.
이 결과를 LLM에게 전달한다.
사용자 질문:
하트 결제했는데 안 들어왔어요.
검색된 문서:
하트 충전 후 미반영 시 PG 승인 여부를 확인한다.
LLM 답변:
하트 충전 후 반영되지 않은 경우 먼저 PG 승인 여부를 확인해야 합니다...
이것이 RAG의 기본 검색 흐름이다.
7. 벡터DB는 의미 검색을 위한 저장소다
임베딩된 벡터는 어딘가에 저장해야 한다.
그 역할을 하는 것이 벡터DB다.
벡터DB는 일반적인 데이터베이스와 비슷하지만,
숫자 벡터를 저장하고 비슷한 벡터를 빠르게 찾는 데 특화되어 있다.
일반 DB에서는 보통 이런 검색을 한다.
SELECT *
FROM documents
WHERE title LIKE '%환불%';
이 검색은 “환불”이라는 단어가 포함된 문서를 찾는다.
반면 벡터DB에서는 의미가 비슷한 문서를 찾는다.
질문:
결제 취소하고 싶어요.
벡터 검색 결과:
- 환불 정책 문서
- 결제 취소 처리 매뉴얼
- 미사용 하트 환불 기준
질문에 “환불”이라는 단어가 없어도,
의미가 비슷하면 관련 문서를 찾을 수 있다.
벡터DB에는 보통 다음 정보가 함께 저장된다.
- 문서 조각 ID
- 원본 문서 ID
- 문서 제목
- 문서 내용
- 임베딩 벡터
- 작성일 또는 수정일
- 접근 권한
- 문서 링크
- 섹션 제목
예를 들어 하나의 데이터는 다음과 같이 볼 수 있다.
{
"chunkId": "chunk_001",
"documentId": "doc_payment_policy",
"title": "결제 실패 및 하트 미반영 처리 매뉴얼",
"section": "2. PG 승인 후 미반영 처리",
"content": "PG 승인 완료 후 서비스 충전 내역이 없는 경우 충전 처리 로그를 확인한다.",
"embedding": [
0.12,
-0.45,
0.87,
0.03
],
"updatedAt": "2026-05-01",
"allowedRoles": [
"operation",
"admin"
]
}
벡터DB는 단순히 벡터만 저장하는 곳이 아니다.
검색 결과를 답변에 활용하려면 원문 내용, 제목, 권한 정보, 출처 링크 같은 메타데이터도 함께 필요하다.
벡터DB는 임베딩된 벡터를 저장하고, 의미가 비슷한 벡터를 빠르게 찾는 데이터베이스다.
RAG에서는 질문과 관련 있는 문서 조각을 찾는 데 사용된다.
8. 유사도 검색은 얼마나 가까운지를 계산한다
벡터 검색은 결국 “얼마나 가까운가”를 계산하는 일이다.
사용자 질문 벡터와 문서 벡터를 비교해서 가까운 순서대로 문서를 찾는다.
질문 벡터 Q
문서 벡터 A: 가까움
문서 벡터 B: 멀다
문서 벡터 C: 중간
결과는 보통 점수와 함께 나온다.
검색 결과:
1. 결제 실패 및 하트 미반영 처리 매뉴얼 - score 0.91
2. 하트 충전 정책 문서 - score 0.84
3. 환불 처리 기준 - score 0.72
4. 비밀번호 재설정 절차 - score 0.21
점수가 높을수록 질문과 의미가 비슷하다고 볼 수 있다.
다만 점수는 절대적인 정답이 아니다.
검색 점수가 높아도 실제로는 답변에 필요 없는 문서일 수 있고,
점수가 조금 낮아도 중요한 문서일 수 있다.
예를 들어 사용자가 이렇게 묻는다.
하트가 안 들어왔는데 환불 가능한가요?
이 질문에는 두 종류의 문서가 필요할 수 있다.
- 하트 미반영 처리 매뉴얼
- 환불 정책 문서
가장 높은 점수 문서 하나만 가져오면 환불 정책을 놓칠 수 있다.
그래서 RAG에서는 보통 상위 여러 개의 문서를 가져온다.
top_k = 5
→ 가장 관련 높은 문서 5개 검색
하지만 너무 많이 가져오면 문제가 생긴다.
- AI에게 전달하는 문맥이 길어진다.
- 비용이 증가한다.
- 불필요한 문서가 섞인다.
- AI가 핵심 문서를 놓칠 수 있다.
검색 결과 개수는 적절히 조정해야 한다.
top_k는 검색 결과 중 상위 몇 개를 가져올지 정하는 값이다.
예를 들어 top_k가 5이면 가장 관련성이 높은 문서 조각 5개를 가져온다.
9. 키워드 검색과 벡터 검색은 함께 쓰는 것이 좋다
벡터 검색은 의미 검색에 강하다.
하지만 항상 벡터 검색만 좋은 것은 아니다.
키워드 검색이 더 좋은 경우도 있다.
예를 들어 사용자가 특정 API 이름을 검색한다고 해보자.
GET /broadcast/start
이런 경우는 의미 검색보다 정확한 키워드 검색이 더 좋을 수 있다.
또 특정 에러 코드도 마찬가지다.
ERR_PAYMENT_409
IVS_STREAM_TIMEOUT
HTTP 429
이런 값은 의미보다 정확한 문자열 일치가 중요하다.
벡터 검색은 다음 상황에 강하다.
- 표현이 다르지만 의미가 비슷한 문서를 찾을 때
- 사용자가 자연어로 질문할 때
- 문서 표현과 사용자 표현이 다를 때
- 긴 문서 중 관련 내용만 찾을 때
키워드 검색은 다음 상황에 강하다.
- API 이름
- 에러 코드
- 설정 키
- 함수명
- 클래스명
- 티켓 번호
- 정확한 용어
그래서 실무에서는 둘을 함께 쓰는 것이 좋다.
이를 하이브리드 검색이라고 부를 수 있다.
사용자 질문
→ 키워드 검색
→ 벡터 검색
→ 결과 병합
→ 중복 제거
→ 재정렬
→ 상위 문서 반환
예를 들어 사용자가 이렇게 묻는다.
ERR_PAYMENT_409 발생하면 어떻게 처리해?
키워드 검색은 ERR_PAYMENT_409가 포함된 문서를 정확히 찾는다.
벡터 검색은 결제 실패 처리 매뉴얼처럼 의미상 관련 있는 문서를 찾는다.
둘을 합치면 더 좋은 결과가 된다.
하이브리드 검색은 키워드 검색과 벡터 검색을 함께 사용하는 방식이다.
정확한 용어 검색과 의미 기반 검색을 모두 활용할 수 있다.
10. 문서 분할 방식이 검색 품질을 좌우한다
임베딩과 벡터 검색을 사용할 때 문서를 어떻게 나누느냐가 중요하다.
긴 문서를 통째로 하나의 벡터로 만들면 문제가 생길 수 있다.
예를 들어 “운영 매뉴얼”이라는 100페이지짜리 문서가 있다고 해보자.
이 문서 안에는 여러 주제가 들어 있다.
- 로그인 장애 대응
- 결제 실패 대응
- 방송 입장 장애 대응
- Redis 장애 대응
- 고객 공지 기준
- 배포 롤백 절차
이 문서를 통째로 임베딩하면 너무 많은 의미가 섞인다.
사용자가 “하트 충전이 안 됐을 때”를 물었을 때,
문서 전체는 관련 있어 보이지만 정확한 위치를 찾기 어렵다.
그래서 문서를 작은 단위로 나눠야 한다.
운영 매뉴얼
→ 로그인 장애 대응
→ 결제 실패 대응
→ 방송 입장 장애 대응
→ Redis 장애 대응
→ 고객 공지 기준
→ 배포 롤백 절차
이렇게 나눈 조각을 chunk라고 한다.
chunk가 너무 크면 여러 주제가 섞인다.
너무 큰 chunk:
결제, 환불, 정산, 고객 공지가 한 조각에 섞임
chunk가 너무 작으면 문맥이 부족해진다.
너무 작은 chunk:
“먼저 승인 여부를 확인한다.”
이 문장만 보면 무엇의 승인인지 알 수 없다.
좋은 chunk는 하나의 의미 단위를 담아야 한다.
좋은 chunk:
하트 충전 후 서비스에 반영되지 않은 경우,
먼저 PG 승인 여부를 확인한다.
PG 승인이 완료되었지만 충전 내역이 없는 경우,
충전 처리 로그를 확인하고 재처리 여부를 판단한다.
이 정도면 질문과 매칭되기도 좋고,
AI가 답변에 사용할 문맥도 충분하다.
문서 분할은 RAG 품질을 좌우하는 중요한 작업이다.
11. chunk 크기를 정할 때 고려할 점
chunk 크기는 너무 크지도, 너무 작지도 않아야 한다.
적절한 크기는 문서 종류와 질문 방식에 따라 달라진다.
예를 들어 FAQ 문서는 한 질문과 답변이 하나의 chunk가 되기 좋다.
Q. 하트 충전 후 반영되지 않으면 어떻게 하나요?
A. 먼저 PG 승인 여부를 확인하고, 승인 완료 후 미반영이면 충전 로그를 확인합니다.
운영 매뉴얼은 섹션 단위로 나누는 것이 좋을 수 있다.
2.1 결제 승인 확인
2.2 충전 처리 로그 확인
2.3 재처리 기준
2.4 고객 안내 문구
API 문서는 엔드포인트 단위로 나누는 것이 좋다.
POST /broadcast/start
GET /broadcast/{id}
POST /broadcast/stop
chunk 크기를 정할 때는 다음을 고려한다.
- 하나의 chunk가 하나의 주제를 담고 있는가?
- 질문에 답할 만큼 문맥이 충분한가?
- 너무 많은 주제가 섞이지 않았는가?
- 출처로 보여주기 적절한 단위인가?
- AI에게 전달했을 때 비용이 과도하지 않은가?
실무에서는 처음부터 완벽한 chunk 크기를 찾기 어렵다.
그래서 샘플 질문으로 테스트해봐야 한다.
질문:
하트 충전 후 반영이 안 되면 어떻게 처리해?
검색 결과:
정확한 결제 미반영 처리 chunk가 나오는가?
환불 정책만 나오지는 않는가?
너무 긴 운영 매뉴얼 전체가 나오지는 않는가?
검색 결과를 보면서 chunk 크기를 조정한다.
chunk는 RAG에서 문서를 검색하기 좋은 단위로 나눈 조각이다.
너무 크면 주제가 섞이고, 너무 작으면 문맥이 부족해진다.
12. overlap은 문맥이 끊기는 것을 줄인다
문서를 chunk로 나눌 때 한 가지 문제가 생긴다.
중요한 내용이 chunk 경계에서 끊길 수 있다.
예를 들어 원문이 다음과 같다고 해보자.
하트 충전 후 서비스에 반영되지 않은 경우 먼저 PG 승인 여부를 확인한다.
PG 승인이 완료되었지만 충전 내역이 없는 경우 충전 처리 로그를 확인한다.
이미 후원에 사용된 하트는 환불 대상에서 제외된다.
이 문서를 잘못 나누면 이렇게 될 수 있다.
chunk 1:
하트 충전 후 서비스에 반영되지 않은 경우 먼저 PG 승인 여부를 확인한다.
chunk 2:
PG 승인이 완료되었지만 충전 내역이 없는 경우 충전 처리 로그를 확인한다.
이미 후원에 사용된 하트는 환불 대상에서 제외된다.
사용자가 “하트 충전 후 미반영”을 물었을 때 chunk 1만 검색되면,
충전 처리 로그 확인 내용이 빠질 수 있다.
이런 문제를 줄이기 위해 overlap을 사용한다.
overlap은 chunk 사이에 일부 내용을 겹치게 넣는 방식이다.
chunk 1:
하트 충전 후 서비스에 반영되지 않은 경우 먼저 PG 승인 여부를 확인한다.
PG 승인이 완료되었지만 충전 내역이 없는 경우 충전 처리 로그를 확인한다.
chunk 2:
PG 승인이 완료되었지만 충전 내역이 없는 경우 충전 처리 로그를 확인한다.
이미 후원에 사용된 하트는 환불 대상에서 제외된다.
이렇게 하면 문맥이 덜 끊긴다.
다만 overlap을 너무 많이 주면 저장량과 비용이 증가한다.
overlap이 적음:
저장량은 적지만 문맥이 끊길 수 있음
overlap이 많음:
문맥은 유지되지만 중복 저장이 많아짐
적절한 overlap은 문서 성격에 따라 다르다.
운영 매뉴얼이나 정책 문서처럼 문맥 연결이 중요한 문서는 어느 정도 overlap이 도움이 된다.
overlap은 chunk를 나눌 때 앞뒤 조각의 일부 내용을 겹치게 하는 방식이다.
문맥이 경계에서 끊기는 문제를 줄일 수 있다.
13. 메타데이터는 검색 품질과 권한 제어에 중요하다
벡터DB에는 문서 내용만 저장하면 부족하다.
문서에 대한 추가 정보, 즉 메타데이터가 필요하다.
예를 들어 문서 chunk 하나에 다음 정보를 함께 저장할 수 있다.
{
"chunkId": "chunk_001",
"documentId": "doc_payment_manual",
"title": "결제 실패 및 하트 미반영 처리 매뉴얼",
"section": "2. 충전 미반영 처리",
"content": "PG 승인 완료 후 서비스 충전 내역이 없는 경우 충전 처리 로그를 확인한다.",
"updatedAt": "2026-05-01",
"department": "operation",
"allowedRoles": [
"operation_manager",
"admin"
],
"sourceUrl": "https://docs.example.com/payment-manual"
}
메타데이터는 여러 곳에서 사용된다.
첫 번째는 출처 표시다.
AI 답변에 문서 제목과 섹션을 함께 보여줄 수 있다.
근거:
결제 실패 및 하트 미반영 처리 매뉴얼 > 2. 충전 미반영 처리
두 번째는 권한 제어다.
사용자의 role에 따라 검색 가능한 문서를 제한할 수 있다.
사용자 role:
operation_manager
검색 대상:
allowedRoles에 operation_manager가 포함된 문서만
세 번째는 최신 문서 우선 검색이다.
동일한 주제의 문서가 여러 개 있을 때 updatedAt을 기준으로 최신 문서를 우선할 수 있다.
오래된 문서:
2024년 환불 정책
최신 문서:
2026년 환불 정책
검색 시 최신 문서 우선
네 번째는 문서 유형별 필터링이다.
- 정책 문서만 검색
- 장애 보고서만 검색
- API 문서만 검색
- 고객센터 매뉴얼만 검색
메타데이터가 없으면 검색 결과를 통제하기 어렵다.
RAG를 운영 서비스로 만들려면 문서 내용뿐 아니라 메타데이터 설계가 중요하다.
14. 검색 결과를 그대로 쓰지 않고 재정렬할 수 있다
벡터 검색은 관련 문서를 빠르게 찾지만, 항상 완벽한 순서로 정렬하지는 않는다.
그래서 검색 결과를 한 번 더 재정렬할 수 있다.
이 과정을 reranking이라고 한다.
예를 들어 벡터 검색 결과가 다음과 같다고 해보자.
질문:
하트 충전 후 반영이 안 됐을 때 환불 가능한가요?
벡터 검색 결과:
1. 하트 충전 미반영 처리 매뉴얼
2. 하트 충전 방법 안내
3. 환불 정책 문서
4. 결제 승인 확인 절차
5. 고객 공지 문구 가이드
여기서 질문에는 “환불 가능한가요?”가 포함되어 있다.
따라서 “환불 정책 문서”가 더 위로 올라와야 할 수 있다.
reranker는 검색된 후보 문서들을 다시 읽고, 질문과 더 관련 있는 순서로 재정렬한다.
재정렬 후:
1. 환불 정책 문서
2. 하트 충전 미반영 처리 매뉴얼
3. 결제 승인 확인 절차
4. 하트 충전 방법 안내
5. 고객 공지 문구 가이드
reranking은 검색 품질을 높이는 데 도움이 된다.
하지만 비용과 시간이 추가될 수 있다.
장점:
- 검색 결과 품질 향상
- 질문 의도에 더 맞는 문서 선택
- 불필요한 문서 제거 가능
단점:
- 추가 처리 시간 발생
- 추가 비용 발생 가능
- 구현 복잡도 증가
처음 RAG를 만들 때는 기본 벡터 검색으로 시작해도 된다.
하지만 검색 결과가 자주 엉뚱하거나, 답변 품질이 들쭉날쭉하다면 reranking을 고려할 수 있다.
reranking은 1차 검색 결과를 다시 평가해서 더 적절한 순서로 재정렬하는 과정이다.
RAG 검색 품질을 높이는 데 자주 사용된다.
15. 검색 결과 개수와 답변 품질의 관계
RAG에서는 검색 결과를 몇 개 가져올지 정해야 한다.
보통 top_k라는 값을 사용한다.
top_k = 3
→ 관련 문서 3개 가져오기
top_k = 5
→ 관련 문서 5개 가져오기
top_k = 10
→ 관련 문서 10개 가져오기
검색 결과를 적게 가져오면 장점이 있다.
- AI에게 전달하는 문맥이 짧다.
- 비용이 줄어든다.
- 응답 속도가 빠르다.
- 불필요한 문서가 적다.
하지만 단점도 있다.
- 중요한 문서를 놓칠 수 있다.
- 복합 질문에 답하기 어렵다.
예를 들어 사용자가 이렇게 묻는다.
하트 충전이 안 됐고 환불 가능한지도 알고 싶어요.
이 질문에는 두 문서가 필요할 수 있다.
- 하트 미반영 처리 매뉴얼
- 환불 정책 문서
top_k가 너무 작으면 하나만 가져올 수 있다.
반대로 검색 결과를 너무 많이 가져오면 다른 문제가 생긴다.
- 비용이 증가한다.
- 답변이 느려진다.
- 관련 없는 문서가 섞인다.
- AI가 어떤 문서를 우선해야 할지 헷갈릴 수 있다.
따라서 top_k는 업무에 맞게 조정해야 한다.
간단한 FAQ:
top_k 3 정도로 시작
복합 정책 질문:
top_k 5~8 정도 검토
긴 문서 분석:
검색 후 reranking 또는 문서 요약 단계 추가
정답은 없다.
실제 질문 샘플을 가지고 검색 결과를 보면서 조정해야 한다.
16. 벡터 검색이 항상 정확한 것은 아니다
벡터 검색은 강력하지만 완벽하지 않다.
의미가 비슷하다고 판단했지만 실제로는 답변에 필요 없는 문서를 가져올 수 있다.
예를 들어 사용자가 이렇게 묻는다.
하트 환불 기준 알려줘.
벡터 검색은 “하트”와 관련된 문서를 많이 가져올 수 있다.
- 하트 충전 방법
- 하트 후원 이벤트 정책
- 하트 미반영 처리 매뉴얼
- 하트 환불 기준
이 중에서 진짜 필요한 문서는 “하트 환불 기준”이다.
하지만 “하트”라는 단어 때문에 다른 문서들도 관련 있어 보일 수 있다.
또 비슷한 표현이지만 다른 의미인 경우도 있다.
방송 정지
계정 정지
결제 정지
서비스 점검 정지
모두 “정지”라는 단어가 있지만 의미가 다르다.
그래서 벡터 검색 결과는 항상 확인이 필요하다.
RAG 품질을 높이려면 다음 방법을 함께 사용한다.
- 키워드 검색과 함께 사용
- 문서 메타데이터 필터 적용
- 최신 문서 우선
- 권한 필터 적용
- reranking 적용
- 검색 결과 점수 기준 설정
- 답변에 출처 표시
벡터 검색은 의미 기반 검색을 가능하게 해주지만,
검색 결과가 항상 정답이라는 뜻은 아니다.
17. RAG 검색 품질을 평가하는 방법
RAG를 만들었다면 검색 품질을 평가해야 한다.
AI 답변만 보고 평가하면 원인을 알기 어렵다.
답변이 틀렸을 때 두 가지 가능성이 있다.
1. 검색이 잘못되었다.
2. 검색은 맞았지만 AI가 답변을 잘못 만들었다.
이 둘을 구분하려면 먼저 검색 결과를 봐야 한다.
예를 들어 질문이 있다.
하트 충전 후 반영이 안 되면 어떻게 처리해?
좋은 검색 결과는 다음과 같다.
1. 결제 실패 및 하트 미반영 처리 매뉴얼
2. PG 승인 확인 절차
3. 충전 처리 로그 확인 방법
나쁜 검색 결과는 다음과 같다.
1. 하트 이벤트 운영 정책
2. 방송 후원 랭킹 정책
3. 회원 등급별 혜택 문서
검색 품질을 평가할 때는 질문 샘플을 만들어두는 것이 좋다.
질문 샘플:
- 하트 충전 후 반영이 안 됐어요.
- 비밀번호를 잊어버렸어요.
- 방송방 입장이 안 돼요.
- 엑셀 다운로드 권한은 누가 가질 수 있나요?
- 환불 가능한 조건은 무엇인가요?
각 질문에 대해 기대 문서를 정해둔다.
질문:
하트 충전 후 반영이 안 됐어요.
기대 문서:
결제 실패 및 하트 미반영 처리 매뉴얼
PG 승인 확인 절차
검색 결과에 기대 문서가 포함되는지 확인한다.
평가 기준:
- 기대 문서가 top 3 안에 있는가?
- 기대 문서가 top 5 안에 있는가?
- 관련 없는 문서가 너무 많이 섞이지 않았는가?
- 최신 문서가 우선 검색되는가?
- 권한 없는 문서가 검색되지 않는가?
RAG 품질 개선은 답변을 예쁘게 만드는 것보다,
먼저 검색 결과를 정확하게 만드는 데서 시작해야 한다.
18. 정리
임베딩은 문장이나 문서를 숫자 벡터로 바꾸는 방식이다.
컴퓨터는 문장의 의미를 그대로 이해하지 못하기 때문에,
의미를 비교할 수 있는 숫자 형태로 바꿔야 한다.
벡터 검색은 사용자 질문 벡터와 문서 벡터를 비교해서 의미가 비슷한 문서를 찾는 방식이다.
RAG에서는 문서 조각을 미리 임베딩해서 벡터DB에 저장해두고,
사용자 질문이 들어오면 질문도 임베딩해서 관련 문서를 검색한다.
벡터 검색은 키워드가 정확히 일치하지 않아도 의미가 비슷한 문서를 찾을 수 있다는 장점이 있다.
하지만 완벽하지는 않다.
정확한 API 이름, 에러 코드, 함수명처럼 문자열 일치가 중요한 경우에는 키워드 검색이 더 유리할 수 있다.
그래서 실무에서는 키워드 검색과 벡터 검색을 함께 사용하는 하이브리드 검색이 자주 사용된다.
또 문서 분할, chunk 크기, overlap, 메타데이터, 권한 필터, reranking, top_k 설정이 검색 품질에 큰 영향을 준다.
RAG의 답변 품질은 검색 품질에서 시작된다.
이 장에서 기억해야 할 핵심은 하나다.
RAG에서 AI가 좋은 답을 하려면,
먼저 질문과 관련 있는 좋은 문서를 찾아야 한다.
임베딩과 벡터 검색은 그 문서를 찾기 위한 핵심 기술이다.
13장 핵심 요약
| 핵심 내용 | 설명 |
|---|---|
| RAG의 핵심은 관련 문서 검색이다 | 검색된 문서가 부정확하면 AI 답변도 좋아지기 어렵다. |
| 임베딩은 의미를 숫자로 바꾼다 | 문장이나 문서를 벡터로 변환해 컴퓨터가 비교할 수 있게 한다. |
| 벡터 검색은 의미 기반 검색이다 | 키워드가 정확히 일치하지 않아도 의미가 비슷한 문서를 찾을 수 있다. |
| 문서와 질문 모두 임베딩한다 | 문서 chunk를 미리 임베딩해 저장하고, 질문도 임베딩해 가까운 문서를 찾는다. |
| 벡터DB는 의미 검색을 위한 저장소다 | 임베딩 벡터와 문서 내용, 제목, 권한, 출처 같은 메타데이터를 함께 저장한다. |
| 키워드 검색도 여전히 중요하다 | API 이름, 에러 코드, 함수명처럼 정확한 문자열 검색이 필요한 경우가 있다. |
| 하이브리드 검색이 실무에 유용하다 | 벡터 검색과 키워드 검색을 함께 사용하면 검색 품질을 높일 수 있다. |
| 문서 분할이 검색 품질을 좌우한다 | chunk가 너무 크면 주제가 섞이고, 너무 작으면 문맥이 부족해진다. |
| overlap은 문맥 단절을 줄인다 | chunk 사이 일부 내용을 겹치게 해 중요한 문맥이 끊기지 않게 한다. |
| 메타데이터는 필수다 | 출처 표시, 권한 제어, 최신 문서 우선 검색, 문서 유형 필터링에 필요하다. |
| reranking은 검색 결과를 개선한다 | 1차 검색 결과를 다시 평가해 더 관련 있는 문서를 위로 올린다. |
| 검색 품질은 따로 평가해야 한다 | 답변 품질만 보지 말고, 기대 문서가 검색 결과에 포함되는지 확인해야 한다. |