데이터베이스 따라잡기

NoSQL 개요

meellon 2026. 7. 4. 05:30

학습 목표

NoSQL 네 가지 데이터 모델(KV·문서·와이드컬럼·그래프)과 대표 제품을 구분할 수 있다.

스키마 유연성정규화·JOIN 트레이드오프를 access pattern 기준으로 설명할 수 있다.

CAP에서 분할(partition)일관성 vs 가용성 선택을 설명할 수 있다.

워크로드(lookup·range·관계 탐색·ad-hoc 집계)별 적합한 모델을 고를 수 있다.

RDBNoSQL공존하는 이유 — polyglot persistence — 를 설명할 수 있다.

문제 상황

  • 상품 속성이 매주 바뀌는데 ALTER TABLE 배포월 1회 — 스키마 병목
  • 피드 쓰기 TPS 8만 — 단일 PostgreSQL WAL·connection 한계 (샤딩 비용 큼)
  • MongoDB에 주문·결제 원장 — 다중 문서 TX·정산 취약
  • Redis에 주문 영구 저장 — AOF만으로 감사·복잡 쿼리 불가
  • Cassandra range scan 없이 전 partition fan-out — 쿼리 설계 실패
  • "NoSQL이 빠르다" — 패턴 없이 벤더만 선택

앞서 복제·샤딩·분산 TX — RDB 확장 한계를 봤다. 다른 데이터 모델 등장했는지, 엔진 관점에서 정리한다.

1. RDB 한계와 NoSQL

NoSQL — "SQL 없음"이 아니라 관계형·ACID·JOIN 중심 모델 의 저장소 계열.

RDB 강점 (앞서) 확장·유연성 병목
ACID·제약 수평 write — shard·2PC 비용
JOIN·ad-hoc SQL 스키마 migration 배포
성숙 도구 wide row·nested 데이터 비효율
Scale-up exhausted  →  replication (read)  →  sharding (write)
Still mismatch?     →  model fit: embed doc, partition key, graph edge
  • NoSQL ≠ 항상 빠름access pattern맞을 때 이득
  • Architecture 데이터 저장소 선택 — 시스템 조립; 여기서는 모델·엔진 동작

2. 네 가지 데이터 모델

유형 단위 쿼리 대표 잘 맞는 패턴
Key-value key → blob get/put by key Redis, DynamoDB 세션·캐시·rate limit
Document JSON/BSON 문서 key + 필드 filter MongoDB aggregate 단위 CRUD
Wide-column partition + sort → columns partition key 필수 Cassandra, HBase append log·시계열
Graph node·edge 관계 traverse Neo4j 추천·권한·경로

Key-value

# code/kv-session.example
SET session:u42 "{\"cart\":[101,205],\"ttl\":3600}" EX 3600
GET session:u42
INCR rate:api:u42
  • 초저지연 · TTL원장·복잡 쿼리 부적합
  • DynamoDB도 KV 계열 — partition key + optional sort key

Document

// code/document-order.example
{
  "_id": "ord-9001",
  "user_id": 42,
  "status": "paid",
  "line_items": [
    { "sku": "A1", "qty": 2, "price": 9900 },
    { "sku": "B3", "qty": 1, "price": 15000 }
  ],
  "shipping": { "city": "Seoul", "zip": "06234" }
}
  • 한 문서 = aggregateJOIN 대신 embed
  • 스키마 유연 — 필드 추가migration 없이 가능 (운영 검증은 필요)

Wide-column

-- code/wide-column-events.cql (Cassandra CQL)
CREATE TABLE events_by_user (
    user_id     bigint,
    event_time  timestamp,
    event_type  text,
    payload     text,
    PRIMARY KEY (user_id, event_time)
) WITH CLUSTERING ORDER BY (event_time DESC);

INSERT INTO events_by_user (user_id, event_time, event_type, payload)
VALUES (42, '2026-07-04T10:00:00Z', 'click', '{"page":"/p/101"}');
  • = (partition key, sort key) → columns
  • 쿼리테이블 설계 시 고정partition key 없는 scan 비용
  • 쓰기 분산·append강함

Graph

// code/graph-social.cypher
MATCH (u:User {id: 42})-[:FOLLOWS]->(friend)-[:POSTED]->(p:Post)
RETURN friend.name, p.title
LIMIT 20;
  • 관계1급 — SQL 재귀 JOIN·many-hop 비용
  • 스케일·운영 비용도메인진짜 graph일 때

3. 스키마 유연성 vs JOIN

  RDB (정규화) Document (embed)
