프로젝트에서 어떤 DB를 사용할까? (1)
서론
이전까지는 프로젝트를 진행할 때 특별한 고려사항 없이 그냥 익숙한 DB
인 MySQL
을 사용하였다. MySQL
은 익숙한 RDBMS
였고, NoSQL
에 익숙하지 않았기 때문이다.
하지만 이전 프로젝트를 진행하면서 RDBMS
의 한계를 느낀 부분이 바로 게시판에서의 검색 기능이었다. MySQL
은 LIKE
, FULLTEXT
인덱스 기능 제한적, 집계 성능 저하 등의 문제가 있었고, 이는 NoSQL
중 하나인 Elastic Search
를 사용하여 역색인(inverted index
) 기반 실시간 풀텍스트 검색으로 해결할 수 있었다.
이를 통해 지금까지는 쿼리 최적화, 비동기 처리 등을 통해 성능 개선을 이루어냈지만, 성능을 위해서 서비스 특성에 맞는 데이터베이스를 선택하는 것이 중요하다는 것을 깨달았다.
그렇다면 어떤 상황에서 어떤 DB를 선택해야 될까? 이번 포스팅에서는 여러 종류의 데이터베이스가 어떤 특징이 있고, 실제 프로젝트에서 어떻게 선택하면 좋을지 알아보도록 하겠다.
RDB(관계형 데이터베이스)
개요
- RDB
는 행(Row)과 열(Column)로 이루어진 테이블 형태로 데이터를 저장
- 엑셀 시트처럼 직관적인 구조
- 여러 테이블 간에 키(Key)를 통해 서로 연관 관계를 설정
핵심 특징 - ACID 트랜잭션
- Atomicity
: 트랜잭션 내 모든 작업이 모두 성공하거나, 하나라도 실패하면 전부 취소
- Consistency
: 트랜잭션 전·후 데이터 일관성 유지
- Isolation
: 동시성 제어로 트랜잭션 간 간섭 방지
- Durability
: 커밋된 트랜잭션은 시스템 오류에도 영구히 보존
- 은행 송금 예시
* A 계좌에서 100원을 출금
* B 계좌에 100원 입금
* 중간에 장애 발생 → 둘 중 하나만 적용되는 상태를 방지하고, 모두 롤백
장점
- 강력한 데이터 무결성 : 외래 키(FK), 제약 조건(Unique, Not Null)으로 데이터 정합성 보장
- 복잡한 관계형 쿼리 지원 : JOIN, 서브쿼리, 뷰(View), CTE(Common Table Expression) 등
- 성숙한 생태계 : 다양한 오픈소스·상용 솔루션과 커뮤니티 지원
- Managed 서비스 제공 : AWS Aurora, Azure SQL Database 등
단점 및 고려사항
- 스키마 변경 비용 : ALTER TABLE 시 테이블 락(lock) 발생 가능
- 수평 확장(Scale-out) 한계 : 마스터-리플리카 구조에서 쓰기 병목
- 대용량 분석 워크로드 : 수십억 건 이상의 데이터 처리 시 디스크 I/O 및 복잡 쿼리 성능 저하
대표 제품 및 서비스
- 오픈소스 : MySQL, PostgreSQL, MariaDB
- 상용 : Oracle Database, Microsoft SQL Server
- 클라우드 : Amazon Aurora, Google Cloud SQL, Azure SQL
언제 RDB를 선택?
- 엄격한 트랜잭션 보장이 필요한 금융, 주문처리 시스템
- 복잡한 관계형 쿼리를 빈번히 수행하는 백오피스·ERP
- 스키마가 안정적이고 큰 구조 변경이 드문 서비스
NoSQL
종류
Columnar Database
Document Database
Graph Database
Key-Value Database
Time-Series Database
+ Vector Database
Columnar Database - 빅데이터 분석
개요
- 컬럼 단위 저장 : 데이터를 행(Row)이 아닌 열(Column) 단위로 물리 저장
- 예시
* RDB: 한 학생의 모든 과목 점수를 한 행에 저장
* 컬럼 DB: ‘수학’ 열에 전교생의 수학 점수만 연속 저장
핵심 특징
- 열 단위 I/O 최적화 : 분석할 때 필요한 열만 골라 읽음 → 불필요한 디스크 읽기 최소화
- 높은 압축 효율 : 같은 열의 값끼리 연속 저장되므로 데이터 패턴이 유사 → 컬럼별 압축률 ↑
- 분산 처리 친화적 : 노드 간에 열 단위로 파티셔닝 가능 → 대규모 분석 워크로드 수평 확장
장점
- 대규모 집계 연산에 최적화 : 평균·합계·카운트 같은 OLAP 쿼리 성능 극대화
- 낮은 디스크 I/O : 필요한 열만 읽기 때문에 디스크 대역폭 절약
- 우수한 압축률 : 컬럼별 특성에 맞춰 압축 알고리즘 적용
- 손쉬운 확장성 : 노드 추가만으로 처리량 및 저장용량 확보
단점 및 고려사항
- 행(레코드) 기반 업데이트 비효율 : 전체 행을 건드려야 하므로 쓰기·수정 성능 저하
- 실시간 트랜잭션(OLTP)에 부적합 : 짧은 대기 시간, 자주 변경되는 데이터 처리에는 RDBMS가 더 적합
- 복잡한 행 스캔 비용 : 여러 열을 한 번에 참조해야 할 때 디스크 I/O가 증가
대표 제품 및 서비스
- 클라우드 기반 : Amazon Redshift, Google BigQuery, Azure Synapse Analytics
- 오픈소스 컬럼형 : ClickHouse, Apache Druid, Apache Kudu
- 컬럼 패밀리형 : Apache HBase, Apache Cassandra (Wide-Column Store)
언제 컬럼형 DB를 선택?
- 데이터 웨어하우스/BI : 대시보드용 대규모 집계 쿼리
- 로그·시계열 분석 : 수억~수십억 건 로그에서 빠른 통계 산출
- ETL 파이프라인 : 배치성 데이터 처리 후 고속 보고서 생성
- OLAP 워크로드 : 다차원 분석, 리포트, 머신러닝 피처 엔지니어링
Document Database - 유연한 데이터 구조의 강자
개요
- 문서(Document) 단위로 데이터를 저장하는 NoSQL 계열 데이터베이스
- JSON, BSON, XML 같은 유연한 포맷을 그대로 보관
- 스키마리스(schema-less) 특성으로 다양한 속성을 가진 데이터를 손쉽게 관리
핵심 특징
- 스키마 유연성 : 필드 추가·제거에 테이블 마이그레이션 불필요
- 중첩 구조 : 배열, 객체(Object) 형태의 중첩 데이터도 자연스럽게 표현
- 스키마 진화 : 서비스 요구사항 변화에 따라 문서 구조를 자유롭게 확장
- 분산 처리 : 샤딩(sharding) 기반으로 노드 추가 시 수평 확장 용이
장점
- 다양한 도메인 모델링 : 상품, 사용자 프로필, 로그 등 속성별 편차가 큰 데이터에 적합
- 개발 생산성 향상 : 객체지향 언어의 DTO/POJO를 JSON으로 곧바로 직렬화
- 빠른 프로토타이핑 : 초기 요구사항 분석 없이도 문서 구조를 곧바로 저장 후 개선 가능
- 읽기 성능 최적화 : 단일 문서 조회 시 JOIN 없이 관련 데이터 일괄 반환
단점 및 고려사항
- 데이터 정합성 관리 : 스키마가 자유로운 만큼 누락·오타 데이터 주의, 공통 필드에 대한 가이드라인(Validation, Schema Registry) 권장
- 관계 탐색 제약 : 복잡한 조인(Join)·재귀 탐색은 한계가 있어, 관계형 DB나 그래프 DB 보완 필요
- 인덱스 설계 : 잘못된 인덱스 설정 시 쓰기 성능 저하 발생 가능
문서 예시 - json
// 의류 상품 예시
{
"product_id": "A1234",
"category": "의류",
"name": "데님 재킷",
"size": ["S", "M", "L"],
"color": ["blue", "black"],
"material": "denim",
"price": 79000
}
- 필요한 필드만 문서에 포함 → 불필요한 NULL 필드 없음
- 중첩 객체 및 배열로 복잡한 속성 표현 가능
대표 제품
- MongoDB (가장 널리 사용)
- Couchbase
- Amazon DocumentDB
- RavenDB
Graph Database
개요
- 노드(Node)와 엣지(Edge) 구조로 데이터를 모델링
- 노드는 엔티티(사용자, 제품, 장소 등), 엣지는 노드 간의 관계(친구, 팔로우, 거래 등)를 나타냄
- 복잡한 연결성 (소셜 네트워크, 추천 시스템, 권한 계층 등) 을 직관적으로 표현
핵심 특징
- 그래프 탐색 최적화 : 깊이 우선·너비 우선 탐색, 최단 경로, 서브그래프 추출 등이 네이티브로 지원
- 스키마 유연성 : 노드·엣지에 필요한 속성(Property)을 자유롭게 추가 가능
- 패러다임 적합성 : 객체지향·관계지향 모델보다 관계 위주의 도메인에 자연스러운 매핑
- 분산 처리 : 대규모 그래프도 샤딩·파티셔닝으로 수평 확장
장점
- 고속의 관계 쿼리 : JOIN 없이 인접 노드 탐색만으로 복잡한 관계 추적
- 직관적인 데이터 모델링 : 도메인 개념(사람·사물·행위)을 그래프로 표현 → 설계 가시성 ↑
- 다양한 그래프 알고리즘 내장 : 커뮤니티 탐지, PageRank, 유사도 계산 등
- 유연한 속성 관리 : 노드·엣지 단위로 속성 추가·삭제 → 스키마 변경 부담 ↓
단점 및 고려사항
- 트랜잭션 처리 한계 : 일부 그래프 DB는 ACID 보장 범위가 제한적
- 운영 복잡도 : 대규모 분산 그래프 파티셔닝 설계가 까다로울 수 있음
- 학습 곡선 : Cypher, Gremlin 같은 전용 쿼리 언어 학습 필요
- 정형 데이터 분석 부적합 : 단순 집계·통계 쿼리는 컬럼형 또는 시계열 DB가 더 효율적
활용 사례
- 소셜 네트워크 : 친구 추천, 인맥 탐색
- 추천 시스템 : 사용자-상품 그래프 기반 유사 사용자/상품 추출
- 사기 탐지 : 거래 간 연관성 분석으로 이상 패턴 식별
- 지식 그래프 : 개체(Entity) 간 의미 관계 저장·질의
- 페이스북 : 친구·페이지·그룹 구조를 그래프로 모델링하여 “추천 친구” 기능 구현
- LinkedIn : 인맥 그래프 기반 “People You May Know” 추천
대표 제품
- 오픈소스 : Neo4j, JanusGraph, Apache TinkerPop (Gremlin)
- 클라우드 및 상용 : Amazon Neptune, Azure Cosmos DB (Gremlin API), TigerGraph
Key-Value Database
개요
- Key–Value 쌍으로 데이터를 저장하는 아주 단순한 구조
- 대부분 인메모리(in-memory) 저장소로 동작해 서브밀리초 수준의 읽기·쓰기 성능을 제공
- TTL(Time-To-Live), 만료 정책, LRU 제거 등 캐시 기능 내장
핵심 특징
- 단순성 : 키 하나만으로 즉시 값 조회
- 인메모리 우선 : 디스크 I/O 없이 메모리에서 바로 처리(백업·영속화 옵션 제공)
- 수평 확장 : 샤딩(sharding)·클러스터 모드로 노드 추가만으로 용량·처리량 확대
- 만료 정책 : Key별 TTL 설정 및 LRU(Least-Recently-Used) 자동 제거
장점
- 초고속 응답 : 로그인 세션·설정·캐시 조회처럼 실시간성이 중요한 워크로드에 최적
- 운영 용이성 : 복잡한 스키마 설계 없이 바로 사용 가능
- 다양한 활용 : 분산 잠금 분산 카운터, 메시지 큐 등으로도 활용
단점 및 고려사항
- 데이터 모델 단순 : 복잡한 조건 탐색·관계형 조인 불가
- 내구성 옵션 필요 : 기본은 메모리 저장 → 장애 복구·내구성 보장을 위해 AOF/RDB 스냅샷 등 설정 권장
- 데이터 크기 관리 : 무제한 저장 시 메모리 과다 사용 위험
대표 제품
- Redis: 캐시, 세션 스토어, 분산 잠금, 스트림 처리 등 멀티모달 활용
- Memcached: 순수 캐시용 경량 솔루션
- Amazon DynamoDB (Key-Value 모드): AWS Managed 서비스, 서버리스 확장
- etcd: Kubernetes 클러스터 상태 저장용 내장 Key-Value 저장소
활용 사례
- 세션 관리
* Key: session:user:12345
* Value: 사용자 로그인 정보(JSON)
- 캐시 레이어 : 빈번 조회되는 API 응답, 설정값, 추천 결과 등
- 게임 서버 : Key - player:state:67890 → 실시간 위치·스코어·버프 상태 저장
- 쇼핑카트 : 아마존은 DynamoDB로 사용자 장바구니 데이터 고가용성 처리
Time-Series Database
개요
- 시간(timestamp)이 붙은 연속적인 데이터 저장·처리에 최적화된 비관계형 데이터베이스
- 센서, 모니터링, 메트릭, 로그 등 시계열 데이터 워크로드를 주로 다룸
핵심 특징
- 고집적 쓰기 처리 : 초당 수천~수만 건의 시계열 데이터 연속 저장
- 자동 다운샘플링 : 오래된 데이터는 집계(예: 1분→1시간 평균) 후 보관
- 효율적 압축 : 자주 변하지 않는 필드는 delta or Gorilla 압축 등으로 저장 공간 절감
- 시계열 특화 쿼리 : 특정 기간 최대·최소·평균, 이상치 탐지(예: “CPU 90% 초과 시점”), 윈도우 함수 기반 집계
장점
- 실시간 모니터링 : 대시보드·알림 시스템의 기초가 되는 초저지연 데이터 조회
- 데이터 보존 정책 : retention policy로 저장 기간 관리 → 스토리지 부담 경감
- 스케일 아웃 : 노드 추가만으로 쓰기·읽기 처리량 확장
- 풍부한 분석 기능 : downsample, histogram, percentile, derivative 등 내장
단점 및 고려사항
- 복잡한 관계 모델링 부적합 : 시계열 외 다른 도메인 데이터와 JOIN 등 어려움
- 운영 부담 : 샤딩·리텐션 정책·백업 전략 설계 필요
- 롤업 시 계산 비용 : 다운샘플링 주기가 짧을수록 자원 소비↑
대표 제품
- 오픈소스 TSDB : InfluxDB, TimescaleDB, OpenTSDB
- 모니터링 통합 플랫폼 : Prometheus, VictoriaMetrics
- 클라우드 매니지드 : AWS Timestream, Azure Data Explorer
활용 사례
- 서버 모니터링 : CPU 사용률, 메모리·디스크·네트워크 트래픽 실시간 그래프
- IoT 센서 수집 : 스마트 팜·스마트 팩토리의 온습도·작동 로그
- 금융 시계열 : 주식·암호화폐 가격, 주문 체결 기록
- 애플리케이션 성능 관리(APM) : 지연 시간, 실패율, QPS 지표
Vector Database
개요
- 임베딩(Embedding)을 통해 텍스트·이미지·음성·동영상 등 비정형 데이터를 고차원 벡터로 변환하여 저장
- 벡터 간의 거리 계산(유클리드, 코사인 유사도 등)으로 유사도 검색에 특화
핵심 특징
- 고속 근사 최근접 이웃 검색(ANN) : 대규모 벡터셋에서도 실시간 유사도 조회
- 스케일 아웃 : 샤딩·파티셔닝으로 벡터 차원과 수 증가에 유연 대응
- 메타데이터 연동 : 각 벡터에 원본 ID나 속성 정보 연결 가능
- 지속적 업데이트 : 신규 벡터 추가·삭제가 자주 일어나도 성능 저하 최소화
장점
- 정밀한 검색 경험 : “이 이미지와 비슷한 이미지”, “이 질문과 의미가 유사한 문장” 탐색에 최적
- RAG(Retrieval-Augmented Generation) 지원 : LLM이 모르는 최신·사내 정보 등을 벡터 DB에서 찾아와 답변 품질 향상
- 다양한 데이터 타입 처리 : 텍스트 임베딩, 이미지 특징 벡터, 음성 스펙트럼 등 이종 데이터 통합 검색 가능
- 운영 부담 경감 : 복잡한 전처리 없이 “벡터만 넣고 검색”하면 되므로 개발 생산성↑
단점 및 고려사항
- 임베딩 품질 종속 : 벡터 생성 모델 성능이 검색 품질을 좌우
- 스토리지 비용 : 고차원 벡터 다량 저장 시 디스크·메모리 요구량↑
- 일관성 모델 : 분산된 클러스터 간 동기화 전략 필요
- 메타데이터 인덱싱 : 벡터 외 부가 속성 검색을 원할 땐 별도 인덱스 설계
대표 제품 및 활용 기업
- Pinecone : MS, 액센츄어, 노션 등 대형 기업의 RAG·추천 시스템에 활용
- Milvus : 세일즈포스, 그랩 등에서 이미지·문서 검색 파이프라인에 도입
- Weaviate : 디스코드, 존슨앤존슨, 퍼플렉시티 등에서 유사 문맥 검색·QA 시스템 구축
- Qdrant : 실시간 추천·검색 서비스에 적합한 경량 오픈소스 솔루션
- Amazon Kendra : AWS 관리형 서비스로, 기업 문서 검색용 RAG 워크로드 지원
활용 사례
- 콘텐츠 추천 : 넷플릭스 시청 이력 → 유사 콘텐츠 자동 추천
- 이미지 검색 : 핀터레스트 “이와 비슷한 이미지” 탐색 기능
- 챗봇 강화(RAG) : 기업 내부 문서·제품 매뉴얼을 벡터화해 LLM에 제공
- 지식 그래프 보강 : 엔터티 임베딩을 통해 연관성 기반 질의 응답
간단 예시
// 문서 임베딩 저장 예시
{
"id": "doc-1001",
"vector": [0.123, -0.987, …, 0.456],
"metadata": {
"title": "제품 소개서",
"category": "마케팅"
}
}
→ 검색 쿼리도 임베딩 벡터로 변환 후, “vector similarity” API 호출
그래서 언제, 어떤 DB를 사용해야 할까?
그렇다면 언제 어떤 DB를 사용해야 할까? 새로운 DB를 도입하거나, 교체할 때는 합당한 이유가 있어야 한다. 괜히 새로운 기술을 도입해보려다가는 운영 안정성이나 비용 측면에서 손해를 볼 수 있기 때문이다.
그리고 새로운 DB로 교체할 때는 지금 사용하는 DB에서도 문제를 해결할 수 있는지부터 확인해야 한다. 예를 들어, RDB라면 테이블에 적절한 인덱스를 추가하거나, 쿼리 최적화를 하면 속도를 크게 개선할 수 있다.
아니면 DB 딴에서가 아닌 캐싱 레이어를 추가해서 자주 쓰는 데이터를 메모리에서 처리하면, 데이터베이스 본체에 가해지는 부하를 줄일 수도 있다.
하지만 새로운 DB를 도입하고자 한다면 가장 우선적으로 고려해야할 것은 현재 서비스가 어떤 유형의 데이터를 다루고, 어떤 기능을 필요로 하는가?
이다.
- RDB
: 금융이나 재고처럼 트랜잭션 안정성이 매우 중요한 분야일 때
- Columnar Database
: 대규모 로그나 분석 같은 통계성 작업을 빠르게 처리해야 할 때
- Document Database
: 상품 속성이 각기 다를 때
- Graph Database
: 소셜 관계나 추천 시스템처럼 복잡한 연결고리를 찾야 할 때
- Key-Value Database
: 세션이나 캐싱처럼 단순 조회가 중요할 때
- Time-Series Database
: 시간대별로 쌓이는 로그나 센서 데이터일 때
- Vector Database
: AI나 ML 모델을 쓰고 있을 때
이처럼 DB마다 장단점이 확실하고, 서비스 유형에 맞게 적절한 DB가 다르다. 따라서 우리는 서비스 상황에 맞게 가장 적합한 DB를 선택해야 한다. 아니면 하나의 시스템에서 여러 DB를 함께 사용하는 경우도 있다.
후기
이번 포스팅에서는 여러 DB들의 특성과 장단점에 대해서 알아보았다. 프로젝트에서 서비스에 적합한 DB를 선택하는 것이 성능 측면에서 중요하다. 지금까지 나는 서비스 특성을 고려하지 않고 RDB 중 MySQL만을 써왔다. 하지만 이번 포스팅을 쓰면서 여러 DB들에 대해서 공부하게 되었고, 어떤 상황에서 어떤 DB를 선택하면 좋을지 알게 되었다. 그래서 현재 진행하고 있는 HomeProtector
프로젝트에서는 MySQL을 사용하지 않고 다른 DB를 사용하게 되었다. 서비스 기능이 뭐가 있고, 어떤 상황이라서 어떤 DB를 사용하는지는 다음 포스팅에서 알아보도록 하겠다.