모든 NoSQL 데이터베이스가 비슷한 것도 아니고, 같은 문제를 해결해주는 것도 아니다. 따라서 이들 제품을 비교해 하나를 선택하더라도 큰 소득은 없다. 하지만 특정 상황과 맥락에 어떤 데이터베이스가 적합한지 이해하는 일만큼은 여전히 중요하다. 이 장에서는 사용 가능한 NoSQL 제품을 비교, 대조하는 데 도움되는 사실과 견해를 소개한다. 이 과정에서 NoSQL 데이터베이스를 분류하고 서로의 장단점을 가늠하기 위해 기능, 성능, 맥락 기반의 조건을 사용한다.
NoSQL의 진화와 RDBMS를 넘어선 데이터베이스의 발전은 과거 몇 년간 여러 프로그래밍 언어가 빠르게 발전한 것에 견줄 수 있다. 여러 프로그래밍 언어를 사용할 수 있게 되면서 우리는 특정 작업에 맞는 적합한 언어를 사용할 수 있게 됐고, 한 개발자가 종종 여러 언어를 활용하는 일도 일어났다. 여러 언어를 활용할 수 있는 개발자는 여러 외국어를 말할 수 있는 사람에 비유할 수 있다. 여러 언어에 대한 지식을 갖춘 사람은 다국어 활용자가 된다. 다국어 활용자는 곤란한 상황에서도 효과적으로 의사소통할 수 있다. 마찬가지로 여러 프로그래밍 언어를 받아들이는 것을 다언어(polyglot) 프로그래밍이라고 한다. 종종 다언어 프로그래밍은 작업에 적합한 언어를 사용하는 현명한 프로그래밍 방식으로 간주한다. 같은 선상에서 한 데이터베이스가 모든 크기에 적합하지 않은 만큼 여러 데이터베이스에 대한 지식과 채택도 현명한 전략이라 할 수 있다. 여러 데이터베이스 제품에 대한 지식과 활용 및 방법론은 현재 다언어 영속성이라고 부른다.
NoSQL 데이터베이스는 모양, 크기, 형태가 다양한 만큼 이를 논리적으로 분류하려면 먼저 기능을 중심으로 비교해야 한다. 보통 많은 문제에 대한 해결책은 결국 특정 기능으로 매핑되기 때문이다.
NOSQL 제품 비교
이 절에서는 다음 기능을 중심으로 NoSQL 제품을 비교, 대조한다.
- 확장성
- 트랜잭션 정합성 및 일관성
- 데이터 모델링
- 쿼리 지원
- 접근성 및 인터페이스 가용성
확장성
모든 NoSQL 데이터베이스가 수평적 확장성을 약속하지만 이 문제를 동일하게 해결해주는 것은 아니다. 이 기능에 있어서는 빅테이블 복제품(HBase 및 하이퍼테이블)이 가장 앞서 있고 인메모리 저장소(멤베이스 및 레디스)와 도큐먼트 데이터베이스(몽고디비, 카우치베이스 서버)는 뒤처져 있다. 이런 차이는 데이터의 크기가 훨씬 커짐에 따라 더욱 두드러진다. 특히 데이터가 페타바이트 이상 커질 경우에는 더욱 그렇다.
앞의 몇 장을 통해 대부분의 주류 NoSQL 데이터베이스에서의 저장 아키텍처에 대해 깊이 있게 이해할 수 있었다. 빅테이블과 그 복제품은 대규모의 개별적 데이터 포인트와 대규모 데이터 컬렉션의 저장 방식을 선호한다. 빅테이블 모델은 많은 칼럼과 수많은 행을 지원한다. 데이터는 많은 칼럼에 값이 없을 경우 희소성을 보일 수 있다. 물론 빅테이블 모델은 공간을 낭비하지 않으며 값이 없는 셀은 그냥 저장하지 않는다.
Note
HBase 클러스터에서 칼럼 및 행의 개수는 이론적으로 제한이 없다. 칼럼 패밀리의 개수는 약 100개로 제한된다. 행의 개수는 데이터를 저장할 수 있는 새 노드를 사용할 수 있는 한 계속해서 늘어날 수 있다. 칼럼 개수는 보통 몇 백 개를 넘는 경우가 거의 없다. 칼럼이 지나치게 많으면 데이터셋을 관리하는 게 논리적으로 어려워진다.
구글은 크롤러가 가져오는 웹 인덱스가 날로 증가함에 따라 이를 저장하기 위해 칼럼 패밀리 중심의 데이터 저장소 혁명을 이끌었다. 웹은 지난 몇 년간 무한히 성장했다. 구글은 늘어나는 인덱스와 함께 성장할 수 있는 저장소가 필요했다. 따라서 빅테이블과 그 복제품은 클러스터 내에서 새로운 노드로 분화할 수 있는 하드웨어의 가용성을 통해서만 확장성에 제한을 받게끔 개발됐다. 지난 몇 년간 구글은 빅테이블 모델을 성공적으로 사용해 규모가 매우 큰 수많은 데이터를 저장하고 조회했다.
HBase 위키의 Powered By 페이지(http://wiki.apache.org/hadoop/Hbase/PoweredBy)에서는 수많은 사용자를 볼 수 있다. 그리고 이 중 일부 사용자는 HBase의 확장성을 충분히 증명해준다.
Note
다음 단락에서는 HBase의 기능을 다루고 있지만 구글 빅테이블의 또 다른 복제품인 하이퍼테이블도 이와 동일한 약속을 제공한다.
미트업(www.meetup.com)은 사용자 그룹과 이익 단체가 지역 이벤트와 미팅을 주선할 수 있게 해주는 인기 있는 사이트다. 미트업은 2001년 알려지지 않은 작은 사이트에서 출발해 100개국 800만 회원, 65,000개 이상의 모임 주선자, 80,000개 이상의 모임 그룹, 매주 50,000개의 미트업으로 발전했다(http://online.wsj.com/article/SB10001424052748704170404575624733792905708.html). 미트업도 HBase를 사용한다. 모든 그룹 활동은 HBase에 직접 쓰고, 회원별로 인덱싱된다. 회원의 커스텀 피드는 HBase로부터 직접 제공된다.
페이스북도 HBase를 사용하는 또 다른 주요 사용자다. 페이스북의 메시지 기능은 HBase를 기반으로 개발됐다. 2010년 페이스북은 인터넷상에서 가장 많은 방문자가 찾는 사이트로 기록됐다. 페이스북은 5억 명 이상의 유효 사용자(http://www.facebook.com/press/info.php?statistics)를 갖고 있으며 사용자 수로 보면 세계에서 가장 큰 소프트웨어 애플리케이션이다. 페이스북의 메시지 기능은 채팅, SMS, 이메일을 통합하는 강력한 인프라스트럭처다. 매달 페이스북의 메시지 인프라스트럭처를 통해 수천억 개의 메시지가 전달된다. 페이스북의 엔지니어링 팀은 메시지 인프라스트럭처에 HBase를 사용하는 것과 관련해 몇 가지 글을 공유했다. 이 글은 http://www.facebook.com/notes/facebook-engineering/the-underlying-technology-of-messages/454991608919에서 볼 수 있다.
HBase는 확장 시스템과 관련해 태생적인 장점이 몇 가지 있다. HBase는 자동 로드 밸런싱, 장애 극복(failover), 압축, 서버별 다중 샤드를 지원한다. HBase는 하둡 분산 파일 시스템(즉 HDFS로, 대규모 확장이 가능한 분산 파일 시스템)과도 잘 연동된다. 앞에서 다른 장을 통해 HDFS가 여러 서버에 걸친 대규모 파일을 손쉽게 수용하기 위해 복제 및 자동 재밸런싱을 한다는 사실을 이미 배운 바 있다. 페이스북은 이와 같은 여러 기능을 활용하기 위해 HBase를 선택했다. 페이스북이 서비스하는 사용자의 수와 메시지 수를 감안하면 HBase는 꼭 필요한 선택이었다. 페이스북 기술 팀은 자신들의 인프라스트럭처에서 메시지가 짧고, 휘발성이 강하며, 임시 메시지 성격을 띠는 만큼 나중에 다시 접근하는 일이 드물다고 언급한다. HBase 및 일반적으로 빅테이블 복제품은 데이터의 애드혹 쿼리가 중요하지 않을 때 특히 적합하다. 이전 장을 통해 HBase는 데이터셋 쿼리를 지원하지만 쿼리 기능과 관련해서는 RDBMS를 대체하기에는 약하다는 사실을 배웠다. 구글 앱 엔진(GAE) 같은 인프라스트럭처는 빅테이블 기반 위에 고급 쿼리 기능을 갖춘 데이터 모델링 API를 제공한다. 쿼리에 대한 자세한 정보는 이 장에서 나중에 다루는 ‘쿼리 지원’을 참고하자.
따라서 극단적인 확장성이 필요할 때는 칼럼 패밀리 중심의 NoSQL 데이터베이스가 확실히 좋아 보인다. 하지만 이런 데이터베이스가 모든 시스템에 가장 적합한 선택은 아니다. 특히 실시간 트랜잭션 처리가 필요한 시스템의 경우에는 더욱 그렇다. 트랜잭션 정합성이 매우 중요한 경우에는 NoSQL 제품보다 RDBMS가 더 나은 선택이 될 수 있다. 또 조금 약한 일관성도 받아들일 수 있다면 카산드라나 리악처럼 궁극적인 일관성을 제공하는 NoSQL 옵션도 활용할 만하다. 아마존은 궁극적으로 일관적인 데이터 저장소를 사용할 수 있는 사례로 대규모 확장이 가능한 e-commerce 사이트가 존재한다는 사실을 보여줬지만, 아마존을 제외하면 이런 모델을 적용한 곳을 찾기 어렵다. 카산드라 같은 데이터베이스는 아마존 다이나모의 패러다임을 따르며 궁극적인 일관성을 지원한다. 카산드라는 매우 빠른 읽기 및 쓰기 속도를 약속한다. 또 카산드라는 빅테이블 같은 칼럼 패밀리 중심의 데이터 모델링도 지원한다. 아마존 다이나모는 리악에도 영감을 줬다. 리악은 궁극적으로 일관적인 데이터 저장소이면서 도큐먼트 저장소 추상화를 지원한다. 카산드라와 리악 모두 수평적 클러스터에서 잘 확장되지만, 확장성이 가장 중요한 경우라면 궁극적으로 일관적인 저장소보다는 HBase나 하이퍼테이블을 권장한다. 궁극적으로 일관적인 저장소가 정렬된 칼럼 패밀리 저장소보다 적합한 때는 쓰기 속도나 지연 시간이 중요한 경우다. 따라서 수평적 확장성과 빠른 쓰기 속도가 모두 필요하다면 카산드라나 리악을 고려하는 게 좋다. 하지만 이런 경우에도 데이터 쓰기 작업을 접근 및 분석 작업과 논리적으로 분할하고 각 작업에 두 개의 별도 데이터베이스를 활용하는 하이브리드 접근 방식을 고려해봄 직하다.
대규모 데이터를 매우 빠른 속도로 접근해야 하는 의미의 확장성이라면, 예를 들어 주식 시장의 틱 데이터나 광고 클릭 추적 데이터를 다룬다면 칼럼 패밀리 저장소만으로는 완전한 해결책을 제공하기 어렵다. 이들 저장소에 늘어나는 데이터를 저장하고 맵리듀스 작업을 활용해 배치 쿼리를 실행하고 데이터 마이닝을 하는 것도 좋지만 빠른 읽기 및 실시간 조작을 하려면 좀 더 민첩한 수단이 필요하다. 메모리상에 있는 데이터를 조작하는 것보다 더 빠른 방법은 없으므로 이때는 메모리에 데이터를 저장하고 가용 공간을 모두 채우면 디스크에 쓰는 NoSQL 옵션이 좋은 선택이 될 수 있다. 몽고디비와 레디스는 모두 이 전략을 따른다. 현재 몽고디비는 mmap을 사용하고 레디스는 메모리에서 디스크로 쓰는 커스텀 매핑을 구현한다. 하지만 몽고디비와 레디스 모두 자신들의 메모리 매핑 기능에 대한 리엔지니어링을 활발히 하고 있는 만큼 시간이 지나면서 상황은 계속 달라질 것이다. 실시간 데이터 조작이 필요한 시스템이나 방대한 데이터 마이닝을 수행하는 저장소에서는 HBase 또는 하이퍼테이블과 더불어 몽고디비나 레디스를 사용하는 게 좋다. 또 몽고디비나 레디스 대신 Memcached 및 멤베이스를 사용할 수도 있다. Memcached 및 멤베이스는 빠르고 효과적인 캐시 레이어 역할을 하므로 칼럼 패밀리 저장소를 보완하는 역할을 잘 할 수 있다. 멤베이스는 하둡 기반 시스템과 함께 이런 사용 사례에 효과적으로 활용되고 있다. 멤베이스와 카우치디비의 합병으로 인해 빠른 캐시를 중심으로 하는 기능과 분산 확장 가능 저장소를 중심으로 한 기능을 모두 잘 통합한 NoSQL 제품이 곧 등장할 것 같다.
여러분의 데이터 요구 조건이 구글이나 페이스북만큼 커진다면 확장 가능성이 매우 중요하겠지만 모든 애플리케이션이 규모가 크지는 않다. 물론 이들 시스템보다 훨씬 작은 시스템에서도 확장 가능 시스템이 중요할 수 있지만 자칫 확장 가능 시스템을 만들려고 하다가 과도한 엔지니어링을 적용하는 우를 범할 수 있다. 이런 불필요한 복잡성은 누구도 바라지 않을 것이다. 많은 시스템에서 데이터 정합성과 트랜잭션 일관성이 다른 요구 조건보다 중요하다. 그렇다면 이런 시스템에서도 NoSQL을 선택해 활용할 수 있을까?
트랜잭션 정합성 및 일관성
트랜잭션 정합성은 데이터를 수정, 업데이트, 생성, 삭제할 때만 중요하다. 따라서 트랜잭션 정합성 문제는 순수 데이터 웨어하우스나 데이터 마이닝 맥락에서는 중요하지 않다. 이 말은 웨어하우스 데이터에 대한 배치 중심의 하둡 기반 분석도 트랜잭션 요구 조건의 대상이 아니라는 뜻이다.
웹 트래픽 로그 파일이나 소셜 네트워크 상태 업데이트(트윗, 버즈 등), 사용자의 광고 클릭 흔적, 도로 교통 데이터, 주식 시장 틱 데이터, 게임 점수 등은 주로 한 번만 쓰고 여러 번 읽는다. 이처럼 한 번만 쓰고 여러 번 읽는 데이터셋도 트랜잭션 요구 조건이 제한적이거나 거의 없다.
어떤 데이터셋은 업데이트 및 삭제되지만 종종 이런 수정이 단일 항목으로 제한되고, 데이터셋 내의 범위에 속하지 않는다. 또 때로는 업데이트가 빈번하게 일어나고 범위 작업을 필요로 한다. 범위 작업이 일반적이고 업데이트 정합성이 요구된다면 RDBMS를 선택하는 게 가장 좋다. 개별 항목 수준의 원자성으로도 충분하다면 칼럼 패밀리 데이터베이스, 도큐먼트 데이터베이스, 일부 분산 키/값 저장소가 이를 보장해준다. 시스템에서 트랜잭션 정합성이 필요하지만 비일관성 창[^1]을 수용할 수 있다면 궁극적인 일관성도 고려할 만하다.
[^1]: 업데이트가 이뤄진 시점과 다른 노드로 업데이트 정보가 복제되는 시점까지의 시간을 의미한다. 이 시간 동안은 임시로 비일관적인 상태를 보이게 된다.
NoSQL을 반대하는 사람들은 ACID 지원 부족을 많은 확장 가능 및 비관계형 데이터베이스의 주된 약점으로 지적한다. 하지만 많은 데이터셋에서 트랜잭션 지원 기능은 거의 필요 없거나 전혀 필요하지 않다. 더불어 대부분의 데이터셋(트랜잭션 요구 조건이 거의 필요 없는)은 NoSQL의 확장 가능하고 유연한 아키텍처로 인해 곧바로 이득을 볼 수 있다. NoSQL 데이터베이스에서 맵리듀스 작업을 활용한 확장 가능 병렬 처리의 강력한 위력은 대규모 데이터셋을 효과적으로 조작하고 마이닝할 수 있게 도와준다. 불필요한 트랜잭션 정합성에 대한 걱정으로 스스로를 옭아매지 말자.
HBase와 하이퍼테이블은 행 수준의 원자적 업데이트를 제공하고 Paxos의 도움을 받아 일관적인 상태를 제공한다. 몽고디비는 도큐먼트 수준의 원자적 업데이트를 제공한다. 마스터-슬레이브 복제 모델을 따르는 모든 NoSQL 데이터베이스는 암시적으로 트랜잭션 정합성을 지원한다.
데이터 모델링
RDBMS는 데이터를 모델링할 수 있는 일관된 방법을 제공한다. 데이터 모델 아래에는 관계 대수가 있다. 이 이론은 잘 정립돼 있으며 구현체는 표준화돼 있다. 따라서 데이터를 모델링하고 정규화하는 일관된 방식은 사람들이 잘 이해하고 있고 문서화도 잘 돼 있다. NoSQL 세계에는 이런 표준이나 잘 정의된 데이터 모델이 없다. 이는 모든 NoSQL 제품이 같은 문제를 해결하기 위해 개발된 것도 아니며, 같은 아키텍처를 갖고 있지도 않기 때문이다.
저장 및 쿼리에 RDBMS 중심의 데이터 모델이 필요하고 이런 정의에서 한 발자국도 벗어날 수 없다면 그냥 NoSQL을 사용하지 않으면 된다. 하지만 SQL 같은 쿼리를 제공하면서 비관계형 저장 모델을 수용하고 싶다면 몇 가지 선택할 수 있는 NoSQL 옵션이 있다.
몽고디비 같은 도큐먼트 데이터베이스는 공식적인 RDBMS 모델에서 도큐먼트 중심 모델로 점차 전환하는 데 도움이 된다. 몽고디비는 SQL 같은 쿼리 기능과 기초적인 관계 참조, 표준 테이블 및 칼럼 기반 모델에서 많은 영감을 얻은 데이터베이스 객체를 지원한다. NoSQL을 사용하는 주된 이유가 완화된 스키마 때문이라면 NoSQL을 처음 시작할 때 몽고디비가 가장 적합한 선택이 될 수 있다.
몽고디비는 많은 웹 중심 기업에서 사용 중이다. 이 중 아마도 포스퀘어가 가장 유명할 것이다. 셔터플라이, bit.ly, etsy, 소스포지 등에서도 몽고디비를 사용한다. 몽고디비는 유연한 데이터 모델을 지원하고 빠른 읽기 및 쓰기를 제공하므로 이런 사용 사례에서 선호된다. 웹 애플리케이션은 종종 빠르게 발전하는 만큼 내부 RDBMS 모델을 계속해서 수정하는 게 번거로울 수 있다. 특히 수정이 빈번하고 규모가 크다면 더욱 그렇다. 스키마 변경뿐 아니라 데이터 이관과 관련한 이슈도 있다.
몽고디비는 웹 프레임워크 연동을 잘 지원한다. 가장 인기 있는 웹 애플리케이션 프레임워크 중 하나인 레일즈는 몽고디비와 효과적으로 연동된다. 레일즈 애플리케이션의 데이터는 객체 매퍼를 통해 영속화할 수 있다. 따라서 RDBMS 대신 몽고디비도 쉽게 사용할 수 있다. 레일즈 3 연동에 대해서는 http://www.mongodb.org/display/DOCS/Rails+3+-+Getting+Started를 읽어보자.
자바 웹 개발자라면 스프링이 제공하는 스프링 데이터 프로젝트를 통해 몽고디비용 지원 기능을 활용할 수 있다. 몽고디비를 지원하는 스프링 데이터 도큐먼트 출시와 관련한 자세한 내용은 www.springsource.org/node/3032를 참고하자. 사실 스프링 데이터 프로젝트는 몽고디비뿐 아니라 여러 NoSQL 제품을 지원한다. 이 프로젝트는 레디스, 리악, 카우치디비, Neo4j, 하둡과 스프링을 연동한다. 자세한 정보는 스프링 데이터 프로젝트 홈페이지인 www.springsource.org/spring-data에서 볼 수 있다.
몽고디비는 데이터를 메모리에 보관하고 필요할 때 디스크에 쓰는 영속성 캐시처럼 동작한다. 따라서 몽고디비는 RDBMS와 인메모리 저장소 또는 플랫 파일 구조 사이의 중간 정도로 생각할 수 있다. 실시간 분석 시스템, 댓글 시스템, 평점 저장소, 콘텐츠 관리 소프트웨어, 사용자 데이터 시스템, 이벤트 로깅 애플리케이션 등 많은 웹 애플리케이션이 몽고디비가 제공하는 유연한 스키마의 도움을 받을 수 있다. 더불어 이런 애플리케이션은 몽고디비의 RDBMS와 유사한 기능 및 테이블을 닮은 컬렉션으로 데이터를 분화하는 기능을 활용할 수 있다.
아파치 카우치디비는 몽고디비 대신 사용할 수 있는 도큐먼트 데이터베이스다. 아파치 카우치디비는 카우치디비의 주요 개발자들이 자신들의 회사인 카우치원을 멤베이스와 합병함에 따라 현재 카우치베이스 서버로 사용할 수 있다. 카우치베이스는 GeoCouch를 갖춘 아파치 카우치디비 패키징 버전을 제공하고 카우치베이스 서버 형태로 제품을 지원한다.
카우치베이스 서버는 웹 표준을 준수하는 전형을 보여준다. 카우치베이스의 데이터 저장소에 대한 주요 인터페이스는 RESTful HTTP 상호작용을 거치며, 다른 어떤 데이터베이스보다도 웹 중심적이다. 카우치베이스는 데이터 저장소 내에 웹 서버를 포함한다. 카우치베이스는 얼랭 OTP 기반으로 개발됐다. 이 말은 카우치베이스를 사용해 전체 애플리케이션을 모두 개발할 수도 있다는 뜻이다. 카우치베이스의 미래 버전에는 멤베이스의 속도 관리 기능을 십분 활용해 Memcached 프로토콜을 통한 데이터 저장소 접근 기능도 추가될 것이다. 또 카우치베이스는 멤베이스의 탄력적 기능에서부터 좀 더 많은 노드 사이에서 매끄럽게 확장되는 확장 기능도 계획하고 있다. 카우치베이스가 매우 강력하고 기능이 풍부하긴 하지만 아직 남긴 족적은 매우 미미하다. 간편하다는 특징 덕분에 카우치베이스는 스마트폰 또는 임베디드 기기에 설치하기 적합하다. 모바일 카우치베이스에 대한 자세한 정보는 http://www.couchbase.com/products-and-services/mobile-couchbase를 참고하자.
카우치베이스 모델은 REST 방식의 데이터 관리를 지원한다. 카우치디비 내 데이터베이스는 JSON 형식의 도큐먼트와 더불어 추가 메타데이터 또는 지원 아티팩트를 포함할 수 있다. 데이터에 대한 모든 연산(생성, 조회, 수정, 삭제)은 RESTful HTTP 요청을 통해 수행된다. 복제된 카우치베이스 서버 사이에서 오랜 시간이 걸리는 복잡한 쿼리는 맵리듀스를 활용한다.
Note
표현적 상태 전송의 약어인 REST는 월드 와이드 웹 같은 분산 하이퍼미디어 시스템에 적합한 소프트웨어 아키텍처의 한 방식이다. REST란 용어는 로이 필딩이 자신의 박사 논문에서 소개하고 정의했다. REST에 대한 자세한 내용은 http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm을 참고하자.
단순 맵이 아니다
일반적인 인메모리 데이터베이스 및 캐시에서 가장 잘 알려진 데이터 구조는 맵 또는 해시다. 맵은 키/값 쌍을 저장하고 데이터에 대한 빠르고 쉬운 접근을 제공한다. 인메모리 NoSQL 저장소는 파일 시스템을 통한 인메모리 데이터의 영속화 기능을 제공한다. 이 말은 시스템을 재부팅하더라도 저장된 데이터가 남아 있다는 뜻이다. 많은 NoSQL 인메모리 데이터베이스는 단순 맵 이상의 데이터 구조를 지원하며, 이를 통해 단순 데이터 캐시 이외의 여러 용도로 데이터베이스를 활용할 수 있게 해준다. 가장 기본적인 수준에서 버클리디비는 바이너리 키/값 쌍을 저장한다. 내부 저장소 자체는 저장된 키/값 쌍에 대해 아무런 메타데이터도 첨부하지 않는다. 기본 저장 레이어 위에 있는 영속성 API나 객체 래퍼 같은 레이어는 버클리디비 저장소에 고수준 추상화를 통한 영속화를 제공한다.
그에 반해 멤베이스는 텍스트와 바이너리 모두로 Memcached 프로토콜을 지원하고 기본 키/값 저장소 위에 분산 복제 및 일관적 해싱을 중심으로 기능을 추가한다. 또 멤베이스는 클라이언트 접근을 방해하지 않으면서 클러스터를 구성하는 서버 개수를 늘이거나 줄이는 기능도 추가한다. 레디스는 이와는 조금 다른 접근 방식을 취한다. 레디스는 인기 있는 데이터 구조를 대부분 기본적으로 지원한다. 사실 레디스는 ‘데이터 구조’ 서버로 정의된다. 레디스는 맵뿐 아니라 리스트, 세트, 정렬 세트, 문자열을 지원한다. 레디스는 여러 작업 사이의 원자성을 지정하기 위해 트랜잭션과 유사한 기능도 추가했다.
파일 지원 인메모리 NoSQL 제품을 활용할 생각이라면 가장 적합한 데이터베이스를 선택하기 위해 각 데이터베이스가 지원하는 데이터 모델을 고려하자. 많은 경우 키/값 저장소로 충분하지만 키/값 저장소만으로 충분하지 않다면 버클리디비, 멤베이스, 레디스를 살펴보자. 대규모 사용자와 활동 부하를 지원할 수 있는 강력하고 안정적인 분산 키/값 저장소가 필요할 경우 멤베이스를 선택하면 잘못될 일이 거의 없다.
HBase와 하이퍼테이블은 어떨까?
확장 가능성을 다룬 앞 절에서 필자는 칼럼 패밀리 저장소를 전적으로 옹호한 바 있다. 하지만 풍부한 모델 지원과 관련해서는 보통 칼럼 패밀리 저장소가 가장 좋은 선택은 아니다. 룩업에 행 키를 사용하려는 것과 칼럼 패밀리 중심 모델 메타데이터만 지원하는 특징은 많은 경우 적합하지 않을 수 있다. 칼럼 패밀리 저장소 위에 강력한 추상 레이어를 적용하면 많은 것이 가능해진다.
구글은 칼럼 패밀리 저장소 혁명을 시작했다. 구글은 자신들의 인기 있는 앱 엔진을 위해 칼럼 패밀리 저장소 위에 데이터 모델링 추상화도 구현했다. GAE 데이터 모델링 지원은 파이썬과 자바를 활용한 풍부한 데이터 모델링을 지원한다(이 주제는 10장에서 자세히 다룬다). DataNucleus JDO와 JPA 지원 기능을 활용하면 자바에서 인기 있는 객체 모델링 추상화를 통해 HBase 및 하이퍼테이블로 데이터를 영속화할 수 있다. 또 앱 엔진과 잘 연동되는 장고의 비관계형 지원으로부터도 영감을 얻을 수 있다.
쿼리 지원
저장소는 전체 퍼즐 중 절반일 뿐이다. 나머지 절반은 바로 저장 데이터를 쿼리하는 방식이다. 빠르고 효과적으로 데이터를 쿼리할 수 있는 기능은 모든 데이터베이스가 심각하게 고려해야 하는 의무적인 기능이다. 특히 사람들이 사용하는 애플리케이션용 데이터 저장소를 구축할 때 쿼리 기능이 중요하다. RDBMS는 데이터에 쉽게 접근해 조회할 수 있다는 점에서 SQL 지원 기능에 앞서 있다. 표준화된 구문과 의미는 RDBMS를 매력적인 데이터베이스로 만들어 준다. 이 책의 1장에서는 NoSQL 세계에서 SQL과 유사한 쿼리 언어를 찾아 떠나는 여정에 대해 설명했고 이후 장에서 이런 기능이 어떻게 구현되는지 보여준 바 있다.
도큐먼트 데이터베이스 중에는 몽고디비가 가장 좋은 쿼리 기능을 제공한다. 하지만 가장 좋다는 말은 상대적인 기준이며, 개발자들 사이에는 어떤 데이터베이스가 더 우수한지에 대한 논쟁이 있다. 하지만 필자는 다음의 세 가지 요소를 근거로 이런 주장을 뒷받침한다. 바로 SQL과의 유사성, 쉬운 구문, 낮은 학습 곡선이다. 카우치디비의 쿼리 기능도 몽고디비만큼 강력하며, 뷰 및 설계 도큐먼트의 개념을 이해하고 나면 오히려 더 간편하다. 하지만 카우치디비의 뷰 개념은 카우치디비에서 정의하는 새로운 개념인 만큼 처음 접하는 개발자들에게 어려울 수 있다.
키/값 쌍 및 인메모리 저장소의 경우 쿼리 기능과 관련해 레디스만큼 기능이 풍부한 데이터베이스는 없다. 레디스는 저장된 데이터 구조를 쿼리할 수 있는 방대한 기능을 제공한다. 또 문서화도 잘 돼 있다. 레디스의 데이터 접근 방법은 http://redis.io/commands를 참고하자.
HBase 같은 칼럼 패밀리 저장소에는 풍부한 쿼리 기능은 거의 없다. 하지만 하이브라는 연계 프로젝트 덕분에 SQL 같은 구문과 의미를 사용해 HBase를 쿼리할 수 있다. 12장에서는 하이브를 다룬 바 있다. 하이퍼테이블은 HQL이란 쿼리 언어를 정의하며 하이브도 지원한다.
하이브를 사용할 수 있다고 하면 운영 용도로 데이터를 조작하는 것과 배치 처리 및 비즈니스 인텔리전스를 위해 데이터에 접근하는 것 중 어떤 사례에 하이브가 적합한지에 대한 궁금증이 생기기 마련이다. 아쉽지만 하이브는 RDBMS의 SQL이 그러하듯 인터랙티브한 툴이 아니다. 하이브는 구문상 SQL을 닮긴 했지만 실제로는 맵리듀스 방식의 조작을 추상화하는 수단일 뿐이다. 하이브는 map과 reduce 함수 정의 대신 SQL 같은 서술식 중심의 구문을 사용해 데이터셋에 대한 배치 데이터 조작을 수행한다.
접근 및 인터페이스 가용성
몽고디비는 드라이버 개념을 갖고 있다. 몽고디비는 몽고디비와 인터페이스하고 상호작용할 수 있는 주류 라이브러리용 드라이버를 대부분 지원한다. 카우치디비는 웹 표준에 따른 상호작용 방식을 사용하는 만큼 웹 통신을 지원하는 프로그래밍 언어라면 아무 언어나 사용해 접속할 수 있다. 카우치디비에서는 항상 RESTful HTTP 인터페이스를 사용할 수 있기는 하지만 카우치디비와의 통신을 위한 일부 언어용 래퍼는 몽고디비의 드라이버와 비슷한 기능을 한다.
레디스, 멤베이스, 리악, HBase, 하이퍼테이블, 카산드라, 볼드모트는 대부분의 주류 언어에서 연결할 수 있게끔 언어 바인딩을 지원한다. 이들 래퍼는 대부분 내부적으로 쓰리프트나 에이브로 같은 직렬화 메커니즘을 통해 언어 독립적인 서비스 레이어를 사용한다. 따라서 다양한 직렬화 형식의 성능 특징을 잘 이해하는 게 중요하다. JVM상에서 직렬화 형식의 성능 특징을 잘 살펴볼 수 있는 벤치마크 중 하나는 jvm-serializer 프로젝트로, https://github.com/eishay/jvmserializers/wiki/에서 볼 수 있다. 이 프로젝트에서는 다음과 같은 여러 데이터 형식에 대한 성능을 측정한다. 다루는 형식은 다음과 같다.
- protobuf 2.3.0 : 구글 데이터 교환 형식. http://code.google.com/p/protobuf/
- thrift 0.4.0 : 페이스북이 오픈소스화함. HBase, 하이퍼테이블, 카산드라 같은 NoSQL 제품에서 널리 사용됨. http://incubator.apache.org/thrift/
- avro 1.3.2 : 아파치 프로젝트. 일부 NoSQL 제품에서 쓰리프트를 대신함. http://avro.apache.org/
- kryo 1.03 : 자바용 객체 그래프 직렬화 프레임워크. http://code.google.com/p/kryo/
- hessian 4.0.3 : 바이너리 웹 서비스 프로토콜. http://hessian.caucho.com/
- sbinary 0.3.1-SNAPSHOT : 스칼라 타입을 위한 바이너리 형식을 설명. https://github.com/harrah/sbinary
- google-gson 1.6 : 자바 객체를 JSON으로 변환하는 라이브러리. http://code.google.com/p/google-gson/
- jackson 1.7.1 : 자바 JSON 프로세서. http://jackson.codehaus.org/
- javolution 5.5.1 : 실시간 및 임베디드 시스템을 위한 자바. http://javolution.org/
- protostuff 1.0.0.M7 :protobuf를 활용한 직렬화. http://code.google.com/p/protostuff/
- woodstox 4.0.7 : 고성능 XML 프로세서. http://woodstox.codehaus.org/
- aalto 0.9.5 : Aalto XML 프로세서. http://www.cowtowncoder.com/hatchery/aalto/index.html
- fast-infoset 1.2.6 : 바이너리 XML을 위한 빠른 인포셋 오픈소스 구현체. http://fi.java.net/
- xstream 1.3.1 : XML을 직렬화, 역직렬화하기 위한 라이브러리. http://xstream.codehaus.org/
이 성능 실행 결과는 JVM에서 수행한 결과지만, 다른 플랫폼에서도 중요한 의미가 있다. 이 결과를 보면 protobuf, protostuff, 카이로 및 수동 처리가 직렬화와 역직렬화에 가장 효과적인 것으로 드러났다. kyro와 에이브로 직렬화 크기 및 압축 크기 측면에서 가장 효과적인 형식이다.
이로써 각 형식의 성능에 대해 알게 됐으니 다음 절에서는 이어서 NoSQL 제품 자체의 벤치마크 결과를 살펴보겠다.