Node.js에서 Redis 사용하기

Node.js에서 Redis 사용하기

모듈 설치

$ npm install redis

API 레퍼런스

https://github.com/mranney/node_redis

프로그래밍

모듈 가져오기

var redis = require("redis");

서버에 접속하기

var client = redis.createClient(6379, "reshout.com");

Redis 명령어 실행하기

모든 Redis 명령어는 client 객체의 함수를 통해 실행할 수 있다. 모든 함수는 args 배열에 이어 callback을 전달 받는다.

두가지 형태로 호출할 수 있다.

client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {});

다른 형태는 다음과 같다.

client.mset("test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {});

callback은 생략 가능하다.

client.set("some key", "some val");
client.set(["some other key", "some val"]);

기본으로 제공되는 redis.printcallback으로 사용하여 간단히 결과를 출력할 수 있다.

명령어에 해당하는 함수명은 대소문자 모두 사용 가능하다. client.get() 함수와 client.GET() 함수는 동일하다.

client.get("missingkey", function(err, reply) {
    // reply is null when the key is missing
    console.log(reply);
});

존재하지 않는 key에 대한 get() 함수의 결과로 null이 전달된다.

reply의 타입은 커맨드의 결과에 따라 아래와 같다.

  • single line: JavaScript String
  • integer: JavaScript Number
  • bulk: node Buffer
  • multi bulk: array of node Buffer

이벤트

client 객체는 상황에 따라 다음과 같은 이벤트를 발생(emit) 시킨다.

  • ready
  • connect
  • error
  • end
  • drain
  • idle

error 이벤트에 대한 리스너를 등록하지 않으면 에러가 발생했을때 프로그램이 종료된다.

예제

client.on("error", function (err) {
    console.log("Error " + err);
});

인증

Redis 서버가 인증을 요구하는 경우, client.auth(password, callback) 함수를 호출해 인증을 수행할 수 있다.

접속 종료

close() 함수를 호출해 강제로 접속을 종료할 수 있다. 명령어 실행에 따른 결과가 전달되기까지 기다리지 않고 즉시 접속을 종료하기 때문에 아래 코드는 아무것도 출력하지 않는다.

var redis = require("redis"),
    client = redis.createClient();

client.set("foo_rand000000000000", "some fantastic value");
client.get("foo_rand000000000000", function (err, reply) {
    console.log(reply.toString());
});
client.end();

Ubuntu에서 Redis 설치, 빌드, 실행

Ubuntu에서 Redis 설치, 빌드, 실행

다운로드

$ wget http://download.redis.io/releases/redis-2.8.4.tar.gz
$ tar xvzf redis-2.8.4.tar.gz
$ cd redis-2.8.4/

빌드

$ make
$ make test

설치

$ make install

바이너리 파일들이 /usr/local/bin에 설치된다. 시스템에 설치하지 않고 src 디렉토리에 위치한 바이너리를 사용해도 무방하다.

서버에서 정식으로 redis를 운영하고자 한다면 Ubuntu나 Debian 시스템에서 init script 설정을 도와주는 스크립트를 활용할 수 있다.

$ cd utils
$ ./install_server

이 스크립트는 몇가지 질문을 통해 Redis가 백그라운드에서 데몬으로 동작하며, 재부팅 되었을때 자동으로 실행되도록 설정하는데 도움을 준다.

Redis 서버 시작

기본 설정

$ cd src
$ ./redis-server

기본 설정은 6379포트를 사용함

설정 파일 활용

$ cd src
$ ./redis-server ../redis.conf

설정 파라미터 활용

$ cd src
$ ./redis-server --port 9999 --slaveof 127.0.0.1 6379
$ ./redis-server /etc/redis/6379.conf --loglevel debug

Redis 사용해 보기

서버를 시작한 후, redis-cli를 통해 Redis 서버에 명령을 보내고 답을 얻을 수 있다.

% cd src 
% ./redis-cli
redis> ping
PONG
redis> set foo bar 
OK  
redis> get foo 
"bar"
redis> incr mycounter
(integer) 1
redis> incr mycounter
(integer) 2
redis> 

Redis Tutorial

Redis Tutorial

http://try.redis.io

Key-Value

SET

SET server:name "fido"

GET

GET server:name

INCR

SET connections 10
INCR connections

DEL

DEL connections

EXPR

SET resource:lock "Redis Demo 1"
EXPIRE resource:lock 120
TTL resource:lock

List

RPUSH

RPUSH friends "Alice"
RPUSH friends "Bob"

LPUSH

LPUSH friends "Sam"

LRANGE

LRANGE friends 0 -1
LRANGE friends 1 2

A value of -1 for the second parameter means to retrieve elements until the end of the list.

LLEN

LLEN friends

LPOP

LPOP friends

RPOP

RPOP friends

Set

SADD

SADD superpowers "flight"

SREM

SREM superpowers "reflexes"

SISMEMBER

SISMEMBER tests if the given value is in the set.

SISMEMBER superpowers "flight"

SMEMBERS

SMEMBERS returns a list of all the members of this set.

SMEMBERS superpowers

SUNION

SUNION combines two or more sets and returns the list of all elements.

Sorted Set

ZADD

ZADD hackers 1940 "Alan Kay"
ZADD hackers 1906 "Grace Hopper"
ZADD hackers 1953 "Richard Stallman"
ZADD hackers 1965 "Yukihiro Matsumoto"
ZADD hackers 1916 "Claude Shannon"
ZADD hackers 1969 "Linus Torvalds"
ZADD hackers 1957 "Sophie Wilson"
ZADD hackers 1912 "Alan Turing"

ZRANGE

ZRANGE hackers 2 4

Hash

HSET

HSET user:1000 name "John Smith"
HSET user:1000 email "john.smith@example.com"
HSET user:1000 password "s3cret"

HGET

HGET user:1001 name

HGETALL

HGETALL user:1000

HMSET

HMSET user:1001 name "Mary Jones" password "hidden" email "mjones@example.com"

안드로이드 배터리 잔량 구하기

Intent.ACTION_BATTERY_CHANGED는 Sticky Intent로 시스템에 등록되어 있어서 registerReceiver()를 호출하면 즉시 반환됩니다. 반환된 Intent에서 필요한 값을 추출해 배터리 잔량을 %로 계산해 반환하는 메서드입니다.

public static int getBatteryPercentage(Context context) {
    Intent batteryStatus = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
    int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);

    float batteryPct = level / (float)scale;
    return (int)(batteryPct * 100);
}

