블로그 이미지
윤영식
Full Stacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2014. 4. 25. 00:15 NodeJS/Concept

Node.js를 제대로 배워보고 싶다면 이렇게 시작해보자


1. Node.js 사용 영역

  - fast, real-time 어플리케이션 개발

  - scalable 확장가능성이 높은 어플리케이션 개발

  - data-driven modern web 어플리케이션 개발

  * 클라우드 환경 이해



2. 잘 못 된 코스 

  - 온라인 및 동영상 강좌들부터 보지 말기

  - 서점에서 서평들 읽고 책 고르지 말기 



3. 제대로 된 코스

  - 봐야할 리소스 

    + 초보 : The Node Beginner Book 번역본

    + Felix's NodeJS Guide 번역본

   + Node.js 소개 자료 -여름으로 가는 문

   + Mastering NodeJS (비젼미디어)


  - JavaScript 를 배운다 : JavaScript Graden 번역본


  - 설치 : Professional Node.js 1장 보고 개발환경 셋업

  - 이해 : Beginner Book 보고서 간단히 프로그램들 돌려보기 

  - 모듈 : CommonJS에 대하여 이해하기

  - Professional Node.js 3장부터 쭉 읽자. 그러면 서버단 개발에 대해서 이해할 수 있다

  - 우리 목적은 modern web application개발이니 front-end의 backbone.js 를 배운다 



4. Node.js & Backbone.js를 익혔다면 

  - http://dailyjs.com/web-app.html 여기서 다양한 어플리케이션의 모험을 해보시라

  - 더 나아가서는 템플릿을 위한 Handlebars.js 와 MongoDB를 익힌다


  * 2013.2.20 일에 작성한 블로그라서 backbone.js가 나왔다. 이제는 angular.js로 옮겨가는 분위기

    3주를 목표로 잡고 시작하시라~~~ Good Luck!



<참조>

  - 원문 : http://javascriptissexy.com/learn-node-js-completely-and-with-confidence/

posted by 윤영식
2013. 9. 23. 11:40 NodeJS/Concept

Node.js 위에 기본적으로 Express.js를 많이 사용하지만 좀 더 추상화 되고 MVC 다운 프레임워크를 사용해 보고자. Express.js 및 Socket.io 와 다양한 데이터베이스를 추상화해서 사용할 수 있는 기능을 갖춘 Sails.js Framework을 사용해 보도록 한다. 



1. 사용 배경

  - Enterprise 급 MVC Framework : Express.js + Socket.io 기본 설정되어 사용

  - Waterline 이라는 adapter를 통하여 다양한 Database의 호환성 보장 

    + 흐름 : Model 객체 <-> Waterline <-> Databases 

    + 지원 데이터베이스 : MySql, PostgreSql, MongoDB, etc

    + 데이터베이스 연결을 하지 않으면 파일 또는 디스크에 백만개 밑으로 key:value 저장하는 node-dirty의 어뎁터를 사용한다

  - 손쉬운 설치 및 RESTful Web Services 개발

  - socket.io 및 redis 통합 

  - SPA (Single Page Application) 개발을 위한 client framework (backbone, ember, angular)의 adapter 제공 

    + Yeoman generator 제공 : Generator Sails AngularJS



2. 설치 및 사용

  - Yeoman을 기본 설치한다 : Yeoman 이해와 설치하기

  - "generator-sails-angular" 설치 후 "yo" 명령수행 : 빨간색의 Sails-angular 선택 (주의, sails 0.9.4 버전과 호환안됨)

// generator 설치

$ sudo npm install -g generator-sails-angular generator-angular


// yeoman 명령 수행

$ yo

[?] What would you like to do? (Use arrow keys)

 ❯ Run the Angular generator (0.3.1)

   Run the Backbone generator (0.1.7)

   Run the Bootstrap generator (0.1.3)

   Run the Express generator (0.1.0)

   Run the Generator generator (0.2.0)

   Run the Mocha generator (0.1.1)

   Run the Sails-angular generator (0.0.1)

   Update your generators

   Install a generator

   Find some help

   Get me out of here!


// 선택을 하면 Server에 Sails 환경과 Client에 AngularJS 환경이 동시에 설정된다 

// Client는 기본 Twitter bootstrap을 사용하고 Client 추가 Component는 "bower install <Component명칭>" 을 사용하여 설치한다 

// Server는 "npm install <module명칭>"을 사용하여 설치한다


  - "sails lift" 수행 (2013.09.23현재 0.9.4 버전으로 sails upgrade : sudo npm update sails -g )

$ sails lift

info:

info:

info:    Sails.js           <|

info:    v0.9.4              |\

info:                       /|.\

info:                      / || \

info:                    ,'  |'  \

info:                 .-'.-==|/_--'

info:                 `--'-------'

info:    __---___--___---___--___---___--___

info:  ____---___--___---___--___---___--___-__

info:

info: Server lifted in `/Users/prototyping/sails/test`

info: To see your app, visit http://localhost:1337

info: To shut down Sails, press <CTRL> + C at any time.


debug: --------------------------------------------------------

debug: :: Mon Sep 23 2013 10:05:04 GMT+0900 (KST)

debug:

debug: Environment : development

debug: Port : 1337

debug: --------------------------------------------------------



3. Sails MVC 이해하기 

  - Model 

    + Waterline 이라는 Sails Adapter를 통하여 다양한 데이터베이스의 객체로 사용되어 진다 

    + 단, Waterline의 형식(JSON 포멧)에 맞추어서 Model을 정의한다 : 모든 데이터베이스에 추상화된 정의이다 

    + /config/adapters.js 파일에 Database 환경 설정을 한다 또한 관련 데이터 베이스 adapter를 설치해야 함 

       예) MongoDB 설치 

$ npm install sails-mongo --save

npm http 200 https://registry.npmjs.org/sails-mongo

npm http GET https://registry.npmjs.org/sails-mongo/-/sails-mongo-0.9.5.tgz

.. 중략 ..

    + /api/models/ 디렉토리 밑에 <Model>.js 파일이 위치한다

// model 생성  

$ sails generate model Person


// 생성 내역 : Model의 맨앞자는 자동으로 대문자로 변경됨 

$ /api/models> cat Person.js

/*---------------------

:: Person

-> model

---------------------*/

module.exports = {

attributes : {

// Simple attribute:

// name: 'STRING',


// Or for more flexibility:

// phoneNumber: {

// type: 'STRING',

// defaultValue: '555-555-5555'

// }

}

};/


// CRUD : 기본 Deferred Promised 지원 

생성 : Person.create

조회 : Person.findOne/find

갱신 : Person.update

제거 : Person.destroy



  - Controller

    + view와 model 사이의 제어 역할을 한다

    + /api/controllers/ 디렉토리에 위치함 

// comment controller 만들기 : 최종 명령 tag뒤에 스페이스가 있으면 안된다. 

// controller 뒤 첫번째 인자 : comment가 controller의 명칭

// controller 두번째 인자이후 : comment의 메소드 명칭들 열거  

$ sails generate controller comment create like tag 


// 결과 

$ /api/controllers> cat CommentController.js

/*---------------------

:: Comment

-> controller

---------------------*/

var CommentController = {

// To trigger this action locally, visit: `http://localhost:port/comment/create`

create: function (req,res) {

// This will render the view: /views/comment/create.ejs

res.view();

},


// To trigger this action locally, visit: `http://localhost:port/comment/like`

like: function (req,res) {

// This will render the view: /views/comment/like.ejs

res.view();

},


// To trigger this action locally, visit: `http://localhost:port/comment/tag`

tag: function (req,res) {

// This will render the view:/views/comment/tag.ejs

res.view();

}


};

module.exports = CommentController; 


// 브라우져 호출 

http://localhost:1337/comment/create (like, tag) 


  - Route

    + RESTful 호출을 uri를 제어하고 싶다면 Route를 지정한다 

    + /config/routes.js 파일안에 정의한다 

    + controller와 action을 정의한다 

    + home의 경우 

       1) /config/routes.js 에 하기와 같이 home 컨트롤러 정의 

       2) /api/controllers/HomeController.js 존재 : index액션(펑션) 존재

       3) /views/home/index.ejs 파일 존재 : 서버에서 rendering되어 클라이언트 응답 

// Routes

// *********************

// 

// This table routes urls to controllers/actions.

//

// If the URL is not specified here, the default route for a URL is:  /:controller/:action/:id

// where :controller, :action, and the :id request parameter are derived from the url

//

// If :action is not specified, Sails will redirect to the appropriate action 

// based on the HTTP verb: (using REST/Backbone conventions)

//

// action을 정의하지 않으면 다음의 기본 형식을 따른다 

// GET:     /:controller/read/:id

// POST:   /:controller/create

// PUT:      /:controller/update/:id

// DELETE:/:controller/destroy/:id

//

// If the requested controller/action doesn't exist:

//   - if a view exists ( /views/:controller/:action.ejs ), Sails will render that view

//   - if no view exists, but a model exists, Sails will automatically generate a 

//       JSON API for the model which matches :controller.

//   - if no view OR model exists, Sails will respond with a 404.

//

module.exports.routes = {

// To route the home page to the "index" action of the "home" controller:

'/' : {

controller : 'home'

}


// If you want to set up a route only for a particular HTTP method/verb 

// (GET, POST, PUT, DELETE) you can specify the verb before the path:

// 'post /signup': {

// controller : 'user',

// action : 'signup'

// }


// Keep in mind default routes exist for each of your controllers

// So if you have a UserController with an action called "juggle" 

// a route will be automatically exist mapping it to /user/juggle.

//

// Additionally, unless you override them, new controllers will have 

// create(), find(), findAll(), update(), and destroy() actions, 

// and routes will exist for them as follows:

/*


// Standard RESTful routing

// (if index is not defined, findAll will be used)

'get /user': {

controller : 'user',

action : 'index'

},

'get /user/:id': {

controller : 'user',

action : 'find'

},

'post /user': {

controller : 'user',

action : 'create'

},

'put /user/:id': {

controller : 'user',

action : 'update'

},

'delete /user/:id': {

controller : 'user',

action : 'destroy'

}

*/

};


  - View

    + Sails는 기본 ejs를 사용한다 

    + /views/ 밑에 위치한다 

    + Partial 파일을 include 할 수 있다 

    + 메인 파일 : layout.ejs 

   


  - Adapter

    + 데이터베이스를 바꾸고 싶다면 /config/adapters.js 에서 내용을 바꾼다 : MongoDB를 사용한다면 mongo adapter를 설치해야 한다

