NodeJS/Prototyping

[Node.js] Node.js, Express, MongoDB를 이용하여 REST API 만들기

Peter Note 2013. 1. 29. 21:57

Node.js를 설치하고 MongoDB를 사용하여 REST API를 만들어보자. native MongoDB driver를 사용하며 REST API를 쉽게 만들기 위하여 Node.js의 웹애플리케이션 프레임워크인 Express를 이용한다. 원문의 내용을 보고 수행한 결과를 요약한다 



1) Node.js 설치 

  - http://nodejs.org/dist/  : 사이트에서 최신 버전을 선택하여 다운로드한다 

  - 예) linux 

[mongodb@localhost ~]$ wget http://nodejs.org/dist/v0.9.8/node-v0.9.8-linux-x86.tar.gz 

--2013-02-01 21:24:48--  http://nodejs.org/dist/v0.9.8/node-v0.9.8-linux-x86.tar.gz

Resolving nodejs.org... 165.225.133.150

Connecting to nodejs.org|165.225.133.150|:80... connected.

HTTP request sent, awaiting response... 200 OK

Length: 4491882 (4.3M) [application/octet-stream]

Saving to: “node-v0.9.8-linux-x86.tar.gz”


100%[=========================================================>] 4,491,882    284K/s   in 17s     


2013-02-01 21:25:07 (263 KB/s) - “node-v0.9.8-linux-x86.tar.gz” saved [4491882/4491882]


[mongodb@localhost ~]$ ls

aggregation  mongo  mongod  mongodb  mongofiles  mongos  node-v0.9.8-linux-x86.tar.gz  shard

[mongodb@localhost ~]$ tar zxf node-v0.9.8-linux-x86.tar.gz

[mongodb@localhost ~]$ ls

aggregation  mongod   mongofiles  node-v0.9.8-linux-x86         shard

mongo        mongodb  mongos      node-v0.9.8-linux-x86.tar.gz

[mongodb@localhost ~]$ rm node-v0.9.8-linux-x86.tar.gz

[mongodb@localhost ~]$ mv node-v0.9.8-linux-x86 node-v0.9.8

[mongodb@localhost ~]$ ls

aggregation  mongo  mongod  mongodb  mongofiles  mongos  node-v0.9.8  shard

[mongodb@localhost ~]$ cd node-v0.9.8/

[mongodb@localhost node-v0.9.8]$ cd bin

[mongodb@localhost bin]$ ./node -v

v0.9.8


2) Node.js 수행하기 

  - 적당한 디렉토리에 nodecellar 디렉토리 만듦

  - nodecellar 안에 server.js 파일 생성

  - server.js 코딩 

////////////////////////////////////////////////
// server.js
var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(3000, '127.0.0.1');
console.log('Server running at http://127.0.0.1:3000/');


  - server.js 수행하고 브라우져에서 http://127.0.0.1:3000/ 호출 

[mongodb@localhost ~]$ cd nodecellar/

[mongodb@localhost nodecellar]$ node server.js

Server running at http://127.0.0.1:3000/



3) Express 설치하기 

  - Node.js의 Web Application Framework 이고, REST API 생성을 쉽게 해준다 

  - nodecellar 디렉토리안에 package.json 파일을 만들어서 Node.js가 의존하는 모듈을 정의한다 

////////////////////////////////////////////
// package.json
{
    "name": "wine-cellar",
    "description": "Wine Cellar Application",
    "version": "0.0.1",
    "private": true,
    "dependencies": {
        "express": "3.x"
    }
}

  - express 설치하기 

// package.json의 의존관계 모듈을 읽어서 자동 설치해 준다 

[mongodb@localhost nodecellar]$ npm install

npm WARN package.json wine-cellar@0.0.1 No README.md file found!

npm http GET https://registry.npmjs.org/express

npm http 200 https://registry.npmjs.org/express

npm http GET https://registry.npmjs.org/express/-/express-3.1.0.tgz

... 중략 ...
express@3.1.0 node_modules/express
├── methods@0.0.1
├── fresh@0.1.0
├── range-parser@0.0.4
├── cookie-signature@0.0.1
├── buffer-crc32@0.1.1
├── cookie@0.0.5
├── commander@0.6.1
├── debug@0.7.0
├── mkdirp@0.3.3
├── send@0.1.0 (mime@1.2.6)
└── connect@2.7.2 (pause@0.0.1, bytes@0.1.0, formidable@1.0.11, qs@0.5.1)



4) server.js를 Express 형식으로 바꾸기 

  - express 프레임워크를 이용하여 HTTP Listener를 바꾼다

