GraphRAG - 지식 그래프 기반 RAG
지난 글까지 벡터 검색과 Hybrid Search로 관련 문서를 찾는 방법을 다뤄왔습니다. 그런데 벡터 검색은 문서 하나하나를 독립적으로 비교하는 방식이라, 문서 여러 개에 걸쳐 흩어진 관계 정보를 종합해야 답할 수 있는 질문에는 약합니다. 이번 글에서는 이 빈틈을 메우는 GraphRAG의 개념과 구조를 정리합니다.
1. 벡터 검색이 답하기 어려운 질문 유형
지금까지 다뤄온 벡터 검색은 "질문과 의미가 비슷한 청크를 찾는" 방식입니다. 그런데 다음과 같은 질문은 어느 한 청크만 봐서는 답이 나오지 않습니다.
질문: "김철수 팀장이 승인권을 가진 정책들을 전부 알려줘"
문서 A: "재택근무는 김철수 팀장 승인 하에 가능합니다"
문서 B: "출장비 정산은 김철수 팀장 결재가 필요합니다"
문서 C: "연차 승인권자는 소속 팀장입니다" (이름 언급 없음)
벡터 검색은 각 청크를 독립적으로 비교하기 때문에, "김철수 팀장"과 관련된 정책들을 한 번에 모아서 종합적으로 답하는 데는 한계가 있습니다. 특히 문서 C처럼 이름이 직접 언급되지 않고 "소속 팀장"이라는 간접 표현만 있는 경우, 벡터 유사도만으로는 이 문서가 김철수 팀장과 관련 있다는 걸 알아내기 어렵습니다.
2. GraphRAG의 핵심 아이디어
GraphRAG는 문서를 청크 단위로만 쪼개는 게 아니라, 문서 안에서 개체(Entity)와 개체 간의 관계(Relationship)를 미리 추출해서 지식 그래프로 만들어두고, 검색 시 이 그래프를 함께 활용하는 방식입니다.
[기존 RAG]
문서 → 청크 분할 → 임베딩 → 벡터 검색
[GraphRAG]
문서 → 청크 분할 → 개체·관계 추출 → 지식 그래프 구축
↓
질문 → 관련 개체 파악 → 그래프 순회로 연결된 정보 수집 → LLM에 전달
"김철수"라는 개체를 중심으로, "팀장이다", "재택근무 승인권을 가진다", "출장비 결재권을 가진다"처럼 문서 여러 곳에 흩어진 관계를 그래프 상의 연결로 미리 정리해두는 것이 핵심입니다.
3. 지식 그래프 구조 예시
(김철수) --[직책]--> (팀장)
(김철수) --[승인권한]--> (재택근무 정책)
(김철수) --[결재권한]--> (출장비 정산)
(팀장) --[승인권한]--> (연차)
이렇게 그래프로 표현해두면, "김철수"라는 노드에서 출발해 연결된 간선을 따라가는 것만으로 재택근무, 출장비, 연차까지 관련 정보를 한 번에 모을 수 있습니다. "팀장"이라는 직책 노드를 거쳐 "연차" 승인권까지 연결되는 것처럼, 이름이 직접 언급되지 않은 문서 C의 내용도 그래프 상에서는 자연스럽게 이어집니다.
4. 개체·관계는 어떻게 추출하는가
이 그래프는 사람이 수작업으로 만드는 게 아니라, LLM에게 문서를 넘겨 개체와 관계를 추출하도록 요청해서 자동으로 구축합니다.
extraction_prompt = """
다음 문서에서 개체(사람, 조직, 정책, 직책 등)와 그 사이의 관계를 추출해서
(개체1, 관계, 개체2) 형식의 트리플로 정리해줘.
문서: {chunk_text}
출력 형식:
(김철수, 직책, 팀장)
(김철수, 승인권한, 재택근무 정책)
"""
from openai import OpenAI
client = OpenAI()
def extract_triples(chunk_text):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": extraction_prompt.format(chunk_text=chunk_text)}]
)
return parse_triples(response.choices[0].message.content)
지난 글들에서 다룬 청킹 단계 이후에, 각 청크마다 이 추출 과정을 한 번씩 거쳐서 트리플(개체-관계-개체)들을 모아두는 전처리 단계가 추가되는 구조입니다.
5. 그래프 저장하기 - Neo4j 활용
추출된 트리플은 그래프 전용 데이터베이스인 Neo4j 같은 곳에 저장합니다.
MERGE (a:Person {name: "김철수"})
MERGE (b:Position {name: "팀장"})
MERGE (c:Policy {name: "재택근무 정책"})
MERGE (a)-[:직책]->(b)
MERGE (a)-[:승인권한]->(c)
from neo4j import GraphDatabase
driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "password"))
def insert_triple(subject, relation, obj):
with driver.session() as session:
session.run("""
MERGE (a {name: $subject})
MERGE (b {name: $obj})
MERGE (a)-[r:RELATION {type: $relation}]->(b)
""", subject=subject, obj=obj, relation=relation)
6. 검색 시 그래프와 벡터를 함께 활용하기
실제 질문이 들어오면, 질문에서 핵심 개체를 먼저 뽑아내고 그래프에서 관련 노드를 탐색한 뒤, 이 결과를 벡터 검색 결과와 함께 LLM에 전달합니다.
def graph_search(question):
entities = extract_entities_from_question(question) # 예: ["김철수"]
with driver.session() as session:
result = session.run("""
MATCH (a {name: $entity})-[r]->(b)
RETURN a.name AS subject, r.type AS relation, b.name AS object
""", entity=entities[0])
return [f"{row['subject']} - {row['relation']} - {row['object']}" for row in result]
질문: "김철수 팀장이 승인권을 가진 정책들을 전부 알려줘"
그래프 검색 결과:
김철수 - 승인권한 - 재택근무 정책
김철수 - 결재권한 - 출장비 정산
김철수 - 직책 - 팀장
팀장 - 승인권한 - 연차
→ 이 관계들을 벡터 검색 결과와 함께 LLM에 전달해 종합 답변 생성
7. GraphRAG와 기존 벡터 RAG 비교
| 구분 | 벡터 RAG | GraphRAG |
|---|---|---|
| 강점 | 의미적으로 유사한 문서 찾기 | 개체 간 관계를 종합해서 답하기 |
| 약점 | 여러 문서에 흩어진 관계 파악 어려움 | 그래프 구축 비용과 복잡도가 높음 |
| 적합한 질문 | "재택근무 정책이 뭐야?" | "김철수 팀장과 관련된 모든 권한을 알려줘" |
| 구축 비용 | 임베딩만 필요 | 개체·관계 추출 + 그래프 DB 운영 필요 |
GraphRAG는 만능이 아니라, 개체 간 연결 관계를 종합해야 하는 질문이 자주 나오는 도메인(조직도, 승인 체계, 법률 조항 간 인용 관계 등)에서 벡터 RAG를 보완하는 용도로 쓰는 것이 현실적입니다.
8. 도입 시 고려할 점
- 개체·관계 추출은 LLM 호출 비용이 문서량에 비례해서 늘어나므로, 전체 문서에 무조건 적용하기보다 관계 정보가 중요한 문서 집합에 선별적으로 적용하는 것이 좋습니다.
- 그래프 DB 운영이라는 새로운 인프라가 추가되므로, 기존 pgvector 운영에 더해 관리 포인트가 하나 늘어난다는 점을 감안해야 합니다.
- 추출 정확도가 100%가 아니기 때문에, 잘못된 관계가 그래프에 섞여 들어갈 위험도 함께 관리해야 합니다.
9. 정리
- GraphRAG는 문서에서 개체와 관계를 추출해 지식 그래프로 만들고, 검색 시 이 그래프를 함께 활용해 여러 문서에 흩어진 관계 정보를 종합합니다.
- 벡터 검색이 "의미적 유사성" 기반이라면, GraphRAG는 "개체 간 관계"를 기반으로 답하는 질문에 강합니다.
- 그래프 구축 비용과 운영 복잡도가 높아지므로, 관계 정보가 중요한 도메인에 선별적으로 적용하는 접근이 현실적입니다.
다음 글에서는 지금까지 텍스트 문서 위주로 다뤄온 RAG를 확장해서, 이미지와 표가 섞인 문서를 함께 검색할 수 있는 멀티모달 RAG를 다뤄보겠습니다.
'RAG를 활용한 LLM 서비스 구축' 카테고리의 다른 글
| STEP 22 - Query Routing (0) | 2026.07.20 |
|---|---|
| STEP 21 - 멀티모달 RAG (0) | 2026.07.20 |
| STEP 19 - RAG 시스템 부하 테스트와 모니터링 (0) | 2026.07.15 |
| STEP 18 - 권한 기반 RAG 접근 제어 (0) | 2026.07.14 |
| STEP 17 - 대화형 RAG 챗봇 구현하기 (0) | 2026.07.14 |