MongoDB란 - 역사, 설계 목표, 핵심 기능, 몽고DB를 사용하는 이유

Share

Last Updated on 1월 20, 2024 by Jade(정현호)

안녕하세요 
이번 포스팅은 MongoDB in Action(몽고디비 인 액션) 2nd Edition 책의 내용을 정리한 글입니다 

인터넷에서 태어나다

MongoDB 의 역사는 간단하지만, 좀 더 야심 찬 프로젝트로 부터 만들어진 것이라 되새겨 볼 만한 가치는 있습니다.

2007년 중반 뉴욕에 위치한 10gen 이라는 신생 기업이 웹 애플리케이션을 호스트하고 필요하면 확장할 수 있는 애플리케이션 서버와 데이터베이스로 이루어진, PaaS(서비스형 플랫폼) 제품의 구성 요소로 처음 개발하기 시작하였습니다.


10gen 의 플랫폼은 하드웨어와 소프트웨어 인프라의 관리와 확장성을 자동으로 처리하고, 그에 따라 개발자들은 애플리케이션 개발에 집중하게 하려는 목적으로 설계되었습니다.

10gen 은 개발자들이 기존의 정형화된 계층적 구조 상황이 제어하기 어렵다는 점 또는 불편해한다는 점이 있었고, 사용자들은 10gen에게서 새로운 데이터베이스 기술을 원하였습니다.
이는 10gen으로 하여금 이후 부터 MongoDB 에 집중하여 개발하도록 하는 계기가 되었습니다.

2009년에 오픈소스 프로젝트로서 개발 모델을 전환하였으며, 상용 지원과 기타 서비스를 제공하는 방식을 채택하였습니다
그 후 2013년에 10gen은 회사 이름을 MongoDB 로 변경하게 되었습니다

오픈소스이지만 여전히 MongoDB 의 핵심 개발자들은 MongoDB의 설립자이거나 직원이고, 프로젝트의 로드맵은 사용자 커뮤니티의 필요에 의해서, 그리고 관계형 데이터베이스 와 키-값(key-value) 분산 저장 시스템에서 장점만을 통합하는 데이터베이스 설계라는 주요 목표로 개발되어가고 있습니다.

도큐먼트 데이터베이스(NoSQL)

최근에 웹 애플리키에션을 개발한 적이 있다면 일차적으로 데이터의 저장소로는 아마 관계형 데이터베이스(Relational database) 를 사용했을 것입니다.
SQL에 친숙하다면 정규화가 잘된 데이터 모델의 유용함과 트랜잭션(transaction)의 필요성 그리고 안전한(견고한) 저장 엔진을 통해 빠르고 편리하게 사용할 수 있음을 알고 있을 것입니다.

간단하게 말해서 관계형 데이터베이스는 이미 충분히 발전되고 잘 알려져 있는 기술입니다.
개발자들이 데이터 저장 기술의 대안에 대해서 말하기 시작할 때 이 새로운 기술들의 실현 가능성과 유용성에 대한 의문이 생긴다.
또한 새로운 저장 시스템은 관계형 데이터베이스를 대체할 할 것인지? 또는 무엇으로 대체할지 등에서 궁금할 것입니다.

비 관계형 데이터베이스(nonrelational database) 로 옮기면 어떤 장단점이 있을까요?
그렇다면 개발자나 시스템 구성 시 왜 MongoDB에 관심을 갖고 있는 걸까요?

MongoDB 는 웹 애플리케이션과 인터넷 기반을 위해 설계된 데이터베이스 관리 시스템입니다.
또한 데이터 모델과 지속성 전략을 높은 읽기/쓰기 효율과 자동 장애조치(failover)를 통한 확장의 용이성을 염두에 두고 만들어졌습니다.

애플리케이션에서 필요한 데이터베이스 노드가 하나 이거나 혹은 그 이상이거나 관계없이 MongoDB 는 놀라울 정도로 좋은 성능을 보여 줍니다.

관계형 데이터베이스를 사용하면서 확장하는데 어려움을 겪었던 적이 있다면 이것은 매우 반가운 소식일 것입니다.
(물론 모든 경우에 확장이 필요한 것은 아닙니다.)

