새 프로젝트를 시작할 때 어떤 DB를 고를지 빨리 결정해야 하는 순간이 있습니다. 단순히 유명한 제품을 고르면 트랜잭션, 검색, 캐시, 분석 요구가 뒤늦게 충돌합니다. 선택 기준을 정리해두면 팀이 같은 근거로 의사결정할 수 있습니다.
DB 선택은 기술 성능 비교가 아닙니다. 도메인 특성, 쿼리 패턴, 팀의 운영 능력, 일관성 요구사항을 함께 고려해야 합니다. 이 모듈에서는 각 DB의 강점과 약점을 정리하고, 실무에서 반복되는 선택 패턴을 익힙니다.
- 1DB 선택의 핵심 기준 — 쿼리 패턴, 정합성 요구, 운영 비용
- 2관계형 vs 문서형 vs 키-값 — 도메인별 적합한 선택
- 3폴리글랏 퍼시스턴스 — 여러 DB를 함께 사용하는 패턴
- 4CQRS — 쓰기와 읽기 저장소 분리 전략
- 5실무 시나리오별 DB 선택 판단 기준
데이터베이스 선택 기준 — 프로젝트에 맞는 DB 고르기
스타트업 초기에 "빠르게 만들어야 한다"는 이유로 모든 걸 MySQL에 때려박았다. 6개월 뒤, 실시간 피드 조회가 느려지고, 검색 쿼리가 인덱스를 못 타고, 세션 테이블이 DB 부하의 30%를 잡아먹고 있었다. 결국 당시에 팀 전체가 2주를 들여서 Redis와 Elasticsearch로 마이그레이션했다 — 처음부터 올바른 도구를 선택했다면 없었을 작업이었다. DB 선택은 기술 취향의 문제가 아니라 쿼리 패턴과 데이터 특성에 따른 공학적 판단이다. JOIN이 많으면 PostgreSQL, 유연한 문서 구조면 MongoDB, 마이크로초 응답이 필요하면 Redis — 이 기준을 알면 처음부터 맞는 도구를 고를 수 있고, 나중에 갈아엎는 고통을 피할 수 있다.
DB 선택의 핵심 질문 3가지
아키텍처 회의에서 DB를 뭘 쓸지 논쟁이 붙었습니다. "PostgreSQL이 더 빠르다", "MongoDB가 유연하다", "Redis 쓰면 된다"는 말들이 오갑니다. 벤치마크 스펙만 보고 선택하면 나중에 데이터 접근 패턴이 맞지 않아 마이그레이션을 하게 됩니다. DB 선택은 스펙 비교가 아니라 올바른 질문에서 시작됩니다. 어떤 질문을 던지느냐가 선택의 방향을 결정합니다.

스펙이 아닌 질문으로 선택한다
"어떤 DB가 더 빠른가?"는 잘못된 질문입니다. 올바른 질문은 다음 3가지입니다.
① 데이터 관계가 얼마나 복잡한가?
테이블 간 JOIN이 필수인 도메인과 단일 문서로 표현 가능한 도메인은 최적의 DB가 다릅니다.
| 관계 복잡도 | 적합한 DB | 이유 |
|---|---|---|
| 테이블 간 JOIN이 필수 | PostgreSQL, MySQL | 외래키, 트랜잭션, 인덱스 결합 |
| 단일 문서로 표현 가능 | MongoDB | 임베딩으로 JOIN 제거 |
| 키로만 조회 | Redis | 해시맵처럼 단순 K-V |
② 얼마나 강한 일관성이 필요한가?
비즈니스 도메인마다 허용되는 일관성 수준이 다릅니다. 계좌이체는 강한 일관성이 필수지만 좋아요 수는 잠깐 틀려도 됩니다.
강한 일관성 필요 → PostgreSQL (ACID 완전 지원)
예: 계좌이체, 재고 차감
최종 일관성으로 충분 → MongoDB, Cassandra
예: 좋아요 수, 조회수
일관성보다 속도가 중요 → Redis
예: 피드 목록, 세션, 랭킹
③ 쿼리 패턴이 고정인가, 유동적인가?
- 고정 패턴 (주문 조회, 사용자 조회): RDBMS의 정형화된 스키마가 유리
- 유동 패턴 (상품 속성, A/B 테스트 데이터): MongoDB의 유연한 스키마가 유리
- 집계/분석 쿼리: ClickHouse, BigQuery 같은 OLAP DB 고려
도메인별 DB 선택 패턴
이커머스, 소셜, IoT — 도메인마다 데이터 특성과 접근 패턴이 다릅니다. 그런데 "우리도 카카오처럼 하면 된다"는 식으로 남의 아키텍처를 그대로 복사하면 규모와 맥락이 달라 맞지 않습니다. 도메인별로 어떤 DB 조합이 반복적으로 나타나는지 알면, 새 서비스 설계 때 출발점이 생깁니다. 패턴을 아는 것과 모르는 것의 차이는 첫 설계의 품질에서 드러납니다.

