MongoDB는 NoSQL 데이터베이스의 한 종류로, 문서 지향적(Document-Oriented) 아키텍처를 채택한 오픈 소스 데이터베이스 관리 시스템이다. 관계형 데이터베이스 관리 시스템(RDBMS)과 달리 고정된 테이블과 행(Row) 대신 유연한 JSON 형태의 문서를 사용하여 데이터를 저장하고 조회한다. 이는 현대 애플리케이션, 특히 대규모의 비정형 또는 반정형 데이터를 처리해야 하는 웹 서비스, 모바일 앱, IoT 플랫폼 등에서 널리 사용된다.
MongoDB의 핵심 설계 목표는 개발의 용이성, 수평적 확장성(Horizontal Scalability), 그리고 높은 성능을 제공하는 것이다. 전통적인 SQL과 JOIN 연산 대신 풍부한 쿼리 언어와 다양한 인덱싱을 지원하며, 데이터는 자체적인 이진 형식인 BSON으로 인코딩되어 저장된다. 이러한 특성 덕분에 애플리케이션의 데이터 모델이 빠르게 진화하거나 매우 큰 규모로 성장해야 하는 환경에 적합하다.
MongoDB는 단일 서버 구성부터 여러 대의 서버에 데이터를 분산 저장하는 샤딩(Sharding) 아키텍처, 그리고 데이터의 복제와 고가용성(High Availability)을 보장하는 레플리카 셋(Replica Set)을 지원한다. 이는 시스템의 가용성과 내결함성을 높이는 동시에 읽기 및 쓰기 작업의 부하를 분산시키는 데 기여한다.
초기 버전에서는 ACID 트랜잭션을 완전히 지원하지 않았으나, 4.0 버전부터 다중 문서 트랜잭션을 도입하면서 복잡한 데이터 일관성 요구사항을 점진적으로 충족시키고 있다[1]. 따라서 MongoDB는 관계형 데이터베이스를 완전히 대체하기보다는, 특정 문제 영역에 더 적합한 도구로서 데이터베이스 기술 스택의 중요한 옵션으로 자리 잡았다.
NoSQL은 "Not Only SQL"의 약자로, 전통적인 관계형 데이터베이스 관리 시스템(RDBMS)와는 다른 접근 방식을 취하는 데이터베이스의 광범위한 범주를 지칭한다. 이는 고정된 테이블 스키마와 SQL을 사용하는 관계형 모델의 제약을 벗어나, 대규모 분산 데이터 처리, 유연한 스키마, 높은 처리량과 확장성을 더 쉽게 달성할 수 있도록 설계되었다. NoSQL 데이터베이스의 등장 배경에는 웹 2.0, 빅데이터, 실시간 분석, 클라우드 컴퓨팅 환경에서 발생하는 방대한 양의 반정형 및 비정형 데이터를 효율적으로 처리해야 하는 요구가 있었다.
NoSQL 데이터베이스는 데이터 모델에 따라 크게 네 가지 주요 유형으로 분류된다.
유형 | 설명 | 대표적인 데이터베이스 |
|---|---|---|
문서형(Document) | JSON이나 BSON과 같은 문서 형식으로 데이터를 저장한다. 각 문서는 독립적이며 유연한 스키마를 가진다. | |
키-값(Key-Value) | 단순한 키와 값의 쌍으로 데이터를 저장한다. 매우 빠른 조회 성능을 제공한다. | |
컬럼형(Column-Family) | 행과 열로 구성되지만, 관계형 테이블과 달리 각 행이 동일한 열을 가질 필요가 없는 유연한 구조를 가진다. | |
그래프(Graph) | 노드(Node), 엣지(Edge), 속성(Property)으로 데이터와 그 관계를 표현하며, 관계 탐색에 최적화되어 있다. |
이러한 NoSQL 데이터베이스들은 일반적으로 CAP 정리(일관성, 가용성, 분할 내성)의 개념 하에서 설계되며, 특정 응용 분야에 최적화된 성능과 확장성을 제공하기 위해 두 가지 속성을 희생하는 경향이 있다[2]. 또한, 대부분 수평적 확장(Scale-out)을 기본으로 지원하여, 더 많은 서버를 추가함으로써 시스템의 처리 능력을 증가시키는 데 용이하다. 이는 관계형 데이터베이스가 주로 채택하는 수직적 확장(Scale-up, 단일 서버의 성능 향상)과 대비되는 특징이다.
관계형 데이터베이스는 데이터를 테이블과 행, 열의 구조로 저장하며, 정규화를 통해 데이터 중복을 최소화하고 참조 무결성을 유지합니다. 데이터 간의 관계는 기본 키와 외래 키를 통해 정의되며, SQL이라는 강력한 표준화된 질의 언어를 사용하여 복잡한 조인과 트랜잭션을 처리합니다. 이 모델은 데이터 구조가 명확하고 일관성이 중요한 금융, ERP 시스템과 같은 환경에 적합합니다.
반면, NoSQL 데이터베이스는 고정된 스키마와 관계 모델을 따르지 않습니다. 데이터 모델은 애플리케이션의 요구사항에 따라 유연하게 설계될 수 있으며, 주로 대규모 분산 시스템과 빠른 읽기/쓰기 성능, 수평적 확장성을 위해 개발되었습니다. 관계형 데이터베이스의 ACID 트랜잭션보다는 BASE 모델[3]을 따르는 경우가 많아, 즉시 일관성보다는 가용성과 분산 내결함성을 우선시하는 경향이 있습니다.
다음 표는 두 유형의 주요 차이점을 요약합니다.
특성 | 관계형 데이터베이스 (RDBMS) | NoSQL 데이터베이스 |
|---|---|---|
데이터 모델 | 고정된 스키마, 테이블 기반 | 유연한 스키마(스키마리스), 문서/키-값/컬럼/그래프 등 |
확장 방식 | 주로 수직적 확장(Scale-up) | 수평적 확장(Scale-out)에 최적화 |
질의 언어 | 표준화된 SQL | 데이터베이스별 특화 언어 (예: MQL) |
트랜잭션 | 다중 레코드 ACID 트랜잭션 강력 지원 | 기본적으로 단일 문서 수준, 분산 트랜잭션은 제한적[4] |
일관성 | 강한 일관성(Strong Consistency) | 상황에 따른 일관성 (최종 일관성 등) |
이러한 차이로 인해 관계형 데이터베이스는 구조화된 데이터와 복잡한 관계, 정확성이 핵심인 비즈니스 로직에, NoSQL은 반구조화 또는 비구조화된 대용량 데이터, 빠른 프로토타이핑, 급변하는 요구사항을 가진 웹/모바일 애플리케이션에 더 적합한 것으로 평가됩니다.
NoSQL 데이터베이스는 데이터 모델에 따라 크게 네 가지 주요 유형으로 분류된다. 각 유형은 특정한 데이터 구조와 접근 패턴에 최적화되어 있으며, 서로 다른 사용 사례에 적합하다.
첫 번째 유형은 문서형 데이터베이스이다. 이 유형은 JSON이나 XML과 같은 문서 형식으로 데이터를 저장하며, MongoDB와 CouchDB가 대표적이다. 각 문서는 필드와 값의 쌍으로 구성되며, 다른 문서와 다른 구조를 가질 수 있는 유연성이 특징이다. 이는 반정형 데이터를 처리하거나 스키마가 자주 변경되는 애플리케이션에 적합하다. 두 번째 유형은 키-값 저장소이다. 이는 가장 단순한 데이터 모델로, 고유한 키와 그에 연결된 값 하나로 데이터를 관리한다. Redis와 Amazon DynamoDB가 이에 속하며, 세션 저장, 캐싱, 프로필 정보 저장과 같이 빠른 조회가 필요한 간단한 데이터 구조에 주로 사용된다.
세 번째 유형은 컬럼형 데이터베이스 또는 와이드 컬럼 저장소이다. Apache Cassandra와 HBase가 이 범주에 포함된다. 관계형 데이터베이스의 테이블과 유사하지만, 각 행이 동일한 컬럼 집합을 가질 필요가 없으며, 대량의 데이터를 여러 서버에 분산하여 저장하고 처리하는 데 특화되어 있다. 시계열 데이터나 분석 워크로드에 적합하다. 네 번째 유형은 그래프 데이터베이스이다. 이 유형은 노드(Node), 엣지(Edge), 속성(Property)을 사용하여 데이터 간의 관계를 명시적으로 모델링하고 저장한다. Neo4j가 대표적이며, 소셜 네트워크, 추천 엔진, 사기 탐지 시스템처럼 복잡한 관계와 연결성을 분석하는 데 뛰어난 성능을 보인다.
유형 | 주요 특징 | 대표 데이터베이스 | 적합한 사용 사례 |
|---|---|---|---|
문서형(Document) | 콘텐츠 관리, 사용자 프로필, 카탈로그 | ||
키-값(Key-Value) | 단순한 키-값 쌍, 매우 빠른 조회 | 캐싱, 세션 관리, 장바구니 | |
컬럼형(Column-family) | 행 기반이 아닌 컬럼 기반 저장, 수평 확장 용이 | 이벤트 로깅, 시계열 데이터, 대규모 분석 | |
그래프(Graph) | 노드와 관계(엣지) 중심 모델링 | 소셜 네트워크, 추천 시스템, 지식 그래프 |
이러한 유형들은 상호 배타적이지 않으며, 일부 데이터베이스는 여러 모델의 특징을 결합한 멀티 모델 접근 방식을 지원하기도 한다. 애플리케이션의 데이터 접근 패턴, 확장성 요구사항, 그리고 일관성 수준에 따라 적절한 NoSQL 유형을 선택하는 것이 중요하다.
MongoDB의 핵심 데이터 모델은 문서(Document)와 컬렉션(Collection)이다. 문서는 키-값 쌍의 집합으로 구성되며, JSON과 유사한 형태를 가진다. 이러한 문서들이 모여 하나의 컬렉션을 형성한다. 관계형 데이터베이스의 테이블과 달리, 동일한 컬렉션 내의 문서들은 서로 다른 구조를 가질 수 있다. 이는 스키마리스 또는 스키마 유연성이라는 특징으로 이어진다. 각 문서는 고유한 _id 필드를 가지며, 이를 통해 식별된다.
MongoDB는 문서를 BSON 형식으로 저장한다. BSON은 Binary JSON의 약자로, JSON 문서를 이진 형식으로 인코딩한다. 이는 JSON보다 더 많은 데이터 타입을 지원하며, 처리 속도가 빠르고 저장 효율이 높다. BSON은 날짜, 이진 데이터, 정규 표현식 등 다양한 타입을 포함할 수 있다. 스키마 디자인은 애플리케이션의 데이터 접근 패턴에 중점을 두어 진행된다. 자주 함께 조회되는 데이터는 하나의 문서에 내장하는 임베디드 방식을, 독립적으로 접근되거나 무한히 증가할 수 있는 데이터는 별도의 컬렉션으로 분리하고 참조를 사용하는 방식으로 설계한다.
컬렉션은 물리적 또는 논리적 데이터 그룹을 관리하는 단위이다. 컬렉션 내부에는 다양한 인덱스를 생성하여 쿼리 성능을 최적화할 수 있다. 또한, 컬렉션 수준에서 TTL 인덱스를 설정하여 특정 시간이 지나면 문서를 자동으로 삭제하는 기능도 제공한다. 데이터베이스는 여러 컬렉션을 포함하는 최상위 네임스페이스이다.
개념 | 설명 | 관계형 데이터베이스 대비 |
|---|---|---|
문서(Document) | BSON 형식의 레코드 기본 단위. 필드와 값의 집합. | 행(Row)에 대응 |
컬렉션(Collection) | 문서들의 그룹. | 테이블(Table)에 대응 |
데이터베이스 | 컬렉션들의 물리적/논리적 컨테이너. | 데이터베이스 스키마에 대응 |
필드(Field) | 문서 내의 키-값 쌍. | 열(Column)에 대응 |
MongoDB의 기본 데이터 단위는 문서(Document)이다. 문서는 JSON과 유사한 BSON 형식으로 표현되며, 필드와 값의 쌍으로 구성된다. 각 문서는 고유한 _id 필드를 가지며, 이는 문서를 식별하는 기본 키 역할을 한다. 문서는 중첩된 구조를 지원하기 때문에, 복잡한 계층적 데이터를 하나의 레코드에 자연스럽게 저장할 수 있다. 예를 들어, 한 사용자 문서 내에 주소 배열이나 연락처 객체를 직접 포함시킬 수 있다.
문서들이 논리적으로 그룹화된 저장소를 컬렉션(Collection)이라고 한다. 관계형 데이터베이스의 테이블과 유사한 개념이지만, 컬렉션은 고정된 스키마를 강제하지 않는다는 점에서 근본적으로 다르다. 동일한 컬렉션 내의 문서들이 서로 다른 구조를 가질 수 있다. 이 유연성은 애플리케이션 요구사항이 빠르게 변하거나 데이터 형태가 다양할 때 큰 장점이 된다.
문서와 컬렉션의 관계는 다음과 같이 정리할 수 있다.
개념 | 설명 | 관계형 DB 대비 |
|---|---|---|
문서(Document) | 필드-값 쌍의 집합. BSON 형식. 기본 키는 | 하나의 행(레코드)에 해당. |
컬렉션(Collection) | 문서들의 그룹. 물리적 또는 논리적 저장 단위. | 테이블에 해당. |
스키마 유연성 | 동일 컬렉션 내 문서 구조가 달라도 됨. | 테이블은 고정된 열 구조를 가짐. |
이러한 구조는 개발 생산성을 높이는 반면, 데이터 무결성을 애플리케이션 계층에서 더 많이 관리해야 할 수 있다. 따라서 컬렉션 설계 시, 문서의 논리적 관계와 함께 쿼리 패턴 및 성능 요구사항을 함께 고려하는 것이 중요하다.
BSON은 Binary JSON의 약자로, MongoDB가 데이터를 저장하고 네트워크를 통해 전송할 때 사용하는 이진 인코딩 형식이다. JSON과 유사한 구조를 가지지만, 이진 형식으로 인해 더 효율적인 공간 활용과 빠른 파싱 속도를 제공한다. BSON은 날짜(Date), 이진 데이터(BinData), ObjectId와 같은 JSON에는 없는 추가 데이터 타입을 지원하여 데이터 표현력을 확장한다. 이 형식은 문서를 데이터베이스에 저장하거나 쿼리 결과를 반환할 때 내부적으로 사용된다.
MongoDB의 스키마 디자인은 관계형 데이터베이스의 정규화된 테이블 설계와는 근본적으로 다른 접근법을 따른다. 핵심 원칙은 애플리케이션의 데이터 접근 패턴에 맞춰 문서를 설계하는 것이다. 이는 관련된 데이터를 하나의 문서 내에 중첩된 서브도큐먼트나 배열 형태로 모델링하는 임베디드 데이터 모델을 권장한다. 예를 들어, 사용자 정보와 그 사용자의 주문 내역을 별도의 컬렉션이 아닌 하나의 사용자 문서에 포함시킬 수 있다. 이 방식은 읽기 성능을 극대화하고 조인 연산의 필요성을 줄인다.
반면, 데이터 중복이 발생하거나 관계가 매우 복잡한 경우에는 문서 간 참조 데이터 모델을 사용한다. 이는 관계형 데이터베이스의 외래 키 개념과 유사하게, 한 문서가 다른 문서의 ObjectId를 저장하는 방식이다. 적절한 스키마 디자인을 위해서는 애플리케이션이 수행하는 읽기와 쓰기 연산의 비율, 쿼리 패턴, 데이터 일관성 요구사항 등을 종합적으로 고려해야 한다.
데이터 모델 유형 | 설명 | 적합한 시나리오 |
|---|---|---|
임베디드 (Embedded) | 관련 데이터를 단일 문서 내에 중첩시켜 저장 | 일대일 또는 일대다 관계에서 주로 읽기 연산이 빈번한 경우 |
정규화된 참조 (Normalized Reference) | 문서 간 관계를 ObjectId를 통한 참조로 관리 | 데이터 중복을 최소화해야 하거나 관계가 다대다인 복잡한 경우 |
효과적인 스키마 설계는 쿼리 성능, 저장소 효율성, 애플리케이션 개발 편의성에 직접적인 영향을 미친다. 따라서 초기 설계 단계에서 데이터의 성장과 접근 방식을 예측하는 것이 중요하다.
MongoDB는 대규모 데이터와 높은 처리량을 다루기 위해 설계된 분산 데이터베이스 시스템이다. 확장성과 가용성을 핵심 목표로 삼으며, 이를 실현하기 위해 샤딩과 레플리카 셋이라는 두 가지 주요 메커니즘을 제공한다. 샤딩은 데이터를 여러 물리적 서버에 분산하여 수평적 확장을 가능하게 하고, 레플리카 셋은 동일한 데이터의 복사본을 여러 서버에 유지하여 고가용성과 데이터 내구성을 보장한다.
샤딩(Sharding)을 통한 수평적 확장
샤딩은 단일 데이터베이스의 데이터를 여러 서버(샤드)에 분할하여 저장하는 방식이다. 애플리케이션의 부하가 증가함에 따라 단일 서버의 성능 한계를 극복하기 위해 사용된다. MongoDB 클러스터는 샤드 서버들, 라우터 서버(mongos), 그리고 설정 서버(config servers)로 구성된다. 라우터 서버는 클라이언트의 쿼리를 받아 적절한 샤드로 라우팅하고, 설정 서버는 클러스터의 메타데이터(데이터 분포 정보 등)를 저장한다. 데이터는 선택한 샤드 키를 기준으로 분할되며, 범위 기반 또는 해시 기반 샤딩 전략을 사용할 수 있다. 이를 통해 쓰기 및 읽기 작업 부하를 분산시키고, 시스템의 전체 처리량을 향상시킨다.
레플리카 셋(Replica Set)과 고가용성
레플리카 셋은 동일한 데이터 세트를 복제하여 여러 서버(일반적으로 3개 이상)에 저장하는 MongoDB의 고가용성 솔루션이다. 하나의 서버가 프라이머리(주) 노드로 선출되어 모든 쓰기 작업을 처리하고, 나머지 세컨더리(부) 노드들은 프라이머리로부터 데이터 변경 사항을 비동기적으로 복제한다. 프라이머리 노드에 장애가 발생하면 자동으로 새로운 프라이머리 노드를 선출하는 자동 장애 조치 메커니즘이 작동한다. 이는 계획된 유지보수나 예기치 않은 서버 다운타임 동안에도 데이터베이스 서비스의 연속성을 보장한다. 또한, 세컨더리 노드는 읽기 쿼리의 부하 분산에 활용될 수 있다.
구성 요소 | 역할 | 주요 특징 |
|---|---|---|
샤드 | 실제 데이터를 저장하는 서버 | 데이터의 일부를 담당하며, 수평적 확장의 기본 단위이다. |
라우터 서버 (mongos) | 쿼리 라우팅 및 결과 집계 | 클라이언트의 접근점으로, 설정 서버의 메타데이터를 참조하여 쿼리를 적절한 샤드로 전달한다. |
설정 서버 | 클러스터 메타데이터 저장 | 샤드 키 범위와 샤드 매핑 정보 등을 저장하며, 고가용성을 위해 복제본 세트로 배포된다. |
레플리카 셋 | 데이터 복제 및 고가용성 제공 | 하나의 프라이머리와 여러 세컨더리 노드로 구성되며, 자동 장애 조치를 지원한다. |
이 두 아키텍처는 종종 결합되어 사용된다. 각 샤드 자체가 하나의 레플리카 셋으로 구성될 수 있어, 데이터 분산과 함께 각 데이터 조각에 대한 내결함성과 가용성을 동시에 확보하게 된다.
샤딩은 MongoDB가 대규모 데이터셋과 높은 처리량 요구사항을 처리하기 위해 채택하는 핵심적인 수평 확장 전략이다. 이는 단일 서버의 물리적 한계를 극복하기 위해 데이터를 여러 서버(샤드)에 분할하여 저장하고 운영하는 방식이다. 샤딩 클러스터는 주로 샤드 서버, 설정 서버, 라우터 서버라는 세 가지 구성 요소로 이루어진다. 각 샤드는 데이터의 일부를 담당하며, 설정 서버는 클러스터의 메타데이터를 저장하고, 라우터(mongos)는 애플리케이션의 쿼리를 받아 적절한 샤드로 라우팅하는 역할을 한다.
데이터 분할의 기준이 되는 샤드 키를 선택하는 것은 샤딩 설계에서 가장 중요한 결정 중 하나이다. 샤드 키는 문서가 클러스터 내의 특정 샤드에 할당되는 방식을 결정한다. 샤드 키 선택은 데이터 분포의 균형성(샤드 간 부하 분산)과 쿼리 효율성에 직접적인 영향을 미친다. 부적절한 샤드 키는 특정 샤드에 데이터와 트래픽이 집중되는 핫스팟 현상을 초래하거나, 쿼리 성능을 저하시킬 수 있다.
MongoDB는 샤드 키를 기반으로 데이터를 분산시키는 두 가지 주요 샤딩 전략을 제공한다.
전략 | 설명 | 장점 | 단점 |
|---|---|---|---|
범위 기반 샤딩 | 샤드 키 값의 연속적인 범위를 각 샤드에 할당한다. | 범위 쿼리 성능이 우수하다. 샤드 키 순서로 데이터가 정렬되어 저장된다. | 데이터 분포가 불균등할 수 있으며, 특정 범위에 트래픽이 집중될 수 있다. |
해시 기반 샤딩 | 샤드 키 값에 해시 함수를 적용한 결과를 기반으로 데이터를 분산한다. | 데이터가 샤드에 무작위로 분포되어 균일한 부하 분산을 기대할 수 있다. | 범위 쿼리를 수행할 때 모든 샤드를 스캔해야 할 수 있어 비효율적이다. |
샤딩을 구현하면 시스템의 전체 저장 용량과 읽기/쓰기 처리량을 선형적으로 증가시킬 수 있다. 그러나 이는 운영 복잡성을 증가시키며, 조정된 쿼리나 다중 샤드 트랜잭션과 같은 작업은 단일 서버 환경보다 더 많은 주의를 요구한다.
레플리카 셋은 동일한 데이터 셋을 복제하여 유지하는 MongoDB 서버들의 그룹이다. 하나의 서버가 프라이머리(Primary) 노드로 선출되어 모든 쓰기 연산을 처리하고, 나머지 서버들은 세컨더리(Secondary) 노드로 읽기 연산과 데이터 복제를 담당한다. 이 구조는 자동 장애 조치(Failover)를 통해 고가용성을 제공하는 핵심 메커니즘이다. 프라이머리 노드에 장애가 발생하면 나머지 노드들이 새로운 프라이머리를 선출하는 선거 과정을 자동으로 수행하여 서비스 중단 시간을 최소화한다.
레플리카 셋의 구성은 일반적으로 홀수 개의 멤버(예: 3개 또는 5개)로 이루어지며, 데이터 안정성을 위해 다양한 유형의 노드를 포함할 수 있다. 예를 들어, 아비터(Arbiter) 노드는 선거에만 참여하고 데이터를 저장하지 않는 특수 멤버로, 짝수 개의 데이터 노드가 있을 때 투표권을 제공하여 장애 조치 결정을 돕는다. 또한, 히든(Hidden) 노드나 지연된(Delayed) 노드는 백업, 보고, 또는 특정 시간 전의 데이터 스냅샷을 유지하는 용도로 구성된다.
노드 유형 | 주요 역할 | 데이터 보유 | 읽기 가능 | 쓰기 가능 | 선거 참여 |
|---|---|---|---|---|---|
프라이머리(Primary) | 모든 쓰기 연산 처리 | 예 | 예 | 예 | 예 |
세컨더리(Secondary) | 데이터 복제 및 읽기 연산 | 예 | 예 | 아니요 | 예 |
아비터(Arbiter) | 선거 시 투표권 제공 | 아니요 | 아니요 | 아니요 | 예 |
히든(Hidden) | 특수 목적(백업, 보고) | 예 | 설정에 따라 가능 | 아니요 | 예 |
지연된(Delayed) | 지정 시간 전 데이터 보관 | 예 | 설정에 따라 가능 | 아니요 | 예 |
데이터 복제는 프라이머리 노드의 오플로그(Oplog, operation log)를 기반으로 한다. 모든 쓰기 작업은 오플로그에 순서대로 기록되며, 세컨더리 노드는 이 로그를 비동기적으로 적용하여 자신의 데이터 셋을 최신 상태로 유지한다. 이 복제 방식은 결과적 일관성(Eventual Consistency) 모델을 따르지만, 읽기 작업 시 쓰기 고려(Write Concern)와 읽기 선호도(Read Preference) 설정을 조정하여 강한 일관성이 필요한 경우에도 대응할 수 있다.
MongoDB는 MongoDB Query Language를 사용하여 데이터를 조회하고 조작한다. MQL은 JSON과 유사한 구문을 가지며, find(), update(), delete() 등의 메서드를 통해 작업을 수행한다. 쿼리 조건은 중첩된 문서나 배열을 포함한 복잡한 패턴 매칭이 가능하다. 예를 들어, 특정 필드 값에 대한 비교 연산자($gt, $lt)나 논리 연산자($and, $or), 배열 연산자($in, $elemMatch)를 활용할 수 있다. 집계 파이프라인은 $match, $group, $sort 같은 여러 스테이지를 연결하여 복잡한 데이터 변환 및 분석을 지원한다.
인덱싱은 MongoDB의 쿼리 성능을 결정하는 핵심 요소이다. 적절한 인덱스가 없으면 컬렉션 스캔이 발생하여 처리 속도가 크게 저하된다. MongoDB는 다양한 인덱스 유형을 제공하여 다른 데이터 패턴과 쿼리 요구 사항에 대응한다.
인덱스 유형 | 주요 특징 | 일반적인 사용 사례 |
|---|---|---|
단일 필드 인덱스 | 하나의 필드에 대해 생성되는 가장 기본적인 인덱스 | 자주 검색되거나 정렬에 사용되는 단일 필드 (예: |
복합 인덱스 | 두 개 이상의 필드를 조합하여 생성[5] | 여러 필드를 기준으로 하는 쿼리 또는 정렬 (예: |
다중 키 인덱스 | 배열 필드의 각 요소에 대해 생성되는 인덱스 | 배열 필드 내 값을 검색할 때 (예: 태그 배열 |
텍스트 인덱스 | 문자열 내용에 대한 전문 검색을 지원 | 문서 내 텍스트 필드의 키워드 검색 |
지리 공간 인덱스 | 좌표 데이터에 대한 공간 쿼리 지원 | 위치 기반 검색 (예: 반경 내 장소 찾기) |
해시 인덱스 | 필드 값의 해시를 사용하는 인덱스 | 해시 샤딩 키로 주로 사용되며, 범위 쿼리에는 부적합 |
인덱스 관리는 성능 최적화의 중요한 부분이다. 인덱스를 과도하게 생성하면 쓰기 성능이 저하되고 디스크 사용량이 증가할 수 있다. explain() 메서드를 사용하여 쿼리 실행 계획을 분석하고 인덱스 사용 여부를 확인하는 것이 좋다. 또한 쿼리 선택성(선택된 문서 비율)이 높은 필드를 인덱스 선두에 두는 것이 일반적인 최적화 원칙이다. 인덱스는 BSON 문서의 크기 제한(16MB)에 포함되지 않으며, 별도의 데이터 구조로 관리된다.
MongoDB Query Language는 MongoDB에서 데이터를 조회, 삽입, 갱신, 삭제하기 위해 사용하는 질의 언어이다. SQL과 달리 절차적이지 않으며, JSON과 유사한 형태의 객체를 사용하여 쿼리 조건과 작업을 정의한다. 이는 개발자가 애플리케이션 코드에서 사용하는 데이터 구조와 매우 유사하여 직관적으로 사용할 수 있다는 장점을 가진다.
MQL의 기본적인 쿼리 연산은 db.collection.find() 메서드를 통해 이루어진다. 이 메서드는 필터 객체를 인자로 받아 조건에 맞는 문서를 커서 형태로 반환한다. 예를 들어, db.users.find({ age: { $gt: 25 }, status: "active" })는 age 필드가 25보다 크고 status 필드가 "active"인 모든 사용자 문서를 찾는다. 갱신 작업은 db.collection.updateOne() 또는 db.collection.updateMany()를, 삭제 작업은 db.collection.deleteOne() 또는 db.collection.deleteMany()를 사용한다.
MQL은 다양한 쿼리 연산자를 제공하여 복잡한 질의를 구성할 수 있다. 주요 연산자 카테고리는 다음과 같다.
연산자 카테고리 | 주요 연산자 예시 | 설명 |
|---|---|---|
비교 연산자 |
| 필드 값을 비교한다. |
논리 연산자 |
| 여러 조건을 조합한다. |
요소 연산자 |
| 필드의 존재 유무나 데이터 타입을 확인한다. |
평가 연산자 |
| 정규 표현식 평가나 수식 평가를 수행한다. |
배열 연산자 |
| 배열 필드에 대한 질의를 수행한다. |
또한, find() 메서드와 함께 사용하는 프로젝션을 통해 반환되는 문서의 필드를 제한하거나, sort(), limit(), skip() 메서드로 결과의 정렬과 페이징을 처리할 수 있다. 집계 파이프라인은 db.collection.aggregate()를 사용하여 $match, $group, $sort, $project 같은 여러 단계를 거치는 복잡한 데이터 변환과 분석을 가능하게 한다.
MongoDB는 다양한 유형의 인덱스를 지원하여 쿼리 성능을 최적화한다. 가장 기본적인 형태는 단일 필드 인덱스로, 하나의 필드에 대해 생성된다. 복합 인덱스는 여러 필드를 조합하여 생성되며, 필드의 순서가 쿼리 성능에 중요한 영향을 미친다. 다중 키 인덱스는 배열 필드의 각 요소에 대해 인덱스를 생성할 때 사용된다. 또한, 공간 데이터를 효율적으로 검색하기 위한 2dsphere 인덱스와 전문 검색을 지원하는 텍스트 인덱스, 특정 데이터만 인덱싱하는 희소 인덱스 등 특수 목적의 인덱스도 존재한다.
성능 최적화를 위해서는 쿼리 패턴을 분석하여 적절한 인덱스를 설계하는 것이 핵심이다. 실행 계획을 확인하여 인덱스가 효율적으로 사용되는지 평가할 수 있다. 인덱스는 읽기 성능을 향상시키지만, 쓰기 작업 시에는 인덱스를 갱신하는 오버헤드가 발생하므로 과도한 인덱스 생성은 성능 저하를 초래할 수 있다. 따라서 자주 사용되는 쿼리 필드와 정렬 필드를 우선적으로 인덱싱하고, 필요하지 않은 인덱스는 주기적으로 정리하는 것이 좋다.
인덱스 설계 시 고려해야 할 주요 요소는 다음과 같다.
고려 요소 | 설명 |
|---|---|
선택도 | 인덱스가 쿼리에서 필터링하는 데이터의 비율이다. 선택도가 높은(고유한 값이 많은) 필드를 선두에 두는 것이 효율적이다. |
쿼리 패턴 |
|
인덱스 크기 | 인덱스는 RAM에 상주할 때 성능이 극대화된다. 인덱스의 총 크기가 사용 가능한 메모리를 초과하지 않도록 관리한다. |
쓰기 빈도 | 쓰기 작업이 매우 빈번한 컬렉션에서는 인덱스 개수를 최소화하여 오버헤드를 줄인다. |
마지막으로, 인덱스는 생성 후에도 관리가 필요하다. 인덱스 조각화가 발생하면 성능이 점진적으로 저하될 수 있으므로 주기적인 모니터링과 재구성이 권장된다[6]. 또한, 복제본 세트의 보조 멤버에서 인덱스를 빌드하면 프라이머리의 운영 부하를 줄일 수 있다.
MongoDB는 초기 버전에서는 단일 문서 수준의 원자성만 보장했으나, 버전 4.0부터 다중 문서 트랜잭션을 지원하기 시작했다. 이는 기존 관계형 데이터베이스에서 익숙한 ACID 속성을 어느 정도 충족시키는 중요한 진전이었다. 특히 버전 4.2부터는 샤딩된 클러스터 환경에서도 분산 트랜잭션을 지원하여, 데이터가 여러 물리적 서버에 분산 저장되더라도 일관된 트랜잭션 처리가 가능해졌다.
MongoDB의 트랜잭션은 전통적인 RDBMS의 방식과 유사하게 시작, 커밋, 롤백의 사이클로 관리된다. 그러나 내부적으로는 MVCC(다중 버전 동시성 제어) 메커니즘을 사용하여 동시성을 처리한다. 트랜잭션의 격리 수준은 기본적으로 스냅샷 격리 수준을 제공하며, 이는 트랜잭션 내에서 일관된 데이터 뷰를 보장한다. 다만, 분산 환경에서의 트랜잭션은 네트워크 지연과 장애 조치 가능성으로 인해 성능 오버헤드가 발생할 수 있으며, 적절한 타임아웃 설정과 재시도 로직이 중요하다.
데이터 일관성 측면에서 MongoDB는 기본적으로 강력한 일관성을 제공하는 레플리카 셋의 기본 노드에서 읽기와 쓰기를 수행한다. 그러나 애플리케이션의 요구사항에 따라 일관성 수준을 조정할 수 있다. 예를 들어, 읽기 작업의 일관성을 희생하고 가용성을 높이기 위해 세컨더리 노드에서 읽기를 수행하는 것도 가능하다. 이는 클라이언트가 읽기 설정을 통해 제어할 수 있다.
일관성 모델 | 설명 | 주요 사용 시나리오 |
|---|---|---|
강력한 일관성 | 모든 읽기 작업이 가장 최근에 커밋된 쓰기 결과를 반환함을 보장. 기본 설정. | 금융 거래, 주문 처리 등 데이터 정확성이 최우선인 경우. |
최종적 일관성 | 읽기 작업이 세컨더리 노드에서 수행될 수 있어, 약간의 지연 후에 최신 데이터가 반영됨. | 소셜 미디어 피드, 분석 대시보드 등 실시간성이 덜 중요한 경우. |
분산 트랜잭션 관리에서는 2단계 커밋 프로토콜과 유사한 방식을 사용하여 여러 샤드에 걸친 작업의 원자성을 보장한다. 트랜잭션의 지속 시간은 제한되어 있으며, 장시간 실행되는 트랜잭션은 시스템 리소스를 과도하게 점유하거나 충돌을 유발할 수 있으므로 주의가 필요하다. 따라서 MongoDB에서 트랜잭션을 설계할 때는 작업의 범위를 최소화하고 실행 시간을 짧게 유지하는 것이 권장된다.
초기 MongoDB는 단일 문서 수준의 원자성만 보장하며 전통적인 ACID 트랜잭션을 완전히 지원하지 않았다. 이는 NoSQL 데이터베이스가 높은 확장성과 성능을 위해 일관성 모델을 완화하는 경향과 맞닿아 있었다. 그러나 버전 4.0부터 MongoDB는 복제본 셋 내에서의 다중 문서 트랜잭션을 도입했고, 버전 4.2에서는 샤딩 클러스터 환경에서의 분산 트랜잭션을 지원하게 되었다[7].
현재 MongoDB는 다음과 같은 ACID 속성을 지원한다.
속성 | MongoDB에서의 지원 현황 |
|---|---|
원자성(Atomicity) | 단일 문서 작업은 항상 원자적이다. 다중 문서 트랜잭션에서는 트랜잭션 내 모든 작업이 전체적으로 커밋되거나 롤백된다. |
일관성(Consistency) | 기본적으로 강력한 일관성을 제공한다. 쓰기 작업이 성공하면 후속 읽기는 최신 데이터를 본다. 읽기 일관성 수준을 조정할 수 있다. |
격리성(Isolation) | 다중 문서 트랜잭션은 스냅샷 격리 수준을 제공한다. 트랜잭션 내에서 읽은 데이터는 트랜잭션 시작 시점의 일관된 스냅샷을 기반으로 한다. |
지속성(Durability) | 쓰기 작업이 성공적으로 확인되면 데이터는 지속적 저장소에 안전하게 기록된 것으로 간주한다. 저널링을 통해 장애 복구를 보장한다. |
이러한 지원에도 불구하고, 다중 문서 트랜잭션의 사용은 성능 오버헤드를 수반하므로 신중하게 적용해야 한다. 트랜잭션의 지속 시간은 짧게 유지하고, 가능하면 스키마를 적절히 설계하여 단일 문서 내에서 작업을 완결하는 것이 권장된다. MongoDB의 접근 방식은 관계형 데이터베이스의 엄격한 트랜잭션 모델과 NoSQL의 유연성 및 확장성 요구 사이의 균형을 찾는 것으로 볼 수 있다.
분산 트랜잭션 관리는 여러 샤드에 걸쳐 저장된 데이터의 원자성(Atomicity)을 보장하는 메커니즘을 의미한다. MongoDB는 버전 4.0부터 단일 레플리카 셋 내에서의 다중 문서 트랜잭션을 지원하기 시작했으며, 버전 4.2부터는 샤드 클러스터 환경에서의 분산 다중 문서 트랜잭션을 공식 지원한다. 이는 여러 샤드에 분산된 문서들을 하나의 트랜잭션 단위로 묶어 ACID 속성을 준수하며 처리할 수 있게 한다.
분산 트랜잭션의 내부 동작은 2단계 커밋(Two-Phase Commit) 프로토콜을 기반으로 한다. 트랜잭션을 시작한 몽고스(mongos) 라우터는 조정자(coordinator) 역할을 하며, 관련된 모든 샤드에 트랜잭션 명령을 전파하고 최종 커밋 또는 중단(abort)을 결정한다. 이 과정은 다음과 같은 단계를 거친다.
단계 | 설명 |
|---|---|
준비 단계 (Prepare Phase) | 조정자가 모든 참여 샤드에게 트랜잭션 커밋 준비를 요청한다. 각 샤드는 트랜잭션의 변경 사항을 임시로 기록하고 준비 완료 신호를 보낸다. |
커밋 단계 (Commit Phase) | 모든 샤드가 준비에 성공하면, 조정자는 모든 샤드에게 최종 커밋을 지시한다. 하나라도 실패하면 전체 트랜잭션은 중단된다. |
이러한 분산 트랜잭션은 개발자에게 강력한 데이터 일관성 보장을 제공하지만, 성능과 가용성에 대한 비용이 따른다. 트랜잭션의 지속 시간이 길어질수록 관련 데이터에 대한 잠금이 유지되며, 이는 시스템의 동시성(concurrency)을 저하시킬 수 있다. 또한 네트워크 지연이나 노드 장애가 발생할 경우 트랜잭션 처리 시간이 증가하거나 복잡한 장애 복구 절차가 필요해진다. 따라서 설계 시에는 트랜잭션의 범위를 최소화하고, 스키마 디자인 단계에서 가능한 한 관련 데이터를 동일한 샤드에 배치하는 전략을 고려하는 것이 성능에 유리하다[8].
운영 환경에서 MongoDB의 안정성과 성능을 유지하기 위해서는 체계적인 백업, 복구, 모니터링 전략이 필수적이다. 이는 데이터 손실을 방지하고 시스템 장애 시 신속한 복구를 보장하며, 잠재적인 성능 병목 현상을 사전에 탐지하는 데 핵심적인 역할을 한다.
백업은 mongodump 유틸리티를 사용한 논리적 백업과 파일 시스템 스냅샷을 이용한 물리적 백업으로 구분된다. mongodump는 특정 데이터베이스나 컬렉션을 선택적으로 백업할 수 있어 유연성이 높지만, 대용량 데이터베이스에서는 수행 시간이 길어질 수 있다. 반면, 레플리카 셋의 보조 멤버에서 파일 시스템 스냅샷을 생성하는 물리적 백업은 전체 시스템의 상태를 빠르게 저장할 수 있어 운영 중인 서비스에 미치는 영향을 최소화한다. 복구는 mongorestore를 통해 백업된 데이터를 다시 로드하거나, 스냅샷으로부터 데이터 파일을 복원하는 방식으로 이루어진다. 특히 샤딩 클러스터 환경에서는 각 샤드와 컨피그 서버를 개별적으로 백업하고 조정된 순서로 복구해야 하는 복잡성이 추가된다.
성능 모니터링을 위해 MongoDB는 내장된 진단 도구와 상세한 메트릭을 제공한다. mongostat과 mongotop은 실시간으로 운영 체제 수준의 리소스 사용량(CPU, 메모리, 네트워크)과 데이터베이스 연산 유형별 소요 시간을 보여준다. 보다 심층적인 분석을 위해서는 데이터베이스 프로파일러를 활성화하여 느린 쿼리를 식별하거나, db.currentOp() 명령으로 현재 실행 중인 연산을 조사할 수 있다. 또한, 클라우드 서비스 제공업체의 관리형 서비스나 오픈소스 모니터링 도구(예: Prometheus와 Grafana)를 연동하여 지표를 수집하고 시각화하는 것이 일반적이다. 주요 관찰 지표는 다음과 같다.
모니터링 범주 | 주요 지표 | 설명 |
|---|---|---|
리소스 사용률 | CPU 사용률, 메모리 사용량, 디스크 I/O | 서버의 기본적인 여유 용량과 병목 지점을 파악한다. |
연산 성능 | 쿼리 실행 시간(Query Execution Time), 연산 수(ops/sec) | 인덱스 효율성과 애플리케이션 부하를 반영한다. |
복제 상태 | 레플리카 멤버 간 지연 시간(oplog lag), 멤버 상태 | 고가용성과 데이터 일관성에 영향을 미친다. |
샤딩 클러스터 | 청크 밸런스, 샤드 간 데이터 이동 현황 | 데이터 분산의 균형과 샤딩 효율성을 확인한다. |
이러한 운영 작업은 자동화 스크립트나 CI/CD 파이프라인에 통합하여 정기적으로 실행함으로써 인적 오류를 줄이고 운영 효율성을 높일 수 있다.
MongoDB의 백업 전략은 데이터의 중요성, 시스템 규모, 복구 시간 목표에 따라 달라진다. 가장 기본적인 방법은 mongodump와 mongorestore 명령줄 도구를 사용하는 것이다. mongodump는 데이터베이스나 컬렉션 단위로 BSON 형식의 바이너리 덤프를 생성하며, mongorestore는 이 덤프 파일로부터 데이터를 복구한다. 이 방법은 간단하지만, 백업 수행 중인 데이터베이스에 부하를 줄 수 있으며, 대용량 데이터셋에서는 완료 시간이 길어질 수 있다.
보다 안정적인 운영을 위해서는 파일 시스템 스냅샷을 활용하는 방법이 권장된다. 레플리카 셋의 보조 멤버에서 LVM[9], EBS[10] 스냅샷 또는 클라우드 공급자의 스냅샷 기능을 이용해 데이터 파일이 위치한 볼륨의 일관된 스냅샷을 생성한다. 이 방법은 데이터베이스를 잠그지 않고 빠르게 백업을 수행할 수 있으며, 특히 대규모 배포 환경에서 효율적이다. 스냅샷 생성 시점의 oplog(운영 로그)를 함께 보관하면, 특정 시점으로의 정확한 복구가 가능해진다.
복구 전략은 장애 시나리오에 따라 다르게 수립된다. 단일 문서나 컬렉션의 손실에는 mongorestore를 사용해 특정 컬렉션만 복원할 수 있다. 전체 노드 장애 시에는 레플리카 셋의 자동 복구 메커니즘에 의존하거나, 백업된 멤버를 새로운 노드로 교체한다. 가장 심각한 데이터 센터 장애와 같은 재해 복구 시나리오에는 지리적으로 분산된 백업 스냅샷이나 보조 데이터 센터의 레플리카 셋을 활용한다. 정기적인 복구 훈련을 통해 백업의 무결성과 복구 절차의 신뢰성을 검증하는 것이 필수적이다.
백업 방법 | 주요 도구/기술 | 장점 | 고려사항 |
|---|---|---|---|
논리적 백업 |
| 특정 DB/컬렉션 선택 백업 가능, 이식성 좋음 | 대용량 시 성능 저하, 운영 중 부하 발생 |
물리적 스냅샷 | 파일 시스템/볼륨 스냅샷 (LVM, EBS 등) | 빠른 수행, 운영 영향 최소화, 대용량 적합 | 스토리지 수준 지원 필요, 일관된 시점 확보 중요 |
지속적 백업 | Oplog 테일링, 클라우드 매니지드 서비스 | 거의 실시간 백업, 특정 시점 복구 정밀도 높음 | 구성이 복잡할 수 있음, 추가 스토리지 필요 |
MongoDB의 성능과 상태를 지속적으로 관찰하고 문제를 사전에 감지하기 위해 다양한 모니터링 도구를 사용할 수 있다. MongoDB는 자체적으로 제공하는 무료 도구와 상용 솔루션, 그리고 타사 모니터링 플랫폼과의 통합을 지원한다.
주요 모니터링 도구는 다음과 같다.
도구명 | 제공 주체 | 주요 특징 |
|---|---|---|
mongostat | MongoDB Inc. (내장 CLI 도구) | 실시간 서버 상태(연결 수, 큐 길이, CRUD 작업량, 네트워크 트래픽 등)를 터미널에서 간략히 확인[11] |
mongotop | MongoDB Inc. (내장 CLI 도구) | 컬렉션별 읽기/쓰기 작업에 소요된 시간을 보여주어 핫스팟 식별에 유용함 |
MongoDB Atlas | MongoDB Inc. (클라우드 서비스) | 클라우드 호스팅 환경에서 통합된 GUI 기반 모니터링, 성능 차트, 경고 설정, 로그 조회 제공 |
MongoDB Ops Manager / Cloud Manager | MongoDB Inc. (온프레미스/엔터프라이즈) | 자체 호스팅 배포를 위한 상용 모니터링, 자동화, 백업 솔루션[12] |
Database Profiler | MongoDB Inc. (내장 기능) | 느린 쿼리(기본 임계값 100ms)를 캡처하여 성능 병목 현상을 분석할 수 있게 함[13] |
이 외에도 널리 사용되는 APM(Application Performance Management) 및 인프라 모니터링 플랫폼과의 통합이 일반적이다. 예를 들어, Datadog, New Relic, Prometheus와 Grafana 조합은 지표 수집, 대시보드 시각화, 경고 발송을 위한 강력한 오픈소스 스택을 구성한다. Prometheus는 MongoDB Exporter를 통해 메트릭을 수집하고, Grafana에서 이를 사용자 정의 대시보드로 표현한다. 모니터링의 핵심 지표에는 QPS(초당 쿼리 수), 연결 수, 복제 지연 시간, CPU/메모리/디스크 사용률, 인덱스 히트율 등이 포함된다.
MongoDB는 유연한 스키마와 수평적 확장이 용이한 특성 덕분에 다양한 현대 애플리케이션에서 선호되는 데이터베이스이다. 특히 데이터 구조가 빠르게 진화하거나 예측하기 어려운 환경, 그리고 대규모 사용자 기반을 처리해야 하는 시나리오에서 강점을 발휘한다.
MongoDB가 적합한 대표적인 사용 사례는 다음과 같다.
사용 사례 | 설명 |
|---|---|
콘텐츠 관리 시스템(CMS) 및 사용자 프로필 | 블로그, 뉴스, 전자상거래의 제품 카탈로그 등 각기 다른 속성을 가진 콘텐츠를 하나의 컬렉션에 저장할 수 있다. 사용자 프로필도 선호도나 설정이 각기 달라 문서형 데이터베이스의 유연성이 빛을 발한다. |
실시간 분석 및 IoT 플랫폼 | 센서, 장치, 로그에서 발생하는 시간 순서의 대량 데이터를 효율적으로 수집한다. 도큐먼트 구조는 다양한 형식의 센서 데이터를 수용하며, 샤딩을 통해 데이터 유입량을 처리할 수 있다. |
모바일 및 소셜 애플리케이션 | 친구 관계, 피드, 위치 기반 데이터, 메시지 등 관계가 복잡한 데이터를 저장한다. 읽기 중심의 작업이 많고 급격한 사용자 증가에 대응하기 위한 수평 확장이 필요하다. |
캐싱 및 세션 저장소 | 키-값 저장소의 역할로도 사용될 수 있어, 빠른 응답이 필요한 세션 정보나 애플리케이션 캐시 데이터를 저장하는 데 적합하다. |
반면, MongoDB는 복잡한 다중 레코드 트랜잭션이 빈번하게 발생하는 금융 거래 시스템이나, 데이터 간의 관계가 매우 복잡하고 조인 연산이 쿼리의 핵심을 이루는 전통적인 엔터프라이즈 자원 관리 시스템에는 덜 적합할 수 있다. 이러한 경우에는 관계형 데이터베이스 관리 시스템이 더 나은 선택지가 될 수 있다. 결국 기술 선택은 애플리케이션의 데이터 모델, 일관성 요구사항, 확장성 목표를 종합적으로 평가한 후에 이루어져야 한다.