MongoDB·Cassandra·Neo4j로 보는 NoSQL 데이터 모델과 쿼리 설계

MongoDB, Cassandra, Neo4j의 데이터 모델과 분산 구조, 일관성 제어, 인덱스 및 쿼리 설계 방식을 비교한다.

2026-08-14 · 최초 발행 2024-04-29

데이터 모델이 쿼리와 확장 방식을 결정한다

NoSQL 데이터베이스는 스키마 유연성, 수평 확장성, 고가용성을 목표로 하는 비관계형 데이터베이스군이다. 다만 MongoDB, Apache Cassandra, Neo4j는 같은 문제를 서로 다른 데이터 모델과 실행 방식으로 푼다.

MongoDB는 JSON 유사 문서를 다루는 분산 데이터베이스다. CRUD와 집계를 위해 MongoDB Query Language 및 Aggregation Pipeline을 제공하며, 기본 트랜잭션 단위는 단일 문서다. 멀티 도큐먼트 트랜잭션도 지원한다.

Cassandra는 키스페이스, 테이블, 파티션으로 구성되는 와이드 컬럼 스토어다. Consistent Hashing을 이용해 데이터를 분산하고, 가용성 우선(AP) 설계와 튜너블 일관성을 제공한다. 쓰기 경로는 LSM-Tree 기반이다.

Neo4j는 노드, 관계, 속성으로 이루어진 Property Graph 모델을 사용한다. Cypher로 패턴을 찾고 경로를 탐색하며, ACID 트랜잭션과 네이티브 그래프 엔진을 제공한다.

스키마와 분산 구조를 설계하는 방식

MongoDB는 컬렉션 단위에서 스키마 유연성을 제공하고 JSON/BSON 문서를 중심으로 모델링한다. 필요한 최소 제약은 스키마 밸리데이션으로 설정할 수 있다. 샤딩은 샤딩 키를 기준으로 범위 또는 해시 방식으로 구성하며, mongos가 쿼리를 적절한 샤드로 보낸다. 가용성은 리플리카셋으로 확보한다.

Cassandra에서는 읽기 패턴이 테이블 설계의 출발점이다. 파티션 키와 클러스터링 컬럼이 성능을 좌우하므로, 조회 요구를 먼저 정하고 데이터를 배치해야 한다. 가상 노드(vNode)와 Consistent Hashing은 자동 리밸런싱을 지원하며, Gossip, Hinted Handoff, Repair가 노드 장애에 대응한다.

Neo4j의 스키마는 라벨, 관계 타입, 속성 중심으로 구성된다. 그래프 구조 자체는 유연하지만 인덱스와 제약을 통해 데이터 품질을 관리해야 한다. 단일 인스턴스 성능이 우수하고, Causal Cluster에서는 읽기를 수평 확장할 수 있다. 쓰기는 리더 중심으로 처리한다.

일관성 수준과 조회 비용의 차이

MongoDB는 Read Concern, Write Concern, Read Preference를 통해 일관성과 지연의 균형을 조절한다. Majority 커밋 옵션은 내구성을 강화하는 선택지다.

Cassandra는 ONE, QUORUM, ALL 같은 Consistency Level을 읽기와 쓰기별로 지정한다. R+W>N 규칙으로 강한 일관성을 달성할 수 있다.

Neo4j는 ACID 트랜잭션과 Causal Consistency를 제공한다. 리더 장애가 발생하면 선출 알고리즘으로 자동 복구한다.

조회 최적화의 관점도 다르다. MongoDB는 단일, 복합, TTL, 텍스트 인덱스를 사용하고 $lookup, $graphLookup으로 조인 또는 그래프 유사 질의를 수행한다. 실행계획은 explain()으로 점검한다.

Cassandra는 파티션 키를 이용한 범위 접근에 맞춰 설계한다. 보조 인덱스는 신중하게 사용하고, Materialized View나 서브테이블로 조회 패턴을 분리한다.

Neo4j는 라벨과 속성 인덱스로 탐색의 시작점을 좁히고, 관계 중심 탐색으로 조인 비용을 줄인다. 패턴의 선택성과 카디널리티가 핵심 변수다.

