MongoDB의 Replica Set(복제)과 Sharding(수평 확장)을 정리합니다.
Replica Set (복제)
Replica Set은 동일한 데이터를 여러 노드에 복제하여 고가용성과 읽기 분산을 제공합니다.
구조
Primary (읽기/쓰기) ──→ Secondary 1 (읽기)
└──→ Secondary 2 (읽기)
└──→ Arbiter (투표만, 데이터 없음, 선택적)
핵심 개념
| 구성 요소 |
설명 |
| Primary |
모든 쓰기를 처리하는 유일한 노드 |
| Secondary |
Primary의 데이터를 복제, 읽기 가능 |
| Arbiter |
투표에만 참여 (데이터 저장 안함, 짝수 노드 시 사용) |
| Oplog |
복제에 사용되는 작업 로그 (capped collection) |
| Election |
Primary 장애 시 자동 선출 |
Replica Set 설정
초기화
// mongosh에서 실행 (Primary가 될 노드)
rs.initiate({
_id: "myReplicaSet",
members: [
{ _id: 0, host: "mongo1:27017" },
{ _id: 1, host: "mongo2:27017" },
{ _id: 2, host: "mongo3:27017" }
]
})
상태 확인
rs.status() // Replica Set 상태
rs.isMaster() // 현재 노드 역할
rs.conf() // 설정 확인
rs.printReplicationInfo() // Oplog 정보
rs.printSecondaryReplicationInfo() // 복제 지연
멤버 관리
// 멤버 추가
rs.add("mongo4:27017")
// Arbiter 추가
rs.addArb("arbiter1:27017")
// 멤버 제거
rs.remove("mongo4:27017")
// 우선순위 변경 (높을수록 Primary 선출 우선)
cfg = rs.conf()
cfg.members[1].priority = 2
rs.reconfig(cfg)
Read Preference (읽기 분산)
| 모드 |
설명 |
| primary |
Primary에서만 읽기 (기본값, 최신 데이터 보장) |
| primaryPreferred |
Primary 우선, 불가 시 Secondary |
| secondary |
Secondary에서만 읽기 |
| secondaryPreferred |
Secondary 우선, 불가 시 Primary |
| nearest |
네트워크 지연이 가장 적은 노드 |
// Secondary에서 읽기
db.users.find().readPref("secondary")
// Connection String에서 지정
// mongodb://mongo1,mongo2,mongo3/mydb?replicaSet=myReplicaSet&readPreference=secondaryPreferred
Write Concern (쓰기 보장 수준)
| 값 |
설명 |
| w: 0 |
확인 안함 (Fire & Forget) |
| w: 1 |
Primary 확인 (기본값) |
| w: “majority” |
과반수 노드 확인 (권장) |
| w: 3 |
3개 노드 확인 |
| j: true |
저널링까지 확인 |
db.users.insertOne(
{ name: "홍길동" },
{ writeConcern: { w: "majority", j: true, wtimeout: 5000 } }
)
Sharding (수평 확장)
Sharding은 데이터를 여러 서버(Shard)에 분산 저장하여 수평 확장을 제공합니다.
구조
Client → mongos (Router) → Config Server (메타데이터)
├→ Shard 1 (Replica Set)
├→ Shard 2 (Replica Set)
└→ Shard 3 (Replica Set)
구성 요소
| 구성 요소 |
설명 |
| Shard |
데이터를 저장하는 노드 (각각 Replica Set) |
| mongos |
클라이언트 요청을 적절한 Shard로 라우팅 |
| Config Server |
클러스터 메타데이터, 청크 매핑 정보 저장 |
| Chunk |
데이터 분할 단위 (기본 128MB) |
| Shard Key |
데이터 분배 기준 필드 |
Shard Key 선택
Shard Key는 한번 설정하면 변경이 어려우므로 신중하게 선택해야 합니다.
| 좋은 Shard Key |
나쁜 Shard Key |
| 높은 카디널리티 |
낮은 카디널리티 (성별, 상태) |
| 균등한 분포 |
단조 증가 (ObjectId, 타임스탬프) |
| 쿼리에 자주 포함 |
쿼리에 사용 안되는 필드 |
Shard Key 전략
| 전략 |
예시 |
장점 |
단점 |
| Hashed |
{ _id: "hashed" } |
균등 분배 |
범위 쿼리 비효율 |
| Ranged |
{ created_at: 1 } |
범위 쿼리 효율 |
핫스팟 가능 |
| Compound |
{ tenant_id: 1, _id: 1 } |
균형 잡힌 분배 |
설계 복잡 |
Sharding 설정
// 1. Sharding 활성화 (mongos에서)
sh.enableSharding("mydb")
// 2. Shard Key로 인덱스 생성
db.orders.createIndex({ user_id: "hashed" })
// 3. 컬렉션 샤딩
sh.shardCollection("mydb.orders", { user_id: "hashed" })
// 상태 확인
sh.status()
db.orders.getShardDistribution()
아키텍처 선택 가이드
| 요구사항 |
권장 구성 |
| 개발/테스트 |
단일 인스턴스 |
| 고가용성 필요 |
Replica Set (3노드) |
| 읽기 분산 |
Replica Set + Read Preference |
| 대용량 데이터 (TB+) |
Sharded Cluster |
| 글로벌 분산 |
Zone Sharding |
관련된 글 (mongodb > lecture-mongodb)