RAG·Agent

LLM 없이 만든 GraphRAG: 법령 인용 그래프 16,281개 엣지 구축기

GraphRAG는 하나의 기법이 아니라 스펙트럼입니다. 법령처럼 관계가 텍스트에 형식화된 도메인에서 LLM 엔티티 추출 없이 정규식 3개로 인용 그래프를 만들고, RRF 가산으로 검색에 섞고, 평가로 역할을 재정의한 과정을 정리합니다.

GraphRAG라는 말의 스펙트럼

GraphRAG는 하나의 기법이 아니라 스펙트럼입니다. 한쪽 끝에는 Microsoft GraphRAG가 있습니다. LLM으로 코퍼스 전체에서 엔티티·관계를 추출하고, 커뮤니티를 나눠 요약까지 만들어 두는 방식입니다. “이 데이터셋의 주요 테마는 무엇인가” 같은 전역 질의와 멀티홉 추론에서 벡터 검색을 이긴다고 보고되지만(원 논문), 인덱싱 단계에서 LLM을 코퍼스 전체에 돌리므로 비용이 큽니다. 이 비용 문제 때문에 LLM 호출을 질의 시점으로 미루는 LazyGraphRAG, 그래프와 임베딩을 결합하고 증분 갱신을 지원하는 LightRAG 같은 경량화 흐름이 나왔습니다.

다른 쪽 끝에는 도메인 구조를 그대로 그래프로 옮기는 방식이 있습니다. 해양 법령 RAG를 만들면서 택한 것이 이쪽입니다. 결론부터 말하면, 법령 도메인에서는 LLM 추출이 필요 없었습니다.

법령의 관계는 이미 텍스트에 형식화되어 있다

일반 문서에서 관계 추출이 어려운 이유는 관계가 암묵적이기 때문입니다. “A사가 B사를 인수했다”는 문장에서 (A)-[인수]->(B)를 뽑으려면 언어 이해가 필요합니다. 그런데 법령은 다릅니다. 조문이 다른 조문을 참조할 때는 “「해양환경관리법」 제63조”, “제12조제1항”, “법 제5조에 따라” 같은 형식화된 표기를 씁니다. 관계가 자연어가 아니라 사실상 문법으로 적혀 있는 것입니다.

그래서 관계 추출기는 정규식 3개가 전부입니다. 실제 구현도 이 세 패턴입니다.

# parsing/crossref.py — 관계 추출기의 전부
_EXTERNAL = re.compile(...)  # 「법령명」 제N조[의M][제K항] — 다른 법령의 조문
_INTERNAL = re.compile(r"(?P<num>\d+)(?P<sub>\d+)?(?:(?P<clause>\d+))?")
_PARENT   = re.compile(r"(?<![가-힣])\s*(?P<num>\d+)(?P<sub>\d+)?")  # 시행령·규칙 → 모법

관계의 종류도 텍스트가 알려줍니다. 참조 표기 직후 30자 안에 “준용”이 있으면 준용 관계(APPLIES), 아니면 인용(CITES)으로 분류하고, 위임 패턴은 IMPLEMENTS로 만들었습니다. 해양 법령 105개, 조문 7,506건에 이 규칙을 돌리면 CITES 11,025개, APPLIES 394개, IMPLEMENTS 4,862개, 합계 16,281개 엣지가 나옵니다. LLM 비용은 0원이고, 같은 입력에는 항상 같은 그래프가 나오므로 재현과 디버깅이 쉽습니다.

법령 인용 그래프 구축 파이프라인 — 조문 7,506개를 정규식 3종으로 스캔해 엣지 3종을 만들고 Neo4j에 적재한 뒤, 검색 시점에 1홉 확장을 RRF 세 번째 랭킹으로 가산하는 구조

코퍼스 밖 법령을 가리키는 참조 1,902건은 버리지 않고 미해결(unresolved)로 집계해 두었습니다. 그래프의 경계가 어디인지 아는 것도 그래프의 일부라고 봤기 때문입니다.

그래프를 검색에 섞는 방식: 대체가 아니라 가산

그래프 검색이 벡터 검색을 대체하는 구조는 피했습니다. 대신 벡터·BM25 상위 후보를 시드로 삼아 Neo4j에서 인용 관계를 1홉 확장하고, 확장 결과를 (홉수 오름차순, 시드 점수 내림차순)으로 정렬해 세 번째 랭킹으로 RRF에 가산했습니다. RRF(Reciprocal Rank Fusion)는 각 랭킹에서의 순위 r에 1/(k+r) 점수를 주고 합산하는 단순한 병합 방법인데(구현은 retrieval/fusion.py, k=60), 점수 스케일이 다른 랭킹들을 정규화 없이 섞을 수 있어 이런 가산 구조에 잘 맞습니다.

hybrid = RRF(vector 랭킹, BM25 랭킹)
graph  = RRF(vector 랭킹, BM25 랭킹, 그래프 확장 랭킹)