이벤트·시계열·관계 탐색에 맞춘 모델링

MongoDB 이벤트 집계

실시간 이벤트 분석에서는 Ingest(Producer) → Kafka → MongoDB Sharded Cluster → Aggregation API 구조를 사용할 수 있다. 복합 인덱스 (eventType, timestamp)로 컬럼 스캔을 줄이고, Incremental Aggregation으로 시간창(Window)을 처리한다.

예시 코드/환경: MongoDB 6.x, mongosh

// 전제: 컬렉션 events(eventType, userId, timestamp, payload)
db.events.createIndex({ eventType: 1, timestamp: -1 });

db.events.aggregate(
  [
    {
      $match: {
        eventType: "click",
        timestamp: { $gte: ISODate("2025-11-01") },
      },
    },
    { $group: { _id: { hour: { $hour: "$timestamp" } }, cnt: { $sum: 1 } } },
    { $sort: { "_id.hour": 1 } },
  ],
  { allowDiskUse: true },
);

Cassandra 시계열과 IoT 데이터

대규모 타임시리즈 또는 IoT 환경에서는 Devices → Ingest API → Cassandra Cluster(3+ DC) → Spark/Presto 분석 흐름을 구성할 수 있다. 파티션 키를 device_id + day로, 클러스터링 키를 timestamp DESC로 잡아 핫파티션을 방지한다. 데이터 수명은 QUORUM과 TTL을 이용해 관리한다.

예시 코드/환경: Apache Cassandra 4.1, cqlsh

CREATE KEYSPACE iot WITH replication = {
  'class': 'NetworkTopologyStrategy', 'dc1': '3', 'dc2': '3'
};

CREATE TABLE iot.metrics (
  device_id text,
  day date,
  ts timestamp,
  metric map<text, double>,
  PRIMARY KEY ((device_id, day), ts)
) WITH CLUSTERING ORDER BY (ts DESC) AND default_time_to_live = 2592000;

CONSISTENCY QUORUM;
SELECT * FROM iot.metrics WHERE device_id='A1' AND day='2025-11-07' AND ts > '2025-11-07T00:00:00Z' LIMIT 1000;

Neo4j 관계 기반 추천과 탐지

추천 또는 사기탐지에서는 ETL → Neo4j Cluster → 서비스 API → 캐시 구조를 사용할 수 있다. (User)-[PURCHASED]->(Item)-[ALSO_BOUGHT]->(Item)처럼 관계를 모델링하고, 가중치 기반 최단경로와 커뮤니티 탐지를 적용한다.

예시 코드/환경: Neo4j 5.x, cypher-shell

// 생성
CREATE (u:User {id:'u1'})-[:PURCHASED]->(i1:Item {sku:'100'})
CREATE (i1)-[:ALSO_BOUGHT {w:0.8}]->(i2:Item {sku:'200'});

// 질의
MATCH (u:User {id:$uid})-[:PURCHASED]->(i:Item)-[:ALSO_BOUGHT]->(rec:Item)
RETURN rec.sku AS sku, count(*) AS score ORDER BY score DESC LIMIT 10;

워크로드별 특성 비교

항목 MongoDB Cassandra Neo4j
성능 읽기/집계 우수, 샤딩 시 선형 확장 쓰기·시계열 압도적, 낮은 지연 패턴 탐색·조인 대체에 강점
확장성 수평 샤딩, 자동 청크 밸런싱 vNode로 자동 리밸런스, 멀티DC 읽기 스케일아웃, 쓰기는 리더
일관성 Read/Write Concern 조절 튜너블 일관성, R+W>N 강일관 ACID, Causal Consistency
안정성 리플리카셋 자동 선출 Gossip/Repair로 자가치유 리더 선출로 장애 복구
운영 편의 풍부한 도구와 드라이버 스키마 엄격 설계 필요 모델링 직관, 인덱스 관리 중요

요청이 저장소를 통과하는 경로

