icon

안동민 개발노트

14장 : NoSQL과 분산 데이터베이스

RDB vs NoSQL 선택 기준


RDB와 NoSQL은 어느 쪽이 우월한 것이 아니라, 상황에 따라 최적의 선택이 달라집니다. 실제 현장에서 데이터베이스를 선택할 때는 여러 기준을 종합적으로 고려해야 하며, 때로는 하나의 서비스에서 여러 종류의 데이터베이스를 함께 사용하기도 합니다.

데이터베이스 선택은 프로젝트 초기에 결정해야 하는 가장 중요한 아키텍처 결정 중 하나입니다. 한번 선택하면 변경 비용이 매우 크기 때문에, 현재 요구사항뿐 아니라 향후 성장 방향까지 고려해야 합니다.


데이터 구조에 따른 선택

데이터의 형태는 데이터베이스 선택의 가장 기본적인 기준입니다.

데이터 특성RDBNoSQL
정형 데이터 (테이블 구조)최적가능하지만 비효율
반정형 데이터 (JSON, XML)가능 (JSON 타입)Document DB가 자연스러움
비정형 데이터 (로그, 이미지 메타)부적합Wide-Column, Key-Value
관계 중심 데이터조인으로 처리Graph DB가 더 효율적

선택 의사결정 플로

선택 의사결정 흐름
데이터 구조가 자주 변하는가?
├── Yes → Document DB (MongoDB)
└── No
    ├── 복잡한 조인이 많은가?
    │   ├── Yes → RDB (Oracle, MySQL, PostgreSQL)
    │   └── No
    │       ├── 초고속 읽기/쓰기가 필요한가?
    │       │   ├── Yes → Key-Value (Redis)
    │       │   └── No
    │       │       ├── 관계 탐색이 핵심인가?
    │       │       │   ├── Yes → Graph DB (Neo4j)
    │       │       │   └── No → Wide-Column (Cassandra)
    │       │       └──
    │       └──
    └──

정형 데이터와 RDB

RDB가 최적인 경우
특징:
  * 데이터 구조가 명확하고 변경이 드묾
  * 행과 컬럼으로 자연스럽게 표현됨
  * 무결성 제약이 중요
  * 복잡한 관계와 조인이 필요

예시:
  * 회계 시스템: 차변/대변의 엄격한 구조
  * 인사 관리: 사원-부서-급여의 정형 관계
  * 은행 시스템: 계좌-거래의 ACID가 필수인 구조
  * ERP: 업무 프로세스가 정형화된 시스템

반정형 데이터와 Document DB

Document DB가 적합한 경우
특징:
  * JSON/BSON 형태의 유연한 구조
  * 같은 컬렉션 내 문서마다 구조가 다를 수 있음
  * 스키마 변경이 잦음
  * 중첩된 데이터 구조

예시:
  * 상품 카탈로그: 카테고리마다 속성이 다름
    전자기기: {화면크기, 해상도, 무게}
    의류: {사이즈, 색상, 소재}
    식품: {유통기한, 원산지, 알레르기 정보}
  * CMS: 게시글마다 구조가 다른 콘텐츠
  * 설정 관리: 계층적 JSON 설정 데이터

읽기/쓰기 비율에 따른 선택

애플리케이션의 워크로드 패턴은 데이터베이스 성능에 직접적인 영향을 줍니다.

패턴권장이유
읽기 >> 쓰기 (조회 위주)RDB + 캐시(Redis)인덱스와 캐시로 읽기 최적화
쓰기 >> 읽기 (로그, IoT)Cassandra, 시계열 DB분산 쓰기에 최적화
읽기 ≈ 쓰기 (SNS)MongoDB, DynamoDB유연한 스키마와 균형 잡힌 성능
초고속 읽기 (밀리초 이하)Redis (인메모리)메모리 기반 초저지연

읽기 위주 시스템 최적화

읽기 위주 시스템의 아키텍처
클라이언트
┌──────────┐
│ 요청 시작│
└────┬─────┘

┌────────────┐
│ 캐시(Redis)│
└────┬───────┘
     ├─ 캐시 히트 → 응답 < 1ms
     └─ 캐시 미스 → RDB 조회
                    ┌─────────┐
                    │   RDB   │
                    └─────────┘
                    응답 5~50ms

전략
  1차: 인메모리 캐시 (Redis) → 자주 조회되는 데이터
  2차: 읽기 레플리카 → 읽기 부하 분산
  3차: CDN → 정적 데이터 (이미지, 파일)