중복 최소 허용 (read locality)
변경 ALTER·FK 필드 추가 쉬움
쿼리 JOIN·집계 자유 문서 경계
일관성 TX across tables 단일 문서 atomic (제품별)
-- RDB: 3-table join
SELECT o.id, u.name, li.sku, li.qty
FROM orders o
JOIN users u ON u.id = o.user_id
JOIN order_items li ON li.order_id = o.id
WHERE o.id = 9001;
Document: one read by _id  →  line_items embedded
Trade-off: update sku price in catalog  →  denormalized copies stale
선택 기준  
함께 read/write? embed
독립 lifecycle·many-to-many? 정규화·RDB
ad-hoc report? RDB·warehouse
  • 앞서 역정규화 — 같은 트레이드오프, 모델기본값바꿈

4. CAP과 일관성

CAP분산 저장소에서 network partition 발생 시 세 가지동시 만족 불가:

  의미
C (Consistency) 모든 노드 같은 값 (linearizable 에 가까움)
A (Availability) 모든 요청 응답 (에러·timeout 없음)
P (Partition tolerance) 네트워크 분할 허용 (분산 현실)
Partition happens  →  choose C or A (not both in strict CAP)
No partition       →  CA achievable on single node / sync cluster
경향 특징
CP etcd, ZooKeeper, 동기 replica 일관성 · partition 시 일부 unavailable
AP Cassandra, DynamoDB (default) 가용 · eventual consistency
CA 단일 RDB 노드 분할 없음 가정
PACELC (Kleppmann) partition 없을Latency vs Consistency
Cassandra ELlow latency
DynamoDB tunable — strong read 옵션
  • 앞서 replication lag — AP 계열의 stale read 동일 문제
  • 앞서 saga — eventual consistency 수용분산 TX 대체

5. Access pattern과 선택

패턴 1차 모델 주의
Point lookup by id KV · Document hot key
Range by time/user Wide-column · RDB partition partition key 설계
Ad-hoc JOIN·집계 RDB NoSQL secondary
Graph traverse 2~5 hop Graph SQL 재귀 한계
Full-text search Search engine (ES) source of truth 별도
Cache KV (Redis) TTL·invalidation

결정 순서

  1. 데이터 shape — nested doc vs flat relation
  2. 쿼리 — 고정 access path vs ad-hoc SQL
  3. 일관성 — strong TX vs eventual 허용
  4. 규모 — single node · shard · native partition
  5. 운영 — backup·CDC·팀 스킬
Wrong:  "We use Mongo" first
Right:  access pattern → consistency → scale → product

6. RDB와 공존

역할 저장소  
원장 PostgreSQL orders, payments
카탈로그 Document flexible attributes
세션 Redis TTL
이벤트 log Wide-column / Kafka append
검색 Elasticsearch read model
  • Polyglot persistence서비스·워크로드마다 최적 엔진 — 운영 표면적 증가
  • CQRS — write RDB + read cache/search — 캐시·CDC 편과 연결
  • NewSQL (Spanner, CockroachDB) — SQL + 분산 TX비용·운영 tradeoff

7. 체크리스트

항목 확인
Pattern 90% 쿼리가 partition/key 포함?
Truth 원장 하나 — 나머지 파생?
TX cross-document·cross-shard 필요?
Schema 유연 = 검증·migration 계획 있음?
CAP partition 시 C vs A 명시?
Ops backup·repair·compaction runbook?

8. 정리

  • NoSQL모델 특화 — KV·Document·Wide-column·Graph
  • 스키마 유연JOIN·정규화access pattern으로 선택
  • CAP — partition 시 C vs Alag·eventual 이해
  • RDB 대체 아님 — 원장·집계관계형 강함
  • Part 4 마무리 — 다음 Part 5 실무(pool·ORM·캐시)

다음에 다룰 것

  • Connection Pool과 ORM
  • pool 고갈, N+1, 지연 로딩

해당 내용은 Database System Concepts, 7/E (Avraham Silberschatz, Henry F. Korth, S. Sudarshan), Designing Data-Intensive Applications (Martin Kleppmann) 의 내용을 기반으로 합니다.

'데이터베이스 따라잡기' 카테고리의 다른 글

캐시와 DB  (0) 2026.07.06
Connection Pool과 ORM  (0) 2026.07.05
분산 트랜잭션 개요  (0) 2026.07.03
파티셔닝과 샤딩  (0) 2026.07.02
복제  (0) 2026.07.01