NoSQL의 등장 배경
모든 데이터를 RDB에 넣어야 하나요? — 트래픽 규모, 데이터 구조, 일관성 요구 수준에 따라 최적의 선택이 달라집니다.
NoSQL(Not Only SQL)은 관계형 데이터베이스만으로는 해결하기 어려운 문제를 다루기 위해 등장했습니다. 2000년대 후반 구글, 아마존, 페이스북 등 대규모 인터넷 서비스 기업들이 주도적으로 개발하기 시작했으며, 현재는 거의 모든 규모의 서비스에서 활용됩니다.
관계형 데이터베이스의 성공과 한계
RDB가 성공한 이유
관계형 데이터베이스는 1970년 에드거 코드(Edgar F. Codd)의 논문에서 시작되어 50년 넘게 데이터 관리의 표준으로 자리 잡았습니다.
┌──────────────────────────────────────────────────────┐
│ 1. 수학적 기반 │
│ 관계 대수를 기반으로 데이터의 정확성 증명 가능 │
│ │
│ 2. SQL — 선언적 질의 언어 │
│ "무엇"을 원하는지만 기술하면 DBMS가 "어떻게" 처리 │
│ │
│ 3. ACID 트랜잭션 │
│ 데이터 무결성과 일관성을 보장 │
│ │
│ 4. 정규화와 스키마 │
│ 데이터 중복 최소화, 명확한 구조 정의 │
│ │
│ 5. 풍부한 에코시스템 │
│ 수십 년간의 도구, 라이브러리, 전문가 축적 │
└──────────────────────────────────────────────────────┘RDB의 확장 한계
관계형 데이터베이스는 수십 년간 데이터 저장의 표준이었습니다. 하지만 대규모 트래픽과 비정형 데이터가 폭발적으로 증가하면서 한계가 드러났습니다.
| 확장 방식 | 설명 | RDB 적합성 |
|---|---|---|
| 스케일 업 (Scale Up) | 서버 성능을 높임 (CPU, RAM 추가) | 가능하지만 비용이 기하급수적 |
| 스케일 아웃 (Scale Out) | 서버 수를 늘림 (분산) | 어려움 (조인, 트랜잭션 문제) |
사용자 수 증가
100명 → 1만명 → 100만명 → 1억명
RDB (스케일 업)
서버 1대를 계속 업그레이드
→ 어느 시점에서 물리적 한계 도달
→ 비용: $$$$$$$
NoSQL (스케일 아웃)
서버를 여러 대 추가
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│Node 1│ │Node 2│ │Node 3│ │Node 4│
└──────┘ └──────┘ └──────┘ └──────┘
→ 수평 확장 용이
→ 비용: 선형 증가RDB에서 스케일 아웃이 어려운 이유
┌────────────────────────────────────────────────────────┐
│ 1. 조인(JOIN)의 분산 처리 │
│ 두 테이블이 다른 서버에 있으면? │
│ → 네트워크를 통해 데이터를 전송해야 함 │
│ → 성능 급격히 저하 │
│ │
│ 2. 분산 트랜잭션 │
│ ACID를 여러 노드에서 보장하려면? │
│ → 2PC(Two-Phase Commit) 필요 │
│ → 네트워크 지연 + 장애 시 블로킹 문제 │
│ │
│ 3. 스키마 변경 │
│ ALTER TABLE을 수백 대 서버에 동시 적용? │
│ → 다운타임 또는 복잡한 마이그레이션 필요 │
│ │
│ 4. AUTO_INCREMENT / SEQUENCE │
│ 여러 노드에서 고유한 순차 ID 생성? │
│ → 분산 환경에서 병목 │
└────────────────────────────────────────────────────────┘새로운 데이터 요구사항
2000년대 이후, 기존 RDB로는 처리하기 어려운 새로운 유형의 데이터가 급증했습니다.
* 소셜 미디어 게시물 — 스키마가 자주 변함
사진, 동영상, 리액션, 댓글, 공유... 계속 새로운 필드 추가
* IoT 센서 데이터 — 초당 수만 건 쓰기
온도, 습도, 위치... 시간 순서로 쌓이기만 함
* 사용자 세션/캐시 — 단순 키-값 조회
복잡한 관계 불필요, 빠른 읽기/쓰기만 중요
* 소셜 네트워크 관계 — 복잡한 그래프 구조
"친구의 친구의 친구" 같은 관계 탐색은 JOIN으로 매우 비효율적
* 상품 카탈로그 — 카테고리마다 속성이 다름
전자제품: 화면크기, 배터리, CPU
의류: 사이즈, 색상, 소재
→ 정규화하면 테이블이 수백 개NoSQL의 탄생
Not Only SQL
NoSQL은 No SQL(SQL 없음)이 아니라 Not Only SQL(SQL만이 아닌)을 의미합니다. 관계형 모델을 부정하는 것이 아니라, 특정 용도에 더 적합한 대안을 제공합니다.
┌──────────────────────────────────────────────────────┐
│ RDB: "하나의 도구로 모든 문제를 해결" │
│ * 범용적이지만, 특정 시나리오에서 비효율적 │
│ │
│ NoSQL: "문제에 맞는 도구를 선택" │
│ * 키-값 저장: 캐시, 세션 → Redis, DynamoDB │
│ * 문서 저장: 유연한 스키마 → MongoDB, CouchDB │
│ * 컬럼 패밀리: 대규모 분석 → Cassandra, HBase │
│ * 그래프: 관계 탐색 → Neo4j, Amazon Neptune │
└──────────────────────────────────────────────────────┘NoSQL의 공통 특성
* 스키마리스(Schemaless) 또는 유연한 스키마
→ 사전에 테이블 구조를 정의하지 않아도 됨
→ 개발 속도 가속, 스키마 변경 비용 최소
* 수평 확장(Horizontal Scaling) 설계
→ 데이터를 여러 노드에 자동 분산(Sharding)
→ 노드 추가만으로 용량/성능 확장
* 비관계형 데이터 모델
→ 조인 대신 비정규화(Denormalization) 선호
→ 읽기 성능 최적화
* 스키마 변경이 자유로움
→ ALTER TABLE 같은 무거운 작업 불필요
→ 새 필드를 바로 추가 가능CAP 정리
CAP 정리(CAP Theorem)는 2000년 에릭 브루어(Eric Brewer)가 제안한 이론으로, 분산 시스템에서 세 가지 속성을 동시에 모두 만족할 수 없다는 것을 증명했습니다.
| 속성 | 영문 | 설명 |
|---|---|---|
| 일관성 | Consistency | 모든 노드가 같은 데이터를 보여줌 |
| 가용성 | Availability | 모든 요청이 응답을 받음 |
| 분할 내성 | Partition Tolerance | 네트워크 단절에도 시스템 동작 |
C (일관성)
/ \
/ \
/ ? \
/ \
A ─────── P
(가용성) (분할 내성)
분산 시스템에서 네트워크 분할(P)은 피할 수 없으므로,
실질적으로 C vs A 중 하나를 선택해야 합니다.
CP 선택: 일관성 우선 → 일부 요청 거부 가능
AP 선택: 가용성 우선 → 일시적 불일치 허용각 선택의 의미
노드 A와 노드 B 사이 네트워크 단절 발생!
CP 시스템의 동작
사용자 → 노드 A에 쓰기 요청
노드 A: "노드 B에 복제할 수 없으므로 쓰기를 거부합니다"
→ 일관성 유지, 가용성 희생
은행 시스템에 적합
잔액이 다른 노드에서 다르게 보이면 큰 문제!노드 A와 노드 B 사이 네트워크 단절 발생!
AP 시스템의 동작
사용자 → 노드 A에 쓰기 성공
노드 A → 노드 B에 복제 불가 (네트워크 단절)
→ 노드 A와 B의 데이터가 일시적으로 다름
→ 네트워크 복구 후 동기화
소셜 미디어에 적합
"좋아요" 수가 1~2초 다르게 보여도 괜찮음| 선택 | 시스템 예시 | 적합한 경우 |
|---|---|---|
| CP | MongoDB, HBase, Redis Cluster | 금융, 재고 관리, 예약 |
| AP | Cassandra, DynamoDB, CouchDB | SNS, 로그, 캐시 |
| CA | 단일 노드 RDB (PostgreSQL, MySQL) | 분산이 불필요한 경우 |
CAP 정리의 현실적 해석
실제로는 CAP의 경계가 흑백으로 나뉘지 않습니다. 대부분의 현대 시스템은 일관성 수준을 조절할 수 있습니다.
Cassandra 예시
* ONE: 1개 노드에만 쓰면 성공 → 빠르지만 데이터 유실 위험
* QUORUM: 과반수 노드에 쓰면 성공 → 균형
* ALL: 모든 노드에 써야 성공 → 느리지만 강한 일관성
읽기/쓰기 조합
쓰기 QUORUM + 읽기 QUORUM = 강한 일관성 보장
쓰기 ONE + 읽기 ONE = 최종적 일관성 (빠름)BASE vs ACID
RDB는 ACID를, NoSQL은 BASE를 추구합니다. 둘은 대립하는 것이 아니라 서로 다른 우선순위를 반영합니다.
┌──────────────────────────────────────────────────────┐
│ ACID (전통적 RDB) │
│ │
│ A — Atomicity (원자성) │
│ 트랜잭션은 전부 성공 또는 전부 실패 │
│ "계좌 이체: 출금과 입금이 항상 쌍으로" │
│ │
│ C — Consistency (일관성) │
│ 트랜잭션 전후로 제약 조건이 항상 만족 │
│ "잔액은 음수가 될 수 없다" │
│ │
│ I — Isolation (격리성) │
│ 동시 트랜잭션이 서로 간섭하지 않음 │
│ "다른 사람의 미완료 작업이 보이지 않음" │
│ │
│ D — Durability (지속성) │
│ 커밋된 데이터는 영구적으로 보존 │
│ "서버가 꺼져도 데이터가 사라지지 않음" │
├──────────────────────────────────────────────────────┤
│ BASE (NoSQL) │
│ │
│ BA — Basically Available (기본적 가용성) │
│ 일부 노드가 장애여도 시스템 전체는 응답 │
│ "서버 3대 중 1대가 죽어도 서비스 지속" │
│ │
│ S — Soft state (유연한 상태) │
│ 데이터가 시간에 따라 변할 수 있음 │
│ "복제 지연으로 노드마다 데이터가 다를 수 있음" │
│ │
│ E — Eventual consistency (최종적 일관성) │
│ 시간이 지나면 모든 노드가 같은 상태에 도달 │
│ "지금은 다르지만, 결국은 같아진다" │
└──────────────────────────────────────────────────────┘최종적 일관성의 실제 예시
사용자 A가 프로필 사진 변경
┌──────────────────────────────────────────┐
│ t=0초: 사용자 A가 사진 업로드 │
│ → 노드 1에 즉시 반영 │
│ │
│ t=0.1초: 노드 1 → 노드 2 복제 시작 │
│ 사용자 B(노드 2): 이전 사진 보임│
│ │
│ t=0.5초: 노드 2 복제 완료 │
│ 사용자 B: 새 사진 보임 │
│ │
│ t=1초: 모든 노드 동기화 완료 │
│ → 최종적 일관성 달성 │
└──────────────────────────────────────────┘
이 0.5초의 불일치가 허용되는가?
프로필 사진 — 허용됨 ✅
은행 잔액 — 허용 안 됨 ❌NoSQL이 적합한 경우 vs 부적합한 경우
┌────────────────────────────────────────────────────────┐
│ NoSQL이 적합한 경우 │
│ * 대규모 데이터 + 수평 확장 필요 │
│ * 스키마가 자주 변경되거나 비정형 데이터 │
│ * 초당 수만 건 이상의 읽기/쓰기 │
│ * 최종적 일관성으로 충분한 경우 │
│ * 단순한 키 기반 조회가 대부분인 경우 │
├────────────────────────────────────────────────────────┤
│ RDB가 적합한 경우 │
│ * 복잡한 조인과 관계가 필요한 데이터 │
│ * 강한 일관성과 ACID 트랜잭션이 필수 │
│ * 데이터 무결성이 최우선인 경우 (금융, 의료) │
│ * 복잡한 집계 쿼리와 보고서 │
│ * 데이터 양이 적당하고 관계가 복잡할 때 │
├────────────────────────────────────────────────────────┤
│ 혼합 사용 (Polyglot Persistence) │
│ * 사용자 정보: PostgreSQL (관계형) │
│ * 세션/캐시: Redis (키-값) │
│ * 상품 카탈로그: MongoDB (문서) │
│ * 추천/관계: Neo4j (그래프) │
│ * 로그/이벤트: Elasticsearch (검색 엔진) │
└────────────────────────────────────────────────────────┘NoSQL의 역사적 흐름
| 연도 | 사건 |
| ----- | --------------------------------------------- |
| 2004 | Google BigTable 논문 발표 |
| 2007 | Amazon Dynamo 논문 발표 |
| 2008 | Facebook, Cassandra 개발 시작 |
| 2009 | MongoDB 첫 릴리스 |
| 2009 | "NoSQL" 용어 공식 사용 (Johan Oskarsson 밋업) |
| 2010 | Redis, CouchDB 인기 급상승 |
| 2012 | Google Cloud Spanner (NewSQL) 발표 |
| 2013~ | 다중 모델 DB 등장 (ArangoDB, CosmosDB) |
| 2020~ | 서버리스 DB, 벡터 DB 등 특수 목적 DB 급증 |구글과 아마존의 논문이 NoSQL 혁명의 기폭제가 되었습니다. BigTable은 HBase와 Cassandra에, Dynamo는 DynamoDB와 Riak에 직접적인 영향을 주었습니다.
NewSQL: ACID + 수평 확장
NoSQL의 확장성과 RDB의 ACID를 결합한 새로운 카테고리입니다.
┌──────────────────────────────────────────────────────┐
│ NewSQL = RDB의 장점 + NoSQL의 확장성 │
│ │
│ * SQL 지원: 기존 SQL 쿼리를 그대로 사용 │
│ * ACID 트랜잭션: 분산 환경에서도 일관성 보장 │
│ * 수평 확장: 노드 추가로 성능/용량 확장 │
│ * 자동 샤딩: 데이터를 자동으로 분산 배치 │
│ │
│ 대표적인 NewSQL: │
│ Google Spanner — 글로벌 분산, TrueTime API │
│ CockroachDB — PostgreSQL 호환, 오픈소스 │
│ TiDB — MySQL 호환, PingCAP 개발 │
│ YugabyteDB — PostgreSQL 호환, 분산 SQL │
└──────────────────────────────────────────────────────┘NoSQL의 4대 유형 미리보기
NoSQL은 데이터 모델에 따라 크게 4가지로 분류됩니다. 각 유형은 다음 절에서 상세히 다루지만, 여기서 전체 그림을 먼저 파악합니다.
┌─────────────────────────────────────────────────────────┐
│ 1. 키-값 저장소 (Key-Value Store) │
│ 구조: Key → Value (단순 해시 맵) │
│ 특징: 가장 단순, 가장 빠름 │
│ 대표: Redis, DynamoDB, Memcached │
│ 용도: 캐시, 세션, 실시간 카운터 │
│ │
│ "user:1001" → { name: "김철수", age: 25 } │
├─────────────────────────────────────────────────────────┤
│ 2. 문서 저장소 (Document Store) │
│ 구조: Key → JSON/BSON 문서 │
│ 특징: 문서 내부 필드로 검색/인덱싱 가능 │
│ 대표: MongoDB, CouchDB, Firestore │
│ 용도: 웹/모바일 앱, CMS, 카탈로그 │
│ │
│ { _id: "1001", │
│ name: "김철수", │
│ address: { city: "서울", zip: "06101" }, │
│ orders: [{ item: "책", qty: 2 }] } │
├─────────────────────────────────────────────────────────┤
│ 3. 컬럼 패밀리 (Column-Family) │
│ 구조: Row Key → { Column Family: { Column: Value } } │
│ 특징: 컬럼 단위 저장, 대규모 분석에 유리 │
│ 대표: Cassandra, HBase, ScyllaDB │
│ 용도: 시계열 데이터, 로그, IoT │
│ │
│ Row "user:1001": │
│ profile: { name: "김철수", age: 25 } │
│ activity: { last_login: "2024-03-15", visits: 42 } │
├─────────────────────────────────────────────────────────┤
│ 4. 그래프 (Graph) │
│ 구조: 노드(Node) + 엣지(Edge) + 속성(Property) │
│ 특징: 관계 탐색에 최적화 │
│ 대표: Neo4j, Amazon Neptune, ArangoDB │
│ 용도: 소셜 네트워크, 추천, 사기 탐지 │
│ │
│ (김철수)--[친구]--(이영희)--[구매]--(상품A) │
└─────────────────────────────────────────────────────────┘RDB와 NoSQL 유형별 비교
데이터: "고객 김철수가 책 2권을 주문함"
RDB (관계형)
customers 테이블: (1001, '김철수', '서울')
orders 테이블: (5001, 1001, '2024-03-15')
order_items 테이블: (5001, '책', 2)
→ 3개 테이블, JOIN으로 결합
문서 DB
{ _id: "5001",
customer: { id: 1001, name: "김철수", city: "서울" },
date: "2024-03-15",
items: [{ name: "책", qty: 2 }] }
→ 1개 문서에 모든 정보 포함 (비정규화)
키-값
"order:5001" → "{ customer: 1001, items: [{name:'책', qty:2}] }"
→ 키로만 접근, 내부 구조 무관
그래프
(김철수)--[주문]--(주문5001)--[포함]--(책)
→ 관계 자체가 일급 시민분산 시스템의 핵심 개념
NoSQL을 이해하려면 분산 시스템의 기본 개념을 알아야 합니다.
샤딩 (Sharding)
데이터를 여러 노드에 수평으로 분할하여 저장하는 기법입니다.
해시 샤딩
hash(user_id) % 4 → 노드 번호
user_id=1001 → hash(1001) % 4 = 1 → 노드 1
user_id=1002 → hash(1002) % 4 = 3 → 노드 3
장점: 데이터가 균등하게 분산
단점: 범위 쿼리(WHERE id BETWEEN 1000 AND 2000) 어려움
범위 샤딩
user_id 1~2500 → 노드 1
user_id 2501~5000 → 노드 2
user_id 5001~7500 → 노드 3
user_id 7501~10000 → 노드 4
장점: 범위 쿼리 효율적
단점: 핫스팟(특정 노드에 집중) 발생 가능복제 (Replication)
동일한 데이터를 여러 노드에 복사하는 기법입니다.
마스터-슬레이브 (Primary-Replica):
쓰기 → 마스터만
읽기 → 마스터 + 슬레이브
마스터 장애 → 슬레이브 중 하나가 마스터로 승격
마스터-마스터 (Multi-Primary):
쓰기 → 모든 노드 가능
충돌 해결 로직 필요 (Last Write Wins, Vector Clock 등)핵심 정리
┌────────────────────────────────────────────────────────┐
│ RDB의 한계 │
│ 스케일 아웃 어려움 (조인, 분산 트랜잭션) │
│ 비정형 데이터 처리 비효율 │
│ 스키마 변경 비용 │
├────────────────────────────────────────────────────────┤
│ CAP 정리 │
│ C(일관성) + A(가용성) + P(분할내성) 중 2개만 선택 │
│ CP: MongoDB, HBase (일관성 우선) │
│ AP: Cassandra, DynamoDB (가용성 우선) │
├────────────────────────────────────────────────────────┤
│ ACID vs BASE │
│ ACID: 강한 일관성, 트랜잭션 보장 (RDB) │
│ BASE: 최종적 일관성, 높은 가용성 (NoSQL) │
├────────────────────────────────────────────────────────┤
│ NoSQL 적합: 대규모 + 비정형 + 확장 필요 │
│ RDB 적합: 관계 + ACID + 복잡한 쿼리 │
│ 혼합 사용: Polyglot Persistence (현실적 해답) │
├────────────────────────────────────────────────────────┤
│ NewSQL: ACID + 수평 확장 (Spanner, CockroachDB) │
└────────────────────────────────────────────────────────┘다음 절에서는 NoSQL의 구체적인 유형별 특성(키-값, 문서, 컬럼 패밀리, 그래프)을 다루겠습니다.