Skip to content

필사 모드: NoSQL 데이터베이스 완전 비교 가이드 2025: MongoDB, Cassandra, DynamoDB, Couchbase, ScyllaDB

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

TL;DR

- **NoSQL = "Not Only SQL"**: 관계형 DB의 대안, 다양한 모델

- **4가지 모델**: Document, Key-Value, Wide-column, Graph

- **MongoDB**: 문서 DB의 표준, JSON 친화적

- **Cassandra**: 페타바이트 확장, AP 시스템

- **DynamoDB**: 매니지드, single-digit ms latency

- **ScyllaDB**: Cassandra 호환, 10배 빠름 (C++)

- **선택 기준**: 데이터 모델, 일관성, 운영, 비용

1. NoSQL의 등장

1.1 RDBMS의 한계

**1990s-2000s**: PostgreSQL, MySQL, Oracle 지배.

**문제** (대규모 웹 시대):

1. **수평 확장 어려움**: 단일 머신 한계

2. **고정 스키마**: ALTER TABLE 지옥

3. **JOIN 비용**: 분산 환경에서 비효율

4. **임피던스 미스매치**: OOP ↔ 관계형

5. **유연성 부족**: 변하는 요구사항

1.2 NoSQL의 부상 (2007~)

**Google BigTable** (2006), **Amazon Dynamo** (2007) 논문이 시작.

**특징**:

- 수평 확장

- 유연한 스키마

- 단순한 CRUD

- 최종 일관성 (대부분)

1.3 NoSQL의 4가지 모델

| 모델 | 예시 | 사용 |

|---|---|---|

| **Document** | MongoDB, Couchbase | JSON 데이터, 콘텐츠 |

| **Key-Value** | Redis, DynamoDB, Riak | 캐시, 세션, 단순 조회 |

| **Wide-Column** | Cassandra, HBase, ScyllaDB | 시계열, IoT, 메시지 |

| **Graph** | Neo4j, ArangoDB | 관계, 추천, 사기 탐지 |

2. Document DB — MongoDB

2.1 데이터 모델

**JSON-like 문서**:

{

"_id": "user_123",

"name": "Alice",

"email": "alice@example.com",

"addresses": [

{

"type": "home",

"city": "Seoul",

"zipcode": "12345"

},

{

"type": "work",

"city": "Seoul",

"zipcode": "67890"

}

],

"tags": ["premium", "verified"],

"created_at": "2025-04-15T10:00:00Z"

}

**장점**:

- 중첩 구조 자연스러움

- 스키마 유연

- 관련 데이터를 한 문서에 (JOIN 회피)

2.2 쿼리

// 삽입

db.users.insertOne({ name: "Alice", email: "alice@example.com" })

// 조회

db.users.findOne({ name: "Alice" })

// 업데이트

db.users.updateOne(

{ _id: "user_123" },

{ $push: { tags: "vip" } }

)

// 집계

db.orders.aggregate([

{ $match: { status: "completed" } },

{ $group: { _id: "$user_id", total: { $sum: "$amount" } } },

{ $sort: { total: -1 } },

{ $limit: 10 }

])

2.3 인덱싱

// Single field

db.users.createIndex({ email: 1 })

// Compound

db.orders.createIndex({ user_id: 1, created_at: -1 })

// Text search

db.articles.createIndex({ content: "text" })

// Geospatial

db.locations.createIndex({ coords: "2dsphere" })

2.4 Replica Set

[Primary]

↓ replication

[Secondary 1] [Secondary 2]

**자동 failover**: Primary 죽으면 Secondary 승격.

2.5 Sharding

// 샤드 키 설정

sh.shardCollection("mydb.users", { user_id: "hashed" })

**자동 분산**: MongoDB가 알아서 데이터 이동.

2.6 트랜잭션

**MongoDB 4.0+**: Multi-document ACID 트랜잭션.

const session = client.startSession()

session.startTransaction()

try {

await accounts.updateOne({ _id: "A" }, { $inc: { balance: -100 } }, { session })

await accounts.updateOne({ _id: "B" }, { $inc: { balance: 100 } }, { session })

await session.commitTransaction()

} catch (error) {

await session.abortTransaction()

}

**주의**: 분산 트랜잭션은 여전히 비쌈.

2.7 MongoDB 사용 사례

- ✅ 콘텐츠 관리 (블로그, CMS)

