MongoDB 문서 모델과 분산 운영 설계

MongoDB의 BSON 문서 모델, 복제셋과 샤딩 아키텍처, 인덱스·트랜잭션·GridFS 설계와 운영 최적화 기준을 다룬다.

2026-08-14 · 최초 발행 2025-10-14

문서 구조로 정형·비정형 데이터를 함께 다루기

MongoDB는 정형·비정형 데이터 구조를 문서지향 데이터모델(Document-Oriented Data Model)로 통합하는 오픈소스 분산 NoSQL이다. RDBMS의 질의 기능과 Key-Value 시스템의 확장성·단순성을 함께 활용해, 스케일아웃과 개발 민첩성을 확보하는 데 초점을 둔다.

저장과 조회의 기본 단위는 BSON 기반 도큐먼트다. Database, Collection, Document(JSON/BSON), Field 순으로 계층이 이어진다. 컬렉션 안의 문서는 서로 다른 스키마를 가질 수 있으며, 중첩 구조와 배열도 자연스럽게 표현할 수 있다. 이 특성은 도메인 모델과 데이터 구조 사이의 임피던스 미스매치를 줄이는 데 쓰인다.

_id에 쓰이는 ObjectId는 12바이트이며 timestamp(4), machine id(3), process id(2), sequence(3)로 구성된다.

MongoDB는 WiredTiger 스토리지 엔진을 기본으로 채택하며, 저널링(journaling), 압축, 다중 쓰기 동시성을 제공한다.

질의, 인덱스, 확장 방식을 함께 보는 이유

키 기반 get/put뿐 아니라 조건, 범위, 배열, 텍스트, 지리공간 쿼리를 처리할 수 있다. 단일·복합 인덱스 외에도 partial, sparse, TTL, 텍스트, 2dsphere 인덱스를 선택할 수 있다. 관계형 조인이 필요한 경우에는 Aggregation Pipeline의 $lookup으로 조인 시맨틱을 지원한다.

가용성과 일관성은 Replica Set 구성, readPreference, writeConcern의 조합으로 조절한다. 쓰기 확인은 fire-and-forget(ack=0)부터 과반수 커밋(majority)까지 선택할 수 있다.

데이터와 쿼리를 더 넓게 분산해야 할 때는 샤딩을 사용한다. 샤드 키는 range 또는 hash 방식으로 구성하며, 청크(Chunk)는 자동 밸런싱 대상이 된다. 대형 파일은 GridFS로 분할 저장하고 스트리밍할 수 있으며, Aggregation Framework는 대화형·배치 분석 파이프라인의 중심이 된다.

복제셋이 처리하는 쓰기와 장애 조치

Replica Set에서는 Primary가 쓰기를 받고 Oplog를 통해 Secondary로 변경 사항을 전파한다. 응답 시점은 writeConcern에 따라 달라지며, 헬스체크와 선출을 통해 장애 조치를 수행한다.

SecondarySecondaryPrimaryClientSecondarySecondaryPrimaryClientWrite (w: majority)Oplog ReplicationOplog ReplicationAckAckAck after majority commit

샤드 클러스터에서 라우팅이 이뤄지는 방식

mongos는 쿼리를 라우팅하고 청크 메타데이터를 조회한다. 각 샤드는 일반적으로 복제셋으로 구성해 내결함성과 성능을 함께 확보한다.

Client TierMetadataDriver / Routermongos: Query RouterConfig Server Replica SetShard 1Shard 2Shard NReplica SetReplica SetReplica Set

문서 관계와 접근 패턴에 맞춘 모델링

임베드는 1:1 또는 1:소 관계이고 함께 자주 조회되며, 독립 갱신 빈도가 낮고 문서 크기 제한인 16MB 이내일 때 적합하다. 반대로 1:다 또는 다:다 관계, 서로 다른 수명주기, 높은 크기 성장이나 갱신 빈도, 다중 문서 트랜잭션이 필요한 경우에는 레퍼런스를 검토한다.

샤드 키는 높은 카디널리티로 균등 분포를 만들고, 핫 샤드를 피하기 위해 단조 증가 키를 피해야 한다. 자주 사용하는 쿼리 필터에 포함되는지와 라우팅 효율도 함께 고려한다. 범위 쿼리가 많다면 Range, 쓰기 폭주를 분산해야 한다면 Hashed가 기준이 된다.

