티스토리 뷰

LevelDB 를 node.js에서 써보자(levelup 사용하기)

참고 문헌

1. LevelDB(github)란?

LevelDB는 세계정복을 꿈꾸는 구글에서 개발하고 오픈소스로 공개한 Key-Value 경량 데이터베이스입니다. 기존에 경량 DB 시장을 잡고있던 sqlite를 때려잡고자 만든 것 같습니다. 자세한 내용은 공식 홈페이지 및 다른 소개글들을 참고하시기 바랍니다.

2. node.js에서 어떻게 사용함?

leveldb는 C++로 개발이 되다보니 어찌해야 하나.. 하는 분들 많겠지만 오픈소스의 힘은 위대합니다. 다른 개발자분들이 node.js 바인딩을 내놨네요. 대놓고 공식 홈페이지 최상단에 올라와있습니다. 이름은 levelup 입니다.

3. levelup을 사용해보자.

위 내용은 github의 내용과 각종 블로그들을 참고하였습니다. 별도로 참고한 블로그는 위의 참고 문헌에 수록하였습니다.
LevelUP은 node.js 친화적으로 레벨DB의 기능을 드러내는 것을 목표로 삼았다고 합니다. 모든 표준 buffer 인코딩 타입(JSON같은)이 지원된다고 합니다. 시간이 되면 ReadStream까지 예제에 실어보도록 하겠습니다.
LevelDOWN은 pure C++ 바인딩이라고 합니다. levelup 0.9버전에는 필수가 아니여서 pure C++을 체험하고 싶다면 반드시 leveldown을 설치해야 한다고 합니다. level이라는 이름으로 한번에 설치할 수 있지만
var levelup = require('level')
이렇게 써야 한다고 합니다.

3-1. 지원 플랫폼

리눅스(ARM도 지원한다고 합니다. 라즈베리파이에 쓰면 좋을 거 같네요.)
맥 OS
솔라리스(조이엔트 SmartOS나 Nodejitsu)
윈도우(Node.js 0.10 이상에서 가능하며 컴파일(node-gyp)이 가능하도록 설정이 되어있어야 한다고 합니다. - 원본에서 참고하라고 한 링크)

3-2. 설치하기

깔아봅시다.
npm install levelup leveldown
위에서도 이야기했듯이 levelup 0.9버전부터 leveldown이 필수가 아니기때문에 leveldown은 별도 설치하라고 합니다. 비슷한 사례 봤었습니다. redis와 hiredis요 ㅋㅋㅋ
같이 깔고싶으면 이렇게 하라고 합니다.
npm install level
대신 이렇게 하면 level 을 require 해야한다고 합니다.

3-3. 공식 github 예제

다음 코드들은 제가 직접 코딩을 해서 실행한 후 정상 작동하였음을 알려드립니다.

var levelup = require('levelup')

// 1) Create our database, supply location and options.
//    This will create or open the underlying LevelDB store.
var db = levelup('./mydb')

// 2) put a key & value
db.put('name', 'LevelUP', function (err) {
  if (err) return console.log('Ooops!', err) // some kind of I/O error

  // 3) fetch by key
  db.get('name', function (err, value) {
    if (err) return console.log('Ooops!', err) // likely the key was not found

    // ta da!
    console.log('name=' + value)
  })
})

이 정도 짧은 예제에 설명은 필요없으리라 봅니다. 대신, 1)의 스토어는 디렉터리를 가리키기때문에 주의를 요합니다.
스토어의 디렉터리 구조에 대한 설명은 다른 글을 참조하시기 바랍니다.

3-4. 난 파일을 쓰지 않겠다!!!!

인 메모리로 저장을 하고 싶다면 MemDOWN이라는 라이브러리를 설치하라고 합니다.
공홈 예제입니다.

var levelup = require('levelup')
var memdown = require('memdown')
var db = levelup({ db: memdown })

3-5. 여러 명령 실행하기(대량 삽입 등)

원자적 연산이라고 들어보셨을 겁니다. 뭐 트랜잭션이니 뭐니 하는 그런거요. 여기서도 지원합니다. batch라는 명령을 사용하면 됩니다. 방법은 2가지가 있습니다. 배열 vs 체인입니다.
배열은 다음과 같은 방법으로 이뤄집니다.(공홈 소스)

var ops = [
    { type: 'del', key: 'father' }
  , { type: 'put', key: 'name', value: 'Yuri Irsenovich Kim' }
  , { type: 'put', key: 'dob', value: '16 February 1941' }
  , { type: 'put', key: 'spouse', value: 'Kim Young-sook' }
  , { type: 'put', key: 'occupation', value: 'Clown' }
]

