클라우드 컴퓨팅 & NoSQL/Vert.x & Node.js

빠르게 훝어 보는 node.js - redis 사용하기

Terry Cho 2016. 3. 29. 17:36

node.js에서 Redis 사용하기


조대협 (http://bcho.tistory.com)


Redis NoSQL 데이타 베이스의 종류로, mongoDB 처럼 전체 데이타를 영구히 저장하기 보다는 캐쉬처럼 휘발성이나 임시성 데이타를 저장하는데 많이 사용된다.

디스크에 데이타를 주기적으로 저장하기는 하지만, 기능은 백업이나 복구용으로 주로 사용할뿐 데이타는 모두 메모리에 저장되기 때문에, 빠른 접근 속도를 자랑한다.

 

이유 때문에 근래에는 memcached 다음의 캐쉬 솔루션으로 널리 사용되고 있는데, 간단하게 -밸류 (Key-Value)형태의 데이타 저장뿐만 아니라, 다양한 데이타 타입을 지원하기 때문에 응용도가 높고, node.js 호환 모듈이 지원되서 node.js 궁합이 좋다. 여러 node.js 클러스터링 하여 사용할때, node.js 인스턴스간 상태정보를 공유하거나, 세션과 같은 휘발성 정보를 저장하거나 또는 캐쉬등으로 다양하게 사용할 있다.

 

Redis 제공하는 기능으로는 키로 데이타를 저장하고 조회하는 Set/Get 기능이 있으며, 메세지를 전달하기 위한 큐로도 사용할 있다.

 

큐로써의 기능은 하나의 클라이언트가 다른 클라이언트로 메세지를 보내는 1:1 기능뿐 아니라, 하나의 클라이언트가 다수의 클라이언트에게 메세지를 발송하는 발행/배포 (Publish/Subscribe) 기능을 제공한다.




그림 1 RedisPublish/Subscribe의 개념 구조

 

재미있는 것중에 하나는 일반적인 Pub/Sub 시스템의 경우 Subscribe 하는 하나의 Topic에서만 Subscribe하는데 반해서, redis에서는 pattern matching 통해서 다수의 Topic에서 message subscribe 있다.

예를 들어 topic 이름이 music.pop music,classic 이라는 두개의 Topic 있을때, "PSUBSCRIBE music.*"라고 하면 두개의 Topic에서 동시에 message subscribe 있다.

 

자료 구조

 

Redis 가장 기본이 되는 자료 구조를 살펴보자. Redis 다양한 자료 구조를 지원하는데, 지원하는 자료 구조형은 다음과 같다.

1)       String

Key 대해서 문자열을 저장한다. 텍스트 문자열뿐만 아니라 숫자나 최대 512mbyte 까지의 바이너리도 저장할 있다.

 

2)       List

Key 대해서 List 타입을 저장한다. List에는 값들이 들어갈 있으며, INDEX 값을 이용해서 지정된 위치의 값을 넣거나 있고, 또는 push/pop 함수를 이용하여 리스트 앞뒤에 데이타를 넣거나 있다. 일반적인 자료 구조에서 Linked List 같은 자료 구조라고 생각하면 된다.

 

3)       Sets

Set 자료 구조는 집합이라고 생각하면 된다. Key 대해서 Set 저장할 있는데, List 구조와는 다르게 주의할점은 집합이기 때문에 같은 값이 들어갈 없다. 대신 집합의 특성을 이용한 집합 연산, 교집합, 합집합등의 연산이 가능하다.

 

4)       Sorted Set

SortedSet Set 동일하지만, 데이타를 저장할때, value 이외에, score 라는 값을 같이 저장한다. 그리고 score 라는 값에 따라서 데이타를 정렬(소팅)해서 저장한다. 순차성이나 순서가 중요한 데이타를 저장할때 유용하게 저장할 있다.

 

5)       Hashes

마지막 자료형으로는 Hashes 있는데, 해쉬 자료 구조를 생각하면 된다.Key 해쉬 테이블을 저장하는데, 해쉬 테이블에 저장되는 데이타는 (field, value) 형태로 field 해쉬의 키로 저장한다.

키가 있는 데이타를 군집하여 저장하는데 유용하며 데이타의 접근이 매우 빠르다. 순차적이지 않고 비순차적인 랜덤 액세스 데이타에 적절하다.

 

설명한 자료 구조를 Redis 저장되는 형태로 표현하면 다음과 같다.

 



Figure 36 redis의 자료 구조

 

기본적으로 /밸류 (Key/Value) 형태로 데이타가 저장되며, 밸류에 해당하는 데이타 타입은 앞서 언급하 String, List, Sets, SortedSets, Hashes 있다.

 

Redis 대한 설명은 여기서는 자세하게 하지 않는다. 독립적인 제품인 만큼 가지고 있는 기능과 운영에 신경써야할 부분이 많다. Redis 대한 자세한 설명은 http://redis.io 홈페이지를 참고하거나 정경석씨가 이것이 레디스다http://www.yes24.com/24/Goods/11265881?Acode=101 라는 책을 추천한다. 단순히 redis 대한 사용법뿐만 아니라, 레디스의 데이타 모델 설계에 대한 자세한 가이드를 제공하고 있다.

 