////////////////////////////////////////////
// server.js
var express = require('express');
 var app = express();
 
app.get('/wines', function(req, res) {
    res.send([{name:'wine1'}, {name:'wine2'}]);
});
app.get('/wines/:id', function(req, res) {
    res.send({id:req.params.id, name: "The Name", description: "description"});
});
 
app.listen(3000);
console.log('Express Listening on port 3000...');

  - express 실행

[mongodb@localhost nodecellar]$ node server

Express Listening on port 3000...


  - 브라우져 호출하기 

    + 전체 wine들 

  

    + 1번 wine 내역 

  


5) Node.js에서 Controller로써 routes를 만들기 

  - nodecellar 디렉토리 밑으로 routes 폴더를 만든다 

  - routes 밑에 모듈로 wines.js 를 만든다 

////////////////////////////////////////////
// routes 디렉토리 밑의 wines.js
exports.findAll = function(req, res) {
    res.send([{name:'wine1'}, {name:'wine2'}, {name:'wine3'}]);
};
 
exports.findById = function(req, res) {
    res.send({id:req.params.id, name: "The Name", description: "description"});
};


  - server.js 파일에서 wines.js 모듈을 로딩하게 한다. 그리고 다시 브라우져로 호출한다 

////////////////////////////////////////////
// server.js에서 wines.js 모듈 로딩
var express = require('express'),
    wines = require('./routes/wines');
var app = express();
 
app.get('/wines', wines.findAll);
app.get('/wines/:id', wines.findById);
 
app.listen(3000);
console.log('Express Listening on port 3000...');


6) MongoDB Driver 설치하기 

  - MongoDB는 설치되어 있다고 가정한다 (참조)

  - 여기서는 native Node.js driver를 사용한다

  - mongodb driver 설치하기 

[mongodb@localhost nodecellar]$ npm install mongodb

npm WARN package.json wine-cellar@0.0.1 No README.md file found!

npm http GET https://registry.npmjs.org/mongodb

...  중략 ...

npm http GET https://registry.npmjs.org/bson/-/bson-0.1.6.tgz

... 중략 ...

node-gyp clean

node-gyp configure build

gyp http GET http://nodejs.org/dist/v0.9.8/node-v0.9.8.tar.gz

gyp http 200 http://nodejs.org/dist/v0.9.8/node-v0.9.8.tar.gz

make[1]: Entering directory `/home/mongodb/nodecellar/node_modules/mongodb/node_modules/bson/build'

  CXX(target) Release/obj.target/bson/ext/bson.o

  SOLINK_MODULE(target) Release/obj.target/bson.node

  SOLINK_MODULE(target) Release/obj.target/bson.node: Finished

  COPY Release/bson.node

make[1]: Leaving directory `/home/mongodb/nodecellar/node_modules/mongodb/node_modules/bson/build'

child process exited with code 0

mongodb@1.2.11 node_modules/mongodb

└── bson@0.1.6



7) REST API 정의하기 

  - 호출 내역 

    + GET: 전체 wine 목록

    + GET: id로 선택된 wine 정보얻기 

    + POST: 새로운 wine 생성

    + PUT: id로 선택된 wine 정보갱신

    + DELETE: id로 선택된 wine 삭제하기 

  

  

  - server.js에서 wines.js를 확장한 메소드를 추가한다 

  - wines.js 안에 MongoDB 코드로 변경하기 



8) MongoDB 와 Node.js 수행하고 Testing 하기 

  - MongoDB는 default port로 수행한다 

[mongodb@localhost ~]$ ./mongod --dbpath /home/mongodb/aggregation

... 중략 ...

Fri Feb  1 22:30:46 [initandlisten] options: { dbpath: "/home/mongodb/aggregation" }

Fri Feb  1 22:30:46 [initandlisten] Unable to check for journal files due to: boost::filesystem::basic_directory_iterator constructor: No such file or directory: "/home/mongodb/aggregation/journal"

Fri Feb  1 22:30:46 [initandlisten] couldn't unlink socket file /tmp/mongodb-27017.sockerrno:1 Operation not permitted skipping

Fri Feb  1 22:30:46 [initandlisten] waiting for connections on port 27017

Fri Feb  1 22:30:46 [websvr] admin web console waiting for connections on port 28017



  - Node.js 수행하기 

     + MongoDB의 기본 port 27017 로 접근한다 

[mongodb@localhost nodecellar]$ node server

========================================================================================

=  Please ensure that you set the default write concern for the database by setting    =

=   one of the options                                                                 =