읽기 중심 워크로드에서는 커버링 인덱스, 정렬 키를 선두에 포함한 인덱스, 선택도가 높은 필드를 우선 검토한다. 쓰기 중심 환경에서는 인덱스 수를 줄이고 TTL, Partial, Sparse 인덱스로 유지비를 낮춘다. 배열을 위한 다중 키 인덱스와 복합 인덱스는 필드 순서를 필터·정렬 패턴과 맞춰야 한다.

원자성과 트랜잭션의 경계

단일 문서 연산은 기본적으로 원자성을 보장한다. 여러 문서에 걸친 ACID 트랜잭션은 Replica Set과 Sharded Cluster에서 지원하지만, 성능과 복잡도를 고려해 적용 범위를 최소화해야 한다.

읽기 일관성이 필요한 경우 readConcern: "snapshot"으로 스냅샷 읽기를, readConcern: "majority"로 과반수 커밋 기준 읽기를 선택할 수 있다.

운영에서 확인할 항목

로그·이벤트처럼 지연을 허용할 수 있는 데이터는 { writeConcern: { w: 0 } } 또는 배치 버퍼를 고려할 수 있다. 핵심 데이터에는 { w: "majority", j: true }로 내구성을 우선하는 구성이 필요하다.

연결 풀 크기, 서버 선택 타임아웃, maxTimeMS도 워크로드에 맞춰 설정한다. 불용 인덱스는 제거하고, 부분·희소 인덱스를 활용해 쓰기 비용을 줄인다. WiredTiger 압축(Zstd/Snappy)은 컬렉션과 인덱스별 압축 정책을 나눠 적용할 수 있다.

모니터링은 Slow Query Log(Profiler), FTDC 메트릭, explain() 실행계획 검증을 중심으로 구성한다. 샤딩 환경에서는 balancer 스케줄, 핫샤드, 청크 스플릿 정책을 지속적으로 점검한다.

GridFS와 파일 저장의 역할 분리

GridFS는 16MB를 초과하는 파일을 청크로 나눠 컬렉션에 저장하고 스트리밍한다. 이미지와 동영상은 CDN·오브젝트 스토리지에 두고 MongoDB에는 메타데이터만 저장하는 방식도 함께 검토할 수 있다.

인증, 암호화, 복구 설계

인증과 권한 제어에는 SCRAM 및 역할 기반 액세스(RBAC)를 사용한다. 전송 구간은 TLS로 보호하며, Enterprise 환경에서는 디스크 레벨 암호화와 키 관리(KMS) 연동을 적용할 수 있다.

백업과 복구는 스냅샷, Point-in-Time, Oplog 기반 PITR을 기준으로 설계한다.

배포 구성별 선택 기준

형태 구성 용도 장점 유의점
Single Node 단일 mongod 개발/테스트, 임시 도구 단순 가용성 없음, 장애 시 중단
Replica Set Primary + Secondary(≥1) + Arbiter(선택) 고가용성/내구성 자동 장애 조치, 읽기 분산 일관성 옵션 설계 필요
Sharded Cluster mongos + Config RS + Shard RS(N) 대규모 스케일아웃 선형 확장, 데이터 분산 샤드키 선택·운영 복잡성

관계형 데이터베이스와 Key-Value 저장소 사이에서의 위치

항목 MongoDB RDBMS Key-Value Store
데이터 모델 문서지향(BSON) 정규화 테이블 단순 키-값
스키마 유연(Schemaless) 엄격 키/값 수준
조인 $lookup 등 파이프라인 표준 JOIN 없음
트랜잭션 단일문서 원자성 + 멀티문서 ACID 지원 강력 보통 불가
확장성 샤딩 기본기능 수직/수평(복잡) 수평 용이
사용처 콘텐츠·이벤트·카탈로그 OLTP/재무 캐시·세션

전자상거래 카탈로그에서는 다양한 스펙과 옵션을 임베드하고 검색 인덱스를 최적화하며, 썸네일 메타데이터를 저장하고 이미지 파일은 외부 스토리지에 둘 수 있다. 로그·이벤트 수집에서는 fire-and-forget 쓰기와 TTL 인덱스, 시간축 샤딩을 조합한다. 위치 기반 서비스는 2dsphere 인덱스와 반경·다각형 질의, 근접 검색에 활용할 수 있다.