Redis 설치하기

개발환경 구성을 위해서 redis 설치해보자.

 

맥의 경우 애플리케이션 설치 유틸리티인 brew 이용하면 간단하게 설치할 있다.

%brew install redis

 

윈도우즈

안타깝게도 redis 공식적으로는 윈도우즈 인스톨을 지원하지 않는다. http://redis.io에서 소스 코드를 다운 받아서 컴파일을 해서 설치를 해야 하는데, 만약에 이것이 번거롭다면, https://github.com/rgl/redis/downloads 에서 다운로드 받아서 설치할 있다. 그렇지만 이경우에는 최신 버전을 지원하지 않는다.

그래서 vagrant 이용하여 우분투 리눅스로 개발환경을 꾸미고 위에 redis 설치하거나 https://redislabs.com/pricing https://www.compose.io  같은 클라우드 redis 환경을 사용하기를 권장한다. ( 클라우드 서비스의 경우 일정 용량까지 무료 또는 일정 기간까지 무료로 서비스를 제공한다.)

 

리눅스

리눅스의 경우 설치가 매우 간단하다. 우분투의 경우 패키지 메니저인 apt-get 이용해서 다음과 같이 설치하면 된다.

%sudo apt-get install redis-server

 

설치가 끝났으면 편하게 redis 사용하기 위해서 redis 클라이언트를 설치해보자.

여러 GUI 클라이언트들이 많지만, 편하게 사용할 있는 redis desktop 설치한다. http://redisdesktop.com/ 에서 다운 받은 후에 간단하게 설치할 있다.

 

이제 환경 구성이 끝났으니, redis 구동하고 제대로 동작하는지 테스트해보자

%redis-server

명령을 이용해서 redis 서버를 구동한다.

 



Figure 37 redis 기동 화면

 

redis desktop 이용해서 localhost 호스트에 Host 주소는 localhost TCP 포트는 6379 새로운 Connection 추가하여 연결한다.

 

 



Figure 38 redis desktop에서 연결을 설정하는 화면

 

연결이 되었으면 redis desktop에서 Console 연다.

 



Figure 39 redis desktop에서 콘솔을 여는 화면

 

Console에서 다음과 같이 명령어를 입력해보자

 

localhost:0>set key1 myvalue

OK

 

localhost:0>set key2 myvalue2

OK

 

localhost:0>get key2

myvalue2

 

localhost:0>

Figure 40 redis desktop에서 간단한 명령을 통해서 redis를 테스트 하는 화면


위의 명령은 key1 myvalue라는 값을 입력하고, key2 myvalue2라는 값을 입력한 후에, key2 입력된 값을 조회하는 명령이다.

 

Redis desktop에서, 디비를 조회해보면, 앞서 입력한 /밸류 값이 저장되어 있는 것을 다음과 같이 확인할 있다.

\


Figure 41 redis에 저장된 데이타를 redis desktop을 이용해서 조회하기

 

node.js에서 redis 접근하기

 

이제 node.js에서 redis 사용하기 위한 준비가 끝났다. 간단한 express API 만들어서 redis 캐쉬로 사용하여 데이타를 저장하고 조회하는 예제를 작성해보자

 

node.js redis 클라이언트는 여러 종류가 있다. http://redis.io/clients#nodejs

가장 널리 쓰는 클라이언트 모듈로는 node-redis https://github.com/NodeRedis/node_redis 있는데, 예제는 node-redis 클라이언트를 기준으로 설명한다.

 

예제는 profile URL에서 사용자 데이타를 JSON/POST 받아서 redis 저장하고, TTL(Time to Leave) 방식의 캐쉬 처럼 10 후에 삭제되도록 하였다.

그리고 GET /profile/{사용자 이름} 으로 redis 저장된 데이타를 조회하도록 하였다.

 

먼저 node-redis 모듈과, json 문서를 처리하기 위해서 JSON 모듈을 사용하기 때문에, 모듈을 설치하자

% npm install redis

% npm install JSON

 

package.json 모듈의 의존성을 다음과 같이 정의한다.

 

 

{

  "name": "RedisCache",

  "version": "0.0.0",

  "private": true,

  "scripts": {

    "start": "node ./bin/www"

  },

  "dependencies": {

    "body-parser": "~1.13.2",

    "cookie-parser": "~1.3.5",

    "debug": "~2.2.0",

    "express": "~4.13.1",

    "jade": "~1.11.0",

    "morgan": "~1.6.1",

    "serve-favicon": "~2.3.0",

    "redis":"~2.6.0",

    "JSON":"~1.0.0"

  }

}

 

Figure 42 redisJSON 모듈의 의존성이 추가된 package.json

 

다음으로 express 간단한 프로젝트를 만든 후에, app.js 다음과 같은 코드를 추가한다.

 

 

// redis example

var redis = require('redis');

var JSON = require('JSON');

client = redis.createClient(6379,'127.0.0.1');

 

