Node 에서 Redis 사용하기

웹 사이트를 구성할 때 운영 안정성을 고민할 때가 많다. 서버가 고장이 나서 고객들이 접속하면 어떡하지 걱정도 되고 사업이 잘되서 생각보다 많은 사람이 접속을 해서 한 대의 서버로는 감당이 안될 경우에도 문제가 될 수 있다. 이런 경우에는 여러 대의 서버로 사이트를 구성하는 것이 보편적이다. 이렇게 여러 대를 구성하게 되면 자주 발생하는 문제가 고객이 접속하는 서버가 한 대에 고정되는 것이 아니라 여러 대의 서버로 옮겨 다닌다는 것이다. 이로 인해 사용자가 어느 서버에서 작업한 내용이 다른 서버로 옮겨가면서 다 사라져 버리는 불평을 호소하게 된다. 이를 방지하기 위해서 각 서버는 사용자의 작업 내용을 공유하게 되는데 쉽게 공유할 수 있는 방법이 캐시 서버를 두는 방식과 DB 서버를 두는 방식이 있다.
공유가 필요한 사용자의 작업 내용은 데이터로 저장되기 이전의 내용이고 저장된 이후에는 DB에 보관되어 있으므로 굳이 관리가 필요하지 않다. 따라서 여기서는 캐시 서버를 두는 예제를 다루기로 하고 redis 라는 솔루션을 이용하기로 한다.

Redis Install

yum 으로 설치하기

redis 최신 버전을 위해서 remi 저장소를 필요로 한다. 그리고 redis는 jemalloc 패키지를 사용하는데 이 패키지는 epel 저장소에 있다. 필요 저장소를 설치하기 위해서 아래와 같이 rpm 파일을 설치한다. EPEL,Remi 설치하기 를 참고 하시오.

$ wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
HTTP request sent, awaiting response… 200 OK
Length: 14540 (14K) [application/x-rpm]
Saving to: ‘epel-release-6-8.noarch.rpm’

$ wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
HTTP request sent, awaiting response… 200 OK
Length: 7615 (7.4K) [application/x-rpm]
Saving to: ‘remi-release-6.rpm’

$ sudo rpm -Uvh remi-release-6.rpm epel-release-6-8.noarch.rpm
준비 중… ################################# [100%]

yum을 이용하여 redis를 설치하려면 –enablerepo 옵션을 사용하여 epel과 remi 저장소에 접근하도록 지정하여야 한다. 아래와 같이 설치가 완료되면 시스템 서비스로 redis 가 실행되도록 등록하고 서비스를 실행한다.

$ sudo yum –enablerepo=epel,remi install redis -y
Loaded plugins: priorities, update-motd, upgrade-helper
epel/x86_64/metalink | 4.6 kB 00:00
epel/x86_64 | 4.3 kB 00:00
epel/x86_64/group_gz | 149 kB 00:00
epel/x86_64/updateinfo | 739 kB 00:01
epel/x86_64/primary_db | 5.8 MB 00:09

$ sudo chkconfig redis on
$ sudo service redis start

소스로 설치하기

yum 을 이용한 redis 의 설치 버전은 2.4 버전으로 낮은 버전이다. 높은 버전 (예 3.0) 을 설치하려면 소스를 받아서 빌드하고 설치하는 과정이 필요하다. 빌드가 가능하도록 아래와 같이 gcc 컴파일러와 테스트 도구를 설치하자.

$ sudo yum install -y gcc*
$ sudo yum install -y tcl

이제 redis 최신 버전을 받아서 아래와 같이 설치를 진행한다.

$ wget http://download.redis.io/releases/redis-3.0.1.tar.gz
$ tar xzf redis-3.0.1.tar.gz
$ cd redis-3.0.1
$ make
$ make test
$ make install
$ cd utils
$ chmod +x install_server.sh
$ ./install_server.sh

기본 설정을 묻는 질문들이 나오는데 엔터를 쳐서 기본 설정을 그대로 따라가면 된다. 중간에 실행 파일의 위치를 묻는데 which redis-server를 쳐보면 설치된 경로명을 알 수 있다. 여기서는 /usr/local/bin/redis-server 로 되어 있다.

설정 및 실행

설치하면서 실행할 서비스 이름이 달라질 수 있는데 설치 결과 메시지를 주목해서 봐야한다. 여기서는 아래와 같이 실행해야 한다. (포트 번호가 서비스 스크립트에 따라 붙어있다.)

$ sudo service redis_6379 start

redis 가 기본 localhost 에 대해서 동작하도록 되어 있으므로 외부 서버가 이용할 수 있도록 외부에 노출된 서버 ip 를 설정해준다. 아래와 같이 편집기를 이용해서 설정 파일 내용을 수정하자.

$ sudo vi /etc/redis/6379.conf

bind 에 정의된 ip 주소에 서버의 ip를 설정한다. 서버의 ip 주소는 ifconfig 명령으로 알 수 있다. 그리고 외부의 침입을 막기 위해 비밀번호로 보호를 하는 것이 안전하다. requirepass 항목에 적당한 비밀번호를 설정하자. 설정값은 복사해서 바로 사용할 수 있도록 대부분 설정 내용이 주석으로 기술되어 있다.