Sublime Text 3에서 Markdown Syntax Highlighting 적용하기

Sublime Text 3로 Markdown 문서를 편집하고 Marked 2로 Preview를 확인하면서 글을 작성하는 연습을 하고 있습니다.

Sublime Text 3의 아쉬운 점은 Markdown Syntax Highlighting을 지원하지 않더군요. 구글 검색을 통해 관련 문서를 찾았는데, 기본적으로는 버전 2에서 적용방법을 설명하고 있지만, 댓글에 버전 3을 위한 적용방법도 나와 있어 여기에 정리하여 공유합니다.

~/Library/Application Support/Sublime Text 3/Packages/User/customizedMonokai.tmTheme 파일에 다음 내용을 붙여 넣습니다. (기본 테마의 끝부분에 Markdown을 위한 테마를 추가한 것입니다.)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>name</key>
    <string>Monokai</string>
    <key>settings</key>
    <array>
        <dict>
            <key>settings</key>
            <dict>
                <key>background</key>
                <string>#272822</string>
                <key>caret</key>
                <string>#F8F8F0</string>
                <key>foreground</key>
                <string>#F8F8F2</string>
                <key>invisibles</key>
                <string>#3B3A32</string>
                <key>lineHighlight</key>
                <string>#3E3D32</string>
                <key>selection</key>
                <string>#49483E</string>
                <key>findHighlight</key>
                <string>#FFE792</string>
                <key>findHighlightForeground</key>
                <string>#000000</string>
                <key>selectionBorder</key>
                <string>#222218</string>
                <key>activeGuide</key>
                <string>#9D550FB0</string>

                <key>bracketsForeground</key>
                <string>#F8F8F2A5</string>
                <key>bracketsOptions</key>
                <string>underline</string>

                <key>bracketContentsForeground</key>
                <string>#F8F8F2A5</string>
                <key>bracketContentsOptions</key>
                <string>underline</string>

                <key>tagsOptions</key>
                <string>stippled_underline</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Comment</string>
            <key>scope</key>
            <string>comment</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#75715E</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>String</string>
            <key>scope</key>
            <string>string</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#E6DB74</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Number</string>
            <key>scope</key>
            <string>constant.numeric</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#AE81FF</string>
            </dict>
        </dict>

        <dict>
            <key>name</key>
            <string>Built-in constant</string>
            <key>scope</key>
            <string>constant.language</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#AE81FF</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>User-defined constant</string>
            <key>scope</key>
            <string>constant.character, constant.other</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#AE81FF</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Variable</string>
            <key>scope</key>
            <string>variable</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string></string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Keyword</string>
            <key>scope</key>
            <string>keyword</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#F92672</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Storage</string>
            <key>scope</key>
            <string>storage</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string></string>
                <key>foreground</key>
                <string>#F92672</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Storage type</string>
            <key>scope</key>
            <string>storage.type</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string>italic</string>
                <key>foreground</key>
                <string>#66D9EF</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Class name</string>
            <key>scope</key>
            <string>entity.name.class</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string>underline</string>
                <key>foreground</key>
                <string>#A6E22E</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Inherited class</string>
            <key>scope</key>
            <string>entity.other.inherited-class</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string>italic underline</string>
                <key>foreground</key>
                <string>#A6E22E</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Function name</string>
            <key>scope</key>
            <string>entity.name.function</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string></string>
                <key>foreground</key>
                <string>#A6E22E</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Function argument</string>
            <key>scope</key>
            <string>variable.parameter</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string>italic</string>
                <key>foreground</key>
                <string>#FD971F</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Tag name</string>
            <key>scope</key>
            <string>entity.name.tag</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string></string>
                <key>foreground</key>
                <string>#F92672</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Tag attribute</string>
            <key>scope</key>
            <string>entity.other.attribute-name</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string></string>
                <key>foreground</key>
                <string>#A6E22E</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Library function</string>
            <key>scope</key>
            <string>support.function</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string></string>
                <key>foreground</key>
                <string>#66D9EF</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Library constant</string>
            <key>scope</key>
            <string>support.constant</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string></string>
                <key>foreground</key>
                <string>#66D9EF</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Library class/type</string>
            <key>scope</key>
            <string>support.type, support.class</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string>italic</string>
                <key>foreground</key>
                <string>#66D9EF</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Library variable</string>
            <key>scope</key>
            <string>support.other.variable</string>
            <key>settings</key>
            <dict>
                <key>fontStyle</key>
                <string></string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Invalid</string>
            <key>scope</key>
            <string>invalid</string>
            <key>settings</key>
            <dict>
                <key>background</key>
                <string>#F92672</string>
                <key>fontStyle</key>
                <string></string>
                <key>foreground</key>
                <string>#F8F8F0</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>Invalid deprecated</string>
            <key>scope</key>
            <string>invalid.deprecated</string>
            <key>settings</key>
            <dict>
                <key>background</key>
                <string>#AE81FF</string>
                <key>foreground</key>
                <string>#F8F8F0</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>JSON String</string>
            <key>scope</key>
            <string>meta.structure.dictionary.json string.quoted.double.json</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#CFCFC2</string>
            </dict>
        </dict>

        <dict>
            <key>name</key>
            <string>diff.header</string>
            <key>scope</key>
            <string>meta.diff, meta.diff.header</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#75715E</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>diff.deleted</string>
            <key>scope</key>
            <string>markup.deleted</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#F92672</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>diff.inserted</string>
            <key>scope</key>
            <string>markup.inserted</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#A6E22E</string>
            </dict>
        </dict>
        <dict>
            <key>name</key>
            <string>diff.changed</string>
            <key>scope</key>
            <string>markup.changed</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#E6DB74</string>
            </dict>
        </dict>

        <dict>
            <key>scope</key>
            <string>constant.numeric.line-number.find-in-files - match</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#AE81FFA0</string>
            </dict>
        </dict>
        <dict>
            <key>scope</key>
            <string>entity.name.filename</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#E6DB74</string>
            </dict>
        </dict>

        <dict>
            <key>scope</key>
            <string>message.error</string>
            <key>settings</key>
            <dict>
                <key>foreground</key>
                <string>#F83333</string>
            </dict>
        </dict>