가산 구조를 택한 이유는 실패 모드 때문입니다. 그래프 확장을 곱셈형 가중치나 필터로 쓰면 그래프가 틀렸을 때 검색 전체가 무너집니다. RRF의 세 번째 랭킹으로 얹으면 텍스트 신호가 약한데 참조 관계로 연결된 조문이 순위 경계를 넘어올 수 있으면서도, 그래프가 조용할 때는 하이브리드 검색과 같게 동작합니다.

예외가 하나 있습니다. 질문이 조문을 직접 지목하면(“제63조 위반 시 처벌은?”) 정규식으로 파싱해 그 조문을 점수 최상단에 고정합니다. 이 경우만큼은 그래프(정확 조회)가 텍스트 검색보다 확실히 낫다는 것을 알기 때문입니다.

평가가 역할을 다시 정했다: 정밀도 엔진이 아니라 회수 레버

일반적으로는 멀티홉 질의에서 그래프 강화 방식이 벡터 검색을 크게 이긴다고 보고됩니다(법률 도메인 정리 등). 그래서 저도 멀티홉 117문항을 포함한 골드셋 180문항에서 그래프가 이길 것으로 예상했습니다.

실측은 반대였습니다. hit@1은 벡터 0.539, 그래프 0.279로 벡터가 크게 앞섰고, 멀티홉만 떼어 봐도 벡터가 유의하게 높았습니다(McNemar p=0.0005). 그래프가 이긴 지표는 recall@10(0.945 vs 벡터 0.896)뿐이었습니다. 그래프 확장이 정답을 후보 10위 안에 넣는 데는 가장 강했지만, 1위에 올리는 데는 가장 약했던 것입니다.

왜 외부 보고와 달랐는지 되짚어 보면 세 가지가 겹칩니다. 첫째, 한국어 법률 임베딩(KURE-v1)이 이 도메인에서 이미 강했습니다. 둘째, 조문 단위 청킹으로 검색 단위와 정답 단위가 일치해 벡터 검색의 약점(관련 텍스트 부분집합 누락)이 줄었습니다. 셋째, 골드셋 질문이 법령 어휘를 그대로 쓰는 편이라 어휘 갭이 작았습니다. 외부 벤치마크의 승리 조건(이질적 코퍼스, 전역 질의)과 우리 조건이 달랐던 셈입니다.

이 결과로 그래프의 역할을 재정의했습니다. 1순위는 cross-encoder 리랭커에 맡기고(리랭커를 켜면 세 전략 모두 hit@1 약 0.73으로 수렴합니다), 그래프는 후보를 넓히는 회수 레버 + 정확 인용 고정 + 근거 화면의 참조 경로 표시로 씁니다. 그래프를 버린 것이 아니라, 측정이 알려준 자리에 놓은 것입니다. 평가 자체의 전말은 그래프가 이길 줄 알았다에 따로 적었습니다.

개정 대응: 그래프도 코퍼스처럼 늙는다

법령은 개정됩니다. 전체 재구축은 초기 1회로 충분하도록, 운영은 증분으로 설계했습니다. 국가법령정보센터 API의 공포번호를 폴링해 바뀐 법령만 다시 수집하고, 해당 법령의 조문 노드만 지운 뒤 업서트합니다. 엣지 해소는 전체 코퍼스를 기준으로 다시 돌려 교차 참조가 끊기지 않게 했습니다. 조문 ID를 법령ID::조문번호로 결정적으로 만들어 둔 것이 이 멱등 업서트의 전제였습니다.

판단 기준 정리

  • 관계가 텍스트에 형식화된 도메인(법령, 특허 인용, 논문 참조, 코드 임포트)이라면 LLM 추출보다 규칙 기반이 쌉니다. 싸고, 결정적이고, 감사 가능합니다.
  • 관계가 암묵적인 도메인이라면 그때가 LLM 추출(또는 LazyGraphRAG류 지연 추출)의 자리입니다.
  • 그래프는 벡터 검색의 대체재가 아니라 가산 신호로 시작하는 편이 안전합니다. RRF의 랭킹 하나로 얹으면 실패해도 시스템이 무너지지 않습니다.
  • 그리고 어느 쪽이든, 도입 근거는 외부 벤치마크가 아니라 자기 골드셋의 실측이어야 합니다. 같은 “멀티홉”이라도 코퍼스와 질문 분포가 다르면 결과가 뒤집힙니다. 제 경우가 그랬습니다.

구현은 maritime-law-rag-agentparsing/crossref.py(정규식), indexing/graph.py(Neo4j 구축), retrieval/fusion.py(RRF)에 있고, 수치는 reports/embedder_ablation.mdreports/significance.md 기준입니다.

GraphRAGNeo4j지식 그래프RAG
관련 프로젝트
해양 법령 도메인 RAG 개발

해양 법령을 조문 단위로 검색하고 답변마다 근거 조문을 인용하는 RAG 시스템. BM25·벡터·조문 관계 그래프 검색을 병합해 단순 키워드 검색보다 정확한 인용을 만드는 흐름에 초점.

© 2026 Minsu Kang. All rights reserved.