# Accept connections on the specified port, default is 6379.
# If port 0 is specified Redis will not listen on a TCP socket.
port 6379
# If you want you can bind a single interface, if the bind option is not
# specified all the interfaces will listen for incoming connections.
# bind 127.0.0.1
bind 172.31.15.27
# requirepass foobared
requirepass your_password

redis 서비스를 재 시작한다.

$ sudo service redis restart

redis desktop manager 로 서비스를 접속해본다. 이 RDM 다운로드 링크를 이용해서 다운 받아 설치할 수 있다.

Sample Test Coding

이제 redis 서버에 데이터를 저장하고 읽어가는 기능을 테스트 할 수 있도록 웹 사이트를 구성해 보자. node 에서는 웹 사이트 개발을 편리하게 하기 위해 express 라는 모듈을 이용한다. 사이트의 기본 골격을 만들어주는 명령어도 제공되는데 아래와 같이 설치하고 기본 웹 사이트를 만들어 보자.

install express & redis module

어느 폴더 위치에서도 express를 사용할 수 있도록 -g 옵션을 이용해서 설치하자.

$ sudo npm install -g express
$ npm install -g express-generator

express 명령을 이용해서 기본 웹 사이트 구조를 만들고 그 사이트에서 사용할 redis 모듈을 설치하자. –save 옵션을 이용하면 사이트의 package.json 파일에 어떤 모듈이 설치되었는지 기록이 되고 node_modules 폴더에 다운로드 된다.

$ express redisweb
$ cd redisweb

$ npm install –save connect-redis ioredis
$ npm install –save JSON

setup web application

폴더 바로 안쪽에 app.js 파일에 redis, JSON 모듈을 선언하고 접속 정보를 설정한다. (설정 정보는 별도 설정 파일로 존재하는 것이 좋은데 여기서는 생략한다.)

var Redis = require('ioredis');
var JSON = require('JSON');
client = new Redis({port: 6379, host: '52.79.54.249',
  password: 'your_password', db: 0});

express로 app 을 생성한 코드 다음에 redis 사용 가능하도록 아래 코드와 같이 middleware 에 등록하자. 각 함수에서 redis 를 이용할 수 있도록 request 객체에 cache 이름으로 미리 만들어 둔다.

app.use(function(req,res,next) {
  req.cache = client;
  next();
})

routes 폴더 안에 profile.js 파일을 생성하고 아래와 같이 코드를 입력한다.

var express = require('express');
var JSON = require('JSON&');
var router = express.Router();

router.get('/:name', function(req, res, next) {
  var key = req.params.name;
  req.cache.get(key, function(err,data){
    if (err) {
      console.log(err);
      res.send(err);
      return;
    }
    var value = JSON.parse(data);
    res.json(value);
  });
});

router.post('/', function(req, res, next) {
  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(err);
      return;
    }

    req.cache.expire(key, 60);
    req.json(value);
  });
});

module.exports = router;

사용자가 입력한 데이터를 json 형태로 수신 받으면 post 함수에서 req.cache 으로 제공된 redis 로 수신 받은 데이터의 name 항목을 키와 문자열로 변환된 데이터를 저장한다. 저장에 성공하면 키 값의 유효시간을 60초로 하여 시간이 지나면 자동으로 소멸되게 한다.

get 함수에서는 name을 파라미터 값으로 받아서 req.cache 의 redis 를 통해서 데이터를 가져올 수 있다. 가져온 데이터를 json 형태로 사용자 화면에 표기한다.

이제 생성한 profile.js 파일을 app.js 안에 아래와 같이 모듈을 추가한다.

var routes = require('./routes/index');
var users = require('./routes/users');
var profile = require('./routes/profile');

사용자가 접속할 수 있는 주소 경로 /profile를 등록한다. 경로를 등록한 다른 함수 아래에 추가하면 된다.

app.use('/', routes);
app.use('/users', users);
app.use('/profile', profile);

Test

완성된 웹 사이트를 아래 명령으로 실행한다.

$ npm start

http://localhost:3000/ 주소로 브라우저로 접속을 해 보자. 전송할 데이터를 입력한 화면이 완성되지 않은 상태이기 때문에 크롬 브라우저의 POSTMAN 앱을 설치하고 postman 을 통해서 데이터를 작성해서 전송하자. 설치된 postman 을 실행하고 주소를 http://localhost:3000/profile 로 입력하고 그 왼쪽에 GET 을 POST로 변경한다. 그 아래 Headers 탭을 선택하고 Content-Type 항목에 application/json 을 입력한다. Headers 옆에 Body 탭을 선택하고 그 아래 raw 를 클릭하고 그 오른쪽에 입력 형태를 JSON(application/json) 을 선택한다. 그 아래 데이터 입력란에 아래의 json 코드를 입력한다.

{
  'name': 'tom';,
  'address': 'Seoul, Korea',
  'phone': '001-001-0001'
}

이제 send 버튼을 클릭하면 웹 사이트로 입력한 데이터를 전송하고 서버에 tom 을 키 값으로 데이터가 저장된다. 입력한 데이터 아래에 서버에서 응답한 결과가 나타나는데 Body 에 동일한 json 형태의 데이터가 나타나고 Status 에는 200 OK 라고 표시된다.

redis-json-result

 

다시 POST 를 GET 으로 바꾸고 주소에 http://localhost:3000/profile/:name 를 입력하고 send 하면 동일한 json 데이터가 화면 하단에 나타난다.

참고 사이트