실무에서 반복되는 선택 패턴
도메인마다 데이터 접근 패턴이 다르기 때문에 최적의 DB 조합도 달라집니다. 아래 패턴들은 실무에서 가장 자주 등장하는 폴리글랏 구성입니다.
이커머스
주문·결제·재고는 ACID가 필수이므로 PostgreSQL이 핵심이고, 빠른 응답이 필요한 캐시와 검색은 각각 Redis와 Elasticsearch가 담당합니다.
PostgreSQL ← 주문, 결제, 재고 (ACID 필수)
Redis ← 장바구니, 세션, 상품 조회 캐시
Elasticsearch ← 상품 검색, 자동완성
MongoDB ← 상품 상세 (속성이 카테고리마다 다름)
SaaS B2B
조직·사용자·권한처럼 복잡한 관계형 데이터는 PostgreSQL이 담당하고, Rate Limit처럼 TTL이 필요한 임시 데이터는 Redis가 맡습니다.
PostgreSQL ← 조직, 사용자, 권한, 청구 (관계형 + 멀티테넌트)
Redis ← API Rate Limit, 실시간 알림 큐
S3 + PostgreSQL ← 첨부파일 메타데이터
소셜 피드
피드 타임라인은 최신 N개를 O(log N)으로 조회해야 하므로 Redis Sorted Set이 최적이고, 포스트 내용은 미디어·태그 등 구조가 다양해 MongoDB가 유연합니다.
PostgreSQL ← 사용자 계정, 팔로우 관계
Redis Sorted Set ← 타임라인 피드 (ZREVRANGE로 O(log N))
MongoDB ← 포스트 내용 (자유 형식, 미디어 임베딩)
실시간 분석 대시보드
트랜잭션 원본은 PostgreSQL에 두고, 수억 건 집계 쿼리는 OLAP에 특화된 ClickHouse가 초 단위로 처리합니다.
PostgreSQL ← 원본 트랜잭션 데이터
ClickHouse ← OLAP 집계 쿼리 (수억 건도 초 단위)
Redis ← 최근 1시간 지표 캐시
폴리글랏 퍼시스턴스와 CQRS
쓰기는 PostgreSQL에서 하고 읽기는 Redis 캐시에서 합니다. 그런데 캐시 갱신이 늦어 읽기 요청에서 오래된 데이터가 노출됩니다. 검색은 Elasticsearch로 따로 인덱싱하는데 DB와 ES 사이 데이터가 맞지 않을 때가 있습니다. 여러 DB를 함께 쓰면 일관성 유지와 동기화가 새로운 과제가 됩니다. 폴리글랏 퍼시스턴스와 CQRS는 이런 복잡도를 관리하는 설계 패턴입니다.
여러 DB를 함께 쓰는 설계 패턴
폴리글랏 퍼시스턴스 (Polyglot Persistence)
한 서비스 안에서 목적에 맞는 DB를 혼용하는 전략
┌─────────────────────────────────────┐
│ Application │
├──────────┬──────────┬───────────────┤
│ PostgreSQL│ Redis │ MongoDB │
│ (주문/결제)│(캐시/세션)│(상품 상세/로그)│
└──────────┴──────────┴───────────────┘
장점: 각 도메인에 최적화된 DB 사용 단점: 운영 복잡성 증가 (장애 포인트 증가, 팀 숙련도 분산)
결정 기준: 단일 DB로 해결할 수 없는 명확한 이유가 있을 때만 추가
CQRS (Command Query Responsibility Segregation)
쓰기(Command)와 읽기(Query) 저장소를 분리합니다.
사용자 요청
├── 쓰기 (POST /order)
│ └── PostgreSQL (ACID, 정규화)
│ └── 이벤트 발행 →
│ └── Redis / Elasticsearch (읽기 뷰 갱신)
│
└── 읽기 (GET /orders)
└── Redis (캐시) or Elasticsearch (검색 최적화 뷰)
읽기 트래픽이 쓰기보다 10배 이상 많은 서비스에서 효과적입니다.
실습: 시나리오별 DB 선택 판단
다음 시나리오에서 어떤 DB를 고를지 직접 판단해보세요.
시나리오 1: 의료 기록 시스템 — 환자별 진료 기록을 저장하고, 의사가 과거 기록을 시간순으로 조회합니다. 진료 기록 삭제는 절대 불가입니다.
판단 포인트:
- 시간순 조회 → created_at 인덱스
- 삭제 불가 → soft delete + audit log
- 규정 준수 → ACID 필수
→ PostgreSQL (+ 감사 로그용 append-only 테이블)
시나리오 2: 라이브 스트리밍 플랫폼 — 시청자 수를 1초마다 업데이트하고 스트리머 대시보드에 표시합니다.
판단 포인트:
- 초당 업데이트 → 높은 쓰기 빈도
- 정확한 수치보다 빠른 응답이 중요
- 데이터 소실 허용 (±0.1% 오차 무방)
→ Redis INCR (RDBMS에 매초 UPDATE하면 커넥션 병목)
시나리오 3: B2B SaaS 리포트 — 월별 매출, 고객사별 사용량을 집계해서 PDF로 내보냅니다.
판단 포인트:
- 집계 쿼리 (GROUP BY, SUM, 날짜 범위)
- 실시간보다 배치 처리
- 데이터 크기: 수천만 건
→ PostgreSQL (규모 작으면 충분) or ClickHouse (억 단위 이상)
스키마가 자주 바뀐다는 이유로 MongoDB 선택 → 관계형 쿼리 필요해짐
// 처음에는 단순해 보였던 구조
{ user_id: 1, orders: [...] } // 사용자 안에 주문 임베딩
// 6개월 후: "이번 달 특정 상품을 구매한 모든 사용자 목록 뽑아줘"
// → 전체 컬렉션 스캔, 집계 파이프라인으로 복잡한 $unwind + $match 필요
왜 이렇게 됐는가: 초기 요구사항만 보고 DB를 선택했습니다. 비즈니스가 성장하면 분석 쿼리가 반드시 생깁니다.
교훈:
- "스키마가 유연해서 MongoDB" → 잘못된 이유. 스키마 변경은 RDBMS에서 마이그레이션으로 관리 가능
- 예상 쿼리 패턴을 먼저 작성해보고 DB를 선택
- 도메인의 핵심 데이터는 관계형이 거의 항상 유리
이미 MongoDB에 있다면: $lookup(JOIN에 해당)으로 임시 대응하고, 장기적으로 핵심 데이터는 PostgreSQL로 마이그레이션을 계획합니다.
# Redis 재시작 후
redis-cli keys "*"
# (empty array)
# 모든 캐시, 세션, 그리고 잘못 저장한 주문 데이터까지 소멸
실행 완료 또는 조회 결과가 표시됩니다.
- 데이터 성격—관계, 문서, 키-값, 분석 데이터 중 무엇이 중심인지 확인합니다.
- 트래픽 패턴—읽기·쓰기 비율과 확장 방향을 분리해서 봅니다.
- 팀 숙련도—운영 경험이 있는 기술을 우선 후보로 두었는지 점검합니다.
원인: Redis의 기본 설정은 인메모리만 사용합니다. RDB 스냅샷이나 AOF(Append Only File)를 설정하지 않으면 재시작 시 데이터가 사라집니다.
해결: Redis는 캐시·세션·임시 데이터에만 사용하고, 영구 보존이 필요한 데이터는 반드시 RDBMS나 MongoDB에 저장합니다.
# redis.conf에서 영속성 활성화 (캐시 용도가 아닐 때만)
appendonly yes
appendfsync everysec
실무에서 DB 선택 결정이 일어나는 순간
시나리오: 신규 기능 개발 전 아키텍처 리뷰
팀장: "이번에 상품 리뷰 기능 추가하는데, 어디에 저장할까요?"
주니어: "MongoDB요. 리뷰마다 구조가 다를 수 있으니까요."
시니어: "잠깐, 리뷰 조회 패턴이 어떻게 되나요?
- 상품별 리뷰 목록 (product_id로 조회)
- 사용자가 쓴 리뷰 목록 (user_id로 조회)
- 리뷰에 대댓글 기능 예정?
- 구조가 '다를 수 있다'는 게 구체적으로 어떤 부분인가요?"
주니어: "rating이 별점인 상품도 있고 점수인 것도 있어서요..."
시니어: "그건 컬럼 두 개면 해결됩니다. PostgreSQL로 가는 게 낫겠어요.
나중에 '이번 달 평점 4점 이상 리뷰 남긴 사용자에게 쿠폰 발송' 같은
마케팅 쿼리가 반드시 생기거든요. MongoDB에서 그런 집계는 고통스럽습니다."
핵심: DB 선택 전에 "6개월 후 어떤 쿼리가 필요할까?"를 미리 물어보는 것이 중요합니다. 현재 요구사항만으로 결정하면 결국 마이그레이션 비용이 생깁니다.
정리: DB 선택 체크리스트
✅ 데이터 간 관계가 복잡하다 (JOIN 필요) → PostgreSQL/MySQL
✅ ACID 트랜잭션이 필수다 (결제, 재고) → PostgreSQL
✅ 초당 수만 번 읽기, 정확성보다 속도 → Redis
✅ 문서 구조가 진짜로 다양하다 (e-commerce 상품 속성) → MongoDB
✅ 전문 검색, 자동완성이 필요하다 → Elasticsearch
✅ 집계 분석, 수억 건 이상 → ClickHouse, BigQuery
⚠️ "스키마가 유연해서" MongoDB → 잘못된 이유
⚠️ "빠를 것 같아서" Redis를 메인 DB로 → 잘못된 용도
⚠️ 팀이 한 번도 안 써본 DB → 운영 비용 과소평가
다음 모듈에서는 SQL Injection 예방, 최소 권한 접근 제어, 데이터 암호화 등 DB 보안 기초를 다룹니다.