쓰기 위주 시스템 최적화

쓰기 위주 시스템의 특성
대량 쓰기 사례:
  * IoT 센서 데이터: 초당 수만 건
  * 로그 수집: 모든 사용자 행동 기록
  * 시계열 데이터: 주식 호가, 서버 메트릭

RDB의 한계:
  * 단일 마스터에 쓰기 집중
  * 트랜잭션 오버헤드
  * 인덱스 유지 비용

NoSQL의 장점:
  * 여러 노드에 쓰기 분산 (Cassandra)
  * 배치 쓰기 최적화
  * 시간 기반 파티셔닝 (시계열 DB)

일관성 vs 가용성

CAP 정리에 따라, 분산 시스템에서는 일관성과 가용성을 동시에 완벽하게 보장할 수 없습니다. 비즈니스 요구에 따라 어느 쪽에 무게를 둘지 결정해야 합니다.

요구사항선택이유
강한 일관성 필수 (금융, 결제)RDB (ACID)데이터 정합성이 최우선
최종적 일관성 허용 (SNS, 로그)NoSQL (BASE)가용성과 성능이 우선
일관성 + 확장성 모두 필요NewSQL (CockroachDB)두 가지를 절충

일관성이 필수인 경우

강한 일관성이 필요한 시나리오
1. 금융 거래
   A계좌 출금과 B계좌 입금이 원자적으로 처리되어야 함
   중간 상태(A만 출금됨)가 관찰되면 안 됨
   → RDB의 ACID 트랜잭션 필수

2. 재고 관리
   마지막 1개 상품을 두 사람이 동시에 주문할 수 없음
   재고가 음수가 되면 안 됨
   → 강한 일관성과 동시성 제어 필요

3. 예약 시스템
   같은 좌석을 두 사람에게 배정하면 안 됨
   → 유니크 제약과 트랜잭션 필요

최종적 일관성이 허용되는 경우

최종적 일관성으로 충분한 시나리오
1. SNS 타임라인
   게시물이 A에게는 보이고 B에게는 아직 안 보여도 괜찮음
   몇 초 후에는 결국 모든 사용자에게 보임
   → 최종적 일관성으로 충분

2. 좋아요 카운터
   정확한 실시간 수치가 아니어도 됨
   "약 1.2만"처럼 근사값이면 충분
   → 비동기 집계로 성능 확보

3. 로그 수집
   일부 로그가 순서가 바뀌어도 분석에 큰 영향 없음
   → 쓰기 성능이 더 중요

확장성에 따른 선택

스케일 업 vs 스케일 아웃
┌─────────────────────────────────────────────────────┐
│ 스케일 업 (Scale Up): 더 강력한 서버 사용           │
│  * CPU, 메모리, 디스크 업그레이드                   │
│  * 하드웨어 한계가 있음 (물리적 제약)               │
│  * RDB에 적합 (아키텍처가 단일 서버에 최적화)       │
│  * 비용: 고성능 서버일수록 기하급수적으로 비싸짐    │
├─────────────────────────────────────────────────────┤
│ 스케일 아웃 (Scale Out): 서버를 여러 대 추가        │
│  * 수평적 확장, 이론상 무한                         │
│  * 범용 서버로 구성 가능 (비용 효율적)              │
│  * NoSQL에 적합 (분산 아키텍처 설계)                │
│  * 복잡도: 데이터 분산과 동기화 로직 필요           │
└─────────────────────────────────────────────────────┘
데이터 규모별 권장 선택
┌────────────────┬─────────────┬───────────────────┐
│ 데이터 규모    │    권장     │       이유        │
├────────────────┼─────────────┼───────────────────┤
│ 수 GB ~ 수 TB  │     RDB     │ 단일 서버로 충분  │
│ 수 TB ~ 수십 TB│ RDB + 샤딩  │ 파티셔닝으로 분산 │
│ 수백 TB 이상   │ NoSQL       │ 네이티브 분산 필요│
│ PB 이상        │Hadoop 생태계│ 배치 처리 중심    │
└────────────────┴─────────────┴───────────────────┘

대부분의 서비스는 수 TB 이내이므로 RDB로 충분합니다.
"우리 서비스가 페이스북 규모가 될 것이다"라고
미리 예측하여 NoSQL을 선택하는 것은 위험합니다.