// Configure installed adapters

// If you define an attribute in your model definition, 

// it will override anything from this global config.

module.exports.adapters = {


// If you leave the adapter config unspecified 

// in a model definition, 'default' will be used.

'default': 'memory',

// In-memory adapter for DEVELOPMENT ONLY

// (data is NOT preserved when the server shuts down)

        // Sails-dirty는 Node-Dirty의 Adapter를 memory or disk에 JSON 을 저장하는 store이다. 백만개 밑으로 저장시 사용

memory: {

module: 'sails-dirty',

inMemory: true

},


// Persistent adapter for DEVELOPMENT ONLY

// (data IS preserved when the server shuts down)

// PLEASE NOTE: disk adapter not compatible with node v0.10.0 currently 

// because of limitations in node-dirty

// See https://github.com/felixge/node-dirty/issues/34

disk: {

module: 'sails-dirty',

filePath: './.tmp/dirty.db',

inMemory: false

},


// MySQL is the world's most popular relational database.

// Learn more: http://en.wikipedia.org/wiki/MySQL

mysql: {

module : 'sails-mysql',

host : 'YOUR_MYSQL_SERVER_HOSTNAME_OR_IP_ADDRESS',

user : 'YOUR_MYSQL_USER',

password : 'YOUR_MYSQL_PASSWORD',

database : 'YOUR_MYSQL_DB'

}

};

   + generator-sails-angular 를 yeoman통하여 설치하였다면 SPA를 개발하는 것이므로 실제로 ejs 쓸 일이 거의 없고, Client 단에서 AngularJS 정의에 따라 Routing과 View Control이 발생한다. 따라서 Controller를 통하여 수행할 action에서 response.view() 하는 것이 아니라, response.json(<JSON Object>) 만을 응답으로 주면 될 것으로 보인다. 또한 업무적인 처리는 action에서 구현하면 된다   

   + response.send(형식)

res.send(); // 204

res.send(new Buffer('wahoo'));

res.send({ some: 'json' });

res.send('<p>some html</p>');

res.send('Sorry, cant find that', 404);

res.send('text', { 'Content-Type': 'text/plain' }, 201);

res.send(404);

   + response.json(형식)

res.json(null);

res.json({ user: 'tj' });

res.json('oh noes!', 500);

res.json('I dont have that', 404);