db.batch(ops, function (err) {
  if (err) return console.log('Ooops!', err)
  console.log('Great success dear leader!')
})

다른 방법으로는 체인이 있습니다. js 프로그래머분들이 많이 사용하시는 방법입니다. 역시 공홈 소스입니다.

db.batch()
  .del('father')
  .put('name', 'Yuri Irsenovich Kim')
  .put('dob', '16 February 1941')
  .put('spouse', 'Kim Young-sook')
  .put('occupation', 'Clown')
  .write(function () { console.log('Done!') })

catch 등이 없는 것을 봐서는 try-catch 문에서 실행해야 예외처리가 가능할 것 같습니다.

4. Stream과 Event

역시 node.js의 꽃이라고 하면 stream과 event 아니겠습니까?! 보도록 합시다.

4-1. Stream

levelup은 JSON format의 readStream을 제공해줍니다.(WriteStream은 다음 토론을 거쳐서 삭제하였다고 합니다). 역시 공홈 예제로 보도록 하겠습니다.

db.createReadStream({
    //온갖 옵션들
  })
  .on('data', function (data) {
    console.log(data.key, '=', data.value)
  })
  .on('error', function (err) {
    console.log('Oh my!', err)
  })
  .on('close', function () {
    console.log('Stream closed')
  })
  .on('end', function () {
    console.log('Stream closed')
  })

슬쩍 보면 모든 키를 순회하여 결과를 보는 것임을 알 수 있습니다. 값을 많이 넣고 출력해보면 느끼시겠지만 키의 정렬 순서가 오름차순으로 되어있습니다. 이 점을 감안하시면 조금 더 유용해지실 거 같습니다.
기본 이벤트인 data, error, close, end 이거 모르시는 분 아무도 없을테니까 패스하겠습니다.
levelup에서는 몇 가지 쿼리를 제공합니다. createReadStream([options]) 이 되겠습니다. 옵션은 다음과 같습니다.

  • gt, gte
  • lt, lte
  • start, end <- gte, lte로 대신 사용하라고 합니다.
  • reverse
  • keys: 키만 볼 수 있습니다. createKeyStream()을 내부적으로 사용한다고 합니다.
  • values: 값만 볼 수 있습니다. createValueStream()을 내부적으로 사용한다고 합니다.
  • limit: -1은 몽땅 본다고 합니다.
  • fillCache: LevelDB의 LRU캐시를 쓰느냐에 대한 것입니다. 기본값은 false라고 합니다.
  • keyEncoding, valueEncoding: 키와 값의 인코딩 설정을 정합니다.

createKeyStream(), createValueStream() 은 data가 object가 아닙니다.

4-2. Event

levelup 은 각종 경우에 대하여 이벤트를 알려줍니다. 일단 event를 넣어놓은 예제를 쓰겠습니다.

db.on('put', function(key, value) {
  console.log('insert key: ' + key + ', value: ' + value);
});

db.put('foooo', 'barrrr', function(err) {
  if(err) {
    return console.error(err);
  }
  console.log('insert success');
});

실행하면 요렇게 나옵니다.

insert key: foooo, value: barrrr
insert success

이벤트가 발생한 뒤 콜백이 일어납니다. 공홈에 적혀있는 지원하는 이벤트들은 다음과 같습니다.

  • put: key, value가 argument로 옵니다.
  • del: key가 argument로 옵니다.
  • batch: 배치처리할 배열이 argument로 옵니다.
  • ready: DB가 열린 직후 발생합니다.
  • closed: DB가 닫힌 후 발생합니다.
  • opening: DB가 열리고 있는 중 발생합니다.
  • closing: DB가 닫히고 있는 중 발생합니다.
  • error: error가 argument로 옵니다. 비동기 함수에 콜백을 넣지 않았는데 거기서 에러가 발생하면 error 이벤트를 발생시킨다고 합니다.

5. 기타

Node.js LevelDB modules and projects 이 링크에는 온갖 levelup의 확장 모듈이 들어있다고 합니다. 이 중 level-hookslevel-sublevel은 강력추천한다고 합니다. 다음에 한 번 써봐야겠습니다.

6. 맺음말

sqlite 말고 간단한 DB로 써볼 거 있나 하고 뒤지던 와중에 발견하게 되어 정말 대충 글 갯수 채우려고 공식 github 페이지를 베껴서 바로 써보는 글이라 내용이 매우 허접합니다. 자세한 API 등은 공식 github페이지를 확인하시기 바랍니다. 이상 글 마치겠습니다. 감사합니다.

댓글
댓글쓰기 폼