폴리글랏 퍼시스턴스

폴리글랏 퍼시스턴스(Polyglot Persistence)는 서비스의 각 부분에 가장 적합한 데이터베이스를 선택하여 조합하는 전략입니다. 마이크로서비스 아키텍처에서 자연스럽게 채택됩니다.

폴리글랏 퍼시스턴스 예시 — 이커머스
┌───────────────────────────────────────────┐
│              이커머스 플랫폼              │
├──────────────┬───────────┬────────────────┤
│ 상품 카탈로그│ 주문/결제 │ 추천 엔진      │
│ MongoDB      │ PostgreSQL│ Neo4j          │
│(유연한 스키마)│(ACID 필수)│ (관계 탐색)   │
├──────────────┼───────────┼────────────────┤
│ 세션/캐시    │   검색    │ 로그/분석      │
│ Redis        │ Elastic   │   Cassandra    │
│ (초고속)     │(전문 검색)│ (대량 쓰기)    │
└──────────────┴───────────┴────────────────┘

폴리글랏 퍼시스턴스의 장단점

장단점 분석
장점:
  * 각 영역에 최적화된 DB를 사용하여 성능 극대화
  * 서비스별 독립적 확장 가능
  * 특정 DB 장애가 전체 시스템에 영향을 주지 않음

단점:
  * 여러 DB의 운영/모니터링 복잡도 증가
  * DB 간 데이터 동기화 필요
  * 팀 전체가 여러 DB 기술을 알아야 함
  * 분산 트랜잭션 처리 어려움

도입 시점:
  * 시작은 RDB 하나로 (단순함 유지)
  * 특정 영역에서 RDB의 한계가 분명해지면 해당 영역만 분리
  * "만약을 위해 미리" 도입하는 것은 권장하지 않음

마이그레이션 비용

데이터베이스 선택에서 종종 간과되는 것이 마이그레이션 비용입니다. 처음 선택한 DB에서 다른 DB로 전환하는 것은 단순히 데이터를 옮기는 것이 아니라, 시스템 전체를 재설계하는 것과 같습니다.

RDB → NoSQL 마이그레이션 시 고려사항
1. 데이터 변환
   정규화된 테이블 → 비정규화된 문서로 변환
   조인 관계를 임베딩(embedding)으로 재설계
   기존 데이터 이관 스크립트 작성
   NULL 처리 방식 차이 대응

2. 애플리케이션 코드 변경
   SQL 쿼리 → 각 NoSQL API로 변환
   ORM 코드 전면 수정
   트랜잭션 로직 재설계
   에러 핸들링 패턴 변경

3. 운영 체계 변경
   백업/복구 절차 재수립
   모니터링 도구 변경
   DBA 재교육 또는 새 인력 필요
   장애 대응 매뉴얼 재작성

4. 테스트
   데이터 정합성 검증
   성능 벤치마크
   장애 시나리오 테스트
   부하 테스트로 실제 워크로드 시뮬레이션

마이그레이션 전략

단계적 마이그레이션 접근법
1. 듀얼 라이트 (Dual Write)
   RDB와 NoSQL에 동시에 쓰기
   → 읽기는 점진적으로 NoSQL로 전환
   → 데이터 일관성 검증 기간 확보

2. CDC (Change Data Capture)
   RDB의 변경 로그를 NoSQL로 실시간 동기화
   → 애플리케이션 코드 수정 최소화
   → Debezium 같은 도구 활용

3. 스트랭글러 패턴 (Strangler Pattern)
   새로운 기능부터 NoSQL로 개발
   기존 기능은 점진적으로 마이그레이션
   → 위험 최소화, 점진적 전환

비용과 운영 관점

비용 관점에서의 비교
┌──────────────┬─────────────────┬─────────────────────┐
│     항목     │       RDB       │ NoSQL               │
├──────────────┼─────────────────┼─────────────────────┤
│   라이선스   │ 상용: 비쌈      │ 대부분 오픈소스     │
│              │ 오픈소스: 무료  │ (엔터프라이즈 유료) │
├──────────────┼─────────────────┼─────────────────────┤
│   하드웨어   │ 고성능 단일 서버│ 범용 서버 여러 대   │
│              │ (비싸지만 단순) │ (저렴하지만 수량 多)│
├──────────────┼─────────────────┼─────────────────────┤
│     인력     │ DBA 풍부        │ NoSQL 전문가 부족   │
│              │ SQL 숙련자 많음 │ 기술별 전문성 필요  │
├──────────────┼─────────────────┼─────────────────────┤
│   클라우드   │ RDS, Cloud SQL  │ DynamoDB, Cosmos    │
│   매니지드   │ Aurora          │ Atlas (MongoDB)     │
│              │ (관리 부담 최소)│ (관리 부담 최소)    │
└──────────────┴─────────────────┴─────────────────────┘
운영 관점에서의 비교
모니터링:
  RDB: 성숙한 도구 생태계 (pg_stat, MySQL Enterprise Monitor)
  NoSQL: 제품마다 다른 도구 (MongoDB Compass, Redis Insight)

