내가 6주간 Graph RAG를 직접 구축하며 느끼고 배운 것들

Tasker_Jang·2026년 5월 26일
post-thumbnail

1. 왜 이 멘토링에 참여했는가

ChatGPT가 "그건 잘 모르겠어요"라고 답할 때마다, 또는 RAG 시스템이 분명 문서에 있는 정보를 못 찾아낼 때마다 같은 의문이 들었습니다.

비정형 문서 사이의 관계를 LLM이 추론하게 만들 수는 없을까?

VectorRAG는 chunk 단위로 의미가 비슷한 정보를 잘 모아오지만, 문서 간 관계 추론이나 수치 집계 같은 작업에서는 본질적인 한계를 보입니다. "비트코인 가격이 오르면 코스피도 오를까?" 같은 질문에 답하려면 단순 유사도 검색을 넘어선 무언가가 필요했습니다.

그 답을 찾기 위해 오픈소스컨트리뷰션 그래프 RAG 멘토링에 참여하게 되었습니다.


2. SEOCHO 프로젝트와 멘토링 개요

SEOCHO는 다음 3가지로 구성됩니다:

  • Data Ingestion: PDF/CSV/JSON 등 비정형 소스에서 자동 구조 추출
  • Knowledge Graph: 온톨로지 기반 Entity 추출 → 링킹 → 중복 제거 → Neo4j(DozerDB) 적재
  • Agent Query: Router / Debate / Semantic QA 3가지 모드로 그래프 기반 질의응답

저는 이 구조를 doc-graph-agent라는 이름으로 처음부터 구현했습니다. Layer A (Document Structure) — Layer B (Entity Interaction) — Layer C (Community Summary)의 3-layer 그래프 모델을 따랐고, Routing Agent로 질의를 적절한 retrieval 경로로 분기시키는 구조입니다.

평가셋은 8개 문서 기반 80 QA — VectorRAG QA 40개 (단일 문서 fact 추출) + GraphRAG QA 40개 (문서 간 관계, 집계, 추론) — 로 구성했습니다. LLM은 kimi-k2.5 (OpenRouter), Judge는 claude-haiku-4.5로 통제했습니다.

OT에서 멘토님께서 강조하신 메시지가 본 회고의 thesis가 되었습니다:

"GraphRAG는 도구 중 하나일 뿐, 만능이 아님 — 지식그래프가 유용한 부분을 발견하는 것이 핵심"

이 말의 진짜 의미를 6주 후에야 비로소 체득하게 되었습니다.


3. 6주간의 학습 흐름

매 주차는 투 트랙으로 병행 진행되었습니다.

  • 학습 트랙 — GraphRAG / Neo4j 관련 책을 읽고 Velog 에 정리. 한국 GraphRAG 자료 공급 부족인 상황에서 학습 흔적이 커뮤니티 기여로 이어졌습니다.
  • 구현 트랙 — 학습한 내용을 바탕으로 본인 레포 (doc-graph-agent) 에 적용. GitHub PR 로 박혔습니다.

Velog 글 25편 (GraphRAG 15편 + Neo4j 10편) 과 doc-graph-agent의 PR 들이 6주간의 양 트랙 산출물입니다.

