RAG(Retrieval-Augmented Generation) 시스템이 어떤 문서를 인용할지는 단순한 키워드 매칭이 아니라 밀집 벡터 유사도 계산, 희소 검색 점수, 교차 인코더 재순위화의 3중 필터를 통해 결정된다. Perplexity·ChatGPT Search의 인용 패턴이 전통 검색 상위 노출과 62% 불일치하는 근본 원인이 여기 있다. RAG가 출처를 고르는 메커니즘을 이해하지 못하면 콘텐츠를 아무리 잘 써도 LLM의 컨텍스트 창에 진입하지 못한다.
RAG 파이프라인의 3단계 구조
현대 RAG 시스템은 쿼리 입력부터 응답 생성까지 세 단계로 나뉜다. 각 단계에서 문서 후보가 줄어들고, 최종 생존 문서만 LLM 컨텍스트에 삽입된다.
- Retrieval(검색) — 수억 개 청크에서 수십~수백 개 후보를 추출한다. 왜: ANN(Approximate Nearest Neighbor) 인덱스(FAISS·ScaNN·Pinecone)가 O(log N) 연산으로 실시간 응답을 가능하게 한다. 어떻게: 쿼리를 동일 임베딩 모델로 벡터화한 뒤 코사인 유사도 상위 K개(보통 50~200)를 반환한다.
- Reranking(재순위화) — Retrieval 후보를 정밀 모델로 재평가해 상위 5~20개로 압축한다. 왜: bi-encoder 임베딩은 쿼리와 문서를 독립 인코딩하므로 미세한 의미 차이를 놓친다. 어떻게: 교차 인코더(cross-encoder)가 쿼리와 문서를 동시 입력해 관련성 점수를 재계산한다.
- Context Insertion(컨텍스트 삽입) — Reranking 생존 문서를 LLM 프롬프트에 삽입하고, 생성 단계에서 출처가 선택된다. 왜: 컨텍스트 창 토큰 한계 내에서 관련성 높은 청크가 우선 배치되어야 인용 확률이 높아진다. 어떻게: 청크(보통 256~512 토큰) 단위로 삽입되며 URL·제목·날짜 메타데이터가 함께 전달된다.
밀집 검색과 희소 검색: 두 신호의 병행
주요 RAG 시스템은 밀집(dense)과 희소(sparse) 검색을 혼합하는 하이브리드 방식을 채택한다.
- 밀집 벡터 검색: 의미론적 유사도를 포착한다. 왜: "혈당 조절"과 "인슐린 저항성 개선"은 키워드가 달라도 임베딩 공간에서 가깝다. 어떻게:
text-embedding-3-large,E5-mistral-7b-instruct등이 768~4096차원 벡터를 생성하고 FAISS IVF 인덱스가 ANN 검색을 수행한다. - 희소 BM25 검색: 정확한 키워드·고유명사 매칭에 강하다. 왜: 제품명, 법령 조항 번호, API 함수명처럼 의미 압축이 안 되는 고유 토큰을 밀집 검색이 놓친다. 어떻게: Elasticsearch·OpenSearch의 BM25 스코어러가 TF-IDF 기반 역문서 빈도를 계산한다.
- RRF(Reciprocal Rank Fusion): 두 결과 리스트를 단일 랭킹으로 통합한다. 왜: 점수 스케일이 다른 두 시스템을 단순 가중합하면 한 쪽이 지배한다. 어떻게:
score = Σ 1/(k + rank_i)공식(k=60 기본값)으로 순위 기반 통합한다.
| 방식 | 신호 유형 | 강점 | 약점 | 대표 구현 |
|---|---|---|---|---|
| 밀집 벡터(Dense) | 의미 유사도 | 동의어·패러프레이즈 매칭 | 고유명사·숫자 오매칭 | FAISS, Pinecone, Weaviate |
| 희소 BM25(Sparse) | 키워드 빈도 | 정확한 용어·법령·코드 | 의미 변형 쿼리 실패 | Elasticsearch, OpenSearch |
| 하이브리드(RRF) | 순위 앙상블 | 두 방식 단점 상쇄 | 지연 시간 증가 | Weaviate hybrid, LlamaIndex |
| 교차 인코더 Reranking | 쿼리-문서 교차 주의 | 정밀 관련성 점수 | 후보 수 수백 개로 제한 | Cohere Rerank, BGE-reranker |
크롤러 접근 제어: robots.txt와 llms.txt 구성
Retrieval 단계 이전에 크롤러 차단이 없어야 인덱싱이 가능하다. GPTBot·PerplexityBot·ClaudeBot은 각각 OpenAI·Perplexity·Anthropic의 RAG 크롤러이며, robots.txt 지시를 따른다. llms.txt는 Jeremy Howard(fast.ai)가 제안한 LLM 전용 사이트맵 표준으로 크롤러에게 사이트 구조와 핵심 URL을 직접 전달한다.
# /robots.txt — RAG 크롤러 명시 허용
User-agent: GPTBot
Allow: /
User-agent: PerplexityBot
Allow: /
User-agent: ClaudeBot
Allow: /
User-agent: *
Disallow: /admin/
Disallow: /private/
# /llms.txt — LLM용 사이트맵 (llmstxt.org 표준, 루트에 배치)
# 마크다운 형식으로 주요 URL과 맥락 설명을 제공
# 사이트명
> AI/ML 엔지니어링 블로그. RAG·AEO·GEO 구현 가이드 중심.
## 핵심 문서
- [RAG 파이프라인 구조](https://example.com/blog/rag-pipeline): 검색·재순위화·생성 3단계 기술 분석
- [AEO 구현 가이드](https://example.com/blog/aeo-guide): JSON-LD·llms.txt·robots.txt 구성
- [벡터 DB 비교](https://example.com/blog/vector-db): FAISS·Pinecone·Weaviate 성능 벤치마크
## 선택적
- [케이스 스터디](https://example.com/case-studies/): RAG 인용률 개선 실측 사례
흔한 오해: "벡터 유사도 점수가 높으면 인용된다"
Retrieval 단계에서 코사인 유사도 0.95가 나와도 인용되지 않는 경우가 많다. 인용을 결정하는 실질적 게이트키퍼는 Retrieval 점수가 아니라 교차 인코더 Reranking 점수와 컨텍스트 창 내 배치 순서다. Retrieval은 후보 필터일 뿐이다. 실무에서는 청크의 사실 밀도, 문장 완결성, 중복 제거 여부가 재순위화 점수에 직접 영향을 미친다. 검증 방법: Cohere Rerank API로 자사 청크와 경쟁 도메인 청크를 동일 쿼리에 점수 비교한 뒤, 낮은 점수 청크의 문장 구조를 분석하면 개선 지점이 드러난다. 단일 청크에 두 개 이상의 독립 주제가 섞이거나 문장이 중간에 잘린 경우가 점수 하락의 주요 원인이다.
Q1. Perplexity가 우리 사이트를 크롤링하는지 어떻게 확인하나?
서버 액세스 로그에서 PerplexityBot User-Agent를 필터링한다. Nginx 기준: grep "PerplexityBot" /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn 으로 크롤링된 URL 빈도를 확인할 수 있다. 크롤링이 전혀 없다면 robots.txt 차단 여부를 먼저 점검하고, 다음으로 sitemap.xml 제출과 llms.txt 배치를 확인한다. Perplexity는 별도 웹마스터 도구를 제공하지 않으므로 표준 sitemap.xml + llms.txt가 유일한 힌트 채널이다.
Q2. 청크 크기를 몇 토큰으로 설정해야 RAG 인용 확률이 높아지나?
단일 최적값은 없다. 일반적으로 256~512 토큰이 교차 인코더 재순위화에서 유리하지만, 기술 문서처럼 맥락 의존성이 높은 콘텐츠는 512~768 토큰이 더 나을 수 있다. 실무 접근: (1) 타겟 쿼리 100개 선정, (2) 256·512·768 토큰 청크 각각으로 Cohere Rerank 점수 측정, (3) 쿼리 유형별(사실형·방법형·비교형) 평균 점수를 비교해 결정한다. 슬라이딩 윈도우(겹침 50~100 토큰)를 추가하면 문단 경계 절단으로 인한 정보 손실을 보완할 수 있다.
참고 자료
이 글의 권고는 아래 공식 문서·연구를 근거로 합니다.