모든 경우에서 다수의 노드, 확장이 필요하지 않을 수 있으며 어쩌면 단 하나의 데이터베이스 서버만 필요한 경우도 있을 것입니다.
이럴 경우에도 MongoDB를 사용할 이유가 있을까요?

개발자들이 MongoDB 를 사용하는 이유는 아마도 확장성 때문이 아니라 직관적인 데이터 모델 때문 일 것입니다.
MongoDB 는 그 정보를 행(row) 대신 도큐먼트(document) 에 저장합니다.

도큐먼트란 무엇일까요 예제를 통해 확인해 보면 다음과 같습니다.

{
    _id: 10,
    username: 'jade',
    email: 'abc1@test.com'
}


매우 단순한 도큐먼트 입니다. 사용자에 대한 정보를 몇개의 필드(field) 로 저장하고 있습니다.

이와 같은 모델의 장점은 무엇일까요? 각각의 사용자에 대해 여러 개의 이메일 주소를 저장하는 경우를 생각해 보면 관계형 모델에서는 서로 조인(join)을 하기 위해 이메일(email) 주소와 사용자(user) 테이블을 각각 만들어야 할 것입니다.

MongoDB 는 이러한 정보를 저장하기 위한 다른 방법을 제공함으로써 아래와 같은 이메일 주소를 배열로 만들어 문제를 해결할 수 있습니다.

{
    _id: 10,
    username: 'jade',
    email: [
        'abc1@test.com',
        'abc2@test.com'
    ]
}


개발자 입장에서 테이블의 변경이 발생하였을 때 테이블을 추가하거나 스키마를 맞춰야 하는 걱정 없이 구조화된 도큐먼트를 데이터베이스에 저장할 수 있다는 것이 매우 유연하다고 느껴질 수 있습니다.

MongoDB 의 도큐먼트 형식은 임의의 데이터 구조를 저장하는 스키마로 잘 알려진 JSON 에 기반합니다.
JSON 은 JavaScript Object Notation 의 약어 입니다.

위의 내용은 JSON 구조는 키(key) 와 키에 대한 값(value) 로 이루어져 있고, 중첩에 제한이 없습니다.
JSON은 프로그래밍 언어에서 사전(dictionary) 이나 해시 맵(hash map) 과 유사 합니다.

도큐먼트 기반의 데이터 모델은 풍부하고 계층적인 구조의 데이터를 표현할 수 있습니다.
따라서 관계형 데이터베이스에서 필요한 여러 테이블 간의 복잡한 조인 연산이 없어도 됩니다.

예를 들어 우리가 전자상거래 사이트의 상품을 모델링 한다고 할 때 완전히 정규화 된 데이터 모델에서 한 상품의 정보는 아마도 여러 개의 테이블에 나뉘어 저장될 것입니다.

한 상품에 대한 레코드를 얻기 위해서는 조인 연산으로 많이 있는 복잡한 SQL 쿼리를 이용해야 할 것입니다.

그와 반대로, 도큐먼트 모델에서는 대부분의 상품 정보를 하나의 도큐먼트로 표현할 수 있습니다
(물론 업무에 따른 컬렉션에 대한 적절한 모델링은 필요 할 것입니다)

MongoDB 에서 상품 정보를 조회해 보면 JSON 과 같은 형태로 계층 구조를 통해 이해하기 쉽게 표현되어 있음을 알 수 있습니다.
또한 도큐먼트에 대해 조회도 할 수 있고 데이터 변경 조작도 할 수 있습니다.

MongoDB의 쿼리 언어 기능은 특별히 도큐먼트 구조의 조작을 위해 설계되었고, 결과적으로 관계형 데이터베이스로 부터 MongoDB 로 옮겨온 사용자들은 관계형 데이터베이스와 비슷한 수준의 쿼리 언어 성능을 경험하게 됩니다.

또한 대부분의 개발자들은 현재 객체지향 언어를 사용해서 작업하고 있으므로 객체에 잘 매핑(mapping)되는 데이터 저장 구조를 원하게 됩니다.

MongoDB 에서는 프로그래밍 언어에서 정의한 객체가 그대로 저장되므로 객체 매퍼(mapper) 의 복잡성이 사라지게 됩니다.

MongoDB의 핵심 기능

1. 도큐먼트 데이터 모델