Week 1 — Fundamental (Offline, 4/18 ~ 5/1)

  • 구현: Opik Cloud 계정 생성 + Kimi hello-world 검증, Neo4j + Entity 추출 1회 검증, W2 환경 부트스트랩
  • 학습: [GraphRAG #1, #2, #13], [Neo4j #1, #2, #7]

Week 2 — Agent & Ontology (Online, 5/2 ~ 5/5)

  • 구현: 도메인 온톨로지 설계 (FIBO 차용), ADR 0001 / 0002 작성, 인제스트 포팅, Entity 추출 프롬프트 시행착오
  • 학습: [GraphRAG #3, #4, #5, #6]

Week 3 — Knowledge Base Build (Online, 5/9 ~ 5/13)

가장 정성스럽게 다룬 주차입니다. 이 단계의 품질이 시스템 전체를 결정한다는 것을 W6 에서 깨닫게 됩니다.

  • 구현: Entity 추출 파이프라인, NED + Dedup (Cosine 0.92 threshold), Neo4j 적재, ⭐ 첫 KG 시각화, 8 문서 일괄 적재
  • 학습: [GraphRAG #7, #8, #15], [Neo4j #3, #4, #5, #6, #8]

Week 4 — Agent with KB (Offline, 5/16 ~ 5/17)

  • 구현: Layer A (Text2Cypher Agent + Read-only 안전 장치), Layer B (Local Retriever), Layer C (stub), Routing Agent (rule-based), ⭐ 시나리오 점검
  • 학습: [GraphRAG #14, #9, #10]

Week 5 — Observability (Offline, 5/19 ~ 5/22)

  • 구현: Hybrid Score Fusion (Vector + Graph 점수 결합), Opik 트레이싱 통합, 80 QA 측정 자동화
  • 학습: [GraphRAG #11, #12], [Neo4j #9, #10]

측정 가능한 시스템이 곧 진단 가능한 시스템이라는 것을 이 주차에 처음 체감했습니다.

Week 6 — Wrap-up (Hybrid, 5/23)

  • 구현: ⭐ 80 QA 본 측정 수행, 근본 원인 진단 — Neo4j 직접 검증으로 Company 노드 분류 오류 발견, 본 회고록 작성
  • 학습: 종합 회고 (5/25)

이 글의 본격적인 얘기는 여기서부터 시작됩니다.


4. 본 측정 설계 — 80 QA의 구성

4.1 평가셋 구성

qa_set패턴개수의도
vectorragfactual / numerical / summary / negative40단일 문서 내 fact 추출 — RAG의 전통적 영역
graphragmulti_doc_trend / intersection / filter_agg / causal / 1hop / limitation40문서 간 관계, 집계, 추론 — GraphRAG가 의도된 강점 영역

4.2 평가 메트릭

Tier메트릭
Tier 1ROUGE-L, 수치 정확도, Faithfulness, Completeness, Conciseness
Tier 2Answer Correctness (Judge LLM), Entity Coverage, Routing Accuracy

4.3 통제 조건

  • LLM: 동일 조건에서 두 모델 측정
    • openai/gpt-5-mini (OpenRouter)
    • moonshotai/kimi-k2.5 (OpenRouter)
    • Entity 추출 / 답변 생성 모두 동일 모델 사용
  • Judge: claude-haiku-4.5
  • Corpus: 8개 문서 (한화 두산밥캣, DS시황, 미래에셋 1Q~4Q, 농협, 금감원)

GraphRAG의 부진을 LLM의 문제로 잘못 진단할 가능성을 차단하기 위해 두 모델로 동일 80 QA를 측정했습니다. 두 모델 모두 정상 작동했으며 (빈 응답 0건), 결과 패턴이 일관되게 나옴으로써 시스템의 한계가 LLM이 아닌 전처리 단계에 있다는 진단을 정량적으로 뒷받침합니다.

LLMCorrectness (/5)Faithful (%)빈 응답
gpt-5-mini1.2012.5%0/80
kimi-k2.51.415.0%0/80

두 모델의 평균 차이는 0.21점에 불과합니다. 이는 답변 LLM을 어느 것으로 바꿔도 결과가 비슷하다는 뜻 — 부진의 원인이 LLM이 아니라는 핵심 증거입니다.


5. GraphRAG가 빛난 곳과 무너진 곳

5.1 전체 그림 — 두 LLM 일관된 패턴

doc-graph-agent의 80 QA를 gpt-5-minikimi-k2.5 두 모델로 동일하게 측정했습니다. 두 모델 모두 빈 응답 0건으로 정상 작동했으며, 결과 패턴이 일관됩니다. 부진의 원인이 답변 LLM이 아니라 전처리 단계에 있다는 진단의 정량 근거입니다.

메트릭gpt-5-minikimi-k2.5차이
Correctness (/5)1.201.41+0.21
Faithful (%)12.5%5.0%-7.5p
Completeness (/5)1.211.30+0.09
Conciseness (/5)1.691.34-0.35
ROUGE-L0.0710.078+0.007
수치 정확도0.1340.160+0.025
Semantic Similarity0.3660.470+0.104
Entity Coverage0.0140.223+0.209
빈 응답0/800/80

두 모델 모두 정상 작동(빈 응답 0건). 평균 Correctness 차이는 0.21점으로 미미 — 부진의 원인이 답변 LLM이 아니라 전처리 단계임을 시사합니다.

5.2 qa_set 별 — vectorrag(40) vs graphrag(40)

qa_setLLMnCorrectnessFaithfulROUGE-L수치 정확도
vectorraggpt-5-mini401.4012.5%0.0640.150
vectorragkimi-k2.5401.577.5%0.0640.170
graphraggpt-5-mini401.0012.5%0.0780.119
graphragkimi-k2.5401.252.5%0.0920.149

5.3 pattern 별 — 영역별 강약 진단

본 측정의 핵심은 GraphRAG가 균일하게 약한 시스템이 아니라 극단적으로 영역 의존적인 시스템이라는 점입니다. pattern 별 성적을 두 LLM으로 교차 검증해서 보면, 어디서 빛나고 어디서 무너지는지가 명확히 드러납니다.

영역patternngpt-5-mini C/5kimi-k2.5 C/5gpt-5-mini Faithful%kimi-k2.5 Faithful%
✅ 강점negative45.005.00100.0%75.0%
✅ 강점limitation21.004.5050.0%50.0%
✅ 강점filter_agg51.001.600.0%0.0%
❌ 약점numerical231.001.300.0%0.0%
❌ 약점1hop101.001.0010.0%0.0%
❌ 약점intersection81.001.0012.5%0.0%
❌ 약점multi_doc_trend101.001.0020.0%0.0%
❌ 약점causal51.001.000.0%0.0%
❌ 약점factual91.001.0011.1%0.0%
❌ 약점summary41.001.000.0%0.0%

5.4 Routing Accuracy — 라우터는 옳았다

답변 품질과 분리해서 보는 진단 지표입니다. Routing Agent가 옳게 분기시켰는데 답변 단계에서 무너졌다는 사실이 본 측정의 결정적인 진단입니다.

Routing Agent가 질의 유형을 옳게 분류한 비율. 답변 품질과 분리해서 보는 진단 지표.

patternngpt-5-minikimi-k2.5
1hop1090.0%80.0%
multi_doc_trend10100.0%100.0%
intersection8100.0%100.0%
causal5100.0%100.0%
filter_agg50.0%60.0%
limitation20.0%50.0%
전체4080.0%87.5%

5.5 잘한 케이스 — Correctness 4 이상

IDqa_setpatternC/5Faithful질문
ds_005vectorragnegative5이 보고서에서 언급된 한국은행 금통위 일정은?
fss_006vectorragnegative5이 보도자료에서 언급된 회사채 발행 기업의 개별 회사명은?
graph_040graphraglimitation5그래프에서 Company 라벨로 분류된 'AA등급 이상 회사채 발행 비중 73.0%'는 실제 회사명인가?
hanwha_002vectorragnumerical5두산밥칿의 2026년 1분기 예상 영업이익과 OPM은?
mirae_4q_006vectorragnegative5미래에셋증권의 2025년 4분기 배당 지급일은?
nonghyup_005vectorragnegative5이 보고서에 기재된 청산농협의 당기순이익은 얼마인가?
fss_002vectorragnumerical42025년 10월 CP 및 단기사채 발행액 합계와 전월 대비 증감은?
graph_031graphragfilter_agg4공시(disclosure) 유형 문서에서 다루는 주요 통계 metric은 무엇인가?
graph_039graphraglimitation4DS 시황 리포트(2026년 3월)와 한화 두산밥캣 리포트(2026년 3월) 중 어느 것이 더 최신인가?

총 9건 / 80건 = 11.2%. 80% 이상이 negativelimitation 패턴 — 그래프 구조 자체가 답을 만드는 영역.

5.6 두 가지 풍경

위 표들이 말하는 것을 한 줄로 정리하면:

  • GraphRAG가 빛난 영역: negative + limitation + filter_agg 일부 — 약 11% (Correctness 4 이상)
  • GraphRAG가 무너진 영역: 나머지 89%

수치만 보면 압도적인 부진처럼 보입니다. 하지만 왜 일부 영역에서는 만점에 가까운 점수가 나오고, 나머지에서는 1점에 머무는가가 진짜 질문입니다. 다음 두 섹션에서 각각 들여다봅니다.


6. GraphRAG가 빛난 영역 — 그래프 구조 자체에 답이 있을 때

6.1 Negative pattern (4/4, Correctness 5.0) — "이 문서에 없는 것"을 묻는 질문

[ds_005] Q: "이 보고서에서 언급된 한국은행 금통위 일정은?" (정답: 본 보고서에는 언급되지 않음)

Answer: "본 그래프에는 'DS투자증권 시황분석 리포트' 문서 노드 1개가 적재되어 있으며, 해당 문서와 연결된 entity 들 중 '한국은행 금통위 일정'과 관련된 metric/event entity 는 존재하지 않습니다. 따라서 이 보고서에는 금통위 일정이 언급되지 않은 것으로 판단됩니다." ✅ Faithful, Correctness 5/5

[mirae_4q_006] Q: "미래에셋증권의 2025년 4분기 배당 지급일은?" (정답: 본 보고서에는 언급되지 않음)
[nonghyup_005] Q: "이 보고서에 기재된 청산농협의 당기순이익은 얼마인가?" (정답: 청산농협이라는 entity 자체가 본문에 없음)
[fss_006] Q: "이 보도자료에서 언급된 회사채 발행 기업의 개별 회사명은?" (정답: 통계 수치만 있고 개별 회사명 언급 없음)

핵심 인사이트:

Negative 질문은 "~이 없다"를 증명해야 하는 질문입니다. RAG가 chunk를 가져와서 답하려고 하면 환각이 발생하기 쉬운 영역입니다. 반면 GraphRAG는 그래프 안에 entity가 없다는 사실 자체를 명시적인 증거로 활용합니다.

"Cypher 쿼리에 답이 0건이다 → 그래프에 없다 → 본문에 없을 가능성이 높다"

이 추론 사슬이 negative 질문에서 100% 정답을 만든 메커니즘입니다. GraphRAG의 "no answer"는 RAG의 "no answer"보다 신뢰도가 높습니다 — 그래프 구조 자체가 부재의 증거가 되기 때문입니다.

6.2 Limitation pattern (2/2, Correctness 4.5) — 그래프 메타 질의

[graph_039] Q: "DS 시황 리포트(2026년 3월)와 한화 두산밥캣 리포트(2026년 3월) 중 어느 것이 더 최신인가?"

Answer: "Document 노드 속성을 조회한 결과, 두 문서 모두 publication_date 속성이 정의되어 있지 않아 그래프 데이터만으로는 상대적 신선도를 판단할 수 없습니다. 파일명에 명시된 작성월 기준으로는 동일한 2026년 3월입니다." ✅ Correctness 4/5

[graph_040] Q: "그래프에서 Company 라벨로 분류된 'AA등급 이상 회사채 발행 비중 73.0%'는 실제 회사명인가?"

Answer: "아닙니다. 이 entity는 금융 통계 지표입니다. 그래프에서 이 entity는 'Company' 라벨과 함께 'Risk', 'Metric' 라벨도 동시에 부여되어 있는데, 이는 entity 추출 과정에서 텍스트 패턴('XX%')이나 문맥상 수치 정보를 회사명으로 오분류한 결과입니다." ✅ Correctness 5/5

핵심 인사이트:

이 두 케이스에서 GraphRAG는 자기 자신의 그래프 구조를 query 대상으로 삼습니다. Document 노드의 속성 유무, Entity의 라벨 분포, 다중 라벨 부여 패턴 — RAG는 이런 메타 질의에 구조적으로 답할 수 없습니다 (chunk 텍스트에는 이런 정보가 없으므로).

graph_040은 특히 흥미로운 케이스인데, GraphRAG가 자기 시스템의 한계를 명시적으로 자가 진단했습니다. "이 entity가 잘못 분류되어 있다"는 진단 자체가 답이 되는 질의 — 이는 RAG가 본질적으로 접근할 수 없는 영역입니다.

6.3 Filter_agg pattern (1/5 정답이지만 의미 있음) — 그래프 전체 집계

[graph_031] Q: "공시(disclosure) 유형 문서에서 다루는 주요 통계 metric은 무엇인가?"

Answer: "공시 유형 문서에서 가장 많이 언급된 통계 metric은 회사채 발행 규모와 관련된 수치들입니다. 특히 '회사채 발행 규모 23조 6,111억원', 'CP 및 단기사채 발행액 137조 6,459억원', '주식 발행 규모 939억원' 등이 주요 통계 metric으로 추출되었습니다." ✅ Correctness 4/5

핵심 인사이트:

corpus-wide 집계는 BM25나 dense retrieval로는 구조적으로 불가능한 영역입니다 (둘 다 문서 내 검색만 가능). GraphRAG는 그래프 전체를 한 번에 query할 수 있어서 "전 corpus에서 가장 많이 등장한 X는?" 같은 질문에 본질적으로 적합합니다.

filter_agg에서 5건 중 1건만 정답이었지만, 그 1건이 BM25로는 절대 답할 수 없는 영역이라는 점이 중요합니다. 남은 4건의 실패는 Section 7의 entity 추출 품질 문제 때문이지, 패러다임 자체의 한계가 아닙니다.

6.4 정리 — GraphRAG의 진짜 강점

영역메커니즘RAG로 대체 가능?
Negative ("X가 없다")그래프의 부재 자체가 증거❌ 환각 위험
Limitation (메타 질의)그래프 구조 자체를 query❌ 구조적 불가
Filter_agg (corpus 집계)전 그래프 한 번에 query❌ 구조적 불가
Multi-doc 추론 (잠재적)entity 공유를 통한 cross-doc 추론⚠️ 제한적

처음 세 영역은 RAG가 잘하느냐 못하느냐의 문제가 아니라, RAG가 본질적으로 접근할 수 없는 영역입니다. 이게 GraphRAG의 진짜 존재 이유입니다.


7. GraphRAG가 무너진 영역 — 전처리 품질이 받쳐주지 않을 때

7.1 근본 원인 ① — Entity 추출 LLM의 라벨 분류 오류

가장 결정적인 발견은 Neo4j에 직접 접속해서 그래프 자체를 들여다본 순간이었습니다.

MATCH (n:Company) RETURN n.name LIMIT 30

결과를 보고 한참 멍해졌습니다. 30개 중 0개가 실제 회사명이었습니다.

 1. "공모발행액 23조 7,050억원 (2025년 10월)"
 2. "주식 발행 규모 939억원 (2025.10)"
 3. "회사채 발행 규모 23조 6,111억원 (2025년 10월)"
 4. "CP 및 단기사채 발행액 137조 6,459억원 (2025년 10월)"
 5. "기업공개 발행액 524억원 (2025년 10월)"
...
15. "AA등급 이상 회사채 발행 비중 73.0%"
16. "중기채 발행 비중 94.7%"

30개 모두 Metric(수치/지표)인데 Company 라벨로 잘못 분류되어 있었습니다. 진짜 회사들 — 두산밥캣, 미래에셋증권, 한화투자증권 등 — 은 Company 라벨로 저장되어 있지도 않았습니다.

원인 분석: Entity 추출 단계의 LLM 프롬프트가 긴 한국어 명사구를 고유명사로 오인했습니다. 단위(%, 원, 조, 억)와 숫자가 포함되어 있어도 이를 회사명의 일부로 처리해버렸습니다.

예측의 적중: 평가셋 작성 시 graph_040에 이 문제를 메타 질문으로 미리 넣어두었던 것이 정확히 들어맞았습니다. W3 Entity Extraction 학습을 거치며 이 위험을 직감했고, 그 직감을 평가셋에 남겨둔 것이 실제 측정에서 ground truth로 확인된 것입니다.

영향 범위: 80 QA 중 약 40개의 부진이 이 한 가지 원인으로 설명됩니다.

7.2 근본 원인 ② — OCR 글자 깨짐의 entity 검색 실패

한화투자증권 PDF의 OCR 단계에서 "두산밥캣"이 "두산밥칿"으로 깨졌습니다. 한글 종성 처리 실패 — Tesseract 기본 OCR이 한글 받침 인식에 약한 알려진 한계입니다.

GraphRAG의 처리:
질문 파싱 → "두산밥캣" entity 식별
        → Cypher: MATCH (c:Company {name: "두산밥캣"})
        → 그래프엔 "두산밥칿"으로 저장됨 (exact match 실패)
        → 검색 결과 0건
        → "entity 없음" 답변 ❌

영향 받은 11개 QA:

  • hanwha_001~006 (VectorRAG 6개): 두산밥캣 직접 질문
  • graph_011, 012, 016 (1hop 3개): 두산밥캣 관련 리스크/지표/실적
  • graph_034, 038 (causal 2개): 두산밥캣 관련 인과 추론

핵심 인사이트:

GraphRAG는 entity exact match로 전처리 오류를 그대로 전파합니다. 같은 OCR 깨짐 한글 1글자가, RAG라면 chunk 단위 fuzzy 검색으로 흡수될 수 있지만, GraphRAG에는 entity 검색 단계에서 100% 실패로 이어집니다.

이 비대칭성이 production GraphRAG의 첫 번째 결정적 비용입니다.

7.3 근본 원인 ③ — Metric 노드 미생성

질문: "미래에셋증권의 2분기 ROE는?"

Answer: "현재 그래프에 적재된 주요 entity는 회사명과 리스크/전망 관계 위주로 구성되어 있어, ROE 와 같은 구체적인 수치 지표는 entity 추출 과정에서 노드로 분리되지 않았을 가능성이 높습니다."

이 답변이 80 QA에서 17건(numerical 23건 중 대부분) 반복됩니다. 원문 PDF에는 "ROE 8.5%", "세전이익 3,461억원" 같은 수치가 명시되어 있지만, entity 추출 단계가 Company / Risk / Outlook 정도만 잡고 Metric 노드를 만들지 않았습니다.

만약 Metric 노드와 HAS_METRIC 관계가 그래프에 박혀 있었다면:

MATCH (c:Company {name:"미래에셋증권"})-[:HAS_METRIC]->(m:Metric {name:"ROE", period:"2Q25"})
RETURN m.value

이런 쿼리로 답이 나왔을 텐데, 현재는 Metric 노드 자체가 없어 Text2Cypher가 답을 생성할 수 없습니다.

7.4 근본 원인 ④ — Layer C (Community Detection + Summary) 미구현

6개 QA에 영향. Layer C는 진입점 함수 + 라우팅 분기 + stub 안내 응답까지는 구현돼 있고, 본 측정 시 라우터가 글로벌 질의를 Layer C로 정확하게 분기시켰습니다 (multi_doc_trend pattern 10건의 routing accuracy 100%). 다만 Community Detection (Leiden 알고리즘) + Community Summary 사전 생성 + map-reduce 합성 — 즉 답변 생성을 위한 핵심 로직이 미구현 상태입니다.

본인 코드에 명시된 stub 안내:

"질문하신 내용은 전체 문서 corpus의 트렌드/패턴/요약을 요구하는 글로벌 질의로 판단됩니다. Layer C (Community Summary)는 그래프 전체에서 entity 군집(community)을 탐지하고 각 군집의 요약을 사전 생성한 뒤, 글로벌 질의에 대해 map-reduce 방식으로 답변을 합성하는 모듈입니다. 본 프로젝트의 Layer C는 현재 미구현 (stub) 상태이며, 5/24+ W5/W6 영역에서 다음 순서로 구현 예정입니다:
1. Community detection (Leiden 알고리즘) — entity 노드 기반 군집 추출
2. Community summary 사전 생성 — 각 군집의 entity / 관계 / 핵심 chunk 요약
3. Global search — 질의 → community summary 위에서 map-reduce 합성"

본 stub 설계는 의도된 선택입니다. Community 데이터가 없는 상태에서 LLM만으로 "글로벌 답변"을 흉내내는 것은 정직하지 않은 패턴 (community 구조 없이 흉내내면 환각)이라는 판단으로, 라우팅 분기까지만 보여주고 답변 생성은 정직하게 안내하도록 stub을 박았습니다.

평가의 양면성:

  • ✅ Routing 정확도는 정상 — multi_doc_trend pattern 100%. 라우터가 글로벌 질의를 옳게 식별했습니다.
  • ✅ 미구현 부분이 환각이 아닌 정직한 안내로 응답 — Faithfulness는 살려냄.
  • ❌ 답변 자체로는 6개 QA에서 Correctness 1점 — Community Summary 핵심 로직이 미완성이라 정답에 도달하지 못함.

5.1, 5.2, 5.3과 달리 이 케이스는 모델이나 데이터의 문제가 아닌 개선점으로 남아있는 핵심 로직의 미완성입니다. 80 QA 측정 인프라 구축에 시간을 우선 투자한 결과로, 후속 작업의 첫 번째 우선순위입니다.

7.5 정리 — GraphRAG가 무너진 진짜 이유

원인영향 QA본질
Entity 라벨 오분류~40건전처리 LLM 품질
Metric 노드 미생성~17건Entity 추출 스키마
OCR 글자 깨짐11건파싱 전처리
Layer C 미구현6건시스템 미완성

중요한 관찰: 무너진 영역의 부진은 GraphRAG 패러다임의 한계가 아니라 production 전처리 인프라의 한계입니다. 패러다임이 맞아도 전처리가 무너지면 전체가 무너지는 — GraphRAG 특유의 single point of failure가 정확히 드러난 결과입니다.


8. 진짜 인사이트 — GraphRAG는 trade-off이고, 답은 Hybrid다

6주 후, OT에서 멘토님이 강조하셨던 말씀의 진짜 의미를 깨달았습니다.

"GraphRAG는 도구 중 하나일 뿐, 만능이 아님 — 지식그래프가 유용한 부분을 발견하는 것이 핵심"

본 측정이 보여주는 것은 "GraphRAG가 좋다 / 나쁘다"가 아닙니다. GraphRAG가 빛나는 적용 영역이 명확히 존재하고, 그 외에는 다른 도구가 필요하다는 결론입니다.

8.1 GraphRAG가 본질적으로 우월한 영역

본 측정에서 정량적으로 검증된 영역:

  1. Negative 질의 (부재 증명) — 그래프 구조 자체가 부재의 증거. RAG의 환각 위험을 구조적으로 차단.
  2. Limitation 질의 (메타 질의) — 그래프 자체를 query 대상으로 삼는 영역. RAG가 본질적으로 접근 불가.
  3. Corpus-wide 집계 — 전 문서를 한 번에 query. BM25는 문서 내 검색만 가능.

여기에 더해, 전처리 품질만 보강되면 다음 영역도 GraphRAG가 우위를 가질 가능성이 있습니다:

  1. Multi-doc 추론 — 본 측정에서는 부진했지만 Routing Accuracy 100%를 기록. 라우팅 구조 자체는 정상.
  2. 명시적 관계 추적 — entity 간 명시적 edge가 있으면 다중 hop 추론이 chunk 검색보다 정확.

8.2 GraphRAG가 본질적으로 비효율적인 영역

  1. 단일 사실 추출 — chunk 검색으로 충분. Entity 추출 단계의 정보 손실이 오히려 손해.
  2. 요약 / paraphrasing — chunk 텍스트가 직접 LLM에 전달되는 RAG가 자연스러움.

8.3 결론: Hybrid 아키텍처가 답이다

본 측정의 패턴별 결과를 정직하게 받아들이면, 단일 시스템(GraphRAG든 BM25든)은 답이 아닙니다. 질의 유형별로 다른 retrieval 경로가 필요합니다.

사용자 질의
    ↓
[Router Agent] ← 질의 유형 분류
    ↓
    ├─→ 단일 사실 / 요약        → BM25 + LLM
    ├─→ Negative / Limitation   → Graph Cypher (Layer A) ⭐
    ├─→ Multi-hop / 관계        → Graph Local (Layer B)
    └─→ Global trend / 집계     → Community Summary (Layer C) ⭐ 미구현
            ↓
[Reranker / Fusion] ← 여러 경로 결과 통합 (옵션)
    ↓
최종 답변

저는 W4에서 이미 Router를 박았고 (Routing Accuracy 87.5%), Layer A/B 모두 구현했습니다. 남은 건 그 위에 BM25 갈래를 통합하는 것 + Layer C 완성 + 전처리 품질 보강입니다.

production GraphRAG의 진짜 비용은 답변 단계가 아닙니다. 전처리 품질 보증 + Hybrid 라우팅 설계가 진짜 비용입니다.


9. 회고 — 잘한 점, 아쉬운 점, 다음 단계

잘한 점

  • 80 QA 측정 인프라를 끝까지 구축한 점. 측정이 없었다면 "GraphRAG 잘 됩니다" narrative로 흘러갈 위험이 있었습니다. 정량 평가가 진단 가능성을 만들어주었습니다.
  • Neo4j 직접 검증. 왜 부진했는가를 추측이 아닌 증거(MATCH (n:Company) RETURN n.name)로 답할 수 있었습니다.
  • 평가셋 작성 시점의 직감을 측정으로 검증. graph_040 메타 질문이 정확히 들어맞은 것은 W3 학습이 깊이 박혔다는 증거였습니다.
  • 블로그 26편 누적. 학습 흔적이 누적되는 과정 자체가 6주 학습의 복리 효과였습니다.
  • OPIK 활용하기. OPIK이라는 툴을 처음으로 활용해보면서 고민하는 과정을 즐길 수 있었습니다.

아쉬운 점

  • 파싱을 VLM으로 사용하지 못한 점 & Entity 추출 프롬프트 재설계가 WBS 안에 들어가지 못한 점. 진단까지만 하고 개선은 후속 작업으로 미루게 되었습니다.
  • Layer C의 핵심 로직 (Community Detection + Summary 합성) 미완성. 진입점 / 라우팅 분기 / stub 안내까지는 박았지만, 답변 생성을 위한 Leiden + map-reduce 가 남아 있습니다. 6개 QA가 직접 영향을 받았고, multi-doc 영역의 진짜 평가가 불가능했습니다.
  • 두 LLM(gpt-5-mini, kimi-k2.5)으로만 측정. Claude / DeepSeek / GPT-4 등 다양한 모델군은 못 다뤘습니다. 다만 두 모델의 결과 패턴이 일관됐다는 점에서 답변 LLM 변경으로 해결될 부진이 아니다는 진단은 충분히 정량화됐습니다.

다음 단계 (향후 개선점)

우선순위작업기대 효과
P1Entity 추출 프롬프트 재설계 (Metric 라벨 + Few-shot + 후처리 검증)numerical 23건 + filter_agg 4건 회복
P2Neo4j 라벨 교정 쿼리 — 재적재 없이 기존 노드 업데이트Company 30개 → Metric 재라벨링
P3VLM 기반 파싱 파이프라인 도입표/차트/레이아웃 포함 전반적 파싱 품질 향상
P4Layer C 핵심 로직 구현 (Leiden community detection + map-reduce 요약 합성, 진입점은 이미 박혀 있음)6건 + multi_doc_trend 10건 회복
P5BM25 갈래를 Router에 통합factual/summary 13건 회복 + Hybrid 완성
검증동일 80 QA 재측정Faithfulness 5% → 목표 50%+

10. 마치며

한국 GraphRAG 자료가 공급 부족인 시점에서, 제가 작성한 25편 + 본 회고 1편 = 총 26편이 한국 개발자 커뮤니티의 time saver가 되기를 바랍니다.

특히 본 글은 production 적용을 고민 중인 개발자분들께 다음을 권하고 싶습니다:

  1. 영어권의 "GraphRAG 잘 됩니다" 자료에 휘둘리지 마세요. 직접 측정하지 않으면 어디서 빛나고 어디서 무너지는지 알 수 없습니다.
  2. GraphRAG는 적용 영역 선택이 답입니다. Negative / Limitation / Corpus-wide 집계 — 이 영역에서 GraphRAG는 RAG가 구조적으로 접근 불가한 답을 제공합니다.
  3. 단일 시스템은 답이 아닙니다. Hybrid가 답입니다. Router + BM25 + GraphRAG 갈래 + Community Summary가 통합된 아키텍처가 production의 정답입니다.
  4. 전처리 품질 보증 인프라가 production의 진짜 비용입니다. Entity 추출 / 분류 / 링킹 단계가 시스템 전체를 결정합니다.

마지막으로, 6주 동안 함께해주신 정이태(Hardy) 멘토님께 깊은 감사를 드립니다.

"GraphRAG의 한계를 모르고 적용하는 것보다, 한계를 알고 적용하는 것이 훨씬 강력하다"


작업한 코드

profile
ML Engineer 🧠 | AI 모델 개발과 최적화 경험을 기록하며 성장하는 개발자 🚀 The light that burns twice as bright burns half as long ✨

0개의 댓글