데이터베이스 학습 노트 목차

NoSQL — KV·문서·컬럼·그래프·시계열

관계형 DB는 정형 데이터·강한 일관성·복잡한 조인에 강하지만, (1) 스키마가 유동적이거나, (2) 한 대로 감당 못 할 규모로 수평 확장이 필요하거나, (3) 특정 접근 패턴(그래프 탐색·시계열)에 특화가 필요할 때 다른 도구가 낫다. NoSQL"관계형이 아닌" 다양한 데이터 모델의 묶음이다 — 하나의 대안이 아니라 여러 갈래다. 핵심은 *"무엇을 버리고 무엇을 얻는가"*다. (출처: Kleppmann Designing Data-Intensive Applications Ch 2·3 / 각 제품 공식문서.)

왜 NoSQL인가 — ACID를 BASE로 바꾸는 거래

대부분의 NoSQL은 *수평 확장(샤딩)*과 유연한 스키마를 위해 관계형의 무언가를 포기한다 — 보통 조인·다중 행 트랜잭션·강한 일관성 중 일부다. 이 거래를 ACID 대비 BASE로 부른다.

  • Basically Available — 일부 노드가 죽어도 응답은 한다.
  • Soft state — 외부 입력 없이도 상태가 (복제 수렴으로) 변할 수 있다.
  • Eventually consistent — 즉시는 아니어도 언젠가 수렴한다.

또 많은 NoSQL은 집합체 지향(aggregate-oriented) — *함께 읽고 쓰는 데이터를 한 덩어리(문서/레코드)*로 뭉쳐 두어 조인 없이 한 번에 가져온다(대신 중복·갱신 부담).

다이어그램 로딩 중…

1) 키-값(Key-Value) — Redis

키로 값을 넣고 뺀다. 가장 단순하고 빠르다(보통 인메모리). Redis는 단순 KV를 넘어 자료구조를 제공해 캐시·세션·랭킹·레이트리밋·큐에 두루 쓰인다.

SET session:abc123 "{...}" EX 1800      # 30분 TTL 세션
INCR  page:view:2026-06-04               # 원자적 카운터
EXPIRE cart:42 600                       # 10분 후 자동 삭제

# Sorted Set으로 실시간 랭킹 — 점수 기반 정렬을 O(log N)에
ZADD leaderboard 1500 "userA" 1800 "userB"
ZREVRANGE leaderboard 0 9 WITHSCORES     # 상위 10명

강점 — 단순 키 접근이 마이크로초. 한계값 내부 조건 검색·조인이 없다(키로만 찾음). 그래서 접근 경로가 키로 분명한 데이터에 쓴다.

2) 문서(Document) — MongoDB

JSON(BSON) 문서를 저장한다. 스키마가 유연하고, *연관을 문서 안에 내포(embed)*해 조인 없이 한 번에 읽는다.

// 주문을 항목까지 한 문서로 내포 — 조인 없이 한 방에 읽음
db.orders.insertOne({
  _id: 1, memberId: 42, status: "paid",
  items: [ { sku: "A1", qty: 2, price: 9900 },
           { sku: "B7", qty: 1, price: 4900 } ]
});

// 중첩·배열 조건 질의 + 집계 파이프라인
db.orders.aggregate([
  { $match: { status: "paid" } },
  { $unwind: "$items" },
  { $group: { _id: "$memberId", total: { $sum: { $multiply: ["$items.qty","$items.price"] } } } },
  { $sort: { total: -1 } }
]);

*내포(embed) vs 참조(reference)*가 설계의 핵심 — 함께 읽히고 한 문서에 안 너무 커지면 내포, 독립적으로 크게 자라거나 공유되면 참조. 문서 DB도 단일 문서 연산은 원자적이지만 여러 문서 트랜잭션은 (지원하더라도) 비싸다.

3) 와이드 컬럼(Wide-Column) — Cassandra

파티션 키 + 클러스터링 키 + 동적 컬럼 구조로, 초대규모 쓰기·시간순 데이터에 강하고 마스터 없이 수평 분산된다. 핵심 원칙은 쿼리 우선 모델링질의를 먼저 정하고 테이블을 그 질의에 맞춰 만든다(정규화·조인 없음, 중복 감수).

