티스토리 뷰

NoSQL과 관련하여 살펴보고 있는데요. 

오늘은 10gen에서 개발한 몽고디비(MongoDB)에 대해서 간략하게 정리해 보려고 합니다. 

보통 NoSQL이라고 하는 데이터베이스는 스키마가 없이 Key-Value 쌍으로 언제든지 데이터를 저장한다는 특징을 가지고 있습니다. 

MongoDB도 역시 스키마 없는 Document Data Model을 기반으로 하고 있습니다. 


제가 Google App Engine을 사용할 때 Big Table이라는 구글의 NoSQL을 써봤는데요. 

간단한 기능을 개발할 때 DB 스키마를 만들지 않고 문서를 원하는대로 생성하고 저장하는 구조가 상당히 효율적이었던 기억이 나네요. 


아래 내용은 MongoDB in Action 책의 내용을 기반으로 작성했습니다.


MongoDB 개요

MongoDB는 웹 애플리케이션과 인터넷 기반을 위해 설계된 데이터베이스 관리 시스템입니다. 

MongoDB의 데이터 모델은 읽기/쓰기 효율을 높이고 자동으로 장애조치를 하고, 확장이 용이하도록 설계되어 있다고 합니다. 


일반적으로 개발자들이 MongoDB에 관심을 가지는 이유는 확장성 보다는 직관적인 데이터 모델 때문이라고 합니다. 

실제로 SQL보다 더 간결하게 SQL과 유사한 쿼리를 사용할 수 있다는 점이 가장 큰 매력이 아닌가 합니다. 

MongoDB에서는 프로그래밍 언어에서 정의한 객체가 그대로 저장되는 구조이기 때문에 객체 매핑을 하는 복잡함이 없다고 하네요. 


철저하게 확장성과 웹 애플리케이션을 위해서 설계되었기 때문에 기존의 RDB와는 확실한 차별점이 있다고 합니다. 

그래서인지 시스템 업그레이드가 아닌 분산 처리를 위한 확장을 지원하는 자동-샤딩(auto-sharding)이나 웹 문서 구조와 유사한 형태의 Document Data Model을 사용하고 있는것 같네요. 


MongoDB 핵심 기능


Document Data Model

MongoDB에서 가장 중요한 Document Data Model에 대해서 정리해 보겠습니다. 

백문이 불여일견이라고 실제 예제를 통해서 살펴보도록 하죠. 

아래 내용은 웹사이트에서 작성되는 하나의 글(post)라고 생각하면 될 것 같습니다. 


{ _id: ObjectID('4bd9e8e17cefd644108961bb'),
   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'
    }
  ]
}


위 내용을 잘 살펴보면 하나의 Document 안에 다른 Document들이 자유롭게 중첩해서 들어가 있는 것을 확인할 수 있습니다. 

만약 이것을 RDB로 설계했다면 정규화 과정을 통해 Post, Tags, Image, Comments 등의 여러 테이블이 만들어졌어야 겠지요. 


MySQL 명령어와 마찬가지로 use 명령어를 통해 사용할 데이터베이스를 설정하는데요. 

앞서 이야기 한대로 미리 스키마가 만들어진 것이 아니기 때문에 최초 데이터를 입력하는 순간에 생성이 된다고 합니다.  


즉, 위 Document를 처음 생성할때 다음과 같이 사용한다면 첫 라인에서 데이터베이스가 생성되는 것이 아니고 

두번째 라인을 실행할 때 실제 데이터베이스가 생성된다고 보면 됩니다. 


> use mongodb_mini
> db.post.insert({title: 'Adventures in Databases'})



Ad-hoc Query

Ad-hoc Query라는 것은 시스템이 받아들일 수 있는 Query를 미리 정의할 필요가 없다는 것을 의미한다고 합니다. 

기존 RDB의 SQL처럼 필요할 때, Query를 생성해서 결과를 받을 수 있다는 것이죠. 


MongoDB에서는 Query를 작성할 때 정규화된 모델이 아니므로 각 검색 항목들이 Document에 포함되어 있다고 가정하고 진행합니다. 

위에서 예제로 만든 Document 모델에 대해 쿼리를 실행하는 것을 보면 명확하게 이해할 수 있을 것입니다. 

먼저 기존 SQL로 정규화된 테이블에 쿼리를 보낸다면 다음과 같이 했을 것입니다. 


SELECT * FROM POSTS
  INNER JOIN posts_tags ON posts.id = posts_tags.post_id
  INNER JOIN tags ON posts_tags.tag_id = tags.id
  WHERE tags.text = 'politics' AND posts.vote_count > 10;


그러나 같은 Query를 MongoDB에서는 다음과 같이 만듭니다. 


> db.posts.find({'tags': 'politics', 'vote_count': {'$gt': 10}});


굉장히 단순하면서도 직관적인 것을 알 수 있습니다. 

아마도 이래서 MongoDB가 개발자들에게 인기가 많은 것 같네요.. 


기타 기능들

MongoDB에서도 인덱스를 사용할 수 있구요. 

내부적으로 인덱스는 B 트리로 구현되어 있다고 합니다. 

한 컬렉션에서 64개까지 인덱스를 생성할 있으며, 오름차순, 역순, 고유키, 복합키 등 RDB에서 볼 수 있는 모든 인덱스가 가능하다고 합니다. 


데이터베이스는 장애에 대응하기위한 복제 기능을 가지고 있는데요. 