app.use(function(req,res,next){

      req.cache = client;

      next();

})

app.post('/profile',function(req,res,next){

      req.accepts('application/json');

     

      var key = req.body.name;

      var value = JSON.stringify(req.body);

     

      req.cache.set(key,value,function(err,data){

           if(err){

                 console.log(err);

                 res.send("error "+err);

                 return;

           }

           req.cache.expire(key,10);

           res.json(value);

           //console.log(value);

      });

})

app.get('/profile/:name',function(req,res,next){

      var key = req.params.name;

     

      req.cache.get(key,function(err,data){

           if(err){

                 console.log(err);

                 res.send("error "+err);

                 return;

           }

 

           var value = JSON.parse(data);

           res.json(value);

      });

});

 

Figure 43 app.jsredis에 데이타를 쓰고 읽는 부분

 

redis 클라이언트와, JSON 모듈을 로딩한후, createClient 메서드를 이용해서, redis 대한 연결 클라이언트를 생성하자.

 

client = redis.createClient(6379,'127.0.0.1');

 

app.use(function(req,res,next){

      req.cache = client;

      next();

})

 

다음 연결 객체를 express router에서 쉽게 가져다 있도록, 미들웨어를 이용하여 req.cache 객체에 저장하도록 하자.

 

HTTP POST /profile 의해서 사용자 프로파일 데이타를 저장하는 부분을 보면

req.accepts('application/json'); 이용하여 JSON 요청을 받아드리도록 한다.

JSON내의 name 필드를 키로, 하고, JSON 전체를 밸류로 한다. JSON 객체 형태로 redis 저장할 있겠지만 경우 redis에서 조회를 하면 객체형으로 나오기 때문에 운영이 불편하다. 그래서 JSON.stringfy 이용하여 JSON 객체를 문자열로 변환하여 value 객체에 저장하였다.

다음 req.cache.set(key,value,function(err,data) 코드에서 redis 저장하기 위해서 redis 클라이언트를 req 객체에서 조회해온후, set 명령을 이용해서 /밸류 값을 저장한다. 저장이 끝나면 뒤에 인자로 전달된 콜백함수 호출 되는데, 콜백함수에서, req.cache.expire(key,10); 호출하여, 키에 대한 데이타 저장 시간을 10초로 설정한다. (10 후에는 데이타가 삭제된다.) 마지막으로 res.json(value); 이용하여 HTTP 응답에 JSON 문자열을 리턴한다.

 

HTTP GET으로 /profile/{사용자 이름} 요청을 받아서 키가 사용자 이름은 JSON 데이타를 조회하여 리턴하는 코드이다.

app.get('/profile/:name',function(req,res,next) 으로 요청을 받은 , URL에서 name 부분을 읽어서 키값으로 하고,

req.cache.get(key,function(err,data){ 이용하여, 키를 가지고 데이타를 조회한다. 콜백 함수 부분에서, 데이타가 문자열 형태로 리턴되는데, 이를 var value = JSON.parse(data); 이용하여, JSON 객체로 변환한 후에, res.json(value); 통해서 JSON 문자열로 리턴한다.

 

코드 작성이 끝났으면 테스트를 해보자 HTTP JSON/POST REST 호출을 보내야 하기 때문에, 별도의 클라이언트가 필요한데, 클라이언트는 구글 크롬 브라우져의 플러그인인 포스트맨(POSTMAN) 사용하겠다. https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop

 

포스트맨 설치가 끝났으면, 포스트맨에서 HTTP POST/JSON 방식으로 http://localhost:3000/profile 아래와 같이 요청을 보낸다.

 



Figure 44 포스트맨에서 HTTP POSTprofile 데이타를 삽입하는 화면

 

요청을 보낸후 바로 HTTP GET으로 http://localhost:3000/profile/terry 조회를 하면 아래와 같이 앞에서 입력한 데이타가 조회됨을 확인할 있다. 이때 위의 POST 요청을 보낸지 10 내에 조회를 해야 한다. 10초가 지나면 앞서 지정한 expire 의해서 자동으로 삭제가된다.



Figure 45 포스트맨에서 사용자 이름이 terry인 데이타를 조회하는 화면

 

Redisdesktop에서 확인을 해보면 아래와 같이 문자열로 terry 사용자에 대한 데이타가 저장되어 있는 것을 확인할 있다.



Figure 46 redis desktop 에서 입력된 데이타를 확인하는 화면

 

10초후에, 다시 조회를 해보면, terry 키로 가지는 데이타가 삭제된 것을 확인할 있다.

 

지금까지 가장 기본적인 redis 대한 소개와 사용법에 대해서 알아보았다. redis 뒤에 나올 node.js 클러스터링의 HTTP 세션을 저장하는 기능이나, Socket.IO 등에서도 계속해서 사용되는 중요한 솔루션이다. Redis 자체를 다루는 것이 아니라서 자세하게 파고 들어가지는 않았지만, 다소 운영이 까다롭고 특성을 파악해서 설계해야 하는 만큼 반드시 시간을 내서 redis 자체에 대해서 조금 자세하게 살펴보기를 권장한다.