-- 파티션 키(sensor_id) 안에서 시간 역순 정렬 — 시계열 조회에 최적
CREATE TABLE readings (
  sensor_id text, ts timestamp, value double,
  PRIMARY KEY ((sensor_id), ts)
) WITH CLUSTERING ORDER BY (ts DESC);

SELECT * FROM readings WHERE sensor_id = 's-1' LIMIT 100;  -- 한 파티션 = 빠름

주의파티션 키를 안 주는 질의(ALLOW FILTERING)는 전 노드를 훑어 느리고 위험하다. 조인·집계가 필요하면 애플리케이션/별도 테이블로 푼다.

4) 그래프(Graph) — Neo4j

노드·간선으로 관계 자체를 1급으로 다룬다. 친구의 친구·추천·경로처럼 관계형에서 다단계 조인이 폭발하는 질의를 간선을 직접 따라가며 효율적으로 푼다.

// "내 친구의 친구"(2-hop) 추천 — 관계형이라면 self-join 2번
MATCH (me:Person {name:'Kim'})-[:FRIEND]->()-[:FRIEND]->(fof)
WHERE NOT (me)-[:FRIEND]->(fof) AND me <> fof
RETURN DISTINCT fof.name LIMIT 10;

5) 시계열(Time-Series) — InfluxDB·TimescaleDB

시간 인덱스 메트릭에 특화 — 압축·다운샘플링·보존정책(오래된 데이터 자동 만료). IoT·모니터링·금융 틱. PostgreSQL 확장 TimescaleDB처럼 관계형 위 시계열(하이퍼테이블·연속 집계)도 있어, SQL을 그대로 쓰며 시계열 최적화를 얻는다.

NewSQL·멀티모델 — 경계가 흐려진다

요즘은 경계가 섞인다. NewSQL(CockroachDB·Google Spanner·TiDB)은 관계형 SQL + 분산 수평확장 + 강한 일관성을 동시에 노린다(분산 합의로 — [12] 참고). 반대로 PostgreSQL은 *jsonb(문서)·pgvector(벡터)·TimescaleDB(시계열)·hstore(KV)*로 여러 모델을 흡수한다. 그래서 *"NoSQL이냐 RDB냐"*보다 *"이 워크로드에 어떤 모델·일관성·확장 특성이 맞나"*를 묻는 게 옳다.

언제 무엇을 — 선택 기준

워크로드적합이유
강한 일관성·복잡 조인·트랜잭션관계형(기본값)ACID·조인·옵티마이저
캐시·세션·실시간 랭킹·큐KV(Redis)키 접근 마이크로초
유연 스키마·집합체 읽기문서(MongoDB)내포로 조인 회피
초대규모 쓰기·시간순 로그와이드 컬럼(Cassandra)쓰기 분산·쿼리 우선
관계 탐색이 핵심그래프(Neo4j)간선 직접 순회
메트릭·IoT·틱시계열압축·다운샘플·보존

흔한 실수유행을 따라 NoSQL부터 고르는 것. 대부분의 서비스는 관계형으로 충분하고, NoSQL은 명확한 이유(규모·접근 패턴·일관성 요구)가 있을 때 도입한다. 그리고 폴리글랏 퍼시스턴스(여러 저장소 혼용)는 운영 복잡도·데이터 동기화라는 비용을 같이 치른다.

한 줄 요약 — NoSQL은 수평 확장·유연 스키마를 위해 조인·트랜잭션·강한 일관성 일부를 포기(BASE·집합체 지향)한 여러 갈래(KV·문서·컬럼·그래프·시계열). 각자 고유한 질의 언어·모델링 원칙이 있다. 관계형을 기본으로 두고, 분명한 이유가 있을 때 골라 섞는다.

(출처: Kleppmann DDIA Ch 2·3 / Redis Data Types·MongoDB Aggregation·Cassandra CQL·Neo4j Cypher·TimescaleDB 공식문서.)

보안·권한 — 인증·인가·암호화·SQL 인젝션분산 DB — 복제·샤딩·CAP·일관성·2PC/Saga