MongoDB는 도큐먼트 지향적인 데이터베이스입니다.

{ _id: ObjectID("4bd9e8e17cefd644108961bb"), <-- _id 필드가 프라이머리 키
title: "Adventures in Databases",
url: "http://example.com/databases.txt",
author: "msmith",
vote_count: 20,
tags: ["databases", "mongodb", "indexing"], <-- 태그는 문자열의 배열로 저장

image: {  <-- 속성이 또 다른 도큐먼트를 가리킴 
url: "http://example.com/db.jpg",
caption: "",
type: "jpg",
  size: 75381,
data: "Binary" },

comments: [
    { user: 'bjones',
    text: 'Interesting article!'
},
    { 
        user: 'blogger',
        text: 'Another related article is at http://example.com/db/db.txt'
       }
    ]
}


위에서 볼 수 있듯이 도큐먼트는 본질적으로 속성의 이름 과 값으로 이루어진 쌍의 집합입니다.
속성의 값은 문자열이나 숫자, 날짜와 같은 간단한 데이터 타입이 될 수 있습니다.
또는 이 값은 배열이나 심지어 다른 JSON 도큐먼트가 될 수도 있습니다.

이러한 구성 요소들을 통해 하나의 도큐먼트로 다양한 구조의 데이터를 표현할 수 있습니다.
tags 라는 속성 값은 배열로 저장한 것을 볼수 있으며, comments 속성은 이 속성의 값은 다른 도큐먼트로 표현한 코멘트 도큐먼트의 배열 이 되게 됩니다.

MongoDB 는 도큐먼트의 모음인 컬렉션(collection)에 도큐먼트로 저장하는 반면, MySQL 이나 다른 RDBMS 에서는 데이터를 테이블의 행으로 저장합니다.

RDBMS 에서는 보통 한 객체(object)의 데이터를 여러 개의 테이블로 나누어 표현하는 기법인 정규화(normalization) 을 이용하게 됩니다.
하지만 정규화를 많이 하게 되면 그에 따른 비용이 들어가게 되며, 이는 곧 데이터를 모으는 작업에 많은 비용이 들어간다는 것을 의미합니다.

도큐먼트 지향적인 데이터 모델에서는 객체를 자연스럽게 모아 놓는 형태로 표현함으로써 객체를 전체적으로 작업할 수 있다는 점이 있습니다
구조가 다양하는 점 이외에도 도큐먼트에는 미리 정해진 스키마 정의가 없습니다.

관계형 데이터베이스에서는 데이터 열을 테이블에 저장합니다. 각 테이블은 각각의 컬럼에 대해서 허용되는 데이터 타입을 명시하게 됩니다.
그 테이블에서 한 데이터 열에 필드 하나라를 더 추가 해야할 경우는 테이블의 구조를 변경해줘야 합니다.

MongoDB에서는 도큐먼트를 컬렉션으로 모아 놓는데, 어떤 종류의 스키마도 필요하지 않습니다.
이론적으로는 하나의 컬렉션에 포함되어 있는 각각의 도큐먼트들이 서로 완전히 다른 구조를 갖는 것도 가능은 합니다만 실제로는 컬렉션 내에서 도큐먼트들은 상대적으로 균일한 구조를 갖게 됩니다.


2. 스키마가 없는 모델의 장점

스키마가 없다는 것(schema-less)은 몇 가지 장점을 가지게 됩니다.

먼저, 데이터베이스가 아닌 애플리케이션이 데이터 구조를 정한다는 것입니다.
이는 데이터의 구조가 빈번히 변경되는 개발 프로젝트 초기 단계에서 개발 시간을 단축시켜 줄 수 있습니다.

더 중요한 것으로는 스키마가 없는 데이터 모델을 통해 가변적인 속성을 갖는 데이터를 표현할 수 있다는 것입니다.

예를 들어 전자상거래 상품 카탈로그를 만든다고 하였을 때 하나의 상품이 어떤 속성을 갖게 될지 미리 알 수 없으므로 애플리케이션에서는 이러한 가변적인 속성을 처리할 수 있어야 합니다.

도큐먼트로 데이터 모델링을 하게 되면 조인이 필요 없고, 새로운 속성은 한 도큐먼트에 동적으로 추가할 수 있습니다.

