데이터베이스 선택 가이드 | SQL vs NoSQL 완벽 비교
이 글의 핵심
데이터베이스 선택 가이드입니다. SQL과 NoSQL을 비교하고 프로젝트별 최적의 데이터베이스 선택 기준을 제시합니다.
들어가며: 데이터베이스 선택의 중요성
”어떤 데이터베이스를 선택해야 할까?”
데이터베이스 선택은 프로젝트의 성공을 좌우합니다. 잘못된 선택은 나중에 마이그레이션 비용으로 돌아옵니다.
이 글에서 다루는 것:
- SQL vs NoSQL 차이
- 주요 데이터베이스 비교 (MySQL, PostgreSQL, MongoDB, Redis)
- 사용 사례 및 선택 기준
- 성능 및 확장성
목차
1. SQL 데이터베이스
SQL이란?
SQL(Structured Query Language) 데이터베이스는 정형화된 스키마와 관계형 모델을 사용합니다.
SQL 데이터베이스 구조:
graph TB
A[데이터베이스] --> B[테이블: users]
A --> C[테이블: posts]
A --> D[테이블: comments]
B --> B1[id PK]
B --> B2[name]
B --> B3[email]
C --> C1[id PK]
C --> C2[user_id FK]
C --> C3[title]
C --> C4[content]
D --> D1[id PK]
D --> D2[post_id FK]
D --> D3[user_id FK]
D --> D4[content]
C2 -.참조.-> B1
D2 -.참조.-> C1
D3 -.참조.-> B1
MySQL
특징:
- 가장 인기 있는 오픈소스 RDBMS
- 읽기 성능 우수
- 웹 애플리케이션에 적합
예제:
-- 테이블 생성
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 데이터 삽입
INSERT INTO users (name, email) VALUES
('Alice', '[email protected]'),
('Bob', '[email protected]');
-- 조회
SELECT * FROM users WHERE name LIKE 'A%';
-- 조인
SELECT users.name, posts.title
FROM users
INNER JOIN posts ON users.id = posts.user_id;
장점:
- ✅ 빠른 읽기 성능
- ✅ 풍부한 생태계
- ✅ 쉬운 설정
단점:
- ❌ 복잡한 쿼리 성능 제한
- ❌ 수평 확장 어려움
PostgreSQL
특징:
- 고급 기능 지원 (JSON, 전문 검색, GIS)
- ACID 완벽 지원
- 복잡한 쿼리에 강함
예제:
-- JSON 지원
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
attributes JSONB
);
INSERT INTO products (name, attributes) VALUES
('Laptop', '{"brand": "Apple", "ram": 16, "ssd": 512}');
-- JSON 쿼리
SELECT * FROM products
WHERE attributes->>'brand' = 'Apple'
AND (attributes->>'ram')::int >= 16;
-- 전문 검색
CREATE INDEX idx_name_fts ON products USING gin(to_tsvector('english', name));
SELECT * FROM products
WHERE to_tsvector('english', name) @@ to_tsquery('laptop');
장점:
- ✅ 고급 기능 (JSON, 배열, GIS)
- ✅ 확장성 (Extension)
- ✅ 표준 SQL 준수
단점:
- ❌ MySQL보다 복잡
- ❌ 설정 어려움
2. NoSQL 데이터베이스
NoSQL 종류
graph TB
A[NoSQL] --> B[Document MongoDB]
A --> C[Key-Value Redis]
A --> D[Column Cassandra]
A --> E[Graph Neo4j]
B --> B1[JSON 문서]
C --> C1[키-값 쌍]
D --> D1[컬럼 패밀리]
E --> E1[노드-엣지]
MongoDB (Document DB)
특징:
- JSON 형식 문서 저장
- 유연한 스키마
- 수평 확장 (Sharding)
예제:
// 문서 삽입
db.users.insertOne({
name: "Alice",
email: "[email protected]",
age: 30,
interests: ["coding", "music"],
address: {
city: "Seoul",
country: "Korea"
}
});
// 조회
db.users.find({ age: { $gte: 25 } });
// 배열 쿼리
db.users.find({ interests: "coding" });
// 중첩 문서 쿼리
db.users.find({ "address.city": "Seoul" });
// 집계 (Aggregation)
db.users.aggregate([
{ $match: { age: { $gte: 25 } } },
{ $group: { _id: "$address.city", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
]);
장점:
- ✅ 유연한 스키마
- ✅ 수평 확장 쉬움
- ✅ 빠른 개발
단점:
- ❌ 조인 성능 낮음
- ❌ 트랜잭션 제한적
- ❌ 메모리 사용량 많음
Redis (Key-Value Store)
특징:
- 인메모리 저장소
- 초고속 읽기/쓰기
- 캐시, 세션, 큐로 사용
예제:
# 문자열
SET user:1:name "Alice"
GET user:1:name # "Alice"
# 해시
HSET user:1 name "Alice" email "[email protected]"
HGET user:1 name # "Alice"
HGETALL user:1 # name: Alice, email: [email protected]
# 리스트 (큐)
LPUSH queue:tasks "task1"
LPUSH queue:tasks "task2"
RPOP queue:tasks # "task1"
# 셋
SADD tags:1 "python" "coding" "tutorial"
SMEMBERS tags:1 # ["python", "coding", "tutorial"]
# 정렬된 셋 (리더보드)
ZADD leaderboard 100 "Alice"
ZADD leaderboard 200 "Bob"
ZREVRANGE leaderboard 0 9 # 상위 10명
장점:
- ✅ 초고속 (마이크로초 단위)
- ✅ 다양한 자료구조
- ✅ Pub/Sub 지원
단점:
- ❌ 메모리 제한
- ❌ 복잡한 쿼리 불가
- ❌ 주 데이터베이스로 부적합
3. 비교 분석
SQL vs NoSQL 비교표
| 특징 | SQL | NoSQL |
|---|---|---|
| 스키마 | 고정 (Rigid) | 유연 (Flexible) |
| 확장 | 수직 (Scale-up) | 수평 (Scale-out) |
| 트랜잭션 | ACID 완벽 | BASE (제한적) |
| 조인 | 우수 | 제한적 |
| 쿼리 | 복잡한 쿼리 가능 | 단순 쿼리 |
| 일관성 | 강한 일관성 | 최종 일관성 |
성능 비교
읽기 성능 (10만 개 레코드):
단순 조회 (id로 검색):
1. Redis: 0.1ms ⭐
2. MongoDB: 1ms
3. MySQL: 2ms
4. PostgreSQL: 3ms
복잡한 조인 (3개 테이블):
1. PostgreSQL: 50ms ⭐
2. MySQL: 80ms
3. MongoDB: 200ms (조인 약함)
확장성 비교
graph LR
A[수직 확장 Vertical] --> B[더 큰 서버]
A --> C[CPU/RAM 증설]
D[수평 확장 Horizontal] --> E[서버 추가]
D --> F[샤딩 Sharding]
G[SQL] -.어려움.-> D
G -.쉬움.-> A
H[NoSQL] -.쉬움.-> D
H -.쉬움.-> A
4. 선택 가이드
선택 플로우차트
flowchart TD
A[데이터베이스 선택] --> B{정형 데이터?}
B -->|예| C{복잡한 쿼리?}
B -->|아니오| D[NoSQL]
C -->|예| E[PostgreSQL]
C -->|아니오| F[MySQL]
D --> G{주 용도는?}
G -->|문서 저장| H[MongoDB]
G -->|캐시| I[Redis]
G -->|시계열| J[InfluxDB]
G -->|그래프| K[Neo4j]
시나리오별 권장
1. 전자상거래 (E-commerce)
- PostgreSQL: 트랜잭션, 재고 관리
- Redis: 장바구니, 세션
- 예: 주문, 결제, 재고
2. 소셜 미디어
- MongoDB: 게시글, 댓글 (유연한 스키마)
- Redis: 피드 캐시, 실시간 알림
- 예: 페이스북, 트위터
3. 분석 플랫폼
- PostgreSQL: 집계 쿼리
- InfluxDB: 시계열 데이터
- 예: 대시보드, 리포트
4. 실시간 채팅
- MongoDB: 메시지 저장
- Redis: 온라인 사용자, Pub/Sub
- 예: Slack, Discord
5. 콘텐츠 관리 시스템 (CMS)
- PostgreSQL 또는 MySQL: 구조화된 콘텐츠
- MongoDB: 유연한 콘텐츠 타입
- 예: WordPress, Strapi
5. 정리
핵심 요약
SQL (MySQL, PostgreSQL):
- 정형화된 스키마
- 복잡한 쿼리, 조인
- ACID 트랜잭션
- 수직 확장
NoSQL (MongoDB, Redis):
- 유연한 스키마
- 단순 쿼리
- 수평 확장
- 최종 일관성
데이터베이스 선택 기준
| 우선순위 | 선택 |
|---|---|
| 트랜잭션 | PostgreSQL |
| 복잡한 쿼리 | PostgreSQL |
| 빠른 개발 | MongoDB |
| 수평 확장 | MongoDB |
| 캐시 | Redis |
| 시계열 | InfluxDB |
하이브리드 접근
많은 프로젝트에서 여러 데이터베이스를 조합합니다.
PostgreSQL (주 데이터베이스)
├─ 사용자, 주문, 결제
Redis (캐시)
├─ 세션, 장바구니
MongoDB (로그)
├─ 애플리케이션 로그, 이벤트
다음 단계
각 데이터베이스의 자세한 사용법은 아래 글을 참고하세요:
- PostgreSQL C++ 연동
- MongoDB C++ 드라이버
- Redis C++ 연동
관련 주제:
- 데이터베이스 인덱싱
- 트랜잭션 관리
- 데이터베이스 최적화