백업/복구:
  RDB: 표준화된 백업 방식 (pg_dump, mysqldump, RMAN)
  NoSQL: 제품별 고유한 백업 방식, 분산 환경 고려 필요

트러블슈팅:
  RDB: 실행 계획(EXPLAIN), 슬로우 쿼리 로그 등 검증된 도구
  NoSQL: 제품마다 다른 분석 방법, 분산 이슈 디버깅 어려움

보안:
  RDB: 성숙한 접근 제어 (GRANT/REVOKE), 감사 로그
  NoSQL: 초기에 보안이 취약했으나, 최근 크게 개선됨

자주 하는 실수

DB 선택 시 흔한 실수
1. "스케일 문제를 미리 대비하자" → NoSQL 선택
   현실: 대부분의 서비스는 월 사용자 100만도 안 됨
   RDB + 인덱스 최적화면 충분한 경우가 대부분
   → 실제 병목이 확인된 후 전환해도 늦지 않음

2. "NoSQL이 최신이니까 더 좋겠지" → 트렌드 추종
   RDB는 50년 검증된 기술, NoSQL은 아직 20년 미만
   "새로운 것 = 더 좋은 것"은 아님
   → 요구사항에 맞는 기술이 최고의 기술

3. "조인이 느리니까 NoSQL로" → 잘못된 진단
   조인이 느린 원인은 대부분 인덱스 부재 또는 잘못된 쿼리
   NoSQL로 바꿔도 데이터 모델링을 잘못하면 더 느림
   → RDB에서 쿼리 튜닝을 먼저 시도

4. "MongoDB는 스키마가 없으니 편하다" → 착각
   스키마가 없으면 애플리케이션에서 스키마를 관리해야 함
   DB가 하던 검증을 코드에서 해야 하므로 오히려 복잡
   → 스키마 유연성이 진짜 필요한지 확인

5. "팀에 경험자가 없지만 문서를 보며 하면 되겠지"
   운영 중 장애 대응은 경험이 핵심
   프로덕션에서 처음 써보는 DB는 높은 위험
   → 팀의 역량과 경험을 중요한 선택 기준으로

클라우드 시대의 DB 선택

클라우드 매니지드 서비스
AWS:
  * RDS (MySQL, PostgreSQL, Oracle, SQL Server)
  * Aurora (RDB, MySQL/PostgreSQL 호환)
  * DynamoDB (Key-Value/Document)
  * ElastiCache (Redis/Memcached)
  * Neptune (Graph)

GCP:
  * Cloud SQL (MySQL, PostgreSQL, SQL Server)
  * Cloud Spanner (NewSQL, 글로벌 분산)
  * Firestore (Document)
  * Bigtable (Wide-Column)
  * Memorystore (Redis)

Azure:
  * Azure SQL Database
  * Cosmos DB (멀티모델: Document, Graph, Key-Value)
  * Azure Cache for Redis

매니지드 서비스 장점:
  * 설치, 패치, 백업 자동화
  * 고가용성(HA) 기본 제공
  * 모니터링 대시보드 내장
  * 스케일 업/아웃 버튼 하나로

매니지드 서비스 고려사항:
  * 벤더 종속(Lock-in) 위험
  * 세밀한 튜닝이 제한될 수 있음
  * 비용이 셀프 호스팅보다 높을 수 있음

실전 선택 가이드

실제 프로젝트에서 DB를 선택할 때는 기술적 요인뿐 아니라 팀 역량, 비용, 운영 부담 등 비기술적 요인도 함께 고려해야 합니다.