=                                                                                      =

=     w: (value of > -1 or the string 'majority'), where < 1 means                     =

=        no write acknowlegement                                                       =

=     journal: true/false, wait for flush to journal before acknowlegement             =

=     fsync: true/false, wait for flush to file system before acknowlegement           =

=                                                                                      =

=  For backward compatibility safe is still supported and                              =

=   allows values of [true | false | {j:true} | {w:n, wtimeout:n} | {fsync:true}]      =

=   the default value is false which means the driver receives does not                =

=   return the information of the success/error of the insert/update/remove            =

=                                                                                      =

=   ex: new Db(new Server('localhost', 27017), {safe:false})                           =

=                                                                                      =

=   http://www.mongodb.org/display/DOCS/getLastError+Command                           =

=                                                                                      =

=  The default of no acknowlegement will change in the very near future                =

=                                                                                      =

=  This message will disappear when the default safe is set on the driver Db           =

========================================================================================

Express Listening on port 3000...

Connected to 'winedb' database


  - curl을 수행한다 

/////////////////////////////////////////

// POST를 통하여 신규 wine을 생성한다

[mongodb@localhost ~]$ curl -i -X POST -H 'Content-Type: application/json' -d '{"name": "New Wine", "year": "2009"}' http://localhost:3000/wines

HTTP/1.1 200 OK

X-Powered-By: Express

Content-Type: application/json; charset=utf-8

Content-Length: 79

Date: Sat, 02 Feb 2013 06:38:49 GMT

Connection: keep-alive


{

  "name": "New Wine",

  "year": "2009",

  "_id": "510cb4798859a9b51d000001"


/////////////////////////////////////////

// MongoDb 확인 

[mongodb@localhost ~]$ mongo

MongoDB shell version: 2.2.2

connecting to: test

> show dbs

dowonDB 0.03125GB

local (empty)

winedb 0.0625GB

> use winedb

switched to db winedb

> show collections

system.indexes

wines

> db.wines.find()

{ "name" : "New Wine", "year" : "2009", "_id" : ObjectId("510cb4798859a9b51d000001") }


/////////////////////////////////////////

// GET 명령 수행하여 정보 조회

// wine 목록을 얻어온다.

[mongodb@localhost ~]$ curl -i -X GET http://localhost:3000/wines

HTTP/1.1 200 OK

X-Powered-By: Express

Content-Type: application/json; charset=utf-8

Content-Length: 93

Date: Sat, 02 Feb 2013 06:41:37 GMT

Connection: keep-alive


[

  {

    "name": "New Wine",

    "year": "2009",

    "_id": "510cb4798859a9b51d000001"

  }

]


// 특정 wine 조회. _id를 넣어준다 

[mongodb@localhost ~]$ curl -i -X GET http://localhost:3000/wines/510cb4798859a9b51d000001

HTTP/1.1 200 OK

X-Powered-By: Express

Content-Type: application/json; charset=utf-8

Content-Length: 79

Date: Sat, 02 Feb 2013 06:42:14 GMT

Connection: keep-alive


{

  "name": "New Wine",

  "year": "2009",

  "_id": "510cb4798859a9b51d000001"



/////////////////////////////////////////

// PUT 명령 수행하여 정보 수정 

[mongodb@localhost ~]$ curl -i -X PUT -H 'Content-Type: application/json' -d '{"name": "New Wine", "year": "2010"}' http://localhost:3000/wines/510cb4798859a9b51d000001
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 42
Date: Sat, 02 Feb 2013 06:44:00 GMT
Connection: keep-alive

{
  "name": "New Wine",
  "year": "2010"


/////////////////////////////////////////

// DELETE 명령 수행하여 정보 삭제

[mongodb@localhost ~]$ curl -i -X DELETE http://localhost:3000/wines/510cb4798859a9b51d000001
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 2
Date: Sat, 02 Feb 2013 06:46:22 GMT
Connection: keep-alive

/////////////////////////////////////////

// MongoDb 확인 

[mongodb@localhost ~]$ mongo
MongoDB shell version: 2.2.2
connecting to: test
> use winedb
switched to db winedb
> show collections
system.indexes
wines
> db.wines.find()    <=== 데이터가 삭제되어 없음 



<참조>

  - 원문 : Creating a REST API using Node.js, Express, and MongoDB

  - 참조 

    + https://speakerdeck.com/jakobmattsson/writing-restful-web-services-using-nodejs

    + Node.js 설치하기

    + MongoDB 설치하기

  - 심화 : Backbone.js 와 Bootstrap, Node.js로 만들기