* Redis나 데이터베이스의 외부 인터페이스 라이브러리는 Custom Adapter 개발을 수행한다. (만드는 방법



3. MongoDB 연결하여 RESTful 호출 테스트 

  - mongodb 환경설정 : sails-mongo 어뎁터가 설치되어 있어야 함 

$ cd config && vi adapters.js  이동하여 mongodb 설정 입력


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

// adapters.js 수정 내역 

module.exports.adapters = {

  // If you leave the adapter config unspecified 

  // in a model definition, 'default' will be used.

  'default': 'mongo',


  // In-memory adapter for DEVELOPMENT ONLY

  memory: {

    module: 'sails-memory'

  },


  // Persistent adapter for DEVELOPMENT ONLY

  // (data IS preserved when the server shuts down)

  disk: {

    module: 'sails-disk'

  },


  // sails v.0.9.0

  mongo: {

    module   : 'sails-mongo',

    host     : 'localhost',

    port     : 27017,

    user     : '',

    password : '',

    database : 'sailsdb'

  }

};

  

  - Person model 수정

// ProjectName/models/Person.js  수정 내역 

module.exports = {

  attributes: {

  name: 'string',

  phone: 'string',

  address: 'string',

  sex: 'string',

  etc: 'string' 

  }

};


  - PersonController의 create 수정 : Promise 구문 형식 사용가능  

// ProjectName/controllers/PersonController.js  수정 내역

module.exports = {

  create: function (req,res) {

    Person.create({ 

      name: req.param('name'),

      phone: req.param('phone'),

      address: req.param('address'),

      sex: req.param('sex'),

      etc: req.param('etc')

    }).done(function(err, person){

      if(err) throw err;

      res.json(person);

    });

  },

  .. 중략 ..

}


  - Postman을 통하여 호출 테스트 : Postman chrome extension을 설치한다. 


  - mongo shell 에서 person collection 조회 : model이 mongodb에서 collection과 맵핑된다  

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

// mongo shell 확인 

mongo

MongoDB shell version: 2.4.5

connecting to: test

show dbs

local 0.078125GB

sailsdb 0.203125GB

use sailsdb

switched to db sailsdb

show collections

person

system.indexes

> db.person.find();

{ "name" : "도원", "phone" : "1004", "address" : "seoul", "sex" : "man", "etc" : "developer", "createdAt" : ISODate("2013-09-23T02:28:51.281Z"), "updatedAt" : ISODate("2013-09-23T02:28:51.281Z"), "_id" : ObjectId("523fa76377e9f89562000001") }



4. MongoDB의 _id를 sequence number로 바꾸기 

  - "_id" : ObjectId("523fa76377e9f89562000001") 라고 나오는 것을 "_id" : 1 씩 증가하는 정수로 바꾸기 

  - 최대한 sails-mongo adapter의 api를 사용하여 구현한다 

  - sequence document 만들기 

> db.seq.insert(

 {

   _id: 'personid',

   seq: 0

 });

> db.seq.find();

{ "_id" : "personid", "seq" : 0 }


  - Sails Model을 정의한다 

$ sails generate model seq

$ cd models && vi Seq.js


// Seq.js 내역 

// _id를 통하여 여러 model의 sequence 값을 구분하기 위해 사용한다 

module.exports = {

  attributes: {

  _id: 'string',

  seq: 'integer'

  }

};


  - Person의 모델에서 명시적으로 _id 를 integer로 정의한다 

module.exports = {

  attributes: {

  _id: 'integer',

  name: 'string',

  phone: 'string',

  address: 'string',

  sex: 'string',

  etc: 'string'

  }

};


  - PersonController.js 내역 수정 : Gist 소스 파일

  /**

   * /person/create

   */ 

  create: function (req,res) {

      // seq 번호를 얻어온다 

      Seq.find({_id: 'personid'}).done(function(err, seqObj) {

        if(err) throw err;

        // 배열임을 주의  

        var seqNo = seqObj[0].seq;

        seqNo++;

        console.log('>>> seqNo is', seqNo);

        

        // insert시에 _id 값을 넣어준다 

        Person.create({ 

          _id: seqNo, 

          name: req.param('name'),

          phone: req.param('phone'),

          address: req.param('address'),

          sex: req.param('sex'),

          etc: req.param('etc')

        }).done(function(err, person){

          if(err) throw err;

          res.json(person);

        });


       // sails-mongo의 api에 한번에 select & update해주는 findAndModify 메소드가 없는 관계로 seqNo를 update해준다 

        Seq.update({_id: 'personid'}, {seq: seqNo}).done(function(err, seqObj){

          if(err) throw err;

        })

      });

  },


  - Postman으로 테스트 데이터를 입력한다 


  - mongo shell로 mongodb에 저장된 내역을 확인해 보자 

// postman통하여 데이터를 2개 넣었을 경우 

> db.seq.find();

{ "_id" : "personid", "seq" : 2, "updatedAt" : ISODate("2013-09-23T09:47:29.548Z") }


> db.person.find();

{ "_id" : 1, "name" : "윤도원-8", "phone" : "1004", "address" : "목동", "sex" : "사람", "etc" : "모비콘 블로깅", "createdAt" : ISODate("2013-09-23T09:45:36.391Z"), "updatedAt" : ISODate("2013-09-23T09:45:36.391Z") }

{ "_id" : 2, "name" : "윤도원-9", "phone" : "1004", "address" : "목동", "sex" : "사람", "etc" : "모비콘 블로깅", "createdAt" : ISODate("2013-09-23T09:47:29.547Z"), "updatedAt" : ISODate("2013-09-23T09:47:29.547Z") }

>

 

 

5. Sails를 통항 WebApp 만들기

  - SailsCast Site 참조

  - SailsCast GitHub 소스

  - 유튜브 동영상 25 강좌 보기


 

<참조>

  - Sails.js + AngularJS + MongoDB 데모

  - MongoDB auto increment Sequence Field 방법

  - Mongoose Sequence Table 통한 auto increment plugin  : express 와 mongoose 사용시 해당 plugin을 사용

posted by 윤영식
2013. 7. 20. 12:25 NodeJS/Concept

Smart Dashboard라는 장난감을 하나 만들면서 서버단을 Node.js로 코딩을 하고 있다. Node.js에서 가장 햇갈리는 부분 그리고 인식의 전환을 해야하는 것들을 "Art of Node"에서 잘 정리해 주고 있다. Node.js의 핵심은 무엇인지 알아보자.



1. Callback

  - Node.js 는 I/O Platform 이다 : filesystm과 network I/O를 위한 플랫폼이다. Gateway와 같다고 생각해 보자~~ 


  


  - Callback은 node.js에서 나온 개념이 아니라 이미 있던 개념 : C언어에서 "함수포인터"와 같다 

  - Async가 기본이기 때문에 결과에 대한 처리를 요청하는 Callback function을 파라미터로 넘긴다 

  - 다음 예는 undefined가 나온다. Async이기 때문에 addOne() 호출(invoke)하고 바로 console.log(myNumber)으로 이동해 버린다. File I/O보다 Memory I/O가 훨씬 더 빠른다. 

var fs = require('fs') // require is a special function provided by node
var myNumber = undefined // we don't know what the number is yet since it is stored in a file

function addOne() {
  fs.readFile('number.txt', function doneReading(err, fileContents) {
    myNumber = parseInt(fileContents)
    myNumber++
  })
}

addOne()

console.log(myNumber) // logs out undefined -- this line gets run before readFile is done

  - 다음 예가 정확한 예이고 Closure개념을 결합하여 정보를 받아서 출력하고 있다. callback을 addOne 함수의 파라미터로 넘겨서 fs.readFile내부의 doneReading Callback 펑션에서 Closure객체로 callback()을 호출하는 것이다

var fs = require('fs')
var myNumber = undefined

function addOne(callback) {
  fs.readFile('number.txt', function doneReading(err, fileContents) {
    myNumber = parseInt(fileContents)
    myNumber++
    callback()
  })
}

function logMyNumber() {
  console.log(myNumber)
}

addOne(logMyNumber)

  - 이것에 대한 Pseudo Pattern 정리하면 다음과 같다 

function addOne(thenRunThisFunction) {
  waitAMinute(function waitedAMinute() {
    thenRunThisFunction()
  })
}

addOne(function thisGetsRunAfterAddOneFinishes() {})

  - Callback을 하다보면 간혹 이런 가독성이 떨어지는 문구를 볼 수 있다. 이에 대한 해결은 Defer/Promise 를 사용한다. Java 진영에서는 Future라고 한다. 주로 Async 프로그래밍시 Callback을 사용할 때의 문제점을 serial하게 해결할 수 있는 do -> then -> error 처리가 가능함 

a(function() {
  b(function() {
    c()
  })
})



2. Events

  - Node.js는 Even Machine (about ruby on rails or twisted of Python) 이다 

  - Observer Pattern을 사용하고, Publish/Subscribe 개념을 갖는다 

  - on 펑션을 통하여 Subscribe 하고, emit 펑션을 통하여 Publish 한다

  - 하기 예는 Subscribe하여 처리할 Handler를 Callback 펑션 정의(Definition)을 미리한다. 그리고 connect() 펑션에 인자로 넣는다 

var chatClient = require('my-chat-client')

function onConnect() {
  // have the UI show we are connected
}

function onConnectionError(error) {
  // show error to the user
}

function onDisconnect() {
 // tell user that they have been disconnected
}

function onMessage(message) {
 // show the chat room message in the UI
}

chatClient.connect(
  'http://mychatserver.com',
  onConnect,
  onConnectionError,
  onDisconnect,
  onMessage
)

  - 위 예를 다른 형태로 변경하면, 즉, connect() 메소드에서 작용하는 원칙은 다음과 같다. on(<EventName>, <Callback Function>) 를 통하여 Subscribe하는 것과 동일하다 

var chatClient = require('my-chat-client').connect()

chatClient.on('connect', function() {
  // have the UI show we are connected
}) 

chatClient.on('connectionError', function() {
  // show error to the user
})

chatClient.on('disconnect', function() {
  // tell user that they have been disconnected
})

chatClient.on('message', function() {
  // show the chat room message in the UI
})

  


3. Stream

  - Stream I/O 를 통하여 끊김없이 file system, network I/O를 수행할 수 있다. 성능의 병목없이 물흐르듯 데이터가 흘러간다. 

  - Substack사의 Stream Handbook을 보자

  - stream module은 노드의 코어모듈이다 : require('stream')

  - 하기 코드는 data.txt 파일읽는 것이 다 끝나면 Callback의 data로 전달이 된다. 이때 data.txt파일이 크다면 그만틈의 메모리를 사용하게 되고 병목이 생길 수 있다. Async 방식을 고려한다면 성능상의 문제를 야기할 수 있겠다. data.txt파일 읽으면서 http응답 병목발생. 

var http = require('http');
var fs = require('fs');

var server = http.createServer(function (req, res) {
    fs.readFile(__dirname + '/data.txt', function (err, data) {
        res.end(data);
    });
});
server.listen(8000);
  - 위의 예제를 Stream 방식으로 변경한다. 파일을 읽어서 일정 크기단위(Chunk)로 요청한 Client로 응답을 준다.  
var http = require('http');
var fs = require('fs');

var server = http.createServer(function (req, res) {
    var stream = fs.createReadStream(__dirname + '/data.txt');
    stream.pipe(res);
});
server.listen(8000);
  - .pipe() 의미

.pipe() is just a function that takes a readable source stream src and hooks the output to a destination writable stream dst: - 읽을 소스 스트림 src가 있고 쓸 스트림으로 output을 연결해 주는 펑션일 뿐이다

src.pipe(dst)

  - 스트림 체이닝(Chaining)의 표현
a.pipe(b).pipe(c).pipe(d)

위 아래 동일 표현

a.pipe(b);
b.pipe(c);
c.pipe(d);

the command-line to pipe programs

a | b | c | d 

  - 스트림의 5가지 : readable, writable, transform, duplex, classic
  - Readable : pipe의 읽을 소스에 대한 처리를 별도로 해주어 output destination으로 보낸다. readableStream.pipe(dst) 
var Readable = require('stream').Readable;

var rs = new Readable;
rs.push('beep ');
rs.push('boop\n');
rs.push(null);

rs.pipe(process.stdout);
$ node read0.js
beep boop
  - Writable : 소스를 읽고서 표현하는 output에 대하여 별도로 지정한다. src.pipe(writableStream)
var Writable = require('stream').Writable;
var ws = Writable();
ws._write = function (chunk, enc, next) {
    console.dir(chunk);
    next();
};

process.stdin.pipe(ws);
$ (echo beep; sleep 1; echo boop) | node write0.js 
<Buffer 62 65 65 70 0a>
<Buffer 62 6f 6f 70 0a>
  - classic방식은 node v0.4 버전때 처음 나왔다. 
  - duplex는 a.pipe(b).pipe(a) 와 같이 양방향 파이프
  - transform은 read/write filter 이다

 


4. Modules

  - 모듈개념으로 npm(Node Package Manager)를 통하여 필요한 것을 설치한다 : 34,000 개가량의 모듈이 등록되어 있음

  - 모듈 찾기 npm search <ModuleName> : npm search pdf

  - package.json 안에 해당 모듈이 사용하는 다른 모듈 정보와 모듈의 일반 정보(이름, 버전, 저장소등)가 있다 : npm init

  - node코드에서 require('some-module'); 를 찾는다. require 동작 순서

  • if a file called some_module.js exists in the current folder node will load that, otherwise - 현재 디렉토리에 있는지 찾는다 
  • node looks in the current folder for a node_modules folder with a some_module folder in it - 현재 디렉토리에 node_modules 디렉토리가 있는지 찾고 있으면 그 밑으로 some_module 폴더가 있는지 찾는다  
  • if it doesn't find it, it will go up one folder and repeat step 2 - 위 두개다 찾지 못하면 윗쪽 폴더로 가서 두번째 처럼 다시 node_module 폴더를 찾아간다 


  • <참조>

      - art of node 원문

      - 함수 포인터에 대한 이해

      - Closure 알아가기

      - NHN이 이야기하는 함수형 언어와 클로져 이야기

      - Substack사의 Stream Handbook

    posted by 윤영식
    2013. 5. 7. 09:37 NodeJS/Concept

    서비스 또는 솔루션을 만들기 위해 Node.js와 Express.js를 선택하였다면  그 다음 고민은 애플리케이션 개발을 위하여 필요한 스택을 선정하는 일이다. 크게는 로깅, 환경설정, 통신등 기본적인 부분들을 직접 개발하지 말고 이미 만들어진 바퀴를 공짜로 구해서 달아보자 



    1. 준비하기 

      - Programming Javascript Application Book 책의 내용을 발췌한 것이다 

      - Node 버전관리 NVM 설치 

        + https://github.com/creationix/nvm

        + 설치 : nvm install [버전]

        + 수행 : nvm run [버전]

        + 확인 : nvm ls  (설치된 버전 목록을 보여줌)

        + 가능 : nvm ls-remote (설치 가능 버전 목록을 보여줌)

      - nvm 설치 명령 : git 사전 설치요구 : 수행시 nvm.sh 에 syntax오류가 나오면 nvm.sh을 copy하고 기존것 삭제후 다시 paste하여 만듦

    $ curl https://raw.github.com/creationix/nvm/master/install.sh | sh


        + 기타 명령들 

    $ nvm help


    Node Version Manager


    Usage:

        nvm help                          Show this message

        nvm install [-s] <version>  Download and install a <version>

        nvm uninstall <version>     Uninstall a version

        nvm use <version>           Modify PATH to use <version>

        nvm run <version> [<args>]  Run <version> with <args> as arguments

        nvm ls                            List installed versions

        nvm ls <version>             List versions matching a given description

        nvm ls-remote                 List remote versions available for install

        nvm deactivate                Undo effects of NVM on current shell

        nvm alias [<pattern>]      Show all aliases beginning with <pattern>

        nvm alias <name> <version>    Set an alias named <name> pointing to <version>

        nvm unalias <name>                Deletes the alias named <name>

        nvm copy-packages <version> Install global NPM packages contained in <version> to current version


    Example:

        nvm install v0.4.12            Install a specific version number

        nvm use 0.2                    Use the latest available 0.2.x release

        nvm run 0.4.12 myApp.js   Run myApp.js using node v0.4.12

        nvm alias default 0.4        Auto use the latest installed v0.4.x version


      - 프로젝트 만들고 초기화 하기 

        + 디렉토리 만들고 해당 디렉토리로 이동

        + npm init 수행하여 package.json 파일 만들기 : 이름, 버전, 설명, 키워드, 저장소위치, 라이센스 및 기타 정보등을 입력한다 

    $ mkdir basic && cd basic

    $ npm init

    This utility will walk you through creating a package.json file.

    It only covers the most common items, and tries to guess sane defaults.


    See `npm help json` for definitive documentation on these fields

    and exactly what they do.


    Use `npm install <pkg> --save` afterwards to install a package and

    save it as a dependency in the package.json file.


    Press ^C at any time to quit.

    name: (basic) JavaScript-Programming

    version: (0.0.0) 0.0.1

    description: This is a javascript programming

    entry point: (index.js)

    test command: grunt test

    git repository: https:/github.com/ysyun/javascriptacular

    keywords: angularjs

    author: yun dowon

    license: (BSD) MIT

    About to write to /Users/prototyping/express/basic/package.json:


    {

      "name": "JavaScript-Programming",

      "version": "0.0.1",

      "description": "This is a javascript programming ",

      "main": "index.js",

      "scripts": {

        "test": "grunt test"

      },

      "repository": {

        "type": "git",

        "url": "https:/github.com/ysyun/javascriptacular"

      },

      "keywords": [

        "angularjs"

      ],

      "author": "yun dowon",

      "license": "MIT"

    }



    Is this ok? (yes)

    npm WARN package.json JavaScript-Programming@0.0.1 No README.md file found!

    $ ls -lart

    -rw-r--r--  1 nulpulum  staff  360  5  7 09:22 package.json

    drwxr-xr-x  3 nulpulum  staff  102  5  7 09:22 .


      - 모듈 설치시에 package.json 파일에 자동 기록을 위하여 npm install --save [module] 처럼 --save 옵션을 준다 



    2. 준비할 스택들

    • Mout Like Underscore / LoDash. Stuff that should probably be included in JavaScript.

    • Express Web application framework.

    • Nconf Application config.

    • Hogan Mustache for express. (Jade 또는 EJS 를 써도 됨)

    • Superagent Communicate with APIs.

    • Socket.io Realtime communications (websockets).

    • Q Promises.

    • Async Asynchronous functional utilities.

    • Bunyan Logging. (Winston도 많이 사용)

    • Tape Testing. (Mocha, Karma 도 사용)

    • Cuid Better than guid/uuid for web applications.

    • Derby.js Add realtime, collaborative MVC to express. (Sails.js 또는 Bone.js 도 사용)

    • Node-http-proxy Proxy your service APIs.



    3. Express 사용하기 

      - Routing 을 이용한다

      - Middleware를 통하여 중간에 Hooking 하여 처리하고 다음으로 next() 호출 넘기는 use 를 사용한다 

    // Add some data to the request object that your other
    // midleware and routes can use.
    app.use(function (req, res, next) {
      req.foo = 'bar';
      next();

    });

        + 전체 예제 

    'use strict';
    var express = require('express'),
     
      // Create app instance.
      app = express(),
     
      // Use the `PORT` environment variable, or port 44444
      port = process.env.PORT || 44444;
     
    // The new middleware adds the property `foo` to the request
    // object and sets it to 'bar'.
    app.use(function (req, res, next) {
      req.foo = 'bar';
      next();
    });
     
    app.get('/', function (req, res) {
      res.setHeader('Content-Type', 'text/plain');
     
      // Send the value passed from the middleware, above.
      res.end(req.foo);
    });
     
    app.listen(port, function () {
      console.log('Listening on port ' + port);

    });


    // 결과 : use를 설정한 순서대로 처리된다 

    $ curl http://localhost:44444/
    bar



    4. SailsJS

      - 난 sails를 Full Stack Server Side Data-Oriented API Framework 이라고 말하고 싶다.

      - Front-end 단이 SPA로 개발될 경우

      - Back-end를 API 서버로 확장함 

      - Node.js + Express.js + MongoDB 와 연결 및 JSON Memory DB 사용가능

        + sails-angularjs-yeoman 의 로그인 데모

        + sails-mongodb 연결

        + sails-redis 연결



    <참조>

       - 원문 : Getting start with Node and Express 

       - middleware의 next() 사용법 : Node.js의 connect 이해하기

       - AngularJS와 MongoDB 연결 Bridge


    posted by 윤영식
    2013. 3. 22. 10:38 NodeJS/Concept

    Node.js를 이용하여 RESTful Web Services를 작성할 때 Open API에 대한 기본적인 인식을 가지고 시작하는 것이 좋겠다. Open API 를 만들기 위한 기본적인 원칙을 알아보자 



    1) Open API 배우기  

    KTH에서 Baas.io 라는 클라우드 서비스를 런칭하였다. 지인의 추천으로 써볼려고 들어갔는데, powered by Apigee 라는 문구가 낯설었다. apigee에서 이야기하는 Open API 기본 원칙을 보자

      - apigee에 대한 기본 생각 : 도움되는 사이트를 링크함 

      - apigee에서 발간한 Free eBook중 Web API Design 원칙 (한글 의역)


        + 기본 URL에는 동사가 아니라 명사를 사용한다 (단, 계산, 번역, 전환관련 부분은 동사씀)

        + 복수(컬렉션)을 먼저 나오게함 : /dog -> /dogs 처럼

        + 컬렉션뒤에는 개별적인 요소아이디(Elment ID) 가 온다 : /dogs/1234

        + 그외 복잡한 것은 ? 뒤로 두어라 : /dogs/1234?fields=name,age,location

        + 오류를 명확히 처리해라 : code, message, more_info, status 등으로 여기서 code는 HTTP code로 보냄

        + 버전관리를 한다 : /v1/dogs/1234 즉, 컬렉션 앞에 개들의 버전을 두는 것이다

        + 페이징 처리를 한다 : /v1/dogs?limit=25&offset=50  즉, limit, offset 을 키로 한다 

        + 다양한 포멧팅일 경우 . (도트) 사용한다 : /v1/dogs.json 그러나 json 포멧으로 통일해라 

        + 검색은 q 키를 사용 : /search?q=1234

        + 하위 도메인은 : api.xxx.com, developers.xxx.com 으로 api, developers 로 한다 

        + 권한 관리는 OAuth2.0 으로 통일

        + API Facade Pattern 을 지향한다 


      - 유명한 사이트들의 OpenAPI를 검색할 수 있다 : 페이스북, 트위터, GitHub, Google 서비스들 



    2) apigee에서 이야기하는 RESTful API Design Guide


    Web2.0 에 따라 많은 서비스들이 SPA 로 개발되고 Open API화 하면서 이러한 API를 모아서 관리할 수 있는 apigee 와 같은 스타트업이 생겨나고 있다. 큰 사상의 흐름에 따라 기술 또한 성숙하고 이에 따라 하나 둘씩 서비스가 생겨나면서 새로운 생태계가 탄생하였다. 물론 미쿡 이야기지만 우리나라에서도 카카오 플랫폼이 협력업체들과 폐쇄적으로 Open API 협업을 하긴 하는 듯하다. 하지만 생태계를 만들어 간다는 차원에서 그들만의 리그가 아닐까 싶다. 다른 나라에서 카카오의 플랫폼을 활용하려고 몇달씩 대기자 명단을 받으며 기다리고 함께 만들어 가고 싶어할까? 아마도 그것은 개발자 사이트와 Open API 정책 결여 그리고 기타등등 여러 사정이 있겠지만 역시 카카오 같은 모습은 앞으로 지향해 가야할 스타트업 회사들의 과제가 아닐까 싶다. 


    * 퇴근길에 "소프트웨어 개발자에게 성공이란" 글을 읽었다. 카카오에 대해 느낀점 그리고 비즈니스에 대해서 느낀점, 기획한 제품을 끌고 가기위해 그동안 했던 행동들이 주마등처럼 스쳐지나간다. 나의 목표는 https://www.facebook.com/groups/smartdashboard  에서 계속 글로 표현해 가고 있다.



    <참조>

      - 당신의 API가 RESTful 하지 않은 이유

    posted by 윤영식
    2013. 3. 14. 11:48 NodeJS/Concept

    그동안 혼자 고민하여 찾아 해메였던 많은 부분이 채수원씨의 발표자료안에 잘 정리되어 있고, 결과물을 만들며 얻은 팁을 공유하고 있다. 발표 자료를 통해 느낀점을 적어본다 (채수원씨는 2011년 KOSTA에서 MongoDB 수강하며 알게 됨. 강사였음 ^^)



    1) Devnote 사용하는 모듈들 보며 느낀점 

      - 미경험 모듈 : zombie.js, node-i18n, jake, winston, gitfs 등

      - 경험 모듈 : 대부분 노드에서 가장 많이들 사용하는 모듈로 결정

      - 테스트 모듈 : step 코드의 간결함이 좋음

      - 개발툴로 CodeMirror 사용해 봐야겠다. 현재는 Sublime Text 2 를 사용중 임

      - 서버쪽 템플릿은 Jade, SPA(Single Page Application) 개발로 Backbone.js를 사용한다면 Underscore.js를 사용하자 

      



    2) Devnote 아키텍쳐보며 느낀점

      - 스토리지를 gitfs로 했는데 해당 부분을 mongodb로 바꾸고 싶은 욕구가 생김

      - 테스트 자동화에서 브라우저 애뮬레이션으로 CasperJS를 추가하고 싶음  

      - view 영역에서 Backbone.js 가 들어갔으면 함

      - 전부 자바스크립트로 개발 및 테스트 환경을 꾸몄다. 물론 소스도 자바스크립트이다. 

        이제 JavaScript 도 Java처럼 개발과 테스트 환경 생태계가 엄청나게 빨리 성숙해 지고 있다. 이젠 대세~~~ 정대세 ^^;

      - CoffeeScript를 본격적으로 사용하자. 기본 문법수준에서 알고 조금씩 했지만 이젠 가급적 커피로 가자고 결심함 ^^;

        코드의 가독성과 컴파일된 .js 파일의 자체 모듈패턴 적용이 좋음 

      - i18n 을 고려해야 겠다고 생각함 

      - git 스타일의 파일 관리면 버전관리가 가능하겠구나 생각함. 위키니깐~~

      - socket-io 를 통하여 real-time 피드백을 받는다는 개념이 좋음. 역시 피드백은 바로 받아 바로 처리해야~~

      - Markdown 은 배우기도 쉽다. 그리고 소스 문서화 툴 Groc 에서도 사용하니 필히 익혀서 쓰자 

      - 우리 솔루션에도 Twitter Bootstrap CSS 스타일을 따라야 겠다고 생각함. 눈에 익숙한 것이 거부감을 줄여줄 것이라 생각함



    3) 발표자료

      - 시월의 맑은 하루 (OctoberSky.js) 페북모임에 관심이 감 

      - source map 설정을 통해서 자바스크립트 디버깅 가독성있게 하기를 테스트 해봐야 겠음 

      - 자바스크립트 개발자라면 Front-end <-> Back-end 개발 다 하자. 

        페이스북이 그렇게 개발한다. 그리고 테스트팀도 없다. 개발자들이 기본 TDD를 한다 

      



    <참조>

      - 채수원씨 발표자료

      - DevNote : https://github.com/nforge/devnote

      - CodeMirror : https://github.com/marijnh/CodeMirror

      - Markdown 포멧 설명문법설명, GitHub GFM

    posted by 윤영식
    2013. 3. 11. 11:51 NodeJS/Concept

    Node.js 에서 가장 많이 사용하는 Express 프레임워크를 다시 둘러보면서 Connect를 살펴보았다. 데이터 스트림속에서 특정 객체를 가르키는 기술을 쿼리라고 본다. 예로 jQuery는 DOM내에서 특정 노드 객체를 쉽게 찾을 수 있고, Backbone은 el를 통하여 객체를 Fragment화해서 특정 위치에 Render해 준다



    1. 자바스크립트 쿼리의 시대

      - 제일 쿼리 : Underscore.js 

        + 클라이언트 사이드의 Backbone.js의 핵심이 된다


      - 제이 쿼리 : jQuery 

        + 두말이 필요없다. 브라우져 호환성과 셀렉터 그리고 다양한 위젯과 스마트 디바이스 지원까지 


      - 제삼 쿼리 : Backbone.js 

        + Client MV* Framework

        + 클라이언트 SPA (Single Page Web Application) 개발시 기본이 되는 프레임워크 


      - 삼.오 쿼리 : Node.js 

        + 서버 사이드 엔진 (Async I/O, One Thread)

        + Modern Web App 개발


      - 제사 쿼리 : Express & Connect 

        + Server MV* Framework

        + Node.js가 Java의 JVM 이라면 Connect 는 Java의 WAS(Web Application Server) or Apache 기능을 갖춘 middleware 이다

        + Express는 Connect 모듈을 통해 RESTful Web Services를 쉽게 만들게 해주는 Java의 Spring Framework 이다 


      - 제오 쿼리 : MongoDB

        + NoSQL

        + 최신버전의 REPL은 V8 engine (Node.js와 동일한 구글의 JavaScript 엔진 사용예정)

        + HA를 위한 쉬운 Replica Set 지원

        + Scale-out을 위한 Replica Set단위의 Sharding 지원



    2. Connect 살펴보기

      - Node.js에서 모자란 부분을 확장하여 미들웨어 개념으로 제공을 한다.

        미들웨어는 단지 펑션일 뿐이고 사용자가 얼마든지 확장하여 사용할 수 있다.

        Connect가 HTTP 서비스에 대하여 많은 부분 추상화를 하였고, Express가 Connect를 또 Wrapping 하고 있다

      - 출처 :  http://www.senchalabs.org/connect/

      - logger

        + 아파치의 format string을 생각하면 된다 

        + 아파치처럼 %d 와 같은 옵션이 아니라 :date 같은 옵션이다

        + 아파치처럼 다양한 옵션을 제공하진 않는다. %b 와 같이 전송 바이트수 옵션이 없다


      - csrf

        + Cross-site request 로 인한 위조 방지 

        + _csrf 필드가 hidden으로 추가됨 (req.session._csrf, req.body._csrf, req.query._csrf, req.headers['x-csrf-token'])


      - compress

        + gzip 압축지원


      - basicAuth

        + callback(user, pass) 를 지원하여 true를 리턴하면 접근 허용


      - bodyParser

        + request body 파싱 및 appplication/json, application/x-www-form-urlencoded, multipart/form-data 파싱 

        + Express 에서 사용 : express.bodyParser()


      - json

        + JSON 요청 파싱하여 req.body에 파싱한 오브젝트 제공


      - urlencoded

        + x-www-form-urlencoded 요청 파싱하여 req.body에 파싱한 오브젝트 제공


      - multipart

        + multipart/form-data 요청 파싱하여 req.bodyd와 req.files 에 파싱한 오브젝트 제공

        + connect.multipart({uploadDir: path}) 경로를 설정한다 


      - timeout

        + 요청에 대한 timeout (ms 단위), 기본 5000 (ms, 즉 5초)

        + err.status=408 이면 next()를 통하여 timeout 응답페이지 처리함 


      - cookieParser

        + 헤더 쿠키를 파싱하여 req.cookies 객체 제공

        +  req.secret  스트링 전달 가능 


      - session

        + session() 사용하려면 cookieParser()를 반드시 사용해야 한다 (세션아이디 sid 저장)

        + req.session 으로 접근 

        + SessionStore는 MemoryStore 이고 별도 구현하려면 규정된 몇가지 메소드를 구현하면 됨 

           세션 클러스터링에 대한 구현이 필요할 수 있겠다 


      - cookieSession

        + 쿠키 사용 


      - methodOverride

        + req.originalMethod 로 form의  method(GET, POST 같은)가 넘어가는 것을 _method로 override

     

      - responseTime

        + X-Response-Time 헤더 표시 (milliseconds)


      - staticCache

        + 정적 파일 서비스를 위한 메모리 캐싱. 기본 128 개의 오브젝트 캐싱

        + 각 256k 사이즈로 32mb 까지 캐싱가능 

        + Least-Recently-Used (LRU) 알고리즘 사용 : 사용빈도 높은 것이 캐싱

        + respondFormCache() 통하여 캐싱 응답 status=304


      - static 

        + 루트 경로 지정

        + express.static(__dirname + '/public') 형태로 사용함 


      - directory

        + 주어진 루트 경로의 목록

        + . (dot) 파일은 숨김


      - vhost

        + VirtualHost통한 sub domain 설정


      - favicon

        + 설정하지 않으면 /public/favicon.ico 찾음 


      - limit 

        + request body 크기 제한  

        + 5mb, 200kb, 1gb 등으로 설정


      - query

        + query-string을 자동으로 파싱

        + req.query 오브젝트 생성


      - errorHandler

        + error 처리 핸들러에게 stack traces 제공

        + text or json형태로 에러 메세지 응답 

        + /public/error.html 참조



    3. 테스트하기 

      - GitHub connect Test Doc

      - GitHub connect Test Source

      - 테스트는 mocha에 should를 적용하여 BDD 수행한다. (참조)

    $ git clone https://github.com/senchalabs/connect.git

    Cloning into 'connect'...

    remote: Counting objects: 15253, done.

    remote: Compressing objects: 100% (4656/4656), done.

    remote: Total 15253 (delta 10035), reused 14692 (delta 9538)

    Receiving objects: 100% (15253/15253), 3.10


    $ cd connect 

    $ npm install .

    $ mocha --reporter list 

    ... 중략 ...

        at Server.app (/Users/nulpulum/git-repositories/connect/lib/connect.js:65:37)

        at Server.EventEmitter.emit (events.js:99:17)

        at HTTPParser.parser.onIncoming (http.js:1928:12)

        at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:111:23)

        at Socket.socket.ondata (http.js:1825:22)

        at TCP.onread (net.js:404:27)

      ․ connect.urlencoded() should accept a limit option: 2ms

      ․ connect.urlencoded() should support all http methods: 1ms

      ․ connect.urlencoded() should parse x-www-form-urlencoded: 1ms

      ․ utils.uid(len) should generate a uid of the given length: 1ms

      ․ utils.parseCacheControl(str) should parse Cache-Control: 0ms

      ․ utils.mime(req) should return the mime-type from Content-Type: 0ms

      ․ connect.vhost() should route by Host: 2ms

      ․ connect.vhost() should support http.Servers: 1ms

      ․ connect.vhost() should support wildcards: 1ms

      ․ connect.vhost() should 404 unless matched: 2ms

      ․ connect.vhost() should treat dot as a dot: 1ms


      192 tests complete (2 seconds)


      - mocha 수행하면 열라 에러 많이 뜬다 ㅠ.ㅠ; 멘붕온다. 해당 메세지가 정상적인 것인지 아닌지 살펴보자

    // mocha.opts 내역
    --require should
    --require test/support/http

     --growl


      - connect의 Code Coverage 보기 



    <참고>

      - Express 가이드 한글화 (필독)

      - Connect의 다양한 Samples in GitHub

      - 지난주 부터 수강하고 있는 KOSTA 이복영강사님 강의에서는 제사쿼리를 MongoDB 라고 지칭하였고, 제* 쿼리를 도용하여 내 나름으로 Express & Connect를 하나 더 넣었다

      - Connect 개념 설명 및 간단 예제

      - JavaScript Code Coverage 프레임워크


    posted by 윤영식
    2013. 2. 16. 11:21 NodeJS/Concept

    웹 기술에 대한 발전방향을 고찰해 보자.


    1) Physical Level

      - file base - static web (web server : content management, http 통신) - web browser (mime type)

        + Content Delivery Service

      - GET, POST 만 주로 사용



    2) Logical Level

      - framework operation (MVC라는 server side기술에서 출발함)

      - controller : request/response, model : data, view : ui  

      - DRY Service: Don't Repeat Yourself 를 위한 좋은 framework으로 요즘 spring 을 기업에서 많이 사용함 

      - Routing 통한 RESTful Web Services : Data Service -> Cloud Service 로 발전 (CRUD 서비스를 GET/POST/PUT/DELETE)

      - RIA 기술의 태동 : 

      - MVC 초기 document base 에서 stream base 로 이동한다. 이에 따라 DB도 code first 로 이동하면서 어플리케이션과 merge를 쉽게 하는 방향으로 이동한다 

      - Data Service로 가면서 View가 없어지면서(None UI) SPA(MS의 서버사이드 기술임)을 스티브 샌더슨이 말하고 있다

      - 즉,  RIA (activex, flash, etc) -> SPA 로 변해감 (기술이 JavaScript로 통일되어 감)

      - application level 이다 



    3) SNS Level

      - SNS 기술 : community level, Service Level 이다 

      - 2)의 application level 과 service level 로 구분된다 

      - Client-WebApp, Server-Node.js, NoSQL-MongoDB 기술들의 등장 

      - Client Side에서 SPA (Single Page Application)등장 : Backbone(Underscore), Angular (DI 존재), Ember (DI 없음)

       + 2)레벨의 MVC는 의미가 희석됨

       + Backbone의 $el 는 3세대 jQuery 라고 보면됨 

       + Functional programming이 가능 

       + Backbone -> AngularJS로 이동하면 된다 

      - Client + Server + Store 를 합치는 기술 = Meteor 또는 Derby 

      - MV* = Functional 이라는 개념으로 이동한다. 이것은 뷰가 모델이 되고, 컨트롤러가 없어지고, 나뉘었다 합쳐졌다하면서 데이터만 남는다. 즉, 과거 MVC 처럼 역할이 나뉘지 않는다

       


    4) Contextual Level

      - 융합 서비스

      - Trend (500만) -> Culture (1000만) 즉, SNS를 통하여 트랜드나 문화로 가는 서비스 레벨

      - 데이터에 대한 MapReduce만 남는다 

        + Map = Key + Value 예) JSON

        + Reduce Function = Business Intelligence 솔루션으로 가는 것이다


    결론, 기술 변천을 느끼고 만들어 가려면 Coding 하자.... ^^


    <참조>

      - KOSTA : 이복영 강사, MongoDB/Node.js 강의 4주차 

    posted by 윤영식
    2013. 1. 31. 16:34 NodeJS/Concept

    Node.js 에서 Express를 사용하면서 일관된 축약 언어 컴파일러로 JavaScript 코딩은 CoffeeScript를 사용하고, HTML은 Jade를 사용하고 CSS는 Stylus를 사용할 때 가장 기본적인 뼈대가 되는 코드를 만들어 주는 프레임워크 Cham을 알아보자. 


    1) Cham 설치하기 

      - Node.js 와 NPM, CoffeeScript는 기본 설치되어 있어야 한다 

      - git clone 으로 설치하기 

    $ git clone https://github.com/conancat/cham.git

    Cloning into 'cham'...

    remote: Counting objects: 155, done.

    remote: Compressing objects: 100% (103/103), done.

    remote: Total 155 (delta 48), reused 142 (delta 35)

    Receiving objects: 100% (155/155), 136.89 KiB | 59 KiB/s, done.

    Resolving deltas: 100% (48/48), done.


      - Express, jade, stylus 설치하기 

      - 설치후 브라우져 호출 : http://localhost:3000/ 

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

    // 설치 

    $ cd cham

    $ npm install express

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

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

    ... 중략 ...

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

    express@2.4.3 node_modules\express

    ├── mime@1.2.9

    ├── qs@0.5.3

    └── connect@1.9.2 (formidable@1.0.11)


    $ npm install jade

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

    ... 중략 ...

    npm http 200 https://registry.npmjs.org/commander/-/commander-0.6.1.tgz

    jade@0.28.1 node_modules\jade

    ├── commander@0.6.1

    ├── mkdirp@0.3.4

    └── coffee-script@1.4.0


    $ npm install stylus -g

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

    ... 중략 ...

    C:\Users\yuwonsystem01\AppData\Roaming\npm\stylus -> C:\Users\yuwonsystem01\AppD

    ata\Roaming\npm\node_modules\stylus\bin\stylus

    stylus@0.32.0 C:\Users\yuwonsystem01\AppData\Roaming\npm\node_modules\stylus

    ├── debug@0.7.0

    ├── mkdirp@0.3.4

    └── cssom@0.2.5


    $ npm install vows

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

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

    npm http GET https://registry.npmjs.org/vows/-/vows-0.7.0.tgz

    ... 중략 ...

    npm http 200 https://registry.npmjs.org/diff/-/diff-1.0.4.tgz

    vows@0.7.0 node_modules\vows

    ├── eyes@0.1.8

    └── diff@1.0.4


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

    // 실행하기 

    $ node app

    Express server listening on port 3000 in development mode



    2) 구조파악하기 

      - root 폴더에 CakeFile이 존재하여 cake를 수행할 수 있다. (CoffeeScript 형태로 작성)

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

    // cake를 실행하면 사용법이 출력됨 

    D:\git-nulpulum\cham>cake

    Cakefile defines the following tasks:


    cake watch             # Watches all Coffeescript(JS) and Stylus(CSS) files

    cake watchJS         # Watches all coffeescript files for changes

    cake watchCSS      # Watches all CSS files for changes

    cake compileJS       # Compiles all Coffeescript files into JS

    cake test                # Runs all tests

    cake docs              # Create documentation using Docco


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

    // watch 하고 있는 원본 소스들을 볼 수 있다

    // 원본 소스는 전부 src에 위치함

    D:\git-nulpulum\cham>cake watch

    15:10:11 - compiled src\lib\helpers.coffee

    15:10:11 - compiled src\lib\module.coffee

    15:10:11 - compiled src\lib\conf.coffee

    15:10:11 - compiled src\test\testHelpers.coffee

    15:10:11 - compiled src\public\js\plugins.coffee

    15:10:11 - compiled src\app.coffee

    15:10:11 - compiled src\test\example.test.coffee

    15:10:11 - compiled src\lib\routes.coffee

    15:10:11 - compiled src\public\js\script.coffee

      watching C:\Users\yuwonsystem01\AppData\Roaming\npm\node_modules\stylus\lib\functions\index.styl

      watching src\public\css\conf\base.styl

      watching src\public\css\conf\helpers.styl

      watching src\public\css\conf\colors.styl

      watching src\public\css\elems\reset.styl

      watching src\public\css\elems\helpers.styl

      watching src\public\css\elems\typography.styl

      watching src\public\css\elems\common.styl

      watching src\public\css\pages\layout.styl

      watching src\public\css\pages\index.styl

      watching src\public\css\media\media.styl

      compiled public\css\style.css

      watching src\public\css\style.styl

    15:15:16 - compiled src\app.coffee       <== app.coffee 를 열어서 살짝 수정하였더니 자동으로 재컴파일 됨 


      - 의존관계 파악을 위해 package.json 파일을 열어보자 

    {

      "name": "cham",

      "version": "0.0.1",

      "private": true,

      "dependencies": {

        "express": "2.4.3",

        "jade": ">= 0.0.1"

      },

      "devDependencies": {

        "vows": ">= 0.5.9",     // BDD 테스트

        "stylus": ">= 0.13.9",  // CSS

        "coffee-script": ">= 1.1.2" // Javascript 

      },

      "engines": {

        "node": "*"

      },

      "author": "Grey Ang <conancat@gmail.com> (http://grey-ang.com)",

      "description": "Boilerplate for quick Coffeescript driven app, backed by Jade and Stylus",

      "repository": {

        "type": "git",

        "url": "git://github.com/conancat/cham.git"

      },

      "scripts": {

        "test": "cake test"

      }

    }


      - CoffeeScript 문법의 CakeFile : "task <명칭>, <설명>, -> 펑션"  task 다음에 3개의 아규먼트로 cake task 만듦

        + watchJS 명령 : coffee -cw -o ./ src/

        + watchCSS 명령 : stylus --watch --include ./public --out ./public/css ./src/public/css

        + compileJS 명령 : coffee -c -o ./ src/

        + test 명령 : vows test/*.test.js

        + docs 명령

           docco src/*.coffee

           docco src/lib/*.coffee

           docco src/test/*.coffee 

    //////////////////////////////////////////
    // CakeFile 내역 
    # Module requires
    {spawn, exec} = require 'child_process'
    sys = require 'sys'
    
    # ## Helpers
    
    # Helper function for showing error messages if anyting happens
    printOutput = (process) ->
      process.stdout.on 'data', (data) -> sys.print data
      process.stderr.on 'data', (data) -> sys.print data
      
    # Watch Javascript for changes
    watchJS = ->
      coffee = exec 'coffee -cw -o ./ src/'
      printOutput(coffee)
    
    # Watch CSS for changes
    watchCSS = ->
      
      # Without Nib
      stylus = exec 'stylus --watch --include ./public --out ./public/css ./src/public/css'
      
      # Use this line instead if you're using Nib
      # stylus = exec 'stylus --watch --include ./public --use ./node_modules/nib/lib/nib.js --out ./public/css ./src/public/css'
      
      printOutput(stylus)
      
    # ## Tasks
    # I guess pretty self explainory? lol
    task 'watch', 'Watches all Coffeescript(JS) and Stylus(CSS) files', ->
      watchJS()
      watchCSS()
    
    task 'watchJS', 'Watches all coffeescript files for changes', ->
      watchJS()
      
    task 'watchCSS', 'Watches all CSS files for changes', ->
      watchCSS()
      
    task 'compileJS', 'Compiles all Coffeescript files into JS', ->
     coffee = exec "coffee -c -o ./ src/"
     printOutput(coffee)
      
    task 'test', 'Runs all tests', ->
      vows = exec 'vows test/*.test.js'
      printOutput(vows)
      
    task 'docs', 'Create documentation using Docco', ->
      docco = exec """
        docco src/*.coffee
        docco src/lib/*.coffee
        docco src/test/*.coffee
      """
      printOutput(docco)
    



    3) 사용한 모듈들 알아보기

      - Stylus

        + CSS를 축약해서 표현, 사용이 간단하고, 코드가 간결해짐 

        + ; 과 { } 를 사용할 필요가 없고  DRY (Don't Repeat Yourself) 지원


      - Docco

        + 주석을 MarkDown 으로 줄 수 있다 (GitHub README.md 만들기와 일관성 있어 좋군)

        + 수행한 위치 바로 밑에 docs 폴더에 위치함 

        + 설치 : npm install -g docco

        + 수행 : docco src/*.coffee


      - Jade

        + HTML 템플릿 엔진 : 이것도 < > 사용이 필요없어 코드가 간결해짐

        + 사용 설명


      - Vows

        + 비동기 BDD for Node

    //////////////////////////////////////////
    // vowtest.js
    var vows = require('vows'),
        assert = require('assert');
    
    // Create a Test Suite
    vows.describe('Division by Zero').addBatch({
        'when dividing a number by zero': {
            topic: function () { return 42 / 0 },
    
            'we get Infinity': function (topic) {
                assert.equal (topic, Infinity);
            }
        },
        'but when dividing zero by zero': {
            topic: function () { return 0 / 0 },
    
            'we get a value which': {
                'is not a number': function (topic) {
                    assert.isNaN (topic);
                },
                'is not equal to itself': function (topic) {
                    assert.notEqual (topic, topic);
                }
            }
        }
    }).run(); // Run it 

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

    // 결과 : 성공 

    D:\git-nulpulum\cham>node vowtest.js

    ··· ✓ OK » 3 honored (0.036s)



      - Express

        + 설치 : npm install -g express

        + 수행 : $ express <projectName>

    //////////////////////////////////////////
    // Express로 Listen Server 구성
    var express = require('express');
    var app = express();
    
    app.get('/', function(req, res){
      res.send('Hello World');
    });
    
    app.listen(3000);
    


      - CoffeeScript

        + 설치 : npm install -g coffee-script

        + 실행 : coffee <파일명>.coffee    <== .coffee 확장자 생략가능   



    <참조> 

      - https://github.com/conancat/cham

    'NodeJS > Concept' 카테고리의 다른 글

    [Node.js] Express의 Connect 살펴보기  (0) 2013.03.11
    [Node.js] 기술 발전 방향 4단계  (0) 2013.02.16
    [Node.js] 생태계에 대한 생각들  (0) 2012.12.23
    [Jade] Jade 사용하기  (0) 2012.12.15
    [EJS] 사용하기  (0) 2012.12.15
    posted by 윤영식
    2012. 12. 23. 01:40 NodeJS/Concept

    Node.js를 리안달이 만들고 난후 프로그래밍의 패러다임이 바뀌고 있다. 스타트업을 위한 모바일 서비스 또는 솔루션의 기본 플랫폼으로 사용되고 있다. 특히 요즘은 Client + Server + DB 가 인터넷에서 하나로 연결되고 있다. 인터넷이 하나의 운영체제처럼 변해가고 있는 것이다. 


      - JavaScript : Client + Server + DB 프로그래밍을 할 수 있는 랭귀지로 자리 잡고 있다.

      - JSON : MongoDB를 사용하면 Client + Server + DB 를 하나의 데이터로 통일 할 수 있다.

      - Socket.io : 인터넷에 물려있는 모든 Tier의 통신을 HTTP 프로토콜을 통하여 Bi-Direction 양방향 통신을 할 수 있다.


    1) 인터넷에 연결된 모든 부분이 JSON을 통하여 데이터를 주고 받는다.


    2) Node.js 생태계에 나타난 Framework들 : Realtime쪽에는 전부 Socket.io 가 핵심 모듈로 사용되고 있다.  

      - Backbone에서 본 현재 현황



    3) Node.js 소개 + 코딩 + 클라우드 파운드리 


    4) Derby 와 Meteor 비교 


    5) Node에서도 TDD 개발은 중요하다. Node위에서 Server Side JavaScript 개발을 할 때 Vows와 Twitter를 이용한다.(24page)



    'NodeJS > Concept' 카테고리의 다른 글

    [Node.js] 기술 발전 방향 4단계  (0) 2013.02.16
    [Cham] Express, CoffeeScript, Jade, Stylus boilerplate 코드 생성하기  (0) 2013.01.31
    [Jade] Jade 사용하기  (0) 2012.12.15
    [EJS] 사용하기  (0) 2012.12.15
    [Node.js] Global Objects  (0) 2012.12.10
    posted by 윤영식
    2012. 12. 15. 15:31 NodeJS/Concept

    Express 프레임워크에서 기본으로 사용하는 Jade에 대하여 알아보자. 



    ▶ app.js 연구 


    1) 우선 require를 사용하여 모듈패턴에 의한 모듈을 얻는다. 모듈로 얻음으로 namespace가 분리되므로 서로간의 충돌을 방지 할 수 있다. 물론 접근은 module.<exports Name> 으로 접근한다 

    var express = require('express')

      , routes = require('./routes')             // index.js 파일 

      , user = require('./routes/user')        // user.js 파일 

      , dowon = require('./routes/dowon') // dowon.js 파일 

      , http = require('http')

      , path = require('path');


    2) ./routes/dowon 으로 require 했으므로 routes 디렉토리 밑에 dowon.js 파일을 생성한다. hi 라는 펑션을 exports 객체에 설정하여 모든 인스턴스가 공유할 수 있게 한다. 물론 모듈안에서 공유가 된다. 단, function(req, res) {...} 로 구현하자. 

    exports.hi = function(req, res){  // dowon 모듈에서 hi 펑션 공유 

      res.render('dowon', { title: 'Hi DoWon', name: 'youngsik', age: '30' }); // dowon.jade 지정 

    };


    3) res.render('dowon', ...) 설정에서 dowon이라고 key를 넣었으므로 views 폴더 밑에 dowon.jade 파일을 생성한다. jade syntax에 맞추어 코딩을 하고 값은 #{key} 형식으로 코딩하면 json에서 값을 읽어 자동 셋팅하고, html 파일로 변환된다 

    - var dododo = function() { return 'dododo young!'; };


    p #{title}


    p hi dowon yun


    p

      | hi

      | dowon

      | yun


    p.

      hi

      dowon

      yun


    // error

    p

      hi

      dowon

      yun  


     ul

       li one

       li two

       li #{name}

       li #{age}

       li= dododo()


    // each loop

    //-

    - var users=[{ title: 'Hi DoWon1', name: 'youngsik1', age: '30' }, {title: 'Hi DoWon2', name: 'youngsik2', age: '40' }, { title: 'Hi DoWon3', name: 'youngsik3', age: '50' }];


     ul

         each user in users

            li= user.title

            li= user.name

            li= user.age



    4) app.js 에서 get 요청에 대하여 서비스 되는 모듈의 exports 펑션을 지정한다. 즉, /dowon uri가 호출되면 hi 펑션이 수행함

    app.get('/', routes.index);

    app.get('/users', user.list);

    app.get("/dowon", dowon.hi);


    Node의 require(<js 파일>) 호출을 통하여 모듈을 로딩하고, 모듈로 로딩된 js 파일안에 모듈에서 공유할 펑션을 정의하였다. 해당 펑션에는 jade 파일명을 지정하여 서비스 한다. 결국, Node의 require, exports Global객체를 적절히 사용하여 구성하였다. 하기와 같은 과정을 거치는 것이다



    Route → Route Handler → Template → HTML


    • Route : dowon.js
    • Route Handler : hi에 지정한 function
    • Template : dowon.jade
    • HTML : jade에 의하여 html로 변환 


    <참조>

      - ninja-express

      - Jade syntax 배우기 (필독)

      - Jade code : 동영상 (필감)


    posted by 윤영식
    2012. 12. 15. 14:17 NodeJS/Concept

    EJS (Embedded JavaScript) 엔진은 자바쪽의 JSP 사용과 거의 유사하다고 보면 된다. 


    • 장점 : JSP 코딩처럼 쉽게 적응할 수 있다
    • 단점 : 프레임워크가 무거움 

    > young.js : express를 사용할 것이고, 기본적으로 views 폴더 에 위치한다
    var express = require('express');
    var ejs = require('ejs');
    var app = express();

    app.get('/', function(req, res) {
    res.format({
    html: function() { res.send('<h1> hi dowon in html</h1>');},
    json: function() { res.send({message: 'hi dowon in json'});},
    text: function() { res.send('hi dowon in text');}
    });
    });

    // response.send에서 response.render로 바뀌는 것 뿐이다 
    app.get('/young/:id', function(req, res) {
    res.render('young.ejs', {youngMessage: 'I am ' + req.params.id, layout: false});
    });


    > young.ejs : html 태그는 제외했음

    <%= youngMessage %>


    ejs 보다는 jade를 사용하자 

    'NodeJS > Concept' 카테고리의 다른 글

    [Node.js] 생태계에 대한 생각들  (0) 2012.12.23
    [Jade] Jade 사용하기  (0) 2012.12.15
    [Node.js] Global Objects  (0) 2012.12.10
    [Node.js] File I/O 사용하기  (0) 2012.12.10
    [Node.js] EventEmitter 에 대하여  (0) 2012.12.10
    posted by 윤영식
    2012. 12. 10. 17:22 NodeJS/Concept

    전역범위에서 참조가 가능한 글로벌 오브젝트. already defined object라고 할 수 있겠다. 



    global objects 
    > 하기 객체는 모든 모듈에서 이용할 수 있다. 실제 전역 범위를 가진다 
    > node에서 var something의 something은 지역범위만 갖는다 
    > global : {Object} 전역 네임스페이스 객체 
    > process, console : {Object}
    > Class: Buffer : {Function} 바이너리 데이터를 다루는데 사용 
    > require() : 모듈 로딩으로 지역범위임
    > __filename : {String} 실행되는 코드의 파일명 (코드의 절대경로 포함)
    > __dirname : {String} 현재 실행되는 스크립트가 존재하는 디렉토리 경로 
    > module : {Object} 현재 모듈에 대한 참조. 특히 module.exports는 exports 객체와 같다 
    > exports : require()로 접근가능하게 된 모듈의 모든 인스턴스 사이에서 공유되는 객체다. 
    > setTimeouts(cb, ms) : cb=callback, ms=milliseconds
      clearTimeout(t) : setTimeout()올 생성된 타이머를 멈춘다
    > setInterval(cb, ms) : 반복적으로 callback 수행
      clearInterval(t)


    >> fileName : globalTest.js

    console.log(__filename);

    console.log(__dirname);


    >> 수행 

    D:\Framework\Node.js> node globalTest

    D:\Framework\Node.js\globalTest.js

    D:\Framework\Node.js


    'NodeJS > Concept' 카테고리의 다른 글

    [Jade] Jade 사용하기  (0) 2012.12.15
    [EJS] 사용하기  (0) 2012.12.15
    [Node.js] File I/O 사용하기  (0) 2012.12.10
    [Node.js] EventEmitter 에 대하여  (0) 2012.12.10
    [Node.js] debugger 사용하기  (0) 2012.12.10
    posted by 윤영식
    2012. 12. 10. 16:35 NodeJS/Concept

    node.js에서 File I/O 를 위하여 역시 모듈을 로딩하여 사용한다 



    > require('fs') 포함 
    > 비동기 방식은 마지막 파라미터로 완료 콜백함수를 받고, 첫 아규먼트로 에러를 받음. 성공이면 null 또는 undefined 가 된다 
    > rename과 stat가 비동기 호출이므로 오류 발생가능성 존재 

    fs.rename('/tmp/hello', '/tmp/world', function (err) {

      if (err) throw err;

      console.log('renamed complete');

    });

    fs.stat('/tmp/world', function (err, stats) {

      if (err) throw err;

      console.log('stats: ' + JSON.stringify(stats));

    });

    > 이를 해결하기 위하여 callback chain을 사용한다. 즉, callback안에 callback function을 둔다 

    fs.rename('/tmp/hello', '/tmp/world', function (err) {

      if (err) throw err;

      fs.stat('/tmp/world', function (err, stats) {

        if (err) throw err;

        console.log('stats: ' + JSON.stringify(stats));

      });

    });


    -- 결과 내역 

    stats: {"dev":0,"mode":33206,"nlink":1,"uid":0,"gid":0,"rdev":0,"ino":0,"size":1876992,"atime":"2012-09-17T18:05:45.000Z","mtime":"2012-09-17T18:05:48.000Z","ctime":"2012-09-17T18:05:41.000Z"}


    'NodeJS > Concept' 카테고리의 다른 글

    [EJS] 사용하기  (0) 2012.12.15
    [Node.js] Global Objects  (0) 2012.12.10
    [Node.js] EventEmitter 에 대하여  (0) 2012.12.10
    [Node.js] debugger 사용하기  (0) 2012.12.10
    [Express] Express Framework 사용하기  (0) 2012.10.30
    posted by 윤영식
    2012. 12. 10. 16:08 NodeJS/Concept

    EventEmitter는 말 그대로 이벤트를 발생시키는 모든 객체를 지칭한다. 서버에 접속(connect)할 때 이벤트가 발생하고 파일을 읽을 때 이벤트가 발생하는 식으로 이미 내장된 이벤트들이 존재할 것이고, 사용자 정의 이벤트를 만들 수도 있을 것이다. 



    > require('events') 첨부한다 
    > 이벤트를 발생시키는 모든 객체는 events.EventEmitter 의 인스턴스 
    > 이벤트 발생할 때 실행할 함수를 객체에 연결, 이러한 함수를 리스너(Listener)라고 부른다 
    > EventEmitter 접근 : require('events').EventEmitter
    > emitter.on(event, listener) 또는 emitter.addListener(event, listener)
      예) server.on('connection', function(stream){...});
    > emitter.once(event, listener) : 한번만 수행 즉, 일회성 listener 
    > emitter.removeListener(event, lisetener) : listener 제거 
    > emitter.removeAllListeners() : 모든 listener 제거 
    > emitter.setMaxListeners(n) : listener등록이 10개 default로 제한, emitter의 listener 갯수를 늘릴 수 있다. 


    'NodeJS > Concept' 카테고리의 다른 글

    [EJS] 사용하기  (0) 2012.12.15
    [Node.js] Global Objects  (0) 2012.12.10
    [Node.js] File I/O 사용하기  (0) 2012.12.10
    [Node.js] debugger 사용하기  (0) 2012.12.10
    [Express] Express Framework 사용하기  (0) 2012.10.30
    posted by 윤영식
    2012. 12. 10. 15:42 NodeJS/Concept

    node명령으로 자바스크립트 코드를 수행할 때 콘솔상에서 debugging을 할 수 있다. 


    • debugger 키워드를 코드에 끼워 넣는다 : breakpoint 역할을 한다 
    • cont, c : 계속 진행 
    • next, n : step next
    • step, s : step in
    • out,   o : step out
    • pause  : 실행 멈춤 
    • 상세명령들

    > 예제 코드 (debuggerTest.js)
    x = 5;
    setTimeout(function () {
      debugger;
      console.log("world");
    }, 1000);
    console.log("hello");



    > 디버깅 수행 : node debug <수행 자바스크립트 파일명>

    D:\Framework\Node.js> node debug debuggerTest

    < debugger listening on port 5858

    connecting... ok

    debug> cont

    < hello

    break in D:\Framework\Node.js\debuggerTest.js:3

      1 x = 5;

      2 setTimeout(function () {

      3   debugger;

      4   console.log("world");

      5 }, 1000);

    debug> next

    break in D:\Framework\Node.js\debuggerTest.js:4

      2 setTimeout(function () {

      3   debugger;

      4   console.log("world");

      5 }, 1000);

      6 console.log("hello");

    debug> cont

    < world

    program terminated


    hello을 찍고 debugger가 있는 곳에서 멈추면 next step으로 이동하면 console 객체로 가고 cont하면 수행을 다시 하여 world 문자가 찍힌다. 수행되는 process를 command line에서 추적해 보고자 할 경우 사용하면 좋겠다. 


    'NodeJS > Concept' 카테고리의 다른 글

    [EJS] 사용하기  (0) 2012.12.15
    [Node.js] Global Objects  (0) 2012.12.10
    [Node.js] File I/O 사용하기  (0) 2012.12.10
    [Node.js] EventEmitter 에 대하여  (0) 2012.12.10
    [Express] Express Framework 사용하기  (0) 2012.10.30
    posted by 윤영식
    2012. 10. 30. 21:52 NodeJS/Concept


    Node.js를 위한 Web Framework으로 Express 를 사용한다. GitHub에도 상당한 순위에 올라와 있고, rail 방식과 유사하다. Connect 모듈을 기반으로 템플릿은 EJS와 Jade를 기반으로 하고 있다. 



    ▶ Express 설치하기  (http://expressjs.com/guide.html)

    • npm (Node Package Manager)을 이용하여 설치해 보자 (-g 옵션은 nodejs 설치 전체에 적용된다. -g 옵션을 안 주면 설치 디렉토리내애서만 영향을 미친다)

      설치가 완료되면 nodejs가 global 참조영역인 Application Data/npm/node_modules/express 라고 설치가 된다


    • express 명령으로 HelloExpress라고 만들어 보자. 그러면 기본적인 Web Application 골격이 생긴다. (WAS의 Context war 파일 생성되는 것으로 비유하면 되겠다. 예로
      > routes/*.js 파일은 web.xml의 url-mapping 설정과 유사하다
      > views/*.js 는 템플릿 엔진의 파일들이 위치한다 (ejs 또는 jade를 사용한다. ejs는 JSP 코딩과 유사하여 친숙하고, jade는 간결함이 좋다)
      > public/* 퍼블리싱 하는 static 파일들
      > app.js Express의 main 파일이다


    • HelloExpress 디렉토리로 이동하여 express가 의존관계에 있는 외부 modules를 설치한다


    • 설치가 완료된 후 node app 로 Express 프레임워크를 수행한다 (http server listening 이 포함되어 있음)



    • app.js 코드를 보자 

      > 외부모듈 express를 얻어와서 app변수에 정적 서버환경을 셋팅하고 있다.(default jade 템플릿 셋팅)
      > URL의 호출에 대한 맵핑을 담당하는 rounting 설정을 한다 
      > 맨 마지막줄에 http server 를 시작한다 

    • http://localhost:3000/dowon 이라는 url 셋팅을 해본다. 우선 app.js 에 routing 정보를 넣는다

    • HelloExpress/routes/user.js 안에 exports.dowon 을 추가한다 



    • HelloExpress/app.js 서버를 재시작 하고, 브라우져에서 호출한다.  



    ▶ Node를 위한 Jade Template 사용하여 표현하기

    • routing하기 위하여 user.js에 하드 코딩된 html 코드를 jade 템플릿으로 서비스하는 방법을 알아보자. 우선 views 디렉토리에 dowon.jade 파일을 만든다 (jade는 템플릿 엔진이다)



    • dowon.jade 템플릿 코딩을 한다 (자세한 사항은 http://jade-lang.com 사이트를 참조하자)

    • routes/index.js 안에 정보를 넣으면 app.js 안에서 routes.dowon으로 호출을 할 수 있다


    • routes/index.js 파일안에 설정한 index, dowon은 app.js 에서 routes.index 와 routes.dowon 으로 호출한다 


    • 재시작하고 브라우져에서 http://localhost:3000/dowon2 로 호출하면 jade 내역이 html로 변환되어 서비스 된다




      간단하게 Express Framework을 Node.js에 얻져서 사용하는 방법을 보았다. 사용하며 느낀것은 서비스를 위한 앞단의 url-mapping과 유사한 route 개념은 새롭게 개발할 필요없이 적용할 수 있어서 좋다. 그러나 domain 모델쪽의 개발과 persistence 영역의 개발에 대한 부분이 Express에 있는지 없다면 어떤 외부 module을 통하여 Express와 통합을 해야하는지  찾아 보아야 겠다. 

      * jade 설치 및 사용법 : http://blog.doortts.com/223


    'NodeJS > Concept' 카테고리의 다른 글

    [EJS] 사용하기  (0) 2012.12.15
    [Node.js] Global Objects  (0) 2012.12.10
    [Node.js] File I/O 사용하기  (0) 2012.12.10
    [Node.js] EventEmitter 에 대하여  (0) 2012.12.10
    [Node.js] debugger 사용하기  (0) 2012.12.10
    posted by 윤영식
    prev 1 next