[Daily morning study] 그래프 데이터베이스 개념과 활용
#daily morning study
그래프 데이터베이스란
그래프 데이터베이스(Graph Database)는 데이터를 노드(Node), 엣지(Edge), 프로퍼티(Property) 세 가지 요소로 표현하는 데이터베이스다. 관계형 데이터베이스에서 여러 테이블을 JOIN해서 표현했던 복잡한 관계를 그래프 구조로 자연스럽게 모델링할 수 있다.
- 노드: 엔티티(사람, 상품, 장소 등)를 표현
- 엣지: 노드 간의 관계를 표현 (방향성 있음)
- 프로퍼티: 노드와 엣지에 부여하는 key-value 속성
(User:Alice) -[FOLLOWS]-> (User:Bob)
(User:Alice) -[PURCHASED]-> (Product:Laptop)
(Product:Laptop) -[BELONGS_TO]-> (Category:Electronics)
RDB vs 그래프 데이터베이스
| 항목 | RDB | Graph DB |
|---|---|---|
| 데이터 모델 | 테이블/행/열 | 노드/엣지/프로퍼티 |
| 관계 표현 | Foreign Key, JOIN | 엣지 |
| 깊은 관계 탐색 | JOIN이 중첩될수록 느려짐 | 일정한 성능 유지 |
| 스키마 | 고정 스키마 | 유연한 스키마 |
| 대표 제품 | MySQL, PostgreSQL | Neo4j, Amazon Neptune, ArangoDB |
RDB는 관계가 깊어질수록(n-hop 탐색) JOIN 비용이 기하급수적으로 증가한다. 예를 들어 “친구의 친구의 친구” 쿼리를 RDB로 처리하면 3번의 자기 JOIN이 필요하고, 데이터가 커질수록 성능이 급격히 저하된다. 그래프 DB는 엣지를 직접 따라가기 때문에 hop 수가 늘어도 성능이 크게 떨어지지 않는다.
그래프 데이터베이스의 저장 방식
Native Graph Storage
그래프 구조를 파일 시스템에 직접 저장하는 방식. 노드가 인접한 엣지 목록을 직접 가리키는 포인터를 갖는다.
Node(id=1) → [Edge(id=10), Edge(id=11), Edge(id=12)]
각 노드가 연결된 엣지를 직접 참조하기 때문에 탐색 시 인덱스 조회 없이 포인터를 따라가면 된다. 이를 Index-Free Adjacency라고 부른다. Neo4j가 이 방식을 사용한다.
Non-Native Graph Storage
기존 RDB나 key-value 스토어 위에 그래프 모델을 구현하는 방식. 관계 탐색 시 여전히 인덱스를 사용해야 하므로 성능이 상대적으로 낮다.
Cypher 쿼리 언어 (Neo4j)
Neo4j에서 사용하는 그래프 쿼리 언어. 노드는 (), 엣지는 -[]-> 로 시각적으로 표현한다.
노드와 관계 생성
CREATE (alice:User {name: 'Alice', age: 30})
CREATE (bob:User {name: 'Bob', age: 25})
CREATE (alice)-[:FOLLOWS {since: '2024-01-01'}]->(bob)
데이터 조회
-- Alice가 팔로우하는 사람 조회
MATCH (alice:User {name: 'Alice'})-[:FOLLOWS]->(followed)
RETURN followed.name
-- 친구의 친구 조회 (2-hop)
MATCH (alice:User {name: 'Alice'})-[:FOLLOWS*2]->(fof)
WHERE NOT (alice)-[:FOLLOWS]->(fof)
RETURN fof.name
-- 최단 경로 탐색
MATCH path = shortestPath(
(alice:User {name: 'Alice'})-[*]-(target:User {name: 'Charlie'})
)
RETURN path
조건부 갱신
-- 노드가 없으면 생성, 있으면 기존 것 사용
MERGE (u:User {email: 'alice@example.com'})
ON CREATE SET u.created = timestamp()
ON MATCH SET u.lastLogin = timestamp()
주요 활용 사례
소셜 네트워크
사용자 간의 팔로우, 친구 관계를 모델링하고 “공통 친구 추천”, “영향력 있는 사용자 탐색” 같은 기능을 효율적으로 처리한다.
-- Alice와 Bob의 공통 팔로우 찾기
MATCH (alice:User {name: 'Alice'})-[:FOLLOWS]->(common)
<-[:FOLLOWS]-(bob:User {name: 'Bob'})
RETURN common.name
추천 시스템
“이 상품을 산 사람들이 함께 산 상품” 같은 협업 필터링 추천.
MATCH (u:User {id: 1})-[:PURCHASED]->(p:Product)
<-[:PURCHASED]-(other:User)-[:PURCHASED]->(rec:Product)
WHERE NOT (u)-[:PURCHASED]->(rec)
RETURN rec.name, count(*) AS score
ORDER BY score DESC
LIMIT 10
사기 탐지 (Fraud Detection)
여러 계좌, 기기, IP 주소 간의 연결 패턴을 분석해서 사기 링을 탐지한다. 사기 거래는 보통 복잡한 관계 패턴을 형성하기 때문에 그래프 탐색이 효과적이다.
지식 그래프 (Knowledge Graph)
엔티티와 개념 사이의 관계를 저장하는 데 사용된다. Google의 Knowledge Graph, Wikipedia의 Wikidata 등이 이 구조를 활용한다.
네트워크/IT 인프라 관리
서버, 스위치, 라우터 간의 연결 관계를 그래프로 관리하면 장애 파급 범위 분석이 용이하다.
그래프 알고리즘
Neo4j의 Graph Data Science(GDS) 라이브러리는 다양한 그래프 알고리즘을 제공한다.
| 알고리즘 | 설명 | 활용 |
|---|---|---|
| PageRank | 노드의 중요도 계산 | 영향력 있는 사용자 탐색 |
| Betweenness Centrality | 다른 노드 사이의 중개 정도 | 네트워크 병목 탐지 |
| Community Detection (Louvain) | 밀접하게 연결된 커뮤니티 탐색 | 사용자 그룹 분류 |
| Shortest Path | 두 노드 간의 최단 경로 | 네비게이션, 6단계 분리 |
| Weakly/Strongly Connected Components | 연결된 컴포넌트 찾기 | 사기 링 탐지 |
-- PageRank 실행 (GDS)
CALL gds.pageRank.stream('myGraph')
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS name, score
ORDER BY score DESC
LIMIT 10
언제 그래프 데이터베이스를 선택해야 하는가
적합한 경우
- 데이터 간 관계가 복잡하고 깊은 탐색이 필요할 때
- 관계 자체에 의미 있는 속성이 필요할 때 (e.g., “언제부터 친구인지”)
- 관계 구조가 자주 변하고 유연성이 필요할 때
부적합한 경우
- 대량의 단순 집계 쿼리가 주된 워크로드일 때 (OLAP)
- 관계가 단순하고 정형화된 데이터일 때
- 팀이 SQL에 익숙하고 그래프 쿼리 학습 비용이 부담될 때
대표 그래프 데이터베이스 비교
| 제품 | 쿼리 언어 | 특징 |
|---|---|---|
| Neo4j | Cypher | 가장 성숙한 Native Graph DB, GDS 알고리즘 풍부 |
| Amazon Neptune | Gremlin, SPARQL, openCypher | AWS 완전관리형, 높은 가용성 |
| ArangoDB | AQL | 그래프 + 도큐먼트 + 키-값 멀티모델 |
| TigerGraph | GSQL | 실시간 분석과 대규모 그래프 처리 특화 |
| Dgraph | GraphQL+- | GraphQL 기반 분산 그래프 DB |
정리
- 그래프 데이터베이스는 노드, 엣지, 프로퍼티로 데이터를 표현한다.
- Index-Free Adjacency 덕분에 깊은 관계 탐색에서 RDB보다 월등히 빠르다.
- 소셜 네트워크, 추천 시스템, 사기 탐지, 지식 그래프 등 관계가 핵심인 도메인에 적합하다.
- 단순 집계나 정형 데이터 처리에는 RDB나 컬럼형 DB가 더 적합하다.
- Neo4j의 Cypher는 시각적인 문법으로 그래프 패턴을 직관적으로 표현할 수 있다.