대규모 언어 모델(LLM)은 놀라운 성능으로 다양한 애플리케이션 개발의 지평을 넓히고 있습니다. 그러나 LLM은 여전히 몇 가지 본질적인 한계를 가지고 있다. 모델 학습 시점 이후의 최신 정보를 반영하지 못하거나, 특정 도메인의 전문 지식을 정확하게 답변하지 못하는 경우가 대표적이다. 또한, 때로는 사실과 다른 '환각(Hallucination)' 현상을 보이기도 한다. 이러한 문제들은 LLM을 실제 서비스에 적용하는 데 있어 중요한 제약 사항으로 작용한다.
이러한 한계를 극복하고 LLM 기반 애플리케이션의 신뢰성과 정확도를 높이기 위한 핵심적인 아키텍처가 바로 RAG (Retrieval Augmented Generation, 검색 증강 생성)이다. RAG는 LLM이 답변을 생성하기 전에 외부 지식 저장소에서 관련 정보를 검색하여 이를 근거로 응답을 생성하도록 증강하는 방식이다. 본 글에서는 LLM 기반 애플리케이션 개발을 위한 RAG 아키텍처의 구축 원리, 핵심 구성 요소, 그리고 실질적인 최적화 전략에 대해 심도 있게 다룰 것이다.
📑 목차
Image by FunkyFocus on Pixabay
LLM 기반 애플리케이션의 한계와 RAG의 필요성
LLM은 방대한 텍스트 데이터 학습을 통해 인간과 유사한 언어 이해 및 생성 능력을 획득한다. 그러나 이러한 모델들은 본질적으로 학습 데이터에 의존하며, 다음과 같은 문제에 직면할 수 있다.
- 환각(Hallucination) 현상: LLM은 때때로 사실과 일치하지 않는 정보를 자신감 있게 생성한다. 이는 학습 데이터에 없는 내용을 추론하거나, 학습 과정에서 잘못된 패턴을 학습했을 때 발생할 수 있다. 비즈니스 애플리케이션에서는 치명적인 오류로 이어진다.
- 최신 정보 부족: LLM은 학습이 완료된 시점까지의 데이터만을 반영한다. 따라서 학습 이후에 발생한 사건이나 최신 트렌드, 업데이트된 정보를 알지 못한다. 이는 역동적으로 변화하는 정보를 다루는 애플리케이션에 큰 제약이 된다.
- 비공개/내부 데이터 접근 한계: 기업 내부 문서, 특정 도메인의 전문 지식 등은 LLM 학습 데이터에 포함되지 않는 경우가 대부분이다. 이러한 비공개 데이터에 기반한 답변을 생성하려면 별도의 메커니즘이 필요하다.
- 출처 불명확성: LLM은 답변의 근거를 명확히 제시하지 못하는 경우가 많다. 이는 사용자가 답변의 신뢰성을 검증하기 어렵게 만들며, 법적 또는 규제적 준수 요구사항을 충족시키기 어렵게 한다.
이러한 한계점들은 LLM을 실제 서비스에 적용할 때 중요한 걸림돌이 된다. RAG는 이러한 문제들을 해결하기 위한 강력한 해결책으로 부상했다. 외부의 신뢰할 수 있는 정보 소스에서 관련 지식을 검색하여 LLM의 생성 과정에 통합함으로써, LLM의 정확성, 신뢰성, 그리고 최신 정보 반영 능력을 획기적으로 향상시킬 수 있다.
RAG (검색 증강 생성) 아키텍처의 이해
RAG는 LLM이 질문에 답변을 생성하기 전에 외부 지식 베이스에서 관련 정보를 '검색(Retrieval)'하고, 이 검색된 정보를 바탕으로 '생성(Generation)'하는 아키텍처이다. 이는 마치 사람이 질문을 받았을 때 책이나 문서를 찾아본 후 답변하는 방식과 유사하다.
RAG의 기본 동작 원리
- 질의(Query) 입력: 사용자로부터 질문이 입력된다.
- 검색(Retrieval): 입력된 질문과 관련된 정보를 외부 지식 저장소(예: 벡터 데이터베이스)에서 검색한다. 이 과정에서 질문의 의미를 이해하고 가장 유사한 문서 조각(청크)들을 찾아낸다.
- 증강(Augmentation): 검색된 정보 조각들을 원래의 질문과 함께 LLM에 전달할 프롬프트에 포함시킨다. 이 검색된 정보는 LLM이 답변을 생성하는 데 필요한 '맥락(Context)'을 제공한다.
- 생성(Generation): LLM은 증강된 프롬프트(질문 + 관련 맥락)를 바탕으로 답변을 생성한다. 이 답변은 외부에서 검색된 정보를 근거로 하므로, 환각 현상이 줄어들고 정확성이 높아진다.
RAG는 LLM 자체를 재학습시키는 미세 조정(Fine-tuning) 방식과 비교하여 몇 가지 뚜렷한 이점을 가진다. 아래 표는 RAG와 미세 조정의 주요 특징을 비교한 것이다.
| 특징 | RAG (검색 증강 생성) | 미세 조정 (Fine-tuning) |
|---|---|---|
| 데이터 요구량 | 검색 대상 데이터(문서) 및 임베딩 모델 학습 데이터 | 모델 학습을 위한 대량의 질문-답변 쌍(고품질) |
| 비용 및 시간 | 상대적으로 적은 비용과 시간 (모델 재학습 불필요) | 상대적으로 높은 비용과 시간 (모델 전체 또는 일부 재학습) |
| 정보 업데이트 | 검색 대상 데이터만 업데이트하면 즉시 반영 가능 | 새로운 데이터로 모델을 재학습해야 반영 가능 |
| 환각 제어 | 검색된 정보에 기반하여 생성하므로 환각 가능성 크게 감소 | 학습 데이터 외 추론 시 환각 가능성 상존 |
| 유연성 | 다양한 데이터 소스(문서, DB)에 유연하게 적용 가능 | 학습된 도메인에 특화되며, 새로운 도메인 적용 시 재학습 필요 |
RAG는 특히 빠르게 변화하는 정보, 특정 도메인의 전문 지식, 또는 비공개 데이터를 다루는 LLM 애플리케이션에 매우 적합한 솔루션으로 평가된다.
RAG 아키텍처의 핵심 구성 요소
RAG 아키텍처는 크게 세 가지 핵심 모듈로 구성된다. 각 모듈은 LLM의 성능과 신뢰성을 극대화하는 데 필수적인 역할을 수행한다.
데이터 인덱싱 및 관리 (Vector Database)
RAG 시스템의 기반은 LLM이 검색할 수 있는 잘 구조화된 지식 베이스(Knowledge Base)이다. 이 지식 베이스를 구축하는 과정은 다음과 같다.
- 원본 문서 수집: 웹 페이지, PDF 문서, 데이터베이스 레코드, 슬랙 메시지 등 다양한 형태의 원본 데이터를 수집한다.
- 문서 전처리 및 청킹(Chunking): 수집된 원본 문서는 LLM이 처리하기 적합한 작은 단위로 분할된다. 이 단위를 청크(Chunk)라고 부른다. 청킹 과정에서는 문맥을 유지하면서도 검색 효율성을 높이는 적절한 크기를 결정하는 것이 중요하다. 너무 크면 관련 없는 정보가 포함될 수 있고, 너무 작으면 중요한 문맥이 손실될 수 있다. 문단, 섹션, 또는 고정된 토큰 수를 기준으로 청킹할 수 있으며, 인접 청크 간의 오버랩(Overlap)을 두어 문맥 손실을 최소화하기도 한다.
- 임베딩(Embedding) 생성: 각 청크는 임베딩 모델(Embedding Model)을 통해 고차원 벡터(Vector)로 변환된다. 임베딩 벡터는 텍스트의 의미적 유사성을 숫자로 표현한 것으로, 의미적으로 유사한 텍스트는 벡터 공간에서 가까운 거리에 위치하게 된다.
- 벡터 데이터베이스 저장: 생성된 임베딩 벡터들은 벡터 데이터베이스(Vector Database)에 저장된다. 벡터 데이터베이스는 대량의 벡터 데이터를 효율적으로 저장하고, 질의 벡터와 가장 유사한 벡터들을 빠르게 검색할 수 있도록 최적화되어 있다. 대표적인 벡터 데이터베이스로는 Pinecone, Weaviate, Milvus, Qdrant 등이 있으며, PostgreSQL의 pgvector 확장 기능도 활용될 수 있다.
이 과정은 LLM이 '무엇을' 검색할 것인가를 결정하는 핵심 단계이다. 지식 베이스의 품질과 구조는 RAG 시스템 전체의 성능에 지대한 영향을 미친다.
검색(Retrieval) 모듈
검색 모듈은 사용자의 질문이 주어졌을 때, 지식 베이스에서 가장 관련성이 높은 정보 청크를 찾아내는 역할을 한다.
- 질의 임베딩: 사용자 질의(Query) 또한 지식 베이스의 청크들과 동일한 임베딩 모델을 사용하여 벡터로 변환된다.
- 유사도 검색: 변환된 질의 벡터를 사용하여 벡터 데이터베이스에서 가장 유사한(가까운) 문서 청크들을 검색한다. 이때 코사인 유사도(Cosine Similarity)와 같은 유사도 측정 알고리즘이 활용된다. 검색 결과는 대개 상위 K개의 관련성 높은 청크 목록으로 반환된다.
- 검색 결과 필터링 및 재순위화(Re-ranking): 초기 검색 결과는 때때로 노이즈가 포함되거나, 관련성이 떨어지는 청크를 포함할 수 있다. 이를 개선하기 위해 추가적인 필터링(예: 메타데이터 기반 필터링)이나 재순위화 모델을 적용하여 최종적으로 LLM에 전달될 청크들의 순위를 조정하고 품질을 높일 수 있다.
검색 모듈의 성능은 LLM이 얼마나 정확하고 풍부한 맥락을 얻을 수 있는지를 결정한다. 따라서 검색 정확도를 높이는 것이 RAG 시스템 최적화의 핵심 과제 중 하나이다.
생성(Generation) 모듈
생성 모듈은 검색 모듈에서 얻은 정보와 사용자 질의를 바탕으로 LLM이 최종 답변을 생성하는 단계이다.
- 프롬프트 구성: 검색된 관련 정보 청크들을 사용자 질의와 함께 LLM에 전달될 프롬프트에 포함시킨다. 이 과정에서 프롬프트 엔지니어링 기법을 활용하여 LLM이 검색된 정보를 효과적으로 활용하도록 유도한다. 예를 들어, "다음 정보를 바탕으로 질문에 답하시오. [정보]: {검색된 청크들} [질문]: {사용자 질의}"와 같은 형태로 프롬프트를 구성할 수 있다.
- LLM 답변 생성: 구성된 프롬프트가 LLM에 전달되면, LLM은 주어진 맥락(검색된 정보)과 질문을 기반으로 자연어 답변을 생성한다. LLM은 검색된 정보 내에서 답변을 찾거나, 해당 정보를 종합하여 새로운 답변을 구성할 수 있다.
이 단계에서 LLM은 단순히 검색된 정보를 나열하는 것이 아니라, 이를 이해하고 사용자의 질문에 맞춰 재구성하며, 필요한 경우 추가적인 추론을 수행하여 최종 답변을 제공한다.
Image by bano1997 on Pixabay
효과적인 RAG 아키텍처 구축 전략
성공적인 RAG 시스템을 구축하기 위해서는 각 구성 요소에 대한 신중한 설계와 전략적 접근이 필요하다. 다음은 주요 구축 전략들이다.
데이터 전처리 및 청킹 전략
정보 검색의 효율성과 LLM의 이해도를 높이기 위한 첫 단추는 바로 데이터 전처리 및 청킹이다.
- 적절한 청크 크기 결정: 청크 크기는 RAG 성능에 큰 영향을 미친다. 너무 작으면 문맥이 부족하고, 너무 크면 관련 없는 정보가 포함될 가능성이 높다. 이상적인 청크 크기는 도메인과 데이터 특성, 그리고 사용하려는 LLM의 컨텍스트 윈도우 크기를 고려하여 실험을 통해 결정되어야 한다. 일반적으로 256~1024 토큰 범위가 많이 사용된다.
- 청크 오버랩(Overlap): 인접한 청크 사이에 일정량의 오버랩을 두어 한 청크에서 다른 청크로 넘어갈 때 발생할 수 있는 문맥 손실을 방지한다. 예를 들어, 512 토큰 청크에 100 토큰 오버랩을 두는 방식이다.
- 메타데이터 활용: 각 청크에 출처, 날짜, 작성자, 문서 유형 등 유용한 메타데이터를 함께 저장한다. 이 메타데이터는 검색 단계에서 필터링 조건으로 활용되거나, LLM이 답변을 생성할 때 추가적인 맥락을 제공하는 데 사용될 수 있다.
- 재귀적 청킹(Recursive Chunking): 큰 문서에서 작은 청크로 계층적으로 분할하는 방식이다. 예를 들어, 먼저 문서를 섹션으로 나누고, 각 섹션을 다시 문단으로 나누는 식이다. 이는 다양한 수준의 세밀도로 정보를 검색할 수 있게 하여 복합적인 질문에 대한 응답 정확도를 높일 수 있다.
검색 품질 향상 기법
검색 모듈에서 얼마나 관련성 높은 정보를 찾아내느냐가 RAG 성능의 핵심이다. 다음은 검색 품질을 높이는 기법들이다.
- 임베딩 모델 선택 및 미세 조정: 검색에 사용되는 임베딩 모델의 성능이 매우 중요하다. 도메인 특화된 임베딩 모델을 사용하거나, 일반적인 모델(예: OpenAI의 text-embedding-ada-002, Sentence Transformers 모델)을 자체 데이터로 미세 조정하여 도메인 특화된 의미론적 유사성을 더 잘 포착하도록 할 수 있다.
- 하이브리드 검색(Hybrid Search): 벡터 검색(의미론적 유사성)과 키워드 검색(BM25와 같은 전통적인 검색 알고리즘)을 결합하는 방식이다. 키워드 검색은 정확한 키워드 일치에 강하고, 벡터 검색은 의미론적 유사성에 강하므로, 두 가지 방식을 함께 사용하여 검색 누락을 줄이고 관련성을 높일 수 있다.
- 쿼리 재작성(Query Rewriting) 및 확장: 사용자 질의를 직접 사용하는 대신, LLM을 활용하여 질의를 재작성하거나 관련 키워드를 추가하여 검색의 폭을 넓힐 수 있다. 예를 들어, 복잡한 질문을 여러 개의 하위 질문으로 분해하거나, 모호한 질문을 명확하게 만들 수 있다.
- 재순위화(Re-ranking) 모델 도입: 초기 검색된 상위 N개의 청크들을 LLM 기반의 재순위화 모델(예: Cohere Rerank)을 사용하여 다시 점수를 매기고 순서를 조정한다. 이는 LLM이 최종 답변을 생성할 때 가장 관련성 높은 정보를 먼저 참조하도록 하여 정확도를 더욱 향상시킨다.
- 멀티 스테이지 검색(Multi-stage Retrieval): 한 번의 검색으로 원하는 정보를 찾기 어려울 때, 여러 단계를 거쳐 정보를 검색하는 방식이다. 예를 들어, 첫 번째 검색으로 큰 문서를 찾고, 두 번째 검색으로 해당 문서 내에서 특정 문단을 찾는 방식이다.
# RAG 기반 LLM 프롬프트 구성 예시
system_prompt = "당신은 주어진 문서를 바탕으로 질문에 정확하고 간결하게 답변하는 AI 어시스턴트입니다."
user_query = "RAG 아키텍처의 핵심 이점은 무엇인가요?"
retrieved_context = """
[문서 1] RAG는 LLM이 외부 데이터 소스에서 관련 정보를 검색하여 답변을 생성하는 것을 가능하게 합니다. 이는 LLM의 환각 현상을 줄이고 최신 정보에 접근할 수 있게 합니다.
[문서 2] RAG는 모델을 재학습시킬 필요 없이 새로운 데이터를 쉽게 통합할 수 있는 유연성을 제공하며, 특정 도메인에 특화된 응답을 생성하는 데 유리합니다.
"""
final_prompt = f"{system_prompt}\n\n참고 문서:\n{retrieved_context}\n\n질문: {user_query}\n\n답변:"
print(final_prompt)
위 코드 예시는 RAG 시스템에서 LLM에 전달되는 프롬프트가 어떻게 구성되는지 개념적으로 보여준다. 검색된 `retrieved_context`가 `user_query`와 함께 LLM에게 전달되어 답변의 근거를 제공한다.
프롬프트 엔지니어링
검색된 정보를 LLM이 가장 효과적으로 활용하도록 유도하는 프롬프트 구성은 RAG 성능에 결정적인 영향을 미친다.
- 명확한 지시: LLM에게 "다음 문서를 참고하여 질문에 답하시오", "검색된 정보 내에서만 답변하시오", "사실이 아닌 내용은 언급하지 마시오" 등 명확한 지시를 제공하여 답변의 범위를 제한하고 정확성을 높인다.
- 정보의 명시적 구분: 검색된 정보와 사용자 질문을 프롬프트 내에서 명확하게 구분하여 LLM이 혼동하지 않도록 한다. 예를 들어, `### Context:`, `### Question:`과 같은 구분자를 사용할 수 있다.
- Few-shot Learning 활용: 몇 가지 좋은 질문-답변 예시를 프롬프트에 함께 제공하여 LLM이 원하는 답변 스타일과 형식을 학습하도록 유도한다.
- Chain-of-Thought (CoT) 프롬프팅: LLM에게 답변을 바로 생성하라고 지시하기보다, "단계별로 생각하고 답변하시오"와 같이 중간 추론 과정을 명시하도록 유도함으로써 복잡한 질문에 대한 답변 품질을 향상시킬 수 있다.
RAG 아키텍처 최적화 및 평가
RAG 시스템은 한 번 구축했다고 끝나는 것이 아니다. 지속적인 최적화와 체계적인 평가를 통해 성능을 개선해야 한다.
성능 최적화
- 임베딩 모델 최신화 및 미세 조정: 임베딩 기술은 빠르게 발전하므로, 최신 고성능 임베딩 모델을 주기적으로 검토하고 필요시 업데이트한다. 특정 도메인에 대한 성능이 부족하다고 판단되면, 자체 데이터셋으로 임베딩 모델을 미세 조정하는 것을 고려할 수 있다.
- 벡터 데이터베이스 인덱싱 및 스케일링: 대규모 문서 데이터셋의 경우, 벡터 데이터베이스의 인덱싱 전략(예: HNSW, IVFFlat)과 스케일링 방안을 최적화하여 검색 속도와 효율성을 높여야 한다. 클라우드 기반 벡터 DB 서비스는 이러한 스케일링 부담을 줄여준다.
- 캐싱(Caching) 전략: 자주 발생하는 질문이나 검색 결과에 대해 캐싱을 적용하여 응답 시간을 단축하고 시스템 부하를 줄일 수 있다.
- LLM 최적화: 사용 중인 LLM 자체의 성능을 모니터링하고, 필요에 따라 더 강력하거나 비용 효율적인 LLM으로 교체하는 것을 고려한다. LLM의 파라미터(온도, top-p 등) 조정을 통해 생성되는 답변의 다양성 또는 보수성을 조절할 수 있다.
평가 지표 및 방법
RAG 시스템의 성능을 객관적으로 측정하기 위한 평가 방법은 다음과 같다.
- 검색 성능 평가:
- Recall@k: 실제 관련성 높은 문서 중 몇 개를 상위 k개 검색 결과에 포함시켰는지 측정한다.
- Precision@k: 상위 k개 검색 결과 중 실제로 관련성 높은 문서의 비율을 측정한다.
- MRR (Mean Reciprocal Rank): 첫 번째 관련성 높은 문서가 검색 결과에서 얼마나 상위에 위치하는지를 평가한다.
- 생성 성능 평가:
- Faithfulness (사실 충실도): LLM이 생성한 답변이 검색된 정보를 얼마나 충실하게 반영하는지 평가한다. 검색된 정보와 모순되거나 없는 내용을 지어내지 않는지 확인한다.
- Answer Relevance (답변 관련성): LLM이 생성한 답변이 사용자 질문에 얼마나 관련성이 높은지 평가한다. 불필요한 정보나 질문과 동떨어진 내용을 포함하지 않는지 확인한다.
- Context Relevance (맥락 관련성): 검색된 정보 청크들이 사용자 질문에 얼마나 관련성이 높은지 평가한다. LLM에 전달된 맥락 자체가 유용한지 확인하는 지표이다.
- Human Evaluation (인간 평가): 가장 신뢰할 수 있는 평가 방법으로, 사람이 직접 LLM의 답변을 읽고 정확성, 유용성, 자연스러움 등을 평가한다. 시간과 비용이 많이 들지만, 미묘한 품질 차이를 파악하는 데 필수적이다.
- 자동 평가 도구: RAGAS, LlamaIndex의 평가 모듈 등과 같은 도구를 활용하여 위 지표들을 자동화된 방식으로 측정하고 추적할 수 있다.
Image by onzesuus on Pixabay
RAG 개발 시 고려사항 및 미래 전망
RAG는 강력한 아키텍처이지만, 개발 및 운영 과정에서 몇 가지 고려사항이 존재한다.
- 데이터 보안 및 개인정보 보호: 내부 문서나 민감한 개인정보를 포함하는 데이터를 RAG 시스템에 통합할 경우, 데이터 접근 제어, 암호화, 익명화 등 강력한 보안 및 개인정보 보호 조치를 마련해야 한다.
- 비용 효율성: 임베딩 생성, 벡터 데이터베이스 운영, LLM API 호출 등 RAG 시스템의 각 구성 요소는 비용을 발생시킨다. 특히 LLM 호출 비용은 규모가 커질수록 상당해질 수 있으므로, 효율적인 검색 및 캐싱 전략을 통해 최적화가 필요하다.
- 확장성: 데이터의 양이 증가하고 사용자 트래픽이 늘어남에 따라 RAG 시스템이 안정적으로 확장될 수 있도록 설계해야 한다. 벡터 데이터베이스의 스케일링, 분산 처리, 로드 밸런싱 등이 고려되어야 한다.
- 복잡성 증가: RAG는 단순한 LLM API 호출보다 더 복잡한 파이프라인을 구축해야 하므로, 시스템 설계, 개발, 운영에 더 많은 엔지니어링 노력이 필요하다.
RAG 기술은 지속적으로 발전하고 있다. 단순히 텍스트를 검색하는 것을 넘어, 멀티모달 데이터(이미지, 비디오 등)를 검색하여 LLM에 제공하는 멀티모달 RAG, 검색된 정보를 바탕으로 복잡한 작업을 수행하는 에이전트 기반 RAG, 그리고 LLM이 스스로 검색 전략을 수립하는 자가 개선 RAG 등 다양한 연구와 개발이 활발히 진행되고 있다. 이러한 발전은 RAG가 LLM 기반 애플리케이션의 미래를 이끄는 핵심 기술로 자리매김할 것임을 시사한다.
결론 및 요약
LLM 기반 애플리케이션 개발에 있어 RAG (검색 증강 생성)는 LLM의 본질적인 한계인 환각 현상, 최신 정보 부족, 비공개 데이터 접근성 문제를 해결하는 필수적인 아키텍처이다. RAG는 외부 지식 저장소에서 관련 정보를 검색하여 LLM의 생성 과정에 맥락으로 제공함으로써, 답변의 정확성, 신뢰성, 그리고 투명성을 획기적으로 향상시킨다.
성공적인 RAG 시스템 구축을 위해서는 데이터 전처리 및 청킹, 고품질 임베딩 모델 선택, 하이브리드 검색 및 재순위화 기법을 통한 검색 품질 향상, 그리고 효과적인 프롬프트 엔지니어링 전략이 필수적이다. 또한, 지속적인 성능 최적화와 정량적/정성적 평가를 통해 시스템의 안정성과 효율성을 유지하는 것이 중요하다.
RAG는 LLM의 잠재력을 최대한 발휘하여 실제 비즈니스 가치를 창출하는 데 핵심적인 역할을 수행할 것이다. 복잡한 데이터 환경과 빠르게 변화하는 정보 속에서 LLM 애플리케이션의 성공을 위해서는 RAG 아키텍처에 대한 깊은 이해와 지속적인 최적화 노력이 요구된다.
귀하의 LLM 애플리케이션 개발 여정에서 RAG를 어떻게 활용하고 계신가요? 경험을 댓글로 공유해 주십시오.