node를 이용한 초간단 랭킹 서버 만들기

몇일전에 애니팡과 비슷한 팡류 게임을 하나 만들었다. 이름하야 패치팡! ㅋㅋ 패치팡은 자바스크립트만으로 만들었고, 게임을 만드는데 꼬박 3일이 걸렸다. 3일중 이틀은 구조잡고 기본 알고리즘 만드는데 썻고, 나머지 하루는 대충 콜리로  UI만들고 포샵질 하느라 시간을 보냈다. 여튼 만들고 보니 뭔가 허전하다 제대로 쓸려면 내가 얻은 점수를 서버에 저장하고 친구들끼리 경쟁을 붙여야한다. 그래서 또 대충 랭킹 서버를 만들기로 했다.  랭킹 서버는 랭킹 정보를 저장할 DB가 있어야한다. DB는 SQL로 쓰려다가 쿼리 짜기 귀찮아서 그냥 몽고DB로 결정!!

1. 몽고DB 설치하기

일단 서버에 몽고DB 서버를 설치하고 설정해야한다. 설치와 설정은 다음 링크를 참고~!! 참고로 내 서버는 페도라다! 그리고 테스트 개발은 윈도우 환경에서 진행했다!

http://docs.mongodb.org/manual/tutorial/install-mongodb-on-red-hat-centos-or-fedora-linux/ 서버에 DB를 설치했으니 실행하자!

$service mongod start

2. 몽고DB를 읽고 쓰기 위한 node 모듈 설치하기

$npm install mongoose

물론 노드가 미리 설치되어 있어야한다. 뭐 노드는 이미 깔려있으니까.. 패스! 다음으로 RESTfull API로 만들어서 랭킹을 저장할 것이므로.. 간단한 웹 인터페이스 제작을 위해 express 모듈도 일단 설치!!

$npm install express

그리고 요즘엔 이녀석 없으면 코딩할 맛이 안난다. 바로 underscore.js!!! 뭐 안쓸찌도 모르겠찌만.. 일단 설치부터~~  

$npm install underscore

3. 몽고 DB 스키마 만들기

초간단하게 만들 것이므로 스키마도  간단하다. 물론 나중에 소셜을 연동할 것이므로 나중에는 좀더 복잡하겠지만, 지금은 그냥 동작 확인만 하면 되니까 이름과 점수만 기록하자!

var mongoose = require('mongoose');
var db = mongoose.createConnection('mongodb://localhost/test', {
    server : {
        poolSize : 10
    }
});
var RankSchema = new mongoose.Schema({
    point : Number,
    name : String
});
var PatchPangRank = db.model('PatchPangRank', RankSchema);

요렇게 만들어진 PatchPangRank는 RankSchema를 모델로 하는 일종의 Collection 이 된다. 기억해두자! 콜렉션!!  Backbone.js의 콜렉션과 유사하다고 보면 된다! 보다 자세한 몽구스 사용법은

API 문서를 참고하자.

4. RESTful API 서버 만들기

이제 DB는 대충 만들었고, 다음으로 서버를 구축해야한다. 서버는 당근 node를 이용할꺼다. 아까 설치한 express 모듈을 이용해서 간단하게 만들어보자!

var express = require('express');
var app = express();
app.get('*', function(req, res) {

    //일단 들어온 경우
    res.send('Hello!! Get the Fuck OUT!');

});
app.listen(8888);
console.log('starting server~!');

80번 포트가 아닌 8888번 포트인걸 감안하자. 80 포트로 만들면 아주 쉽겠지만,..  내서버의 80포트는 이미 nginx님아 차지하고 있다! 그래서 계획은 이렇다! 어찌됐는 /api/xxxx 형태로 호출되는 API는 프록시를 이용해 8888번 포트로 넘겨버릴 생각이다. 그럼 이제 API를 만들어보자. 대충 이런식으로 호출하면 점수가 기록되게 할 생각이다!

/api/add/score/[이름]/[점수]

그리고, 랭킹을 얻어오는 API는 대충 이렇다!

/api/get/ranks

뭐 대충대충.. 어떻게 만들지를 정했으니..  또 대충 서버에 해당 API를 추가해보자~!!

var express = require('express');
var app = express();

// 이 녀석은 점수를 추가하는 API
app.post('/api/add/score/:name/:point', function(req, res) {  });

// 이 녀석은 랭킹 정보를 가져오는 API
app.get('/api/get/ranks', function(req, res) { });

app.get('*', function(req, res) {
    //일단 들어온 경우
    res.send('Hello!! Get the Fuck OUT!');
});
app.listen(8888);
console.log('starting server~!');

이제 본격적으로 코딩해야할 시간이다~!!

5. 서버 API 만들기 먼저 점수를 넣는 것부터 만들어보자!!

app.post('/api/add/score/:name/:point', function(req, res) {
    var name = req.params.name;
    var point = req.params.point;
    var rank = new PatchPangRank({
        name : name,
        point : point
    });
    rank.save();
    res.send('{result: INSERT OK}');
});

아까 만들어둔 PatchPangRank에다가 점수를 기록하고 save()만 해주면 끝~!! 정말 간단하다~!! 물론 중복데이터는 걸려줘야한다… 그럼 중복데이터도 걸러내볼까? 난 이미 만들었지만.. 설명하기 귀찮타..-_- 힌트를 준다면.. PatchPangRank 객체에서 기존에 같은 이름이 있는지 검색한다. 대충 쓰면 요런식이 되겠다!!

PatchPangRank
    .find({ name : name })
    .exec(function (err, rank){
        if(err){ return handlerError(err); }

        // ...  여기다가 rank가 중복됐는지 확인하면 된다..
});

여기서 주의해야하는건 rank가 콜렉션이다! 그래서 배열로 넘어온다!! 다음으로 랭킹을 가져오는 API도 만들어보자!

app.get('/api/get/ranks', function(req, res) {
    console.log("--------");
    PatchPangRank
    .find()
    .limit(10)
    .sort('-point')
    .select('name point')
    .exec(function(err, rank) {
       if (err)  return handleError(err);

       var data = [];
       _.each(rank, function(v){
           if(!v.name){
               v.remove();
           }

           data.push({
               name : v.name,
               point : v.point
           });
       });

       var body = JSON.stringify(data);
       res.setHeader('Content-Type', 'x-application/json');
       res.setHeader('Content-Length', body.length);
       res.end(body);
   });
});

요건 뭐 너무 쉬워서 설명할 꺼리도 없겠다!!

5. 마지막 프락시 설정하기

아까도 이야기했지만, 내 서버는 엔진엑스가 80포트를 쓰고 있다. 그래서 노드는 뒷딴으로 밀려버린 상태.. 서버 설정에 프락시를 추가해준다.

location /api {
    proxy_pass_header Server;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Scheme $scheme;
    proxy_pass http://127.0.0.1:8888;
 }

짜잔~~ 이젠 정말 끝~!! 이제 https://miconblog.com/api/get/ranks 로 접근하면 기록된 랭키정보가 나와야한다! 물론 실제 랭킹서버가 이렇게 허술하진 않겠지만… 뭐 어찌됐든 점수를 기록하고 랭킹을 메겨주는건 맞으니까.. 보안 코드는 나중에 또 기회가 되면 얘기하는걸로 하고 여기까지 정리끝~!!