- ✅ 카탈로그 (e-commerce)

- ✅ 사용자 프로필

- ✅ 모바일 앱 백엔드 (Realm)

- ❌ 복잡한 JOIN

- ❌ 강한 일관성 필수

- ❌ 페타바이트 분석

3. Wide-Column — Cassandra

3.1 데이터 모델

**행마다 다른 컬럼**:

user_id | name | email | created_at

---------|-------|-----------------|------------

1 | Alice | a@example.com | 2024-01-01

2 | Bob | (없음) | 2024-01-02

3 | Carol | c@example.com | 2024-01-03

**컬럼 패밀리** = 테이블처럼.

3.2 분산 모델

**완전 분산**:

- Master 없음 (peer-to-peer)

- Consistent hashing

- 각 노드가 일부 데이터

[Token Ring]

Node A (0-25%)

Node B (25-50%)

Node C (50-75%)

Node D (75-100%)

3.3 Replication

keyspace: my_keyspace

replication: { class: 'NetworkTopologyStrategy', dc1: 3 }

**3 replicas**: 데이터가 3 노드에 복제.

3.4 일관성 수준

**Tunable consistency**:

SELECT * FROM users WHERE id = 1

USING CONSISTENCY QUORUM;

| 수준 | 설명 |

|---|---|

| `ONE` | 1개 replica |

| `QUORUM` | 과반수 (RF=3이면 2) |

| `ALL` | 모든 replicas |

| `LOCAL_QUORUM` | 같은 DC의 과반수 |

| `EACH_QUORUM` | 각 DC의 과반수 |

**R + W > N 공식**: 강한 일관성 보장.

- R=1, W=3 (W=ALL): 빠른 읽기, 느린 쓰기

- R=2, W=2 (QUORUM): 균형

- R=3, W=1: 빠른 쓰기, 느린 읽기

3.5 데이터 모델링

**RDBMS 사고 X. 쿼리 우선 사고**:

-- 잘못 - JOIN 생각

CREATE TABLE users (id, name, email);

CREATE TABLE orders (id, user_id, amount);

-- 사용자의 주문 조회 시 JOIN 필요 → 비효율

-- 올바름 - 비정규화

CREATE TABLE user_orders (

user_id UUID,

order_id UUID,

user_name TEXT,

amount DECIMAL,

PRIMARY KEY (user_id, order_id)

);

-- 한 번의 조회로 OK

**원칙**: **쓰기는 비싸고 읽기는 싸다** → 데이터 중복 OK.

3.6 Partition Key vs Clustering Key

CREATE TABLE messages (

conversation_id UUID,

message_id TIMEUUID,

user_id UUID,

text TEXT,

PRIMARY KEY (conversation_id, message_id)

);

- **Partition key (`conversation_id`)**: 같은 conversation은 같은 노드

- **Clustering key (`message_id`)**: 노드 안에서 정렬

**효과**: 한 conversation의 모든 메시지가 같은 노드에 → 빠른 조회.

3.7 사용 사례

- ✅ 시계열 데이터 (메트릭, 로그)

- ✅ IoT 센서 데이터

- ✅ 메시징 (WhatsApp, Discord)

- ✅ 추천 데이터

- ✅ 페타바이트 데이터

- ❌ 트랜잭션

- ❌ Ad-hoc 쿼리

- ❌ JOIN

3.8 사용 회사

- **Apple** (수만 노드)

- **Netflix**

- **Uber**

- **Discord** (메시지 → 나중에 ScyllaDB로 이동)

- **Instagram**

- **Spotify**

4. AWS DynamoDB

4.1 매니지드 서비스

Amazon이 운영하는 NoSQL.

**특징**:

- **완전 매니지드**

- **Single-digit ms latency**

- **무한 확장**

- **Pay per request 또는 Provisioned**

- **Global Tables** (Multi-region active-active)

4.2 데이터 모델

**Key-Value + Document**:

{

"user_id": "user_123",

"email": "alice@example.com",

"addresses": [

{ "city": "Seoul", "zipcode": "12345" }

]

}

4.3 Primary Key

**2가지 방식**:

**1. Partition Key only (Hash)**:

user_id (PK)

**2. Partition Key + Sort Key (Composite)**:

user_id (PK) + created_at (SK)

→ 같은 user의 데이터를 시간순 조회.

4.4 Single Table Design

