# 오픈소스 그래프 DB 비교 및 추천 > Neo4j 대신 사용할 수 있는 오픈소스 그래프 데이터베이스 옵션 **작성일**: 2026-01-24 **대상 프로젝트**: 약국 POS QR 시스템 (PubMed GraphRAG) --- ## 🎯 평가 기준 우리 프로젝트에 필요한 조건: ``` ✅ 완전한 오픈소스 (상업적 제약 없음) ✅ Cypher 또는 유사 쿼리 언어 지원 ✅ Python 통합 용이 ✅ 배포 간편 (별도 서버 최소화) ✅ SQLite/PostgreSQL 같은 익숙한 DB와 통합 ✅ 중소 규모 그래프 최적화 (1,000~10,000 노드) ``` --- ## 📊 오픈소스 그래프 DB 비교 ### 1. **Apache AGE** ⭐⭐⭐⭐⭐ 최고 추천! ``` ┌─────────────────────────────────────────────────────────┐ │ PostgreSQL + 그래프 = Apache AGE │ │ "기존 PostgreSQL에 그래프 기능 추가" │ └─────────────────────────────────────────────────────────┘ ``` #### 🌟 핵심 특징 - **PostgreSQL 확장** (익숙한 DB + 그래프 기능) - **Cypher 쿼리 완벽 지원** (Neo4j와 동일) - **SQL + Cypher 혼합 사용 가능** - **Apache 2.0 라이선스** (완전 오픈소스) - **기존 PostgreSQL 데이터와 그래프 결합 가능** #### ✅ 장점 ```python # SQL과 Cypher를 함께 사용! # 기존 테이블 (users, products) SELECT * FROM users WHERE age > 30; # 그래프 쿼리 (관계 탐색) SELECT * FROM cypher('graph_name', $$ MATCH (u:User)-[:PURCHASED]->(p:Product) WHERE u.age > 30 RETURN u.name, p.name $$) AS (user_name text, product_name text); ``` #### ⚠️ 단점 - PostgreSQL 필요 (SQLite보다 무거움) - 비교적 신생 프로젝트 (2020년 시작) #### 📦 설치 (Ubuntu/Debian 예시) ```bash # PostgreSQL 설치 sudo apt-get install postgresql-14 # Apache AGE 설치 sudo apt-get install postgresql-14-age # 확장 활성화 CREATE EXTENSION age; ``` #### 🐍 Python 사용 ```python import psycopg2 from age import Age conn = psycopg2.connect( host="localhost", database="pharmacy_db", user="postgres" ) cursor = conn.cursor() # 그래프 생성 cursor.execute(""" SELECT create_graph('pharmacy_graph'); """) # Cypher 쿼리 cursor.execute(""" SELECT * FROM cypher('pharmacy_graph', $$ CREATE (n:Drug {name: 'Naproxen', type: 'NSAID'}) RETURN n $$) AS (drug agtype); """) # 경로 탐색 cursor.execute(""" SELECT * FROM cypher('pharmacy_graph', $$ MATCH path = (d:Drug {name: 'Statin'})-[*1..3]->(s:Symptom) RETURN path $$) AS (path agtype); """) ``` #### 🎯 우리 프로젝트 적용 ``` 현재: SQLite (mileage.db) ↓ 마이그레이션: PostgreSQL + Apache AGE ↓ 장점: - 기존 users, transactions 테이블 유지 (SQL) - 약물-증상 관계는 그래프 (Cypher) - 한 DB에서 모두 처리 ✨ ``` --- ### 2. **Memgraph** ⭐⭐⭐⭐ ``` ┌─────────────────────────────────────────────────────────┐ │ 빠른 인메모리 그래프 DB │ │ "Neo4j와 호환되는 Cypher 지원" │ └─────────────────────────────────────────────────────────┘ ``` #### 🌟 핵심 특징 - **완전한 Cypher 지원** (Neo4j 호환) - **인메모리 처리** (매우 빠름) - **스트림 처리 지원** (Kafka 통합) - **BSL 라이선스** (Community Edition 무료) #### ✅ 장점 - Neo4j보다 빠름 (인메모리) - 완전한 Cypher 지원 (학습 곡선 낮음) - Python 라이브러리 우수 #### ⚠️ 단점 - 별도 서버 필요 - 인메모리 → 메모리 많이 필요 - 데이터 영속성 설정 필요 #### 🐍 Python 사용 ```python from gqlalchemy import Memgraph memgraph = Memgraph(host='127.0.0.1', port=7687) # Cypher 쿼리 (Neo4j와 동일) results = memgraph.execute_and_fetch(""" MATCH (d:Drug {name: 'Naproxen'})-[:SAFER_THAN]->(other:Drug) RETURN d.name, other.name """) for result in results: print(result['d.name'], result['other.name']) ``` --- ### 3. **ArangoDB** ⭐⭐⭐⭐ ``` ┌─────────────────────────────────────────────────────────┐ │ 멀티모델 DB (문서 + 그래프 + 키-밸류) │ │ "하나의 DB로 모든 데이터 모델 지원" │ └─────────────────────────────────────────────────────────┘ ``` #### 🌟 핵심 특징 - **멀티모델**: 문서(JSON) + 그래프 + 키-밸류 - **AQL 쿼리 언어** (Cypher와 유사, 더 강력) - **완전 오픈소스** (Apache 2.0) - **Python, JavaScript 등 다양한 드라이버** #### ✅ 장점 - 유연함 (그래프 + JSON 문서 모두 저장) - 성능 우수 - 웹 UI 기본 제공 #### ⚠️ 단점 - Cypher 아님 (AQL 학습 필요) - 별도 서버 필요 - 설정 복잡할 수 있음 #### 🐍 Python 사용 ```python from arango import ArangoClient client = ArangoClient(hosts='http://localhost:8529') db = client.db('pharmacy_db', username='root', password='password') # 그래프 생성 graph = db.create_graph('pharmacy_graph') # 문서 + 그래프 혼합 (강력!) result = db.aql.execute(""" FOR drug IN drugs FILTER drug.type == 'NSAID' FOR vertex, edge, path IN 1..3 OUTBOUND drug GRAPH 'pharmacy_graph' FILTER vertex._id == 'symptoms/pain' RETURN path """) ``` --- ### 4. **Dgraph** ⭐⭐⭐ ``` ┌─────────────────────────────────────────────────────────┐ │ GraphQL 네이티브 그래프 DB │ │ "GraphQL로 그래프 쿼리" │ └─────────────────────────────────────────────────────────┘ ``` #### 🌟 핵심 특징 - **GraphQL 쿼리 언어** (Cypher 대신) - **Go로 작성** (빠르고 가벼움) - **분산 처리 지원** - **Apache 2.0 라이선스** #### ✅ 장점 - GraphQL 사용 시 최적 - 성능 우수 - 분산 확장 용이 #### ⚠️ 단점 - Cypher 미지원 (GraphQL 학습 필요) - 별도 서버 필요 - 커뮤니티 Neo4j보다 작음 --- ### 5. **JanusGraph** ⭐⭐⭐ ``` ┌─────────────────────────────────────────────────────────┐ │ Apache 재단 대규모 그래프 DB │ │ "수억 개 노드 지원" │ └─────────────────────────────────────────────────────────┘ ``` #### 🌟 핵심 특징 - **Apache 재단 공식 프로젝트** - **대규모 그래프 최적화** (수십억 엣지) - **Gremlin 쿼리 언어** (Cypher 아님) - **다양한 백엔드 지원** (Cassandra, HBase 등) #### ✅ 장점 - 대규모 그래프에 최적 - Apache 재단 신뢰성 - 엔터프라이즈급 기능 #### ⚠️ 단점 - **우리 프로젝트에 과함** (중소 규모용 아님) - 설정 매우 복잡 - Gremlin 학습 곡선 높음 --- ### 6. **Nebula Graph** ⭐⭐⭐ ``` ┌─────────────────────────────────────────────────────────┐ │ 분산 그래프 DB │ │ "중국발 오픈소스, 빠른 성능" │ └─────────────────────────────────────────────────────────┘ ``` #### 🌟 핵심 특징 - **nGQL** (Cypher와 유사) - **분산 아키텍처** - **Apache 2.0 라이선스** #### ⚠️ 단점 - 별도 서버 (Meta, Graph, Storage) - 설정 복잡 - 커뮤니티 주로 중국어 --- ## 🏆 종합 비교표 ``` ┌─────────────┬──────────┬──────────┬──────────┬──────────┬──────────┐ │ 항목 │ AGE │ Memgraph │ ArangoDB │ Dgraph │ JanusGrph│ ├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤ │ 쿼리 언어 │ Cypher │ Cypher │ AQL │ GraphQL │ Gremlin │ ├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤ │ 배포 난이도 │ ⭐⭐ │ ⭐⭐⭐ │ ⭐⭐⭐ │ ⭐⭐⭐ │ ⭐⭐⭐⭐⭐│ ├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤ │ 학습 곡선 │ ⭐ │ ⭐ │ ⭐⭐ │ ⭐⭐ │ ⭐⭐⭐⭐ │ ├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤ │ 성능 │ ⭐⭐⭐⭐ │ ⭐⭐⭐⭐⭐│ ⭐⭐⭐⭐ │ ⭐⭐⭐⭐ │ ⭐⭐⭐⭐⭐│ ├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤ │ SQL 통합 │ ✅ │ ❌ │ ❌ │ ❌ │ ❌ │ ├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤ │ 중소규모 적합│ ✅ │ ✅ │ ✅ │ ⭐⭐ │ ❌ │ ├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤ │ 라이선스 │ Apache │ BSL │ Apache │ Apache │ Apache │ ├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤ │ 우리적합도 │⭐⭐⭐⭐⭐│ ⭐⭐⭐⭐ │ ⭐⭐⭐ │ ⭐⭐ │ ⭐ │ └─────────────┴──────────┴──────────┴──────────┴──────────┴──────────┘ ⭐ 적음/쉬움/낮음 = 좋음 ⭐⭐⭐⭐⭐ 많음/어려움/높음 = 나쁨 (배포, 학습 곡선) ⭐⭐⭐⭐⭐ 많음 = 좋음 (성능, 적합도) ``` --- ## 🎯 우리 프로젝트 최적 선택 ### 🥇 1순위: **Apache AGE** #### 선택 이유 ``` ✅ PostgreSQL 확장 (익숙한 환경) ✅ SQL + Cypher 혼합 사용 (마이그레이션 쉬움) ✅ 기존 데이터 + 그래프 한 DB에서 관리 ✅ 완전 오픈소스 (Apache 2.0) ✅ 배포 간단 (PostgreSQL만 있으면 됨) ``` #### 마이그레이션 경로 ``` 현재: SQLite ↓ 1단계: PostgreSQL + 기본 테이블 마이그레이션 ↓ 2단계: Apache AGE 확장 설치 ↓ 3단계: 그래프 노드/엣지 생성 ↓ 결과: SQL (users, transactions) + Cypher (약물 관계) ``` --- ### 🥈 2순위: **Memgraph** #### 선택 이유 ``` ✅ 완전한 Cypher 지원 (Neo4j 호환) ✅ 매우 빠름 (인메모리) ✅ Python 라이브러리 우수 ``` #### 적합한 경우 ``` - 실시간 추천이 매우 중요 - 메모리 충분히 있음 - 별도 서버 운영 가능 ``` --- ### 🥉 3순위: **ArangoDB** #### 선택 이유 ``` ✅ 멀티모델 (유연함) ✅ 성능 우수 ✅ 웹 UI 좋음 ``` #### 적합한 경우 ``` - JSON 문서 + 그래프 모두 필요 - AQL 학습 가능 - 다양한 데이터 모델 실험 ``` --- ## 🛠️ Apache AGE 실전 적용 가이드 ### 1. 설치 (Docker 사용) ```bash # Docker Compose 설정 # docker-compose.yml version: '3.8' services: postgres-age: image: apache/age:latest environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password POSTGRES_DB: pharmacy_db ports: - "5432:5432" volumes: - pgdata:/var/lib/postgresql/data volumes: pgdata: ``` ```bash # 실행 docker-compose up -d ``` ### 2. Python 통합 ```python """ Apache AGE + Python 예시 """ import psycopg2 from age import Age # 연결 conn = psycopg2.connect( host="localhost", database="pharmacy_db", user="postgres", password="password" ) age = Age(conn) cursor = conn.cursor() # 1. 그래프 생성 age.setGraph('pharmacy_graph') cursor.execute("SELECT create_graph('pharmacy_graph');") # 2. 노드 생성 (Cypher) cursor.execute(""" SELECT * FROM cypher('pharmacy_graph', $$ CREATE (statin:Drug {name: 'Statin', type: 'HMG-CoA inhibitor'}), (coq10:Drug {name: 'CoQ10', type: 'Supplement'}), (myopathy:Condition {name: 'Myopathy'}), (evidence:Evidence {pmid: '30371340', reliability: 0.95}) RETURN statin, coq10, myopathy, evidence $$) AS (statin agtype, coq10 agtype, myopathy agtype, evidence agtype); """) # 3. 관계 생성 cursor.execute(""" SELECT * FROM cypher('pharmacy_graph', $$ MATCH (statin:Drug {name: 'Statin'}), (coq10:Drug {name: 'CoQ10'}), (myopathy:Condition {name: 'Myopathy'}), (evidence:Evidence {pmid: '30371340'}) CREATE (statin)-[:INHIBITS {mechanism: 'HMG-CoA pathway'}]->(coq10), (coq10)-[:REDUCES {effect_size: -1.60, p_value: 0.001}]->(myopathy), (evidence)-[:SUPPORTS]->(coq10)-[:REDUCES]->(myopathy) RETURN statin, coq10, myopathy $$) AS (statin agtype, coq10 agtype, myopathy agtype); """) # 4. 경로 탐색 (GraphRAG!) cursor.execute(""" SELECT * FROM cypher('pharmacy_graph', $$ MATCH path = (statin:Drug {name: 'Statin'})-[*1..3]->(myopathy:Condition {name: 'Myopathy'}) RETURN path $$) AS (path agtype); """) results = cursor.fetchall() for row in results: print(row[0]) # 5. SQL + Cypher 혼합! cursor.execute(""" -- SQL: 사용자 조회 WITH high_risk_users AS ( SELECT id, name, age FROM users WHERE age > 60 AND has_hypertension = true ) -- Cypher: 안전한 약물 추천 SELECT u.name, drug_name FROM high_risk_users u, LATERAL ( SELECT * FROM cypher('pharmacy_graph', $$ MATCH (drug:Drug)-[:SAFE_FOR]->(profile:PatientProfile {name: 'Elderly_HTN'}) RETURN drug.name $$) AS (drug_name agtype) ); """) conn.commit() conn.close() ``` ### 3. 실제 추천 시스템 예시 ```python """ Apache AGE 기반 약물 추천 시스템 """ class DrugRecommender: def __init__(self, conn): self.conn = conn self.cursor = conn.cursor() def recommend(self, patient_id, symptom): """ 환자 프로필 + 증상 → 약물 추천 (근거 포함) """ # 1. SQL: 환자 정보 조회 self.cursor.execute(""" SELECT age, hypertension, diabetes FROM users WHERE id = %s """, (patient_id,)) patient = self.cursor.fetchone() age, has_htn, has_dm = patient # 2. 환자 프로필 결정 if has_htn and has_dm: profile = 'Patient_HTN_DM' elif has_htn: profile = 'Patient_HTN' elif age > 65: profile = 'Elderly' else: profile = 'General' # 3. Cypher: 그래프 기반 추천 self.cursor.execute(f""" SELECT * FROM cypher('pharmacy_graph', $$ MATCH (drug:Drug)-[treats:TREATS]->(condition:Condition {{name: '{symptom}'}}) WHERE NOT (drug)-[:CONTRAINDICATED_IN]->(:PatientProfile {{name: '{profile}'}}) MATCH (evidence:Evidence)-[:SUPPORTS]->(treats) RETURN drug.name AS drug, treats.effect_size AS effect, evidence.pmid AS pmid, evidence.reliability AS reliability ORDER BY evidence.reliability DESC, treats.effect_size DESC LIMIT 1 $$) AS (drug agtype, effect agtype, pmid agtype, reliability agtype); """) result = self.cursor.fetchone() if result: return { 'drug': result[0], 'effect_size': result[1], 'evidence_pmid': result[2], 'reliability': result[3], 'patient_profile': profile } else: return None # 사용 예시 recommender = DrugRecommender(conn) # 환자 ID 123, 증상 "Pain" recommendation = recommender.recommend(patient_id=123, symptom='Pain') print(recommendation) # { # 'drug': 'Naproxen', # 'effect_size': -1.8, # 'evidence_pmid': '27959716', # 'reliability': 0.99, # 'patient_profile': 'Patient_HTN_DM' # } ``` --- ## 📊 마이그레이션 로드맵 ### Phase 1: SQLite → PostgreSQL (1주) ```sql -- 기존 SQLite 테이블 PostgreSQL로 이동 -- users, transactions, mileage_ledger 등 ``` ### Phase 2: Apache AGE 설치 (1일) ```bash CREATE EXTENSION age; SELECT create_graph('pharmacy_graph'); ``` ### Phase 3: 그래프 데이터 생성 (1주) ```python # PubMed 논문 → 그래프 트리플 # Cypher CREATE 문으로 노드/엣지 생성 ``` ### Phase 4: 추천 시스템 업그레이드 (1주) ```python # SQL + Cypher 혼합 쿼리 # GraphRAG 추론 경로 자동 생성 ``` --- ## 🎯 최종 권장사항 ### ✅ **즉시 도입 가능: Apache AGE** **선택 이유**: 1. PostgreSQL 확장 (익숙함) 2. SQL + Cypher 모두 사용 가능 3. 기존 데이터 + 그래프 한 DB 4. 완전 오픈소스 5. 마이그레이션 쉬움 **시작 단계**: ```bash # 1. Docker로 테스트 docker run -p 5432:5432 apache/age # 2. Python 라이브러리 설치 pip install psycopg2-binary age # 3. 간단한 그래프 생성 테스트 python test_age.py ``` --- ### 🔮 **대안: Memgraph** (성능 최우선 시) **조건**: - 별도 서버 운영 가능 - 메모리 충분 (8GB+) - 실시간 추천 필수 --- ## 📚 참고 링크 - **Apache AGE**: https://age.apache.org/ - GitHub: https://github.com/apache/age - 문서: https://age.apache.org/age-manual/master/index.html - **Memgraph**: https://memgraph.com/ - 문서: https://memgraph.com/docs - **ArangoDB**: https://www.arangodb.com/ - 문서: https://www.arangodb.com/docs/ - **Dgraph**: https://dgraph.io/ - GitHub: https://github.com/dgraph-io/dgraph --- **작성**: 2026-01-24 **추천**: Apache AGE ⭐⭐⭐⭐⭐