MongoDB도 복제셋(Replica Set)이라는 구성을 통해 서버와 네트워크 장애가 발생할 경우를 위해 마스터-슬레이브 형태로 분산이 가능하다고 합니다.


또한 쓰기 속도 향상을 위해서 write symantics를 사용하고 내구성을 위해서 저널링(journaling)을 사용한다고 합니다. 

쓰기 속도에 시간이 걸리기 때문에 모든 쓰기는 명령하고 잊어버리는 모드로 구성되어 있다고 하네요. 

대신 저널링을 통해 모든 쓰기에 대한 로그를 기록하고, 정전 등 셧다운 발생시 저널이 MongoDB 파일을 복구해서 원래의 상태를 유지할 수 있도록 한다고 합니다. 


확장과 관련해서도 하나의 노드에 대해 메모리와 같은 하드웨어를 업그레이드 하는 대신 

데이터베이스를 여러 서버에 분산할 수 있는 수평적 확장(scaling horizontally) 또는 외적 확장(scale out)을 지원한다고 합니다. 

자동 샤딩 (auto-sharding)으로 알려진 파티션 매커니즘을 통해 데이터를 여러 노드에 걸쳐 분산하는 것을 자동으로 관리해 준다고 하네요. 


MongoDB 라이센스 및 개발도구 

MongoDB는 GNU-AGPL 라이센스를 가지고 있습니다. 

AGPL은 소스 코드는 무료로 이용 가능하지만 커뮤니티가 개발에 기여하는 것을 장려한다는 것이 주요 내용입니다. 

그래서 나타나는 제약 조건이 바로 소스 코드에 대한 수정 사항은 커뮤니티의 이익을 위해 공개되어야 한다는 것입니다. 

만약 공개를 원하지 않을 경우, 상업용 라이센스를 구매해야 한다는 것이죠. 


솔직히 이 부분이 프로젝트에서 MongoDB를 사용하는 것을 주저하게 만드는 이유이기도 합니다. 

MongoDB를 활용한 부분에 대해 어디까지 소스 공개를 해야 하며

만약 소스 코드 수정 없이 그대로 사용한다면 공개를 안해도 되는 것인지 논란이 있기는 합니다. 


MongoDB의 서버는 mongod 라는 실행 프로그램을 통해 구동됩니다. 

mongod 프로세스의 데이터 파일은 모두 같은 서버에 저장되고, 저장되는 위치는 /data/db로 기본 설정되어 있습니다. 


앞서 제가 예제로 보여준 것('>'로 시작하는 명령어)과 같은 명령어를 실행할 수 있는 셀을 제공하는데요. 

이 MongoDB 명령어 셀은 자바스크립트에 기반한 툴로 데이터베이스를 관리하고 데이터를 조작하는데 사용할 수 있습니다. 


프로그래밍과 연동을 위해 10gen에서 공식적으로 제공하는 데이터베이스 드라이버는 C, C++, C#, Java, Perl, PHP, Python, Ruby 등이 있습니다. 

거의 대부분의 언어에 대한 드라이버가 제공되며, Document를 표현하는 방식이 각 언어에 가장 자연스러운 형태로 제공한다고 합니다. 

즉, Ruby에서는 Document가 Ruby Hash로 표현되고, Python에서는 Dictionary로, 그리고 자바에서는 Document Builder Class인 LinkedHashMap을 사용한다고 하네요. 


마지막으로 MongoDB에서는 여러가지 command line 도구를 제공합니다. 

  • mongodump, mongorestore: 백업과 복구를 위한 유틸리티
  • mongoexport, mongoimport: JSON, CVS 등의 데이터를 export/import 할 수 있는 유틸리티
  • mongosniff: BSON을 읽기 쉬운 셀 문장으로 변환한다고 하는데요.. wire-sniffing 도구라고 하는데 안써봐서 아직 ㅠㅠ
  • mongostat: MongoDB를 폴링해서 유용한 통계 데이터를 제공하는 유틸리티


참고로 MonogoDB는 64bit 시스템에서 실행되어야 한다고 합니다. 

32bit 시스템에서는 4GB의 메모리만 사용하므로 최대 사용 가능한 데이터의 크기가 1.5GB에 불과하기 때문이라고 하네요. 


마치면서 

솔직히 아직 MongoDB를 활용한 프로젝트를 수행해 보지는 않았습니다. 

특히 GNU-AGPL이라는 라이센스의 제약 때문에 섣불리 사용하기도 쉽지 않구요. 

그러나 각 NoSQL들의 특성을 하나씩 살펴보면서 현재 프로젝트에 적합한 것이 어떤 것인지 꾸준히 살펴보려고 합니다. 

경우에 따라서는 기존의 RDB가 더 나을 수도 있다는 개인적인 판단을 할 수도 있겠죠.. ^^


댓글
  • 프로필사진 paul_kyeong 모바일 어플리케이션 데이터 저장용이나, 트위터 데이터등을 저장하고 분석핢대 유용한것 같습니다. 다만 몽고디비에 저장된 데이터 row가 100만건 이상인 경우에는 mapreduce의 속도가 많이 떨어지네요.. 그래서 하둡으로 갈아타야하나? 고민하고 있습니닼 2013.02.23 08:11
  • 프로필사진 미니~ 그렇군요.. ^^ 역시 이런 경우에는 하둡이 보다 효율적일 듯 합니다. 하둡 클러스터링을 활용하면 Data Node만 확장해도 MapReduce의 속도 향상을 기대해 볼 수 있을 겁니다. 2013.02.23 11:23 신고
댓글쓰기 폼