MongoDB 는 애플리케이션이 개발을 할 때 추후에 필요할 데이터 필드가 무엇인지에 대해서 고민이나 걱정이 상대적으로 부담이 덜 될 수 있다는 점입니다.


3. 애드훅 쿼리

MongoDB는 Ad hoc 쿼리를 사용합니다.

MongoDB의 설계 목표 중 하나는 관계형 데이터베이스상에서 매우 필수적인 쿼리 언어 성능을 대부분 유지하는 것입니다.


애드혹 쿼리는 특정한 목적을 위해서 라는 의미를 가지게 됩니다.
MongoDB 는 문서를 저장하고 조회 목적에 맞는 조회 방법을 제공하며, 값, 범위($gt,$lt 등) 조회, 정규식 검색 등을 지원하고 자바스크립트의 함수를 사용할 수도 있습니다.


4. 인덱스

MongoDB 도 관계형 데이터베이스에서 필수적으로 사용하는 인덱스를 지원하며 인덱스는 B-Tree 인덱스로 구현되어 있습니다.
대부분의 데이터베이스는 각 도큐먼트 또는 각 행의 기준을 위한 고유의 식별자로서 프라이머리 키(Primary Key) 를 부여합니다.

프라이머리 키는 자동적으로 인덱스되며 고유한 값을 유지하기 위해서 유니크 키 를 사용하게 됩니다.
MongoDB는 여러개의 세컨더리 인덱스를 허용함으로 여러 조회 조건을 빠르게 처리할 수 있도록 합니다.

세컨더리 인덱스에 대해서 오름차순, 내림차순, 고유(unique), 복합 키, 해시, 텍스트, 지리공간적 인덱스 와 같은 관계형 데이터베이스에서 볼 수 있는 거의 모든 인덱스 사용이 가능 합니다.

관계형 데이터베이스와 같은 데이터 구조를 가지므로 인덱스를 관리하기 위한 권고사항이나 전략은 양쪽 다 적용할 수 있습니다.

Note

WiredTiger의 LSM(Log-Structured Merge-trees) 에서는 B-Tree 인덱스가 지원되지 않습니다.



5. 복제

MongoDB 는 복제 세트(Replica Set) 라고 부르는 구성을 통해서 데이터베이스 복제 기능을 제공합니다.

복제 기능은 서버와 네트워크 등의 장애가 발생할 경우를 대비해 중복성 관리와 장애조치 자동화를 위해서 데이터를 여러 대의 서버에 분산하게 됩니다.


또한 복제는 데이터베이스의 읽기에 대한 확장을 위해서도 사용됩니다.
읽기 위주의 서비스에서는 데이터베이스의 읽기를 복제 세트 클러스터 내의 여러 서버에 분산할 수 있습니다.

복제는 많은 MongoDB 서버로 구성되며, 보통 서버는 분리되어 있으며 이를 노드(node) 라고 부릅니다.
어느 순간이든지 하나의 노드는 복제 구성에서 프라이머리 노드(Primary node) 로 존재하게 되며, 하나 또는 그 이상의 세컨더리 노드가 존재하게 됩니다.
관계형 데이터베이스의 복제 방식과 유사하게 프라이머리 노드에서만 읽기와 쓰기가 모두 가능하며 세컨더리 노드는 읽기만 가능 합니다.

복제 세트의 고유한 기능으로 자동 장애조치를 지원한다는 점이며 프라이머리 노드에 장애가 발생하면 클러스터는 자동으로 세컨더리 가운데 하나를 선택해서 프라이머리로 설정(승격) 하게 됩니다.


6. 속도와 내구성

데이터베이스 시스템에서는 쓰기 속도와 내구성(안정성) 사이는 역관계 또는 상충관계(trade-off)가 되게 됩니다.
쓰기 속도는 미리 정해진 시간 내에 데이터베이스가 얼마나 많은 수 또는 량을 삽입, 수정, 삭제 처리할 수 있는 지를 의미합니다.

내구성은 이러한 쓰기 연산이 디스크에 제대로 반영됨을 확신할 수 있다 정도의 의미를 가지고 있습니다.

MongoDB의 경우 쓰기 시맨틱스(Write semantics) 와 저널링(journaling) 을 통해 속도와 내구성 사이에서 타협을 이룰 수 있습니다.