DynamoDB의 **핵심 패턴**:

**전통적 (잘못)**:

Table Users

Table Orders

Table Products

**Single Table (올바름)**:

Table MyApp:

PK | SK | Type | ...

USER#1 | METADATA | User | name: Alice

USER#1 | ORDER#100 | Order | amount: 50

USER#1 | ORDER#101 | Order | amount: 75

PRODUCT#A | METADATA | Product | price: 10

**효과**:

- 한 테이블, 한 쿼리로 user + 모든 orders

- JOIN 불필요

**단점**:

- 학습 곡선 가파름

- 액세스 패턴 미리 알아야

4.5 GSI (Global Secondary Index)

// GSI 생성

{

"IndexName": "EmailIndex",

"KeySchema": [

{ "AttributeName": "email", "KeyType": "HASH" }

],

"Projection": { "ProjectionType": "ALL" }

}

다른 키로 조회 가능.

4.6 가격 모델

**Provisioned**:

- RCU/WCU 미리 구매

- 안정적 트래픽

**On-Demand**:

- Pay per request

- 변동 트래픽

**예시 비용** (월 1억 read):

- Provisioned: ~$100

- On-Demand: ~$125

4.7 사용 사례

- ✅ 매니지드 필요

- ✅ 예측 가능한 패턴

- ✅ 높은 처리량

- ✅ AWS 생태계

- ❌ 복잡한 쿼리

- ❌ 분석

- ❌ AWS 외 환경

5. ScyllaDB — Cassandra의 진화

5.1 ScyllaDB란?

**Cassandra 호환** + **C++ 재작성**.

**비결**:

- C++로 모든 것

- shard-per-core 아키텍처

- io_uring

- Seastar framework

**효과**: Cassandra 대비 **5-10배 빠름**.

5.2 Cassandra와의 차이

| | Cassandra | ScyllaDB |

|---|---|---|

| **언어** | Java | C++ |

| **아키텍처** | JVM thread pool | Shard-per-core |

| **GC** | 있음 (JVM) | 없음 |

| **호환성** | - | 100% 호환 |

| **성능** | 기준 | **5-10배** |

| **메모리** | 많음 | 적음 |

5.3 사용 회사

- **Discord** (Cassandra → ScyllaDB 마이그레이션)

- **Comcast**

- **Disney+**

- **Samsung**

**Discord 사례**:

- Cassandra: 177 노드

- ScyllaDB: 72 노드

- 비용 60% 절감

6. Couchbase

6.1 특징

**MongoDB + Memcached 같은 느낌**.

- **Document store** (JSON)

- **Key-value 캐시** 내장

- **N1QL** (SQL-like 쿼리)

- **Multi-dimensional scaling**

6.2 N1QL

SQL 친화적:

SELECT name, email

FROM users

WHERE city = "Seoul"

ORDER BY created_at DESC

LIMIT 10;

MongoDB의 query language보다 친숙.

6.3 Mobile + Edge

**Couchbase Lite**: 모바일 임베디드 DB.

**Sync Gateway**: 서버와 동기화.

→ **오프라인 우선** 모바일 앱에 강력.

6.4 사용 사례

- ✅ 대형 e-commerce (LinkedIn, eBay)

- ✅ Personalization

- ✅ Offline-first 모바일

- ❌ 작은 프로젝트 (오버킬)

7. 데이터 모델 비교

7.1 같은 데이터, 다른 모델

**시나리오**: 사용자와 주문.

**RDBMS**:

CREATE TABLE users (id, name, email);

CREATE TABLE orders (id, user_id, amount);

SELECT * FROM users JOIN orders ON users.id = orders.user_id;

**MongoDB (Document)**:

{

"_id": "user_1",

"name": "Alice",

"orders": [

{ "id": "order_1", "amount": 50 },

{ "id": "order_2", "amount": 75 }

]

}

**Cassandra (Wide-column)**:

CREATE TABLE user_orders (

user_id UUID,

order_id TIMEUUID,

amount DECIMAL,

PRIMARY KEY (user_id, order_id)

);

**DynamoDB (Single Table)**:

PK | SK | data

USER#1 | METADATA | name=Alice

USER#1 | ORDER#1 | amount=50

USER#1 | ORDER#2 | amount=75

**Redis (Key-Value)**:

user:1:name → "Alice"

user:1:orders → [order_1, order_2]

order:1:amount → "50"

