RAG(Retrieval-Augmented Generation)
💡 TL;DR RAG는 결국 "검색 시스템 + 프롬프트 조립"이다. 벡터 임베딩, ANN 검색이라는 새로운 용어가 붙었을 뿐, 인덱스 튜닝하고 쿼리 최적화하던 감각이 그대로 통한다. 처음엔 뭔가 새로운 AI 기술처럼 느껴졌는데 파고들수록 익숙한 DB 문제였다.
들어가며
요즘 회사들 채용 공고 보면 "RAG 기반 사내 챗봇", "LLM + 벡터 검색" 이런 문구가 꽤 자주 보인다. 처음엔 완전히 새로운 영역처럼 느껴져서 살짝 겁먹었는데, 막상 파보니 4년 넘게 해온 DB 최적화 작업이랑 뿌리가 크게 다르지 않았다. 그래서 개념을 한 번 정리해두고, 다음 글에서 pgvector로 직접 구현까지 해봤다.
LLM은 학습 시점까지의 지식만 파라미터 안에 압축해서 갖고 있다. 그래서 두 가지 문제가 생긴다.
- 지식 컷오프: 학습 이후 정보는 모른다.
- 환각(Hallucination): 모르는 걸 그럴듯하게 지어낸다. 특히 사내 문서처럼 애초에 학습 데이터에 없던 내용일수록 심하다.
🤔 생각 회사 다닐 때 WAF/SWG 정책 문서나 내부 위키 같은 거 신입한테 설명하려면 항상 시간이 오래 걸렸는데, 이런 사내 문서를 RAG로 붙여두면 온보딩 자료로도 꽤 쓸모 있겠다 싶었다. 나중에 사이드 프로젝트로 한 번 만들어봐도 재밌을 듯.
이 문제를 파라미터를 다시 학습(파인튜닝)해서 푸는 대신, 필요한 정보를 매번 외부에서 검색해서 프롬프트에 넣어주는 방식이 RAG다. 오픈북 시험이랑 비슷한 개념.
전체 파이프라인
크게 두 단계로 나뉜다.
1) 색인(Indexing) — 미리 준비하는 과정
원본 문서 → Chunking(분할) → Embedding(벡터화) → Vector DB 저장- Chunking: 문서를 통째로 넣으면 검색 정확도가 떨어져서 문단/섹션 단위로 잘게 쪼갠다.
- Embedding: 각 청크를 임베딩 모델에 통과시켜 고차원 벡터로 변환. 의미가 비슷한 텍스트는 벡터 공간에서 가까이 위치한다.
- 저장: 벡터 + 원본 텍스트 + 메타데이터(문서 ID, 작성일 등)를 같이 저장. 메타데이터를 빼먹으면 나중에 "이 답변 근거가 뭐야?"라는 질문에 답을 못한다.
2) 조회(Query) — 실제 질의응답 시점
사용자 질문 → Embedding → 유사도 검색(ANN) → 관련 청크 추출
→ 프롬프트에 컨텍스트로 삽입 → LLM 생성 → 답변💭 회고 처음엔 "그냥 LLM한테 문서 다 던져주면 안 되나?" 싶었는데, 컨텍스트 윈도우 제한도 있고 무엇보다 관련 없는 내용이 섞이면 답변 품질이 떨어진다는 걸 알고 나서야 왜 굳이 검색 단계를 따로 두는지 이해가 됐다. 예전에 정책 조회 쿼리 7분 → 2초로 줄였던 것도 결국 "필요한 데이터만 빠르게 골라내기"였는데, RAG도 똑같은 문제를 풀고 있는 거였다.
벡터 검색, B-tree 인덱스와 뭐가 다른가
기존 RDB 인덱스(B-tree, Hash)는 정확 일치·범위 조건에 최적화되어 있다. WHERE id = 5, WHERE created_at BETWEEN ... 같은 쿼리. 반면 벡터 검색은 "의미적으로 가장 가까운 것"을 찾는 문제라 접근 방식 자체가 다르다.
고차원 공간에서 완전탐색(brute-force)은 데이터가 커지면 감당이 안 돼서, 실무에서는 근사 최근접 이웃(ANN) 알고리즘을 쓴다.
- HNSW: 계층적 그래프를 타고 내려가며 탐색. 속도·재현율 균형이 좋아서 가장 많이 쓰인다.
- IVFFlat: 벡터 공간을 클러스터로 나눠 후보군을 좁힌 뒤 탐색. 빌드는 빠르지만 정확도는 HNSW보다 조금 떨어짐.
🤔 생각 HNSW의m,ef_construction파라미터 보면서 예전에 인덱스 재설계할 때 fillfactor랑 페이지 크기 튜닝하던 거랑 감각이 똑같다고 느꼈다. 파라미터 올릴수록 정확도는 오르지만 인덱스 크기·빌드 시간·검색 지연이 같이 늘어나는 트레이드오프도 동일. "새로운 기술이라 새로 배워야 한다"기보다 "익숙한 트레이드오프 감각을 새 도메인에 적용한다"는 느낌으로 접근하니 훨씬 덜 부담스러웠다.
Vector DB 선택지
- pgvector: PostgreSQL 확장. 기존 RDB에 벡터 컬럼 + HNSW/IVFFlat 인덱스를 추가하는 방식이라 진입장벽이 가장 낮다. 메타데이터 조인, 트랜잭션도 기존 SQL 그대로.
- Pinecone, Weaviate, Milvus, Qdrant: 벡터 검색 전용 DB. 대규모 트래픽·실시간 필터링에 유리하지만 별도 인프라 운영 부담.
- 선택 기준: 데이터 규모가 크지 않고 기존 RDB 인프라를 재활용하고 싶으면 pgvector, 검색 자체가 핵심 트래픽이고 스케일이 크면 전용 Vector DB.
💭 회고 PostgreSQL 실무 경험이 있다 보니 pgvector 쪽이 훨씬 편하게 느껴졌다. 새 인프라 배우는 것보다 "이미 아는 도구에 확장만 붙이기"가 학습 곡선이 훨씬 완만하다는 걸 다시 느낌. 다음 글(구현편)도 그래서 pgvector로 잡았다.
검색 품질을 좌우하는 실무 포인트
- Chunk 크기와 오버랩: 너무 작으면 문맥이 끊기고, 너무 크면 노이즈가 섞인다. 보통 200~500 토큰 + 약간의 오버랩으로 시작.
- Hybrid Search: 벡터 검색만으로는 고유명사·코드·숫자 같은 정확 매칭에 약하다. 키워드 검색(BM25 등)과 벡터 검색을 함께 쓰고 점수를 합치는 방식이 실무 표준에 가까움.
- Reranking: 1차로 넉넉히 후보를 가져온 뒤, 더 정밀한 재순위 모델(Cross-encoder)로 상위 K개만 추리면 정확도가 크게 개선됨.
- 메타데이터 필터링: "최근 1년 문서만" 같은 조건은 벡터 유사도만으로 못 거른다. SQL WHERE절 같은 필터를 함께 적용해야 함.
- 평가(Evaluation): 그럴듯해 보이는 답이 나오기 쉬워서 정성적 느낌만으로 판단하면 위험하다. Recall, Faithfulness 같은 지표로 정량 평가 필요.
🤔 생각 5번 평가 부분이 개인적으로 제일 낯설었다. 기존 백엔드 작업은 "쿼리 결과가 맞다/틀리다"가 명확한데, RAG는 "그럴듯하지만 틀린 답"이 나올 수 있어서 정량 평가 체계 자체를 따로 설계해야 한다는 게 새로운 개념이었다. 이 부분은 좀 더 공부가 필요할 듯.
마무리 회고
RAG를 한 줄로 요약하면 "검색 시스템 설계 문제 + 프롬프트 엔지니어링". 벡터 임베딩이라는 새 데이터 타입, ANN이라는 새 검색 알고리즘이 등장했을 뿐, 청크 설계(파티셔닝), 인덱스 파라미터 튜닝, 필터링 같은 문제의 본질은 기존 DB 최적화 경험과 크게 다르지 않았다.
백엔드 하다가 AI 쪽으로 넘어가려면 완전히 새로 배워야 한다는 부담이 있었는데, 이번에 정리하면서 "기존 경험 위에 새 레이어 하나 얹는 정도"라는 걸 느꼈다. 다음 글에서는 실제로 pgvector로 파이프라인을 구현해본 과정을 정리한다.
다음 할 일
- pgvector로 미니 RAG 파이프라인 직접 구현
- Hybrid Search(BM25 + 벡터) 실험