강한 정합성이나 복잡한 다중 테이블 조인이 중심인 업무에는 RDBMS가 더 적합할 수 있다. 문서 크기 16MB, 인덱스 관리비, 샤딩 운영 복잡성도 설계에 반영해야 한다. 조인이 빈번한 도메인이라면 임베딩·사전집계 중심의 자료구조 재설계 또는 RDBMS+MongoDB 하이브리드 아키텍처를 선택할 수 있다.

샤드 키와 인덱스를 결정하는 루틴

function plan_shard_and_index(workload):
  stats = analyze_query_patterns(workload)
  candidates = fields_with_high_cardinality(stats)
  if stats.has_heavy_range_queries(candidates):
    shard_key = choose_range_key(candidates, avoid_monotonic=true)
  else:
    shard_key = hash_of(best_cardinality_field(candidates))
  index_plan = []
  for q in stats.top_queries:
    index_plan.append(covering_index(order_fields_by_filter_then_sort(q)))
  return shard_key, deduplicate(index_plan)

PyMongo로 트랜잭션, 인덱스, 집계를 구성하는 예시

from pymongo import MongoClient, ASCENDING, WriteConcern
from pymongo.read_concern import ReadConcern
from pymongo.read_preferences import ReadPreference

client = MongoClient("mongodb://...", tz_aware=True)
db = client.get_database("shop")
col = db.get_collection("orders")

# 인덱스: 상태+일자 커버링
col.create_index([("status", ASCENDING), ("created_at", ASCENDING)])

# 트랜잭션: 주문 + 재고 동시 갱신
with client.start_session() as s:
    with s.start_transaction(read_concern=ReadConcern("snapshot"),
                              write_concern=WriteConcern("majority"),
                              read_preference=ReadPreference.PRIMARY):
        col.update_one({"_id": order_id}, {"$set": {"status": "PAID"}}, session=s)
        db.inventory.update_one({"sku": sku}, {"$inc": {"qty": -1}}, session=s)

# Aggregation: 일자·상태별 집계
pipeline = [
    {"$match": {"created_at": {"$gte": start, "$lt": end}}},
    {"$group": {"_id": {"day": {"$dateToString": {"format": "%Y-%m-%d", "date": "$created_at"}},
                          "status": "$status"},
                 "cnt": {"$sum": 1}, "sum": {"$sum": "$amount"}}},
    {"$sort": {"_id.day": 1}}
]
list(col.aggregate(pipeline))

자주 접근하는 필드는 문서 상위 레벨에 배치해 압축과 캐시 효율을 높인다. 배열 필드는 폭발적으로 커지지 않도록 관리하고, $push 대신 $addToSet과 슬라이싱으로 상한을 유지한다. 배치 쓰기는 bulkWrite로 네트워크 왕복을 줄이며 idempotent하게 설계한다. 조회에서는 필요한 필드만 프로젝션하고, 시간 기반 키를 단독으로 쓰는 대신 해시 프리픽스를 적용해 핫샤드를 피한다.

콘텐츠 플랫폼에서는 사용자 프로필을 임베드하고 활동 로그를 분리할 수 있다. 추천 파이프라인 전처리 결과는 컬렉션으로 구성해 실시간 페이지 로드 시간을 줄인다. 금융 이벤트 수집에서는 원장 시스템을 RDBMS에 두고 이벤트 스트림, 알림, 감사 로그를 MongoDB로 분리하는 폴리글랏 전략을 적용할 수 있다.

쓰기 확인 수준과 저널링

w:0majority+j:1Client WritewriteConcernImmediate AckPrimary Commit + JournalReplicate to SecondariesMajority AckClient Ack

업무 중요도에 따라 쓰기 확인 수준을 조절하면 성능과 내구성 사이의 균형을 설계할 수 있다. MongoDB는 문서 모델, 복제셋, 샤딩을 기반으로 민첩성과 확장성을 함께 다루는 NoSQL 선택지이며, 도메인 모델·쿼리 패턴·운영 복잡도를 기준으로 구성 방식을 결정해야 한다.

MongoDBNoSQL문서지향 데이터베이스샤딩복제셋