7.2 트레이드오프

| | RDBMS | Document | Wide-Column | Key-Value |

|---|---|---|---|---|

| **유연성** | ❌ | ✅ | ✅ | ✅ |

| **JOIN** | ✅ | 제한적 | ❌ | ❌ |

| **확장성** | 어려움 | 보통 | **매우 우수** | 매우 우수 |

| **트랜잭션** | ✅ | 부분 | 제한적 | 제한적 |

| **쿼리 유연** | ✅ | 좋음 | 제한적 | 단순 키 조회 |

| **학습 곡선** | 보통 | 낮음 | 가파름 | 매우 낮음 |

8. 일관성 모델

8.1 ACID vs BASE

**ACID** (RDBMS):

- **A**tomicity

- **C**onsistency

- **I**solation

- **D**urability

**BASE** (NoSQL):

- **B**asically **A**vailable

- **S**oft state

- **E**ventually consistent

8.2 CAP 정리

분산 시스템은 3가지 중 2가지만:

- **C**onsistency

- **A**vailability

- **P**artition tolerance

**P는 필수** (네트워크 분할은 불가피) → CP vs AP.

8.3 NoSQL의 CAP 분류

| | CP (일관성) | AP (가용성) |

|---|---|---|

| **MongoDB** | ✅ (기본) | 설정 가능 |

| **Cassandra** | 설정 가능 | ✅ (기본) |

| **DynamoDB** | 설정 가능 | ✅ |

| **HBase** | ✅ | |

| **Riak** | | ✅ |

8.4 Tunable Consistency

Cassandra의 강점:

- 쿼리마다 일관성 수준 선택

- ONE, QUORUM, ALL

**예시**:

- 사용자 프로필 읽기: ONE (빠름)

- 결제 처리: QUORUM (안전)

9. 마이그레이션 사례

9.1 RDBMS → MongoDB

**언제**:

- JSON 데이터 자연스러움

- 스키마 유연성 필요

- 단일 머신 한계

**전략**:

1. 새 기능을 MongoDB로

2. 기존 테이블을 점진적 마이그레이션

3. ETL로 데이터 변환

9.2 MongoDB → DynamoDB

**Stripe 사례**: MongoDB → DynamoDB

- 매니지드 운영 부담 감소

- AWS 통합

**도전**:

- Single Table Design 학습

- 액세스 패턴 재설계

- 쿼리 유연성 손실

9.3 Cassandra → ScyllaDB

**Discord 사례**:

- Cassandra 177 노드 → ScyllaDB 72 노드

- 같은 워크로드, 60% 비용 절감

- API 호환 → 코드 변경 거의 없음

9.4 일반적 함정

**1. 잘못된 모델 선택**:

- "유행하니까 MongoDB"

- "Big data니까 Cassandra"

- → 요구사항에 맞는 선택

**2. 데이터 모델링**:

- RDBMS 사고로 NoSQL 사용

- 정규화 시도

- → NoSQL은 비정규화

**3. 일관성 오해**:

- "결국 일관"의 의미

- 트랜잭션 부재

- → 비즈니스 요구 명확히

10. 선택 가이드

10.1 의사결정 트리

강한 일관성 + 트랜잭션이 필수?

├─ 예 → RDBMS (PostgreSQL) 또는 NewSQL (CockroachDB)

└─ 아니오

├─ 데이터가 JSON-like?

│ └─ MongoDB (Document)

├─ 시계열 또는 페타바이트?

│ ├─ 자체 운영 → Cassandra/ScyllaDB

│ └─ 매니지드 → DynamoDB

├─ 그래프 관계?

│ └─ Neo4j

└─ 단순 캐시/세션?

└─ Redis

10.2 사용 사례별

**Content Management**: MongoDB

**E-commerce 카탈로그**: MongoDB, Couchbase

**사용자 프로필**: MongoDB, DynamoDB

**시계열 (메트릭, 로그)**: Cassandra, InfluxDB, TimescaleDB

**메시지 (채팅)**: Cassandra, ScyllaDB

**세션/캐시**: Redis, Memcached

**추천 시스템**: Cassandra, Neo4j

**소셜 그래프**: Neo4j, ArangoDB

**IoT 센서**: Cassandra, InfluxDB

**금융 거래**: PostgreSQL (NoSQL X)

**분석**: ClickHouse, BigQuery, Snowflake

