API 서버 개발

MongoDB Schema

MongoDB 에 접속하고 명령어를 실행하기 위하여 MongoDB 용 모듈중 하나인 mongoose 를 설치 합니다.

$ npm install --save mongoose

이제 mongoose 모듈을 사용하여 MongoDB 의 document 인 sequencesurls 의 스키마 정의를 합니다.

models.js 파일을 아래와 같이 작성합니다.

var mongoose = require("mongoose");
var Schema = mongoose.Schema;

var SequencesSchema = Schema({
  _id: { type: String, required: true },
  seq: { type: Number, default: 0 }
});

var sequences = mongoose.model("sequences", SequencesSchema);

var UrlsSchema = new Schema({
  _id: { type: Number },
  url: String,
  created_at: Date
});

UrlsSchema.pre("save", function(next) {
  var self = this;
  sequences.findOneAndUpdate(
    { _id: "url_count" },
    { $inc: { seq: 1 } },
    { upsert: true },
    function(error, result) {
      console.log(result);
      if (error) return next(error);
      self.created_at = new Date();
      self._id = result.seq;
      next();
    }
  );
});

var urls = mongoose.model("urls", UrlsSchema);

module.exports = urls;

mongoose 모듈은 mongoDB의 findAndModify 이름의 함수 대신에, 용도에 맞는 다양한 이름의 함수를 제공하고 있습니다. 본 프로젝트에서는 조회 후 Update 하는 findOneAndUpdate 를 사용했습니다.

자세한 설명은 http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate 를 참조합니다.

Bijective 유틸

bijective.js 파일을 아래와 같이 작성합니다.

var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var base = alphabet.length;

function encode(num){
  var encoded = '';
  if(num==0) return alphabet[num];
  while (num){
    var remainder = num % base;
    num = Math.floor(num / base);
    encoded = alphabet[remainder].toString() + encoded;
  }
  return encoded;
}

function decode(str){
  var decoded = 0;
  while (str){
    var index = alphabet.indexOf(str[0]);
    var power = str.length - 1;
    decoded += index * (Math.pow(base, power));
    str = str.substring(1);
  }
  return decoded;
}

module.exports.encode = encode;
module.exports.decode = decode;

서버 코드

최종 완성된 server.js 파일은 아래와 같습니다.

var express = require('express');
var mongoose = require('mongoose');
var bijective = require('./bijective.js');
var Urls = require('./models');

mongoose.connect('mongodb://localhost/url-shortener');

var app = express();
app.use(express.static('public'));

app.get('/url/:longUrl', function(req, res){

  var shortUrl = '';

  Urls.findOne({url: req.params.longUrl}, function (err, doc){
    if (doc){
      res.send({'key': bijective.encode(doc._id)});
    } else {

      var newUrl = Urls({
        url: req.params.longUrl
      });

      newUrl.save(function(err) {
        if (err) console.log(err);

        res.send({'key': bijective.encode(newUrl._id)});
      });
    }

  });

});

app.get('/:key', function(req, res){

  var id = bijective.decode(req.params.key);

  Urls.findOne({_id: id}, function (err, doc){
    if (doc) {
      res.redirect(doc.url);
    } else {
      res.redirect("/");
    }
  });

});


app.listen(3000, function () {
  console.log('URL Shortener Server listening on port 3000!')
});

이제 실행해 보면서 동작 여부를 확인 합니다.

$ node server.js

results matching ""

    No results matching ""