약국 POS 시스템의 GraphRAG 기반 추천 시스템 구축 관련 문서:
## 핵심 설계 문서
1. 질병코드기반 제품추천.md
- ICD-10 질병 코드 활용 추천 시스템 설계
- 계층 구조 (질병 → 질병군 → 제품군 → 개별 제품)
- 처방전 기반 추천 알고리즘
2. complex-product-graph-modeling.md
- 복합제(비맥스제트 등) 그래프 모델링
- 성분 간 시너지 효과 표현
- 복합 증상 매칭 쿼리 예시
3. pubmed-graphrag-workflow.md
- PubMed → GraphRAG 전체 워크플로우 (5단계)
- 논문 검색, 근거 추출, 지식 그래프 구축
- MCP Server 개발 가이드
## 그래프 DB 비교 및 평가
4. sqlite-graph-evaluation.md
- SQLite vs SQLite-Graph vs Neo4j 비교
- 현 시점(2026-01) 평가: 기존 SQL 유지 권장
- 6개월 후 재평가 계획
5. opensource-graph-db-comparison.md
- 오픈소스 그래프 DB 비교 (Neo4j, ArangoDB 등)
6. 온톨로지로전환.md
- 관계형 DB → 온톨로지 구조 전환 가이드
- PubMed RAG 활용 방안
- 추론 규칙 설계
## PubMed GraphRAG 활용
7. pycnogenol-multi-indication-graphrag.md
- 피크노제놀 다중 적응증 GraphRAG 구축 사례
- 7가지 적응증별 근거 수준
8. grpahrag_아쉬아간다.md
- Ashwagandha GraphRAG 구축 사례
9. pubdmed이용ai.md
- PubMed + AI 통합 활용 가이드
## 추가 워크플로우
10. pubmed-graphrag-workflow_next.md
- 다음 단계 워크플로우
11. PostgresGRAPH전환.md
- PostgreSQL + Apache AGE 전환 가이드
모든 문서는 한국어로 작성되었으며, 코드 예시는 영어로 포함.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
356 lines
11 KiB
Markdown
356 lines
11 KiB
Markdown
# SQLite-Graph 도입 평가
|
|
|
|
> 현재 시점(2026-01-24)에서 SQLite-Graph를 우리 프로젝트에 도입해야 하는가?
|
|
|
|
---
|
|
|
|
## 🎯 결론: **아직은 기존 SQL 유지 권장**
|
|
|
|
### 이유
|
|
|
|
1. **아직 초기 버전** (Cypher 구문 부분 지원)
|
|
2. **핵심 기능 미지원** (ORDER BY, LIMIT, 집계 함수)
|
|
3. **프로덕션 안정성 불확실**
|
|
4. **기존 SQL도 충분히 작동 중**
|
|
|
|
---
|
|
|
|
## ✅ 현재 상황 분석
|
|
|
|
### 우리 프로젝트의 그래프 복잡도
|
|
|
|
```
|
|
현재 그래프 규모:
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
- 노드: ~50개 (약물, 증상, 환자 프로필)
|
|
- 엣지: ~200개 (약물-증상, 약물-부작용 관계)
|
|
- 최대 경로 깊이: 2-3 hop
|
|
|
|
→ 이 정도 규모에서는 SQL JOIN도 충분히 빠름!
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
```
|
|
|
|
### 기존 SQL 쿼리 성능
|
|
|
|
```python
|
|
# 2-hop 경로 탐색 (Statin → CoQ10 → Myopathy)
|
|
# 현재 SQL 쿼리 시간: ~10ms ✅
|
|
|
|
SELECT
|
|
e1.name, r1.predicate, e2.name, r2.predicate, e3.name
|
|
FROM relationships r1
|
|
JOIN entities e1 ON r1.subject_id = e1.id
|
|
JOIN entities e2 ON r1.object_id = e2.id
|
|
JOIN relationships r2 ON r2.subject_id = e2.id
|
|
JOIN entities e3 ON r2.object_id = e3.id
|
|
WHERE e1.name = 'Statin' AND e3.name = 'Myopathy';
|
|
|
|
-- 실행 시간: 8-12ms (50개 노드, 200개 엣지 기준)
|
|
-- 충분히 빠름! 🚀
|
|
```
|
|
|
|
---
|
|
|
|
## 🔬 SQLite-Graph가 필요한 경우
|
|
|
|
### 시나리오 1: 그래프 규모가 클 때
|
|
|
|
```
|
|
대규모 그래프:
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
- 노드: 10,000개 이상
|
|
- 엣지: 100,000개 이상
|
|
- 최대 경로 깊이: 5-10 hop
|
|
|
|
→ 이 경우 SQL JOIN 성능 저하 (재귀 CTE 느림)
|
|
→ SQLite-Graph의 그래프 최적화 필요
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
```
|
|
|
|
### 시나리오 2: 복잡한 경로 쿼리가 많을 때
|
|
|
|
```cypher
|
|
-- 예시: 모든 가능한 경로 탐색
|
|
MATCH path = (drug)-[*1..5]->(symptom)
|
|
WHERE drug.type = 'NSAID'
|
|
RETURN path;
|
|
|
|
-- SQL로 구현: 재귀 CTE 사용, 매우 복잡
|
|
WITH RECURSIVE paths AS (
|
|
SELECT id, name, 1 AS depth, CAST(name AS TEXT) AS path
|
|
FROM entities
|
|
WHERE type = 'Drug'
|
|
UNION ALL
|
|
SELECT e.id, e.name, p.depth + 1, p.path || ' -> ' || e.name
|
|
FROM paths p
|
|
JOIN relationships r ON p.id = r.subject_id
|
|
JOIN entities e ON r.object_id = e.id
|
|
WHERE p.depth < 5
|
|
)
|
|
SELECT * FROM paths WHERE name = 'symptom';
|
|
|
|
-- 복잡도: ⭐⭐⭐⭐⭐ (이해하기 어려움)
|
|
-- vs Cypher: ⭐ (매우 간단)
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 비교표: 우리 프로젝트 기준
|
|
|
|
```
|
|
┌─────────────────────────┬─────────────────┬─────────────────┐
|
|
│ 평가 항목 │ 기존 SQL │ SQLite-Graph │
|
|
├─────────────────────────┼─────────────────┼─────────────────┤
|
|
│ 현재 그래프 규모 │ ✅ 충분 │ ✅ 충분 │
|
|
│ 성능 (50 노드, 200 엣지)│ ✅ ~10ms │ ✅ ~5-10ms │
|
|
│ 배포 난이도 │ ✅ 매우 쉬움 │ ⚠️ 확장 필요 │
|
|
│ 안정성 │ ✅ 검증됨 │ ⚠️ 초기 버전 │
|
|
│ 팀원 학습 곡선 │ ✅ SQL 익숙 │ ⚠️ Cypher 학습 │
|
|
│ 쿼리 가독성 (2-hop) │ ⭐⭐ │ ⭐⭐⭐⭐⭐ │
|
|
│ 쿼리 가독성 (N-hop) │ ⭐ │ ⭐⭐⭐⭐⭐ │
|
|
│ ORDER BY / LIMIT │ ✅ 지원 │ ❌ 미지원 가능 │
|
|
│ 집계 함수 │ ✅ 지원 │ ❌ 미지원 가능 │
|
|
│ 그래프 알고리즘 │ ❌ 수동 구현 │ ✅ 내장 │
|
|
└─────────────────────────┴─────────────────┴─────────────────┘
|
|
|
|
【종합 점수】
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
기존 SQL: ★★★★☆ (4.0/5.0)
|
|
SQLite-Graph: ★★★☆☆ (3.0/5.0) ← 아직 초기 버전
|
|
|
|
【결론】
|
|
현재 시점에서는 기존 SQL 유지 권장
|
|
6개월~1년 후 SQLite-Graph 성숙도 재평가
|
|
```
|
|
|
|
---
|
|
|
|
## 🎯 권장 전략: **하이브리드 접근**
|
|
|
|
### 1단계: 현재 (기존 SQL 유지)
|
|
|
|
```python
|
|
# backend/graph_query.py
|
|
class GraphQuery:
|
|
"""기존 SQL 기반 그래프 쿼리"""
|
|
|
|
def find_path(self, start, end, max_depth=3):
|
|
"""2-3 hop 경로 탐색"""
|
|
# SQL로 구현 (현재 코드 유지)
|
|
pass
|
|
|
|
def recommend_drug(self, patient_profile, symptom):
|
|
"""약물 추천"""
|
|
# SQL로 구현 (현재 코드 유지)
|
|
pass
|
|
```
|
|
|
|
**장점**:
|
|
- ✅ 안정적
|
|
- ✅ 배포 쉬움
|
|
- ✅ 충분한 성능
|
|
|
|
---
|
|
|
|
### 2단계: 6개월 후 (SQLite-Graph 재평가)
|
|
|
|
**평가 항목**:
|
|
```
|
|
1. Cypher 구문 지원 확대 여부
|
|
- ORDER BY, LIMIT 지원?
|
|
- 집계 함수 지원?
|
|
- OPTIONAL MATCH 지원?
|
|
|
|
2. 커뮤니티 성숙도
|
|
- GitHub Stars 증가?
|
|
- 이슈 해결 속도?
|
|
- 프로덕션 사용 사례?
|
|
|
|
3. 우리 그래프 규모 증가
|
|
- 노드 1,000개 이상?
|
|
- 복잡한 N-hop 쿼리 필요?
|
|
```
|
|
|
|
**조건 충족 시 마이그레이션**:
|
|
```python
|
|
# backend/graph_query_v2.py (SQLite-Graph 버전)
|
|
class GraphQueryV2:
|
|
"""Cypher 기반 그래프 쿼리"""
|
|
|
|
def find_path_cypher(self, start, end):
|
|
"""Cypher로 경로 탐색"""
|
|
cypher = f"""
|
|
MATCH path = (a {{name: '{start}'}})-[*1..5]->(b {{name: '{end}'}})
|
|
RETURN path
|
|
ORDER BY length(path)
|
|
LIMIT 1
|
|
"""
|
|
# 실행...
|
|
```
|
|
|
|
---
|
|
|
|
### 3단계: 장기 (Neo4j 검토)
|
|
|
|
**만약 그래프가 매우 커진다면** (노드 10,000개+):
|
|
```
|
|
SQLite-Graph도 한계 → Neo4j 전환 검토
|
|
|
|
Neo4j 장점:
|
|
- 대규모 그래프 최적화
|
|
- 완전한 Cypher 지원
|
|
- 분산 처리 가능
|
|
- Graph Data Science 라이브러리
|
|
|
|
Neo4j 단점:
|
|
- 별도 서버 필요 (배포 복잡)
|
|
- 비용 (엔터프라이즈)
|
|
- SQLite보다 무거움
|
|
```
|
|
|
|
---
|
|
|
|
## 🛠️ 실용적인 팁: SQL을 Cypher처럼 사용
|
|
|
|
### 현재 SQL을 더 읽기 쉽게 만들기
|
|
|
|
```python
|
|
# backend/graph_utils.py
|
|
|
|
def build_path_query(start_entity, end_entity, max_hops=3):
|
|
"""
|
|
경로 탐색 SQL을 자동 생성
|
|
(Cypher처럼 간단하게 호출)
|
|
"""
|
|
# 2-hop
|
|
if max_hops == 2:
|
|
return f"""
|
|
SELECT
|
|
e1.name AS start,
|
|
r1.predicate AS rel1,
|
|
e2.name AS middle,
|
|
r2.predicate AS rel2,
|
|
e3.name AS end
|
|
FROM relationships r1
|
|
JOIN entities e1 ON r1.subject_id = e1.id
|
|
JOIN entities e2 ON r1.object_id = e2.id
|
|
JOIN relationships r2 ON r2.subject_id = e2.id
|
|
JOIN entities e3 ON r2.object_id = e3.id
|
|
WHERE e1.name = '{start_entity}' AND e3.name = '{end_entity}'
|
|
"""
|
|
|
|
# 3-hop (재귀 CTE)
|
|
elif max_hops == 3:
|
|
return f"""
|
|
WITH RECURSIVE paths AS (
|
|
-- 시작 노드
|
|
SELECT
|
|
e.id,
|
|
e.name,
|
|
1 AS depth,
|
|
e.name AS path
|
|
FROM entities e
|
|
WHERE e.name = '{start_entity}'
|
|
|
|
UNION ALL
|
|
|
|
-- 재귀: 다음 노드 탐색
|
|
SELECT
|
|
e.id,
|
|
e.name,
|
|
p.depth + 1,
|
|
p.path || ' -> ' || e.name
|
|
FROM paths p
|
|
JOIN relationships r ON p.id = r.subject_id
|
|
JOIN entities e ON r.object_id = e.id
|
|
WHERE p.depth < {max_hops}
|
|
)
|
|
SELECT * FROM paths WHERE name = '{end_entity}'
|
|
"""
|
|
|
|
|
|
# 사용 (Cypher처럼 간단)
|
|
query = build_path_query('Statin', 'Myopathy', max_hops=2)
|
|
results = cursor.execute(query).fetchall()
|
|
```
|
|
|
|
---
|
|
|
|
## 📌 최종 권장사항
|
|
|
|
### ✅ **지금 당장: 기존 SQL 유지**
|
|
|
|
**이유**:
|
|
1. 현재 그래프 규모에서 충분히 빠름 (10ms 미만)
|
|
2. 안정적이고 검증됨
|
|
3. 배포 간단 (확장 설치 불필요)
|
|
4. SQLite-Graph 아직 초기 버전
|
|
|
|
**개선 방안**:
|
|
- SQL 쿼리를 헬퍼 함수로 감싸서 가독성 향상
|
|
- 자주 사용하는 쿼리 VIEW로 저장
|
|
- 성능 병목 발생 시에만 최적화
|
|
|
|
---
|
|
|
|
### 🔮 **6개월 후: SQLite-Graph 재평가**
|
|
|
|
**체크리스트**:
|
|
```
|
|
□ SQLite-Graph가 ORDER BY/LIMIT 지원?
|
|
□ 집계 함수 (COUNT, AVG) 지원?
|
|
□ GitHub Stars 1,000+ (커뮤니티 활성화)?
|
|
□ 프로덕션 사용 사례 3개 이상?
|
|
□ 우리 그래프 노드 500개 이상?
|
|
□ 복잡한 N-hop 쿼리 빈번?
|
|
|
|
→ 3개 이상 ✅ → 마이그레이션 고려
|
|
```
|
|
|
|
---
|
|
|
|
### 📚 **장기: Neo4j 검토 (선택사항)**
|
|
|
|
**조건**:
|
|
```
|
|
□ 노드 10,000개 이상
|
|
□ 복잡한 그래프 알고리즘 필요 (PageRank, 커뮤니티 탐지)
|
|
□ 실시간 그래프 분석 필요
|
|
□ 분산 처리 필요
|
|
|
|
→ 모두 ✅ → Neo4j 도입
|
|
```
|
|
|
|
---
|
|
|
|
## 🎯 요약
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ 현재 시점 (2026-01-24) 최적 선택: │
|
|
│ │
|
|
│ 기존 SQL 유지 ✅ │
|
|
│ │
|
|
│ 이유: │
|
|
│ - SQLite-Graph 아직 초기 버전 │
|
|
│ - 핵심 기능 미지원 (ORDER BY, LIMIT) │
|
|
│ - 현재 그래프 규모에서 SQL 충분히 빠름 │
|
|
│ - 프로덕션 안정성 중요 │
|
|
│ │
|
|
│ 재평가 시점: 2026년 7-8월 │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 🔗 참고 링크
|
|
|
|
- **SQLite-Graph GitHub**: https://github.com/agentflare-ai/sqlite-graph
|
|
- **현재 지원 구문**: CREATE, MATCH, WHERE, RETURN
|
|
- **미지원 구문**: ORDER BY, LIMIT, 집계, OPTIONAL MATCH
|
|
|
|
---
|
|
|
|
**작성**: 2026-01-24
|
|
**재평가 예정**: 2026-07-24
|