MongoDB 요청은 클라이언트에서 mongos를 거쳐 대상 샤드로 라우팅된다. 인덱스 스캔 뒤 필터와 프로젝션을 수행하고, 파이프라인 집계와 정렬 과정에서는 리밸런싱도 고려한다. 결과는 커서로 스트리밍하며 배치 크기를 조절한다. readConcern(local|majority)writeConcern(majority, wtimeout)로 일관성을 선택한다. DuplicateKey는 upsert 또는 unique 재검토로, LockTimeout은 지수백오프를 둔 재시도로 대응한다.

Cassandra의 쓰기 경로는 CommitLog 기록, Memtable 반영, SSTable 플러시, Compaction 순서다. 읽을 때는 Bloom Filter, Partition Index, SSTable Merge를 거치며 필요하면 Read Repair를 수행한다. 복제수 N과 읽기·쓰기 값 R/W를 조합하고, 강한 일관성은 R+W>N으로 판단한다. 일반적인 권장은 QUORUM이다. ReadTimeout, WriteTimeout에는 idempotent 재시도를 적용하고, Coordinator 장애는 Driver 재시도 정책으로 처리한다.

Neo4j는 Cypher를 파싱한 뒤 휴리스틱 또는 코스트 기반으로 계획을 수립한다. 인덱스에서 탐색 시드를 선택하고 확장과 프루닝을 거쳐 경로를 집계·정렬한 다음 결과를 스트리밍한다. 페이지네이션도 이 과정에 포함된다. 트랜잭션 경계 안에서는 ACID를 보장하고, 클러스터는 causal read를 사용한다. DeadlockDetected는 트랜잭션 재시도로 처리하며, 카디널리티가 급증하면 힌트나 제약을 추가한다.

운영 제약을 설계에 반영하기

전 구간 TLS와 노드 간 mTLS를 적용하고, 저장 데이터는 디스크 또는 필드 레벨에서 암호화한다. 최소 권한(RBAC), 감사 로깅, 네트워크 세그먼테이션도 필요하지만 성능 비용이 따른다.

MongoDB에서는 카디널리티가 높고 핫스팟이 적은 샤딩 키를 고른다. Zone Sharding은 데이터 주권 대응에 사용할 수 있으며, 조인이 많은 경우 컬렉션 정규화와 비정규화의 균형을 검토한다.

Cassandra는 쿼리 우선 스키마와 파티션 균형 모니터링이 중요하다. LWT를 과도하게 사용하면 지연이 증가한다.

Neo4j에서는 고유 제약과 인덱스로 탐색 시드를 최소화한다. 매우 긴 경로 탐색은 제한하거나 배치로 처리한다.

백업과 복구에서는 PITR 및 스냅샷을 자동화하고, 복구 RTO/RPO를 명문화한다. 모니터링 대상은 지연, P99, Compaction, 힙/GC, 코디네이터 타임아웃이며, 알람 임곗값은 단계적으로 튜닝한다. 업그레이드는 롤링 방식을 권장하고, 메이저 버전은 호환성 영향을 사전에 검증한다.

Cassandra는 쓰기 QPS 수십만/노드, MongoDB는 샤딩 시 선형 증가, Neo4j는 관계 탐색 지연 ms~수십 ms 수준을 목표 특성으로 가질 수 있다. 단, Neo4j의 지연은 패턴과 데이터셋에 의존한다. 다중 DC 복제로 99.99% 가용성을 목표로 할 수 있으나 네트워크와 운영 성숙도가 선행돼야 한다. 스케일아웃은 범용 하드웨어 활용을 가능하게 하고, 압축·TTL·컴팩션을 통한 스토리지 효율은 TCO 절감에 기여한다. 스키마 변경 부담이 줄어들면 신규 서비스 요구에 빠르게 모델링을 적용할 수 있다.

Neo4jCassandraMongoDBClientqueryroute by shard keyCQLR/W at CLR/W at CLR/W at CLCyphercausal readtimeout(Retry withBackoff)failoverAPI / Appmongos RouterShard1+ReplicaSetShard2+ReplicaSetCoordinator(Node A)(Node B)(Node C)Driver(Leader)(Follower)
NoSQLMongoDBCassandraNeo4j분산 데이터베이스