GraphRAG와 Neo4j: 실제로 필요한 것은 무엇인가?
요약
GraphRAG는 검색 패턴이며, Neo4j는 그래프 데이터베이스입니다. 이 둘은 경쟁 관계가 아니며, GraphRAG는 Neo4j 위에서 구현될 수 있습니다. Neo4j는 속성 그래프 저장소, Cypher 쿼리 언어의 편리함, 성숙한 순회 성능 등에서 강점을 가집니다.
핵심 포인트
- GraphRAG는 검색 패턴이며, LLM에 컨텍스트를 제공하는 방식이다.
- Neo4j는 데이터 저장 및 그래프 쿼리를 위한 인프라(DB)다.
- Neo4j는 속성 그래프와 Cypher 언어에서 강력한 성능을 보인다.
- 벡터 검색이나 LLM 통합 같은 기능은 전용 도구/라이브러리 호출이 필요하다.

제목에서 언급된 비교는 지난 6개월 동안 아마 스무 번쯤 요청받은 내용이며, 매번 프레임 설정이 잘못되었습니다. GraphRAG와 Neo4j는 경쟁 관계가 아닙니다. GraphRAG는 _검색 패턴(retrieval pattern)_입니다. 즉, 벡터 유사성 검색과 그래프 순회(graph traversal)를 결합하여 LLM에 더 나은 컨텍스트를 제공하는 방식입니다. 반면, Neo4j는 _그래프 데이터베이스(graph database)_입니다. 데이터를 저장하고 그래프 쿼리를 수행하는 인프라입니다. GraphRAG는 Neo4j 위에서 구현할 수 있습니다. 또한 SynapCores나 Postgres+Apache AGE, TigerGraph 또는 사용자 정의 엔진 위에서도 구현할 수 있습니다. 올바른 질문은
Neo4j는 지배적인 네이티브 그래프 데이터베이스입니다. 가장 먼저 상업적으로 성공한 사례였으며, Cypher(대부분의 다른 엔진이 사용하는 그래프 쿼리 언어)를 발명하거나 대중화시켰고, 15년 이상의 프로덕션 배포 경험을 가지고 있습니다. 데이터 모델은 속성 그래프(property graphs)이며, 이는 속성을 가진 타입 지정 노드와 속성을 가진 타입 지정 간선으로 구성됩니다. 그리고 이 쿼리 언어는 지금까지 출시된 어떤 데이터베이스보다도 사용하기 편리합니다.
Neo4j가 탁월하게 수행하는 작업:
- 네이티브 속성 그래프 저장소. 레이블, 속성, 관계에 대한 인덱싱을 지원합니다. 행(row)에서 역으로 설계된 것이 아니라 그래프를 위해 설계되었습니다.
- Cypher. 쿼리 언어 자체가 정말 좋습니다.
MATCH (a)-[r:KNOWS]->(b) WHERE a.name = 'Alice' RETURN b는 적절한 추상화 수준입니다. - 성숙한 순회 성능(traversal performance). 수억 개의 노드를 가진 그래프에서도 밀리초 지연 시간으로 다중 홉 탐색이 가능합니다.
- 프로덕션 도구. 클러스터링, 백업, 멀티 테넌시(multi-tenancy), 모니터링 등. 지루한 문제들은 이미 해결되어 있습니다.
- 생태계. 그래프 데이터 과학 라이브러리, 시각화 도구(Bloom, Neo4j Browser) 등이 있으며 모든 것과의 통합을 지원합니다.
Neo4j가 네이티브하게 수행하지 못하는 작업:
- 벡터 검색(Vector search). Neo4j는 5.11 버전(약 2023년)에서 벡터 인덱스를 추가했습니다. 작동은 합니다. 하지만 대규모 환경에서의 높은 재현율(high-recall) 워크로드를 위해서는 전용 벡터 데이터베이스와 동등하지 않습니다. 만약 벡터가 주된 접근 패턴이라면, Neo4j의 벡터 인덱스는 엔진의 보조적인 기능에 머무릅니다.
- LLM 통합. Cypher 내부에는
GENERATE()함수가 없습니다. Python/LangChain을 호출해야 합니다. - 대규모 관계형 조인(Relational joins at scale). Neo4j는 그래프 순회에는 뛰어나지만,
GraphRAG는 소프트웨어 조각이 아니라 검색 패턴입니다. 이 패턴은 다음과 같습니다:
- 사용자 질문을 임베딩합니다.
- 벡터 유사도를 통해 상위 k개의 청크(또는 노드)를 찾습니다.
- 해당 시드(seed)들로부터 타입별 엣지를 따라 N번 이동하며 그래프를 탐색합니다.
- 결과로 나온 서브그래프(청크 + 노드 + 엣지)를 LLM 컨텍스트에 공급합니다.
이에 대한 상세 내용은 What Is GraphRAG?에서, 그리고 클러스터 비교는 GraphRAG vs Traditional RAG에서 읽을 수 있습니다. 이 게시물에서 중요한 점은 다음과 같습니다: GraphRAG는 벡터 인덱스(vector index)와 그래프 엔진(graph engine) 둘 다를 필요로 합니다. 두 가지 기능이 필요한 것입니다. 어떻게 이를 제공할지는 아키텍처 결정 문제입니다.
Neo4j에서 GraphRAG 구현하기 (멀티 스토어 방식)
Neo4j에서 GraphRAG의 가장 일반적인 아키텍처는 듀얼-스토어(dual-store) 패턴입니다. 즉, 그래프를 위해 Neo4j를 사용하고, 임베딩을 위해 별도의 벡터 데이터베이스(Pinecone, Chroma, Weaviate, pgvector)를 사용하는 방식입니다.
흐름은 다음과 같습니다:
사용자 질문
-> OpenAI/sentence-transformers를 통해 임베딩
-> Pinecone에서 상위 k개 벡터 검색
...
코드 측면(Python + LangChain 유사 의사 코드):
# 1단계: 벡터 검색
seeds = pinecone.query(vector=embed(question), top_k=5)
seed_ids = [s['id'] for s in seeds]
...
이 방식은 작동합니다. 이는 표준 패턴이며, 소규모 규모에서는 아무 문제가 없습니다. Neo4j의 벡터 인덱스도 하나의 옵션입니다. 모든 것을 한 엔진에 유지하고, 일부 벡터 검색 성능을 포기하며, 운영을 단순화할 수 있습니다. 둘 다 유효합니다.
비용은 확장 단계에서 나타납니다. 구체적으로는 다음과 같습니다:
1. 두 개의 스토어, 하나의 진실 공급원 (어느 정도)
Neo4j의 모든 노드는 Pinecone에 대응하는 벡터를 가집니다. 노드의 내용이 변경될 때마다 두 스토어 모두 업데이트되어야 합니다. 쓰기 경로는 다음과 같이 됩니다:
def update_chunk(chunk_id, new_content):
new_emb = embed(new_content)
pinecone.upsert([(chunk_id, new_emb)])
...
두 번의 쓰기 작업이 있지만, 이들 간에 트랜잭션은 없습니다. Pinecone 쓰기가 성공하고 Neo4j 쓰기가 실패하거나(또는 그 반대) 하는 경우, 데이터 불일치(drift)가 발생합니다. 제가 규모로 운영하는 팀들을 볼 때마다, 모두 어떤 종류의 조정 작업(reconciliation job)을 구축해 왔습니다. 보통은 야간 크론(cron)으로 실행되어 불일치를 스캔합니다. 이 조정 작업은 작동합니다. 그것은 세금과 같습니다.
2. 두 개의 운영 환경 구성 요소 (operational footprints)
Neo4j는 자체적인 클러스터 토폴로지, 백업 방식, 모니터링 시스템, 버전 주기(version cadence), IAM 모델을 가지고 있습니다. Pinecone(또는 선택한 벡터 DB)은 또 다른 것을 가집니다. 이제 온콜 로테이션(on-call rotation)이 두 개의 클러스터를 커버해야 합니다. 재해 복구 계획(DR plan)도 두 개의 클러스터를 다룹니다. 버전 업데이트 또한 조정되어야 합니다.
3. 검색 왕복 주기 (retrieval round-trip)
위의 흐름은 쿼리당 두 번의 네트워크 왕복 주기를 수행합니다: 앱 → Pinecone → 앱 → Neo4j → 앱. 각각 10ms라고 가정하면, LLM을 호출하기 전에 순수한 오버헤드가 20ms가 발생합니다. 이는 배치 처리(batching)와 연결 풀링(connection pooling)으로 해결할 수 있지만, 두 인덱스가 프로세스를 공유할 때 사라지는 실제 비용입니다.
4. 스키마 불일치 (Schema divergence)
이것이 미묘한 부분입니다. Pinecone은 Neo4j가 가진 '속성(property)'과는 다른 개념의 '필터(filter)'를 가지고 있습니다. 하이브리드 쿼리, 즉
이쪽의 비용은 다음과 같습니다: 통합 엔진(unified engine)은 Neo4j보다 역사가 짧고, 생태계가 작으며, (이미 Neo4j 운영에 투자했다면) 전환 비용(switching cost)이 발생합니다. 저희는 Why Traditional Databases Fail Modern AI Workloads에서 이 점을 솔직하게 이야기했습니다. 통합 엔진 주장은 구조적인 것이지, 'Neo4j가 나쁘다'는 이야기가 아닙니다.
의사 결정 매트릭스(A decision matrix)

