<p align="center">
<h1 align="center">OverGraph</h1>
<p align="center">
내장 벡터 검색 기능이 있는 터무니없이 빠른 임베디드(embedded) 그래프 데이터베이스입니다.<br>
순수 Rust (Pure Rust). 서브 마이크로초(Sub-microsecond) 읽기 속도. Node.js 및 Python용 네이티브 커넥터 제공.<br>
AI 에이전트 메모리, 지식 그래프(knowledge graphs), RAG 파이프라인, 그리고 의미론적 검색을 위해 구축되었습니다.
</p>
</p>
<p align="center">
<a href="overgraph.io">overgraph.io</a>
</p>
<p align="center">
<a href="LICENSE-MIT"><img src="https://img.shields.io/badge/license-MIT%2FApache--2.0-blue" alt="License"></a>
<a href="https://github.com/Bhensley5/overgraph/actions"><img src="https://img.shields.io/github/actions/workflow/status/Bhensley5/overgraph/ci.yml?branch=main&label=CI" alt="CI"></a>
</p>
OverGraph는 사용자의 프로세스 내부에서 실행되는 그래프 데이터베이스입니다. 서버가 필요 없고, 네트워크 호출이 없으며, Docker 컨테이너도 필요 없습니다. 디렉터리를 열기만 하면 시간적 엣지(temporal edges), 가중치 관계(weighted relationships), 서브 마이크로초 조회 속도, 그리고 내장 벡터 검색 기능을 갖춘 완전한 그래프 데이터베이스를 얻게 됩니다.
이것은 운영해야 하는 서비스가 아니라 라이브러리처럼 느껴지도록 구축되었습니다. 코드를 작성할 때 함수 호출(function calls)을 통해 구동하거나, 익숙한 쿼리 언어를 원한다면 GQL을 통해 구동할 수 있습니다. 두 방식 모두 일급 시민(first-class)이며 동일한 엔진에서 실행되므로, 구현체가 아닌 문법만 선택하면 됩니다. 그리고 정말로 빠릅니다. '데이터베이스치고는 빠른' 수준이 아니라, 존재 자체를 잊게 만들 만큼 빠릅니다. 노드 조회는 수십 나노초에 도달하며 배치 쓰기는 초당 백만 개 이상의 노드를 처리할 수 있어, 엔진이 나머지 스택의 방해 요소가 되지 않습니다.
그래프 구조와 벡터 유사성은 같은 엔진 내에서 존재할 수 있으므로, 별도의 데이터베이스를 붙일 필요 없이 "X로부터 2홉(hops) 이내에서 유사한 노드를 찾아줘"와 같은 요청을 할 수 있습니다. 핵심은 순수 Rust로 작성되었으며, Node.js 및 Python용 네이티브 커넥터를 갖추고 있어 사용자가 개발하는 어떤 환경에서도 호출할 수 있습니다.
구축 목적
- AI 에이전트 메모리(AI agent memory). 대화 내용, 도구 출력물, 개체 관계를 저장합니다. 노드에 임베딩을 첨부하고 의미적 유사성으로 검색할 수 있습니다. 점수 감쇠(decay scoring)를 통해 오래된 컨텍스트는 자동으로 제거됩니다.
- 지식 그래프(Knowledge graphs). 최단 경로 쿼리, 차수 분석(degree analysis), 구조 탐색 기능을 갖춘 도메인 온톨로지입니다.
- 시맨틱 검색(Semantic search). 밀집 HNSW 벡터 검색, 희소 키워드 벡터(SPLADE, BGE-M3), 그리고 하이브리드 융합을 지원합니다. 모든 기능이 그래프 엔진 내부에 위치하며 외부 벡터 데이터베이스가 필요 없습니다.
- RAG 파이프라인(RAG pipelines). 그래프 이웃(graph neighborhoods)으로 범위가 제한된 벡터 검색을 통해 그래프를 증강하는 검색 기능을 제공합니다. 임베딩 유사성과 그래프 구조를 단일 쿼리에서 결합할 수 있습니다.
- 추천 엔진(Recommendation engines). 그래프 순회(graph traversal)를 통한 협업 필터링(collaborative filtering)이 가능합니다. 시드 아이템으로부터의 PPR, 가중치별 상위 K개 검색을 지원합니다.
- 사회 및 네트워크 분석(Social and network analysis). 차수 중심성(degree centrality), 최단 경로, 연결성 확인 등 네트워크 과학의 구성 요소를 제공합니다.
- 사기 탐지(Fraud detection). 연결 패턴과 그래프 알고리즘을 통해 의심스러운 구조를 식별할 수 있습니다.
차별점
- 진정한 임베디드(embedded) 방식. 별도의 프로세스나 소켓이 필요 없습니다. 데이터베이스가 디스크의 폴더 형태입니다.
cp -r 명령어로 복사하고, 이동시키고, 백업할 수 있습니다.
- 단일 엔진에서 그래프와 벡터를 함께 지원합니다. 밀집된 HNSW(Hierarchical Navigable Small World) 및 희소 역색인(sparse inverted indexes)이 동일한 스토리지 엔진 내에서 그래프 인접성 인덱스와 공존합니다. 두 번째 데이터베이스나 동기화 계층 없이도 그래프 이웃 영역("X로부터 2홉 이내의 유사 노드 찾기")으로 벡터 검색 범위를 제한할 수 있습니다.
- 풍부한 그래프 기본 요소(primitives). 가중치 노드 및 엣지, 시간적 유효 기간 창(temporal validity windows), 지수 감쇠 점수(exponential decay scoring), 자동 보존 정책을 지원합니다. 시간이 지남에 따라 진화하는 관계를 모델링하고, 그래프가 더 이상 관련 없는 것을 정리하도록 맡길 수 있습니다.
- 동시 읽기 및 쓰기(Concurrent reads and writes). 쓰기가 커밋되는 동안 리더는 일관된 커밋 스냅샷을 캡처합니다. 순서화된 ID 인덱스는 노드 및 엣지 조회 효율성을 높이며, 이전 스냅샷은 업데이트와 유지보수 과정에서도 유효하게 유지됩니다. 쓰기는 구성된 진입(admission), 리소스, 내구성 제한을 유지합니다.
- 명시적 쓰기 트랜잭션(Explicit write transactions). 순서화된 노드 및 엣지 변경 사항을 로컬에 스테이징하고, 자신의 스테이징된 쓰기를 읽은 다음, 낙관적 충돌 감지(optimistic conflict detection)를 통해 원자적으로 커밋합니다. Rust, Node.js, Python에서 사용할 수 있습니다.
- 세 가지 언어, 하나의 엔진. Rust 코어를 기반으로 하며 Node.js(napi-rs)와 Python(PyO3)을 위한 네이티브 바인딩을 제공합니다. REST API를 감싼 래퍼가 아닙니다. 최소한의 오버헤드로 동일한 Rust 엔진에 대한 실제 FFI(Foreign Function Interface)를 사용합니다.
- 함수로서의 전체 쿼리(Full queries as functions). 모든 작업에 일반 API를 사용합니다: 직접적인 속성 조회를 위한
find_nodes, 완전한 불리언 노드 쿼리를 위한 query_node_ids / query_nodes, 그리고 행 형태의 그래프 패턴, 선택적 일치(optional matches), 경계가 지정된 경로(bounded paths)를 위한 query_graph_rows를 사용합니다.
- GQL. 요청 객체를 구성하는 것보다 더 쉬울 때 그래프 읽기, 쓰기, 그래프 스키마 DDL(Data Definition Language), 및 속성 인덱스 DDL을 GQL/Cypher 스타일의 문자열로 작성할 수 있습니다.
MATCH, WITH, DISTINCT, 집계(aggregation), UNION, 읽기 전용 서브쿼리(read-only subqueries), 제약 조건이 있는 최단 경로(constrained shortest paths), CREATE, MERGE, SET, REMOVE, DELETE r, DETACH DELETE n, 뮤테이션 반환값(mutation returns), ALTER / CHECK / SHOW CURRENT GRAPH TYPE, 그리고 CREATE / DROP / SHOW PROPERTY INDEXES를 사용할 수 있습니다.
이 과거 런칭 측정값은 v0.18 동시성 엔진보다 앞선 것이며, v0.18의 성능 결과가 아닌 참고 자료로 유지됩니다. 이 값들은 Rust 코어(group-commit 내구성 모드, 소규모 프로파일: 10K 노드 / 50K 엣지)에서 측정되었습니다. 사용자의 워크로드 및 내구성 설정에 맞춰 벤치마크 스위트를 재실행하십시오. 전체 방법론 및 재현성 가이드는 docs/04-quality/Benchmark-Methodology.md에서 확인할 수 있습니다.
| 작업 (Operation) | 지연 시간 (Latency) | 처리량 (Throughput) |
|---|
get_node | 34 ns | 29M ops/s |
| ... | | |
| Node.js 및 Python 커넥터는 최소한의 오버헤드만 추가합니다. 배치(Batch) 작업은 FFI 경계 비용을 상쇄하기 때문에 특히 효율적입니다. 전체 크로스 언어 비교는 런칭 벤치마크 패키지에서 확인할 수 있습니다. | | |
설치 (Install)
사전 빌드된 바이너리는 macOS(ARM + Intel), Linux(x64), Windows(x64)용으로 제공됩니다. Rust 툴체인은 필요하지 않습니다.
Python
Node.js
Rust
빠른 시작 (Quick start)
이 코드 스니펫들은 의도적으로 동일한 엔진의 다른 부분을 보여줍니다. 각 워크플로우는 Rust, Node.js, Python 모두에서 사용할 수 있으며, 각 블록은 해당 워크플로우가 가장 깔끔하게 읽히는 언어를 사용합니다.
Python
from overgraph import OverGraph
with OverGraph.open("./my-graph", dense_vector_dimension=384) as db:
...
벡터 검색은 Rust, Node.js, Python 모두에서 사용할 수 있으며, 이 스니펫은 Python 인터페이스를 보여줍니다. 벡터 변수는 사용자의 임베딩 모델에서 가져온 자리 표시자(placeholder)입니다.
Node.js
import { OverGraph } from 'overgraph';
const db = OverGraph.open('./my-graph');
...
이웃 확장(Neighbor expansion), 경계 탐색(bounded traversal), 최단 경로(shortest paths) 기능은 Rust, Node.js, Python 모두에서 사용할 수 있으며, 여기서는 Node.js 인터페이스를 보여줍니다.
Rust
use overgraph::*;
use std::path::Path;
...
개인화된 PageRank(Personalized PageRank)는 Rust, Node.js, Python 모두에서 사용할 수 있으며, 여기서는 Rust 인터페이스를 보여줍니다.
GQL
OverGraph는 GQL을 포함합니다. GQL은 그래프 읽기(reads), 쓰기(writes), 그래프 스키마 DDL, 및 속성 인덱스 DDL을 위한 GQL/Cypher 스타일의 쿼리 언어입니다. 그래프 작업이 텍스트로 읽는 것이 더 쉬울 때 사용하십시오: 레코드 생성, 패턴 일치, WITH를 사용하여 행 모양 지정, 집계(aggregate), UNION으로 브랜치 결합, 읽기 전용 서브쿼리 실행, 제약 조건이 있는 최단 경로 사용, 변경 결과 반환, ALTER, CHECK, DROP, SHOW로 현재 그래프 유형 관리, 또는 CREATE, DROP, SHOW PROPERTY INDEXES로 속성 인덱스 선언 관리.
db.execute_gql(
"""
CREATE (p:Person {elementKey: 'gql-ada', name: 'Ada', status: 'active'})
...
GQL은 Rust, Node.js, Python 모두에서 사용할 수 있습니다. 이는 파라미터(params), 읽기 커서(read cursors), 압축된 행(compact rows), 반환되는 노드 값에 대한 벡터 옵트인(vector opt-in), explain/profile 기능, 읽기 전용 실행, 변경 통계(mutation stats), 스키마 통계(schema stats), 인덱스 통계(index stats), 비동기 커넥터 호출(async connector calls)을 지원하며 언어 전반에 걸쳐 일관된 결과 형태를 제공합니다. 구문, 결과 형태, 옵션 및 예제는 전체 GQL API reference를 참조하십시오.
Async support
Python과 Node.js 커넥터 모두 모든 API의 완전한 비동기(async) 변형을 포함합니다. Python은 asyncio.to_thread()를 통해 동기(sync) 작업을 스레드 풀에서 실행하는 asyncio 래퍼인 AsyncOverGraph를 제공합니다. Node.js 메서드는 접미사로 Async가 붙은 변형(예: upsertNodeAsync, vectorSearchAsync)을 가집니다.
Features
벡터 검색 (Vector search)
- 밀집 벡터 검색 (Dense vector search). 모든 노드에 f32 임베딩 벡터를 첨부할 수 있습니다. HNSW 인덱스는 빠른 근사 최근접 이웃(approximate nearest neighbor) 검색을 위해 플러시 시점마다 세그먼트별로 구축됩니다. 코사인(cosine), 유클리디안(Euclidean), 내적(dot-product) 거리 측정 기준을 지원합니다. DB당 하나의 밀집 벡터 공간이 있으며 차원(dimension)은 설정 가능합니다.
- 희소 벡터 검색 (Sparse vector search). 키워드 가중치 검색을 위해 희소 벡터(sparse vectors, 차원-값 쌍)를 첨부할 수 있습니다. SPLADE나 BGE-M3와 같은 모델에서 사전 계산된 희소 임베딩과 함께 작동합니다. 정확한 내적 점수 산정을 위한 역 인덱스 포스팅 리스트(inverted posting-list indexes)를 사용합니다.
- 하이브리드 검색 (Hybrid search). 빌트인 융합 모드(built-in fusion modes)를 사용하여 밀집 및 희소 결과를 결합할 수 있습니다: 가중치 순위 융합(weighted rank fusion), 상호 역순위 융합(reciprocal rank fusion), 또는 가중치 점수 융합(weighted score fusion). 혼합 정도를 조정하기 위해
dense_weight와 sparse_weight를 조정할 수 있습니다.
- 그래프 범위 검색 (Graph-scoped search). 벡터 검색 범위를 그래프 이웃(graph neighborhood)으로 제한합니다: "노드 X로부터 3홉(hops) 이내의 가장 유사한 노드 10개를 찾기." 간선 레이블 및 시간 지원을 갖춘 순회 기반 도달 가능 노드 필터링(traversal-based reachable-node filtering)을 사용합니다. 그래프 구조와 벡터 유사성을 단일 쿼리에서 결합할 수 있습니다.
- 미사용 시 오버헤드 없음 (Zero overhead when unused). 벡터가 없는 노드는 저장 공간이나 실행 시간 비용이 발생하지 않습니다. 벡터 인덱스 파일은 벡터를 포함하는 세그먼트에 대해서만 생성됩니다.
핵심 그래프 연산 (Core graph operations)
- Upsert 의미론(semantics). 노드는 하나 이상의 레이블과 하나의 키를 가집니다. 각 활성
(레이블, 키) 멤버십은 고유하며, 따라서 다중 레이블 노드는 자신이 지닌 모든 레이블에서 동일한 키를 소유합니다. 공급된 레이블을 통해 동일한 노드로 해결되는 키를 Upsert하면 해당 노드가 업데이트됩니다. 만약 공급된 레이블 멤버십이 서로 다른 노드를 해결한다면, 충돌(conflict)로 인해 쓰기 작업은 거부됩니다. 엣지는 선택적으로 (from, to, label)에 대한 고유성을 강제할 수 있습니다.
- 배치 연산 (Batch operations).
batch_upsert_nodes와 batch_upsert_edges는 WAL 및 memtable 오버헤드를 상각(amortize)합니다. get_nodes와 get_nodes_by_keys는 개별 항목 조회 대신 정렬된 병합-워크(sorted merge-walks)를 사용하여 배치 읽기를 수행합니다. 또한 최대 쓰기 처리량(write throughput)을 위한 패킹된 바이너리 형식도 존재합니다.
- 원자적 그래프 패치 (Atomic graph patch).
graph_patch는 단일 원자적 연산으로 노드 Upsert, 엣지 Upsert, 노드 삭제, 엣지 삭제, 그리고 엣지 무효화(invalidate)를 수행할 수 있게 합니다.
- 명시적 트랜잭션 (Explicit transactions).
begin_write_txn() / beginWriteTxn()은 순서가 지정된 스테이징(staging), 롤백(rollback), 읽기 전용 쓰기 지점 조회(read-own-writes point lookups), 로컬 별칭(local aliases), 원자적 커밋(atomic commit), 그리고 재시도 루프를 위한 깔끔한 충돌 오류 처리를 제공합니다.
시간적 엣지 (Temporal edges)
- 유효성 기간 (Validity windows). 엣지는 선택적인
valid_from 및 valid_to 타임스탬프를 가집니다. at_epoch 매개변수를 사용하여 특정 시점에 질의할 수 있으며, 해당 순간에 유효했던 엣지만을 볼 수 있습니다.
- 엣지 무효화 (Edge invalidation). 엣지를 삭제하지 않고 더 이상 유효하지 않다고 표시합니다. 이 경우 기록(history)은 보존됩니다.
- 감쇠 점수화 (Decay scoring). 이웃 조회에
decay_lambda를 전달하면, 엣지 가중치가 자동으로 exp(-lambda * age_hours)로 조정됩니다. 최근 연결이 더 중요하게 취급됩니다.