신규 프로젝트 DB 선택 체크리스트
기술적 요인:
□ 데이터 구조가 명확한가? → RDB 우선 고려
□ 스키마 변경이 잦을 예정인가? → Document DB 고려
□ 트랜잭션(ACID)이 필수인가? → RDB 필수
□ 예상 데이터 규모가 TB를 넘는가? → NoSQL 검토
□ 초당 쓰기가 만 건을 넘는가? → NoSQL 검토

비기술적 요인:
□ 팀에 해당 DB 경험자가 있는가? → 매우 중요
□ 커뮤니티와 레퍼런스가 충분한가? → 운영 안정성
□ 매니지드 서비스(클라우드)가 있는가? → 운영 비용
□ 장애 발생 시 대응할 수 있는 역량이 있는가? → 리스크
□ 채용 시장에서 해당 DB 전문가를 구할 수 있는가? → 지속성

업종별 권장 아키텍처

업종별 DB 선택 가이드
┌───────────────┬──────────────────────────────────────┐
│     업종      │ 권장 아키텍처                        │
├───────────────┼──────────────────────────────────────┤
│ 금융/은행     │ Oracle/PostgreSQL (ACID 필수)        │
│               │ + Redis (세션/캐시)                  │
├───────────────┼──────────────────────────────────────┤
│   이커머스    │ MySQL/PostgreSQL (주문/결제)         │
│               │ + MongoDB (상품 카탈로그)            │
│               │ + Redis (캐시) + ES (검색)           │
├───────────────┼──────────────────────────────────────┤
│ SNS/미디어    │ MySQL (사용자/관계)                  │
│               │ + Cassandra (타임라인/피드)          │
│               │ + Redis (캐시) + ES (검색)           │
├───────────────┼──────────────────────────────────────┤
│ IoT/센서      │ 시계열 DB (InfluxDB, TimescaleDB)    │
│               │ + Redis (실시간 대시보드)            │
├───────────────┼──────────────────────────────────────┤
│     게임      │ MySQL (계정/결제)                    │
│               │ + Redis (랭킹/세션/실시간 데이터)    │
│               │ + MongoDB (게임 로그)                │
├───────────────┼──────────────────────────────────────┤
│ 스타트업 MVP  │ PostgreSQL + Redis                   │
│               │ (단순 구조로 빠르게 시작)            │
└───────────────┴──────────────────────────────────────┘
실무에서 자주 보는 조합
조합 1: PostgreSQL + Redis
  → 대부분의 웹 서비스에서 충분
  → RDB로 핵심 데이터, Redis로 캐시/세션

조합 2: PostgreSQL + Elasticsearch
  → 검색 기능이 중요한 서비스
  → RDB로 원본 데이터, ES로 검색 인덱스

조합 3: MySQL + MongoDB + Redis
  → 데이터 특성이 다양한 중대형 서비스
  → RDB로 핵심 비즈니스, MongoDB로 유연한 데이터, Redis로 캐시

핵심 정리

RDB vs NoSQL 선택 핵심 요약
┌────────────────────────────────────────────────────────┐
│ 판단 기준 요약                                         │
│                                                        │
│ RDB를 선택하는 경우                                    │
│  * 데이터 구조가 명확하고 안정적                       │
│  * 복잡한 조인과 트랜잭션(ACID)이 필요                 │
│  * 데이터 무결성이 최우선 (금융, 결제)                 │
│  * 데이터 규모가 TB 이내                               │
│                                                        │
│ NoSQL을 선택하는 경우                                  │
│  * 스키마 변경이 잦고 유연성이 필요                    │
│  * 대량의 데이터를 빠르게 읽고/쓰기 (로그, IoT)        │
│  * 수평 확장(스케일 아웃)이 필수                       │
│  * 최종적 일관성으로 충분한 경우                       │
├────────────────────────────────────────────────────────┤
│ 핵심 원칙                                              │
│  * 시작은 RDB (검증된 기술, 풍부한 생태계)             │
│  * 필요가 분명해지면 특정 영역만 NoSQL 도입            │
│  * 폴리글랏 퍼시스턴스는 성숙한 조직에서만             │
│  * "미리 대비"보다 "필요할 때 도입"                    │
└────────────────────────────────────────────────────────┘

대부분의 서비스는 RDB만으로도 충분합니다. NoSQL은 RDB가 감당하기 어려운 규모나 데이터 특성이 있을 때 도입하는 것이 바람직합니다.

다음 장에서는 실운영 환경에서의 데이터베이스 운영을 다루겠습니다.

목차