MongoDB 를 fire-and-forget 모드로 설정하면 확인을 기다릴 필요 없이 서버에 쓰기 작업을 전송할 수 있습니다.
또한 커밋이 되었는지 확인하기 전에 다수의 복제 서버들에 대한 쓰기를 보장하도록 설정할 수도 있습니다.

단위 데이터는 작지만 양은 방대한 데이터(가령 클릭스트림 이나 로그 와 같은)에 대해서는 fire-and-forget 모드 쓰기가 적합하고,
중요한 데이터의 경우에는 안전 모드 쓰기가 더 낫습니다.

MongoDB v2.0 이후로 저널링이 사용 가능 상태로 설정되며, 저널링은 모든 쓰기에 대한 로그를 100ms 마다 한 번씩 저널 파일에 기록하게 합니다.

쓰기 부하에 대한 성능을 향상시키기 위해 저널링을 하지 않은 채 실행할 수도 있습니다.
이렇게 할 때의 단점은 불시에 서버가 셧다운 될 때 데이터 파일이 손상될 수도 있다는 점입니다.

저널링을 사용하지 않는 경우에는 장애가 발생하더라도 손상되지 않은 데이터 복사본을 가질 가능성을 높이기 위해서 다른 데이터 센터의 데이터베이스로 복제를 하는 것이 좋습니다.


7. 확장

일반적으로 애플리케이션이 하나의 데이터베이스 노드 만을 가질 때, 일반적인 경우는 디스크나 메모리 혹은 CPU를 추가해서 데이터베이스 병목 현상을 완화시킬 수 있으며 이를 수직적 확장이라고 합니다.

그와 반대로 수평적 확장은 하나의 노드를 업그레이드하는 것이 아닌, 데이터베이스를 여러 대의 서버에 분산시키는 것을 의미합니다. (scaling horizontally)

수평적 확장 구조는 기존의 하드웨어를 재 사용할 수도 있으므로 비용이 절감할 수 있으며, 시스템 장애가 발생해도 분산된 서버로 인해 장애에 따른 피해가 감소하게 됩니다.

몽고DB는 수평적 확장이 용이하도록 설계되어 있습니다
샤딩(sharding)으로 알려진 범위 기반(range-based) 파티션 메커니즘을 통해 데이터를 여러 노드에 걸쳐 분산하는 것을 자동으로 관리해줍니다.

샤딩 시스템은 샤드 노드를 추가해서 용량을 필요한 만큼 늘리고 자동 장애조치 기능도 제공합니다.
각각의 샤드는 최소한 두 개의 노드로 구성된 복제 세트로 이루어져 있으며 어느 한 노드에서 장애가 발생 하게 되면 자동으로 복구되도록 보장합니다.

애플리케이션에서는 하나의 노드에 연결된 것처럼 샤드 클러스터에 연결을 하면 됩니다.
       

Conclusion

위의 내용들을 정리해보면 "MongoDB 를 사용하는 이유" 정도로 정리할 수 있을 것 같습니다.

위에서 MongoDB 가 좋은 점 여러가지에 대해서 살펴보았으며 이런 내용을 정리하여 MongoDB를 선택하는 당위성이 조금 더 명확해질 것입니다.

MongoDB는 관계형 데이터베이스와 키-값 저장시스템의 장점만 모아서 설계가 되었습니다.
키-값 저장(Key-value store) 시스템은 단순성으로 인해 속도가 매우 빠르고 확장도 상대적으로 용이 합니다.

반면에 관계형 데이터베이스는 수평적인 확장이 어려운 반면에 다양한 데이터 모델과 강력하고 쉬운 SQL 쿼리 언어를 가지고 있습니다.

MongoDB는 이 둘 사이의 유용한 측면을 취하는 타협점을 최종 목표로 쉽게 확장되고, 다양한구조의 데이터를 저장할 수 있고, 정교한 쿼리 언어를 갖는 데이터베이스가 되는 것이 목표로 계속 개발 중입니다.
        

Reference

Reference Book
MongoDB in Action(몽고디비 인 액션) 2nd Edition



관련된 다른 글 

 

 

       

0
글에 대한 당신의 생각을 기다립니다. 댓글 의견 주세요!x