Bluetape4k Graph Part 1: 그래프 데이터베이스 선택 기준

이 글은 bluetape4k-graph 시리즈의 1편입니다. 앞서
GraphDB, 언제 도입해야 할까?에서는 관계 자체가 업무의 중심일 때 그래프
데이터베이스를 검토하자는 기준을 세웠습니다. 이번에는 그래프 데이터베이스를 도입하기로 결정한 뒤 마주치는 질문을
다룹니다. Neo4j와 Memgraph 중 무엇을 운영 후보로 삼을지, PostgreSQL 환경에서 Apache AGE를 선택할지, 테스트에는
어떤 저장소를 사용할지 판단하는 기준입니다.
bluetape4k-graph는 그래프 데이터베이스를 다시 구현하지 않습니다. Neo4j, Memgraph, Apache AGE, TinkerGraph,
FalkorDB의 저장 엔진과 쿼리 언어는 그대로 사용하고, Kotlin/JVM 서비스에서 반복되는 정점·간선 CRUD, 일괄 쓰기,
탐색, 대량 입출력, 프레임워크 통합을 공통 계약으로 묶습니다.

지원하는 그래프 데이터베이스
섹션 제목: “지원하는 그래프 데이터베이스”현재 프로젝트가 지원하는 그래프 저장소는 다음과 같습니다.
| 그래프 데이터베이스 | 쿼리 방식 | 적합한 용도 |
|---|---|---|
| Neo4j | Neo4j Java Driver 기반 Cypher | 성숙한 도구, 인덱스, 트랜잭션 지원이 필요한 운영 그래프 서비스 |
| Memgraph | Neo4j 호환 프로토콜 기반 Cypher | 낮은 지연 시간이 중요한 Cypher 워크로드 후보 |
| Apache AGE | PostgreSQL/JDBC 기반 Cypher-over-SQL | 별도 그래프 서버를 추가하지 않고 PostgreSQL 중심으로 운영하는 환경 |
| TinkerGraph | JVM 인메모리 TinkerPop/Gremlin | 단위·통합 테스트, 예제, 로컬 데모 |
| FalkorDB | Redis 모듈 기반 openCypher 부분집합 | Redis 기반 그래프 워크로드와 경량 그래프 서비스 |
이 표는 하나의 최적 제품을 고르기 위한 순위표가 아닙니다. 운영 환경과 실제 워크로드에 맞는 후보를 추리는 출발점입니다. 예를 들어 PostgreSQL을 표준 데이터베이스로 운영하는 조직은 Apache AGE로 별도 그래프 서버를 줄일 수 있습니다. Redis 기반 운영 체계와 결합해야 한다면 FalkorDB가 후보가 됩니다. Memgraph의 낮은 지연 시간이나 특정 저장소의 쓰기 성능은 프로젝트 설명만으로 확정할 수 없으므로, 실제 데이터 규모와 쿼리 패턴으로 측정해야 합니다.
TinkerGraph는 외부 서버 없이 빠르게 실행할 수 있어 테스트에 적합합니다. 다만 TinkerGraph에서 공통 계약 테스트가 통과했다는 사실만으로 Neo4j, Memgraph, Apache AGE, FalkorDB의 쿼리 계획, 인덱스, 트랜잭션 의미가 같다고 볼 수는 없습니다. 운영 후보는 해당 백엔드와 Testcontainers를 사용한 통합 테스트로 다시 검증해야 합니다.
Cypher는 무엇인가
섹션 제목: “Cypher는 무엇인가”Neo4j, Memgraph, Apache AGE, FalkorDB를 검토하면 Cypher가 등장합니다. Cypher는 그래프의 관계 패턴을 표현하는 쿼리 언어입니다. SQL이 테이블과 행을 기준으로 데이터를 조회한다면, Cypher는 정점과 간선이 만드는 관계를 패턴으로 기술합니다.
MATCH (alice:Person {email: $email})-[:KNOWS]->(friend:Person)RETURN friend.name이 쿼리는 Person 정점에서 시작해 KNOWS 간선을 따라가고, 연결된 Person의 이름을 반환합니다. 복잡한 조인과
재귀 탐색을 애플리케이션 코드에서 조립하는 대신 조회할 관계의 형태를 데이터베이스에 전달합니다.
bluetape4k-graph의 공통 API는 Cypher를 대체하지 않습니다. 서비스의 기본 CRUD, 일괄 쓰기, 탐색, 테스트는
GraphOperations로 시작할 수 있습니다. 쿼리 계획, 인덱스, 프로젝션처럼 저장소별 조정이 필요한 작업은 선택한
백엔드의 드라이버와 네이티브 쿼리 API를 사용해야 합니다. 공통 API는 반복되는 서비스 코드를 줄이는 계약이지,
서로 다른 저장소의 쿼리 의미를 단일화하는 계층이 아닙니다.
모듈 구성
섹션 제목: “모듈 구성”
graph-core의 공통 계약을 중심으로 저장소 어댑터, 대량 입출력, 프레임워크 통합 모듈이 구성됩니다.| 모듈 | 역할 |
|---|---|
graph-core | GraphOperations, 스키마 DSL, 탐색, 알고리즘과 선택적 병합·트랜잭션 기능의 공통 계약 |
graph-age, graph-neo4j, graph-memgraph, graph-tinkerpop, graph-falkordb | 그래프 저장소별 구현 |
graph-io/* | CSV, NDJSON, GraphML 대량 입출력과 OkIO 기반 스트리밍·압축·암호화 조합 |
spring-boot/graph-spring-boot | Spring Boot 4 자동 구성 |
ktor/graph-ktor | Ktor 3 ApplicationPlugin 통합 |
examples/* | 코드 의존성, 사기 탐지, IAM, 추천, 공급망 등 실행 가능한 시나리오 |
GraphOperations는 GraphSession, 정점·간선 저장소, 탐색과 알고리즘 저장소 계약을 조합합니다. 스키마 관리,
병합과 트랜잭션 DSL은 백엔드가 더 강한 보장을 제공할 때 구현하는 선택적 기능입니다. 따라서 공통 인터페이스가 있다고
해서 모든 백엔드가 모든 기능을 같은 방식으로 처리한다고 가정하면 안 됩니다. 지원하지 않는 기능과 실패 의미는
백엔드별 기능 표와 통합 테스트에서 확인해야 합니다.
가장 작은 시작점
섹션 제목: “가장 작은 시작점”테스트와 문서 예제는 TinkerGraph로 간단히 시작할 수 있습니다. Docker 없이 그래프를 만들고 정점과 간선을 추가한 뒤 이웃 정점을 조회합니다.
val ops: GraphOperations = TinkerGraphOperations()
ops.createGraph("demo")
val alice = ops.createVertex("Person", mapOf("name" to "Alice"))val bob = ops.createVertex("Person", mapOf("name" to "Bob"))ops.createEdge(alice.id, bob.id, "KNOWS", mapOf("since" to 2026))
val neighbors = ops.neighbors(alice.id, NeighborOptions(edgeLabel = "KNOWS"))
ops.close()이 예제는 GraphOperations의 기본 계약을 설명합니다. 운영 저장소 선택까지 증명하지는 않습니다. 같은 도메인
시나리오를 Neo4j, Memgraph, Apache AGE, FalkorDB 통합 테스트로 옮기고, 운영 데이터 규모에서 쿼리 지연 시간과
쓰기 처리량을 측정해야 합니다.
선택 기준
섹션 제목: “선택 기준”초기 후보를 정할 때는 다음 순서가 실용적입니다.
| 판단 기준 | 먼저 검토할 후보 | 추가 검증 |
|---|---|---|
| 성숙한 그래프 전용 운영 도구와 Cypher 지원 | Neo4j | 쿼리 계획, 인덱스, 운영 비용 |
| 낮은 지연 시간이 중요한 Cypher 워크로드 | Memgraph | 실제 데이터와 쓰기 패턴을 사용한 벤치마크 |
| PostgreSQL 중심의 운영 체계 | Apache AGE | Cypher-over-SQL 제약과 PostgreSQL 자원 경합 |
| 외부 서버 없는 테스트와 예제 | TinkerGraph | 운영 백엔드와의 의미 차이를 통합 테스트로 보완 |
| Redis 기반 그래프 서비스 | FalkorDB | openCypher 부분집합과 실제 읽기·쓰기 성능 |
기본 조합이 필요하다면 Neo4j를 운영 후보로, TinkerGraph를 빠른 테스트 저장소로 삼을 수 있습니다. 이 조합 역시 정답은 아닙니다. PostgreSQL 통합, Redis 운영 체계, 낮은 지연 시간처럼 더 강한 제약이 있다면 해당 제약에 맞는 백엔드를 먼저 후보로 올리고 측정 결과로 결정해야 합니다.
다음 글에서는 graph-core의 API, 스키마 DSL, 트랜잭션과 병합, 동기·가상 스레드·코루틴 실행 모델을 살펴봅니다.
시리즈
섹션 제목: “시리즈”- Part 1: 그래프 데이터베이스 선택 기준
- Part 2: 핵심 API와 실행 모델
- Part 3: 그래프 입출력과 벤치마크 해석
- Part 4: 워크숍 시나리오와 서비스 통합
- Part 5: 가상 스레드 벤치마크 해석
댓글
GitHub 계정으로 의견을 남기거나 reaction을 남길 수 있습니다.