10.3 운영 고려

**Self-managed**:

- 전문성 필요

- 비용 통제 가능

- 풀스택 책임

**Managed**:

- DynamoDB, Atlas (MongoDB), Astra (Cassandra)

- 비용 높음

- 운영 부담 적음

퀴즈

**답**: RDBMS의 한계: (1) **수평 확장 어려움** — 단일 머신 한계, (2) **고정 스키마** — ALTER TABLE 지옥, (3) **JOIN 비용** — 분산 환경에서 비효율, (4) **임피던스 미스매치** — OOP와 관계형 모델의 차이, (5) **유연성 부족**. 2007년 Amazon Dynamo 논문이 분기점. **Google BigTable, Amazon Dynamo가 영감**. NoSQL = "Not Only SQL" — RDBMS를 대체가 아닌 보완.

**답**: **쿼리 우선 사고**입니다. RDBMS처럼 정규화하지 말고, **각 쿼리마다 별도 테이블**을 만들 수도 있습니다. 원칙: (1) **JOIN 회피** — 데이터 중복 OK, (2) **쓰기 비싸고 읽기 쌈** — 미리 쿼리에 맞게 데이터 구성, (3) **Partition key + Clustering key** — 같은 partition key는 같은 노드, clustering key로 정렬. 예: `(conversation_id, message_id)` → 한 conversation의 모든 메시지가 같은 노드에. **RDBMS 사고로 사용하면 망함**.

**답**: **모든 entity를 한 테이블에 저장**하는 패턴. 전통적: Users 테이블, Orders 테이블 분리. Single Table: PK=`USER#1`, SK=`METADATA` 또는 `SK=ORDER#100`. 한 쿼리로 user + 모든 orders 가져오기. **JOIN 회피, 비용 감소, 빠른 응답**. 단점: 학습 곡선 가파름, 액세스 패턴을 미리 알아야 함, 새 패턴 추가 시 어려움. AWS의 Rick Houlihan이 강력 추천. **DynamoDB의 가장 큰 학습 장벽이자 가장 큰 강점**.

**답**: (1) **C++로 재작성** — JVM 오버헤드 없음, (2) **GC 없음** — Java의 stop-the-world 회피, (3) **Shard-per-core 아키텍처** — 코어마다 독립 shard, 락 없음, (4) **io_uring** — 진정한 async I/O, (5) **Seastar framework** — 사용자 공간 네트워킹. **결과: Cassandra 대비 5-10배 빠름**. **Discord 사례**: 177 노드 Cassandra → 72 노드 ScyllaDB, 60% 비용 절감. 100% Cassandra 호환 → 마이그레이션 쉬움.

**답**: 분산 시스템은 **C, A, P 중 2가지만** 가능. P (네트워크 분할 허용)는 필수 → CP vs AP 선택. **CP (일관성 우선)**: MongoDB (기본), HBase, Spanner — 분할 시 일부 노드 거부. **AP (가용성 우선)**: Cassandra (기본), DynamoDB, Riak — 분할 시 stale data 가능. **Tunable**: Cassandra는 쿼리마다 일관성 수준 선택 (ONE, QUORUM, ALL). 비즈니스 요구에 따라 결정 — 결제는 CP, 소셜 피드는 AP.

참고 자료

- [MongoDB Documentation](https://www.mongodb.com/docs/)

- [Apache Cassandra](https://cassandra.apache.org/)

- [DynamoDB Best Practices](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/best-practices.html)

- [ScyllaDB](https://www.scylladb.com/)

- [Couchbase](https://www.couchbase.com/)

- [Designing Data-Intensive Applications](https://dataintensive.net/) — Martin Kleppmann

- [DynamoDB Book](https://www.dynamodbbook.com/) — Alex DeBrie

- [Cassandra: The Definitive Guide](https://www.oreilly.com/library/view/cassandra-the-definitive/9781098115159/)

- [MongoDB Patterns](https://www.mongodb.com/blog/post/building-with-patterns-a-summary)

- [Discord's ScyllaDB Migration](https://discord.com/blog/how-discord-stores-trillions-of-messages)

- [DB-Engines Ranking](https://db-engines.com/en/ranking)

현재 단락 (1/420)

- **NoSQL = "Not Only SQL"**: 관계형 DB의 대안, 다양한 모델

작성 글자: 0원문 글자: 10,615작성 단락: 0/420