솔직히 말해서, 제가 팀들에게 실제로 조언하는 방식은 이렇습니다:
| 신호(Signal) | Neo4j + 벡터 DB 선택 | 통합 엔진 선택 |
|---|---|---|
| 이미 Neo4j에 깊이 의존하고 있는 경우 | 강력하게 예(Strong yes) | 전환 비용이 현실적이다 (Switching cost is real) |
| ... |
요약하자면: 그래프가 워크로드인 경우 Neo4j가 정답입니다. AI 워크로드(벡터 + 그래프 + LLM)가 워크로드이고 다섯 개의 서비스를 조합하고 싶지 않은 경우 통합 엔진이 정답입니다.
Neo4j가 진정으로 우위를 점하는 분야 (Where Neo4j genuinely wins, in detail)
Neo4j에게 마땅한 평가를 해주고 싶습니다. 비교에 통합 엔진을 추가하는 것이 어리석은 곳도 있고, Neo4j가 가장 깔끔한 선택인 워크로드도 있습니다.
- 순수 그래프 워크로드(Pure graph workloads). 생명 과학의 지식 그래프(Knowledge graphs), 소셜 네트워크 분석, 공급망. 벡터 차원은 부차적이며, 그래프 자체가 핵심입니다.
- 그래프 데이터 과학(Graph data science). GDS 라이브러리 — 커뮤니티 탐지(community detection), 중심성 알고리즘(centrality algorithms), 링크 예측(link prediction), 그래프 노드 임베딩(embeddings) (Node2Vec, GraphSAGE). 성숙하고 빠르며 지원이 잘 됩니다.
- 팀의 Cypher 숙련도. 만약 팀에 Cypher 전문가가 있다면, Neo4j를 활용하는 것이 그 전문성을 상각(amortizes)할 수 있습니다.
- 생태계(The ecosystem). 시각화를 위한 Bloom, 모든 BI 도구와의 통합, 15년간 축적된 패턴과 컨퍼런스 발표 자료.
만약 해당 항목들이 귀하의 프로젝트를 설명한다면, 이중 스토어 동기화 비용은 지불할 가치가 있는 가격입니다. 벡터 차원은 부차적인 관심사이며, 주요한 것은 아닙니다.
통합 엔진이 진정으로 우위를 점하는 경우
반대 상황입니다. 제가 통합 엔진을 기본값으로 선택할 경우:
- 에이전트 메모리/GraphRAG가 주요 제품 기능인 경우. 두 계층(벡터 및 그래프) 모두 1급(first-class)입니다. 동기화는 마찰(friction)입니다.
- 쿼리 내에서 LLM 호출을 원하는 경우. SQL의
GENERATE()는 세 번의 왕복(round-trips)을 한 번으로 통합합니다. - 데이터베이스 내 머신러닝 학습을 원하는 경우.
CREATE MODEL+PREDICT()가 1급입니다. What Is In-Database Machine Learning?를 참조하세요. - 그래프 DB 운영 예산이 없는 경우. 두 가지 엔진을 실행하는 것보다 하나의 엔진을 실행하는 것이, 특히 소규모 팀 규모에서는 의미 있게 저렴합니다.
- 관계형 쿼리에서 지연 시간(Latency) 예산이 빠듯한 경우. 한 번의 왕복 대 두 번의 왕복은 중요합니다.
실제 마이그레이션 시나리오
이미 Neo4j를 사용하고 있으며 통합 엔진으로 이동할지 평가하는 상황이라고 가정해 보겠습니다. 솔직한 평가는 다음과 같습니다:
- 그래프가 1억 개 노드 미만이고 벡터 볼륨이 적은 경우: 통합 엔진이 보통 분기(quarter) 내에 비용을 회수합니다. 삭제할 수 있는 동기화 코드가 마이그레이션 비용보다 더 큽니다.
- 그래프가 크고 그래프 네이티브인 경우 (깊은 순회, 복잡한 알고리즘, GDS 의존성): Neo4j에 머무르세요. 벡터 DB를 추가하세요. 통합 엔진은 마이그레이션할 가치가 없습니다.
- 새로운 프로젝트이며 요구 사항에 두 계층이 모두 포함되는 경우: 통합으로 시작하세요. 그래프 워크로드가 통합 엔진의 범위를 초과할 때 Neo4j로 채택하세요.
한 문장으로 요약하면 다음과 같습니다: 동기화 세금(sync tax)이 마이그레이션 비용을 초과할 때 마이그레이션하세요. 이념 때문에 마이그레이션하지 마세요.
GraphRAG 패턴이 두 시스템 간에 어떻게 번역되는가
구체적으로 말씀드리자면, GraphRAG 패턴 자체는 이식성이 있습니다. 어느 쪽에서든 구현할 수 있습니다. 아키텍처 선택은 GraphRAG가 가능한지 여부가 아니라 _구현의 운영적 형태_에 관한 것입니다.
Neo4j (듀얼 스토어)의 경우:
seeds = vector_db.search(embed(q), k=5)
subgraph = neo4j.run("MATCH (n) WHERE n.id IN $ids MATCH (n)-[*1..2]-(m) RETURN ...", ids=[s.id for s in seeds])
answer = llm.complete(format(subgraph))
통합 엔진의 경우:
WITH seeds AS (
SELECT id FROM chunks
WHERE COSINE_SIMILARITY(embedding, EMBED(:q)) > 0.6
...
패턴은 동일합니다. 운영 방식만 다를 뿐입니다.
가이드된 버전을 원하시나요?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기