2026년 4월 2일 | 프로젝트
요즘 GraphRAG를 따로 트랙으로 굴리면서 가장 먼저 막혔던 건, 멋있는 구조를 상상하는 일보다 최소한의 검색 흐름을 실제로 끝까지 연결하는 일이었다. 문서에서 엔티티를 뽑고, 관계를 만들고, 그래프 점수와 벡터 점수를 같이 써서 질의 결과를 정렬하는 흐름은 말로 쓰면 간단한데 막상 손으로 붙이기 시작하면 어디까지를 1차 목표로 잡아야 할지가 애매했다. 그래서 이번에는 욕심을 줄이고, 외부 모델 없이도 재현 가능한 아주 작은 MVP를 먼저 만들었다.
핵심은 세 가지였다. 첫째, 문서를 넣으면 청크 단위로 자를 수 있어야 한다. 둘째, 청크에서 엔티티와 관계를 뽑아 그래프 모양의 연결 정보를 만들 수 있어야 한다. 셋째, 질의가 들어왔을 때 단순 키워드 매칭이 아니라 그래프 연결 정보가 조금이라도 점수에 영향을 줘야 한다. 이 세 개가 한 번에 이어지지 않으면 나중에 임베딩 모델이나 추출기를 바꿔도 무엇이 실제로 좋아졌는지 판단하기 어렵다.
1. 이번 단계에서 실제로 만든 것
이번 커밋에서는 문서 로더, 문장 단위 청킹, 규칙 기반 엔티티/관계 추출, TF-IDF 기반 벡터 검색, 그리고 그래프 연결 점수를 합치는 hybrid retrieval까지 한 경로로 연결했다. 데이터셋도 비워 둔 상태로 시작하지 않고, 작은 샘플 문서셋을 같이 넣어서 테스트가 바로 돌아가도록 만들었다. 아직은 장난감 데이터에 가깝지만, 적어도 파이프라인이 끊기지 않는 상태를 만든 게 중요했다.
문서 입력은 JSON으로 단순화했다. 문서 ID, 제목, 본문, 소스 정도만 받게 해 두면 나중에 PDF 파서나 웹 크롤러를 붙여도 중간 포맷을 크게 안 흔들 수 있다. 청킹도 일단은 문장 몇 개씩 묶는 정도로만 잡았다. 나중에 토큰 길이 기반 청킹이나 의미 단위 세그먼트를 붙일 수는 있지만, 지금 단계에서 먼저 확인하고 싶었던 건 청킹 전략의 정교함보다 그래프와 검색기가 연결되는 최소 구조였다.
Figure 1: 이번 1차 MVP에서 실제로 연결한 GraphRAG 파이프라인. 문서 로딩, 청킹, 규칙 기반 엔티티·관계 추출, 그래프 구성, hybrid retrieval이 한 흐름으로 이어지도록 만들었다.
2. 엔티티와 관계 추출은 일단 규칙 기반으로 시작했다
처음부터 LLM을 붙이면 보기에는 그럴듯해도 디버깅이 어려워진다. 그래서 이번 버전은 대문자 패턴을 기준으로 엔티티를 뽑고, uses, stores, connects, supports 같은 몇 가지 동사를 기준으로 관계를 읽어 오게 했다. 당연히 한계가 많다. 문장 형태가 조금만 바뀌어도 쉽게 깨지고, 한국어 문서에는 바로 적용하기도 어렵다. 그래도 관계가 아예 없는 상태와 비교하면, 질의와 연결된 엔티티가 어떤 청크에 있는지 추적하는 감각을 얻기에는 충분했다.
중간에 한 번 삽질도 있었다. 처음에는 청크 전체에서 키워드 앞뒤 엔티티를 한 번에 잡는 식으로 관계를 만들었는데, 문장이 두 개 이상 섞이면 엉뚱한 엔티티끼리 연결되는 문제가 바로 나왔다. 예를 들어 앞 문장의 주어와 뒤 문장의 목적어가 같은 관계에 묶여 버렸다. 그래서 관계 추출 범위를 문장 단위로 다시 줄였다. 이 수정 하나만으로도 관계 품질이 꽤 안정됐고, 테스트도 그 지점에서 한 번 실패한 뒤 다시 통과했다. 이런 종류의 오류는 나중에 모델을 붙여도 계속 나올 수 있어서, 지금처럼 작은 데이터셋으로 빨리 깨보는 게 훨씬 낫다고 느꼈다.
3. 검색은 벡터 점수만 쓰지 않고 그래프 점수를 같이 더했다
이번 MVP의 중심은 retrieval 쪽이다. 나는 여기서 그래프를 저장하는 것 자체보다, 그래프가 실제 검색 순위에 어떤 식으로 개입할지를 먼저 잡고 싶었다. 그래서 기본 검색 점수는 TF-IDF 코사인 유사도로 두고, 질의에서 잡힌 엔티티가 청크의 엔티티와 직접 겹치거나 그래프 이웃으로 연결되면 추가 점수를 주는 식으로 단순하게 시작했다.
이 방식의 장점은 해석이 쉽다는 점이다. 왜 특정 청크가 위로 올라왔는지 설명할 수 있다. 단어가 비슷해서 올라온 건지, 아니면 질의 엔티티와 연결된 노드가 있어서 올라온 건지 분해해서 볼 수 있다. 지금은 정교한 랭킹 모델이 아니라 점수 합산 수준이지만, 바로 이 단순함 덕분에 다음 실험에서 무엇을 바꿔야 할지가 보인다. 예를 들어 임베딩 검색기로 바꾸면 vector score가 어떻게 달라지는지, 관계 추출기를 바꾸면 graph score가 얼마나 안정되는지 분리해서 볼 수 있다.
샘플 질의로 Payment API와 Database Timeout의 연결을 물어보면, 관련 청크가 제일 위로 올라오고 연결된 엔티티가 같이 잡힌다. 완성형 QA는 아니지만, retrieval 단계에서 그래프가 개입하는 첫 번째 기준선은 세운 셈이다. 나는 GraphRAG에서 이 기준선이 꽤 중요하다고 본다. 처음부터 복잡한 구조로 가면 모델이 잘한 건지, 데이터가 잘 맞아떨어진 건지, 랭킹이 운 좋게 맞은 건지 구분하기 어려워지기 때문이다.
Figure 2: Payment API와 Database Timeout 연결 질의에 대한 hybrid retrieval 결과 요약. 그래프 점수가 개입하면서 실제 연결 청크가 상단으로 올라오는 흐름을 정리했다.
4. 왜 처음부터 Neo4j나 Qdrant부터 붙이지 않았는가
이번에는 일부러 저장소 기술을 뒤로 미뤘다. GraphRAG를 만들다 보면 금방 Neo4j, 벡터 DB, 시각화 대시보드 같은 쪽으로 손이 간다. 나도 그 유혹이 꽤 컸다. 그런데 지금 단계에서 그걸 먼저 붙이면 시스템이 커지는 속도에 비해 검증 속도가 너무 느려진다. 인덱스 스키마를 정하고, 로컬 실행 환경을 맞추고, 직렬화 포맷을 손보는 동안 정작 중요한 질문인 "그래프 정보가 retrieval에 실제로 도움을 주는가"는 뒤로 밀리기 쉽다.
그래서 이번 MVP는 저장을 최소화하고 메모리 안에서 전부 돌게 만들었다. 덕분에 문서셋을 바꾸거나 규칙을 수정했을 때 바로 테스트하고 결과를 비교할 수 있었다. 나중에 저장 계층을 붙일 때도 이 구조가 기준선 역할을 해 줄 수 있다. 즉, 지금은 인프라를 아끼려는 게 아니라 비교 가능한 실험 단위를 먼저 확보하려는 선택에 가깝다.
5. 이번 커밋이 남긴 의미
이번 작업의 가장 큰 수확은 코드가 많이 늘어난 것 자체가 아니라, 앞으로 교체 가능한 지점이 분명해졌다는 데 있다. 문서 로딩 계층, 추출 계층, 검색 계층, 테스트 계층이 나뉘어 있으니 다음 단계에서는 한 부분씩 바꿔도 된다. 예를 들어 엔티티 추출만 더 나은 모델로 바꾸거나, 벡터 검색만 임베딩 기반으로 교체해도 전체 비교가 가능하다. 즉, 이제부터는 막연한 아이디어 노트가 아니라 실험 가능한 구조가 생긴 셈이다.
테스트를 붙여 둔 것도 같은 이유다. 지금은 샘플 데이터 기준의 작은 단위 테스트 두 개뿐이지만, 적어도 관계 추출이 이상하게 흔들릴 때 바로 감지할 수 있다. GraphRAG 류 프로젝트는 겉으로는 그럴듯한데 내부 연결이 틀어진 상태로 오래 가기 쉬워서, 이런 얇은 테스트라도 초반에 붙여 두는 편이 훨씬 낫다.
5. 다음에는 무엇을 붙일지
다음 단계에서는 세 가지를 순서대로 해볼 생각이다. 첫 번째는 규칙 기반 추출기를 더 나은 엔티티/관계 추출기로 바꾸는 일이다. 한국어와 영어가 섞인 문서에서도 버틸 수 있어야 하고, 대문자 패턴에 너무 의존하는 상태는 빨리 벗어나야 한다. 두 번째는 임베딩 기반 검색과 지금의 기준선을 나란히 두고 비교하는 일이다. 그래프 점수가 실제로 어떤 경우에 도움을 주는지 보려면, 벡터 검색 품질을 먼저 한 단계 끌어올릴 필요가 있다. 세 번째는 작은 평가 세트를 만들어 retrieval hit rate를 기록하는 것이다. 지금은 눈으로 결과를 보고 있지만, 이 단계를 넘어가려면 적어도 질문 몇 개에 대해 어느 청크가 맞는지 정답 셋은 있어야 한다.
개인적으로는 이번처럼 작은 단위로 먼저 붙이는 방식이 잘 맞는 것 같다. GraphRAG는 이름만 들으면 거대한 시스템처럼 보이지만, 결국 문서가 들어와서 어떤 연결이 만들어지고 그 연결이 검색에 어떤 이득을 주는지 하나씩 확인해야 한다. 이번 1차 MVP는 딱 거기까지다. 아직 거칠고, 규칙도 단순하고, 데이터도 작다. 그래도 이제는 다음 실험을 어디에 꽂아야 할지 분명해졌다. 그 점에서는 꽤 괜찮은 첫 번째 커밋이었다.
다음 업데이트에서는 이 기준선 위에 실제 임베딩 검색과 더 나은 추출기를 얹어 보려고 한다. 그때는 단순히 동작한다는 수준을 넘어서, 어떤 질문에서 그래프가 검색을 살리고 어떤 질문에서는 오히려 노이즈를 만드는지까지 숫자로 남겨볼 생각이다. 그 단계까지 가면 GraphRAG가 그냥 트렌드 키워드가 아니라, 내가 직접 만져 보며 판단할 수 있는 프로젝트가 될 것 같다.
'[AI 실험실] > [개인 프로젝트] GraphRAG' 카테고리의 다른 글
| GraphRAG | Query Cluster 집계 추가 (0) | 2026.04.16 |
|---|---|
| GraphRAG | Rank Shift Reason Labels (0) | 2026.04.15 |
| GraphRAG | Rank Shift Focus Report (0) | 2026.04.15 |
| GraphRAG | Profile Eval Trace Bundle (0) | 2026.04.13 |
| GraphRAG Relation-Weighted Scoring (0) | 2026.04.05 |