<dict>
  <key>name</key>
  <string>Markdown: Linebreak</string>
  <key>scope</key>
  <string>text.html.markdown meta.dummy.line-break</string>
  <key>settings</key>
  <dict>
    <key>background</key>
    <string>#A57706</string>
    <key>foreground</key>
    <string>#E0EDDD</string>
  </dict>
</dict>
<dict>
  <key>name</key>
  <string>Markdown: Raw</string>
  <key>scope</key>
  <string>text.html.markdown markup.raw.inline</string>
  <key>settings</key>
  <dict>
    <key>foreground</key>
    <string>#269186</string>
  </dict>
</dict>
<dict>
  <key>name</key>
  <string>Markdown: Punctuation for Inline Block</string>
  <key>scope</key>
  <string>punctuation.definition.raw.markdown</string>
  <key>settings</key>
  <dict>
    <key>foreground</key>
    <string>#269186</string>
  </dict>
</dict>
<dict>
  <key>name</key>
  <string>Markup: Heading</string>
  <key>scope</key>
  <string>markup.heading</string>
  <key>settings</key>
  <dict>
    <key>fontStyle</key>
    <string>bold</string>
    <key>foreground</key>
    <string>#cb4b16</string>
  </dict>
</dict>
<dict>
  <key>name</key>
  <string>Markup: Italic</string>
  <key>scope</key>
  <string>markup.italic</string>
  <key>settings</key>
  <dict>
    <key>fontStyle</key>
    <string>italic</string>
    <key>foreground</key>
    <string>#839496</string>
  </dict>
</dict>
<dict>
  <key>name</key>
  <string>Markup: Bold</string>
  <key>scope</key>
  <string>markup.bold</string>
  <key>settings</key>
  <dict>
    <key>fontStyle</key>
    <string>bold</string>
    <key>foreground</key>
    <string>#586e75</string>
  </dict>
</dict>
<dict>
  <key>name</key>
  <string>Markdown: Punctuation for Bold, Italic</string>
  <key>scope</key>
  <string>punctuation.definition.bold.markdown, punctuation.definition.italic.markdown</string>
  <key>settings</key>
  <dict>
    <key>foreground</key>
    <string>#586e75</string>
  </dict>
</dict>
<dict>
  <key>name</key>
  <string>Markup: Underline</string>
  <key>scope</key>
  <string>markup.underline</string>
  <key>settings</key>
  <dict>
    <key>fontStyle</key>
    <string>underline</string>
    <key>foreground</key>
    <string>#839496</string>
  </dict>
</dict>
<dict>
  <key>name</key>
  <string>Markup: Quote</string>
  <key>scope</key>
  <string>markup.quote</string>
  <key>settings</key>
  <dict>
    <key>fontStyle</key>
    <string>italic</string>
    <key>foreground</key>
    <string>#268bd2</string>
  </dict>
</dict>
<dict>
  <key>name</key>
  <string>Markup: Separator</string>
  <key>scope</key>
  <string>meta.separator</string>
  <key>settings</key>
  <dict>
    <key>background</key>
    <string>#eee8d5</string>
    <key>fontStyle</key>
    <string>bold</string>
    <key>foreground</key>
    <string>#268bd2</string>
  </dict>
</dict>

    </array>
    <key>uuid</key>
    <string>D8D5E82E-3D5B-46B5-B38E-8C841C21347D</string>
</dict>
</plist>

Sublime Text 3에서 Preferences > Settings - User 메뉴를 실행하면 Preferences.sublime-settings 파일이 열립니다. 아래와 같이 수정해 줍니다.

// Settings in here override those in "Default/Preferences.sublime-settings",
// and are overridden in turn by file type specific settings.
{
    "color_scheme": "Packages/User/customizedMonokai.tmTheme"
}

결과는 이렇습니다.

스크린샷 2013-10-31 오후 10.57.36