블로그 이미지
Peter Note
Web & LLM FullStacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2013. 3. 11. 17:13 Backbone.js

Backbone.js를 익히기 전에 Underscore에 대해서 알아보자.



1) Underscore

  - Functional Programming을 위한 자바스크립트 유틸리티 라이브러리 

  - 80 개의 펑션을 가지고 있다 

  - Groc 포멧의 소스코드 보기

  - GitHub Underscore.js

  - var _  변수 사용



2) 테스트 돌려보기 

  - GitHub에서 다운로드 : git clone https://github.com/documentcloud/underscore.git

  - package.json 내역

{

  "name" : "underscore",
  "description" : "JavaScript's functional programming helper library.",
  "homepage" : "http://underscorejs.org",
  "keywords" : ["util", "functional", "server", "client", "browser"],
  "author" : "Jeremy Ashkenas <jeremy@documentcloud.org>",
  "repository" : {"type": "git", "url": "git://github.com/documentcloud/underscore.git"},
  "main" : "underscore.js",
  "version" : "1.4.4",
  "devDependencies": {
    "phantomjs": "1.8.1-3"
  },
  "scripts": {
    "test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true"
  }
}


  - scripts 의 test 에서 phantomjs 사용함 : 참조에서 phantomjs를 설치한다 (웹브라우져 없이 테스트시 많이 사용)

    + phantomjs 를 이용한 테스트 코드 작성 연구에 도움이 되겠다 

    + 테스트 코드는 underscore/test 디렉토리에 존재함 

$ npm test


> underscore@1.4.4 test /Users/nulpulum/git-repositories/underscore

> phantomjs test/vendor/runner.js test/index.html?noglobals=true


2013-03-11 13:58:26.100 phantomjs[32711:f07] *** WARNING: Method userSpaceScaleFactor in class NSView is deprecated on 10.7 and later. It should not be used in new applications. Use convertRectToBacking: instead.

Took 2309ms to run 588 tests. 588 passed, 0 failed.

  


3) Collection Functions

  - 테스트 코드

    + 모듈 설치하기 : npm install underscore 

  - 테스트 결과 

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

// 샘플 코드 짜고 node 로 결과 확인하기 

$ node collection.js

-------each  : 개별 요소를 지정한 function에서 수행

1 0 [ 1, 2, 3 ]

2 1 [ 1, 2, 3 ]

3 2 [ 1, 2, 3 ]

-------map : 각 요소를 지정한 callback에서 수행

3

6

9

-------reduce : 리듀싱

6

-------find : callback에서 찾는 즉시 break

2

-------filter : callback에 매칭되는 것만 

[ 2, 4, 6 ]

-------reject : callback에 매칭되지 않는 것만 

[ 1, 3, 5 ]

-------every : 모두가 지정한 값일 경우 참

false

-------some : 하나라도 지정한 값일 경우 참

true

-------contains : 포함하면 참

true

-------invoke : 펑션 호출 

[ [ 1, 5, 7 ], [ 1, 2, 3 ] ]

-------pluck : 지정한 프러퍼티만 뽑아냄

[ 'dowon', 'haha', 'youngsik' ]

-------max : 지정한 프로퍼티중 최대인 것

{ name: 'youngsik', age: 99 }

-------min : 지정한 플터피중 최소인 것 

3

-------groupBy : 그룹핑 

{ '1': [ 1.3, 1.9 ], '2': [ 2.1, 2.4 ] }

-------countBy : callback 계산된 그룹핑 건수 

{ odd: 3, even: 2 }

-------toArray : 배열 리턴

[ 2, 3, 4 ]

-------size : 크기 

3

** 기타 몇가지 테스트 안한 API : where, findWhere, sortBy, shuffle 등



4) Array Functions

  - 테스트 코드 

  - 테스트 결과

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

// 테스트 코드를 작성하면서 nodemon 을 통하여 결과값을 확인한다

$ nodemon array.js

------first : 배열 첫번째 요소

5

------initial : 마지막 요소 제외한 배열

[ 5, 4, 3, 2 ]

------last : 배열 마지막 요소 

1

------rest : 첫번째 요소 제외한 요소 

[ 4, 3, 2, 1 ]

------compact : '' 0 false null등을 제외한 요소만 

[ 4, 2 ]

------flatten : 1차원 배열로

[ 1, 2, 3, 4 ]

------without : 지정한 요소를 제거한 배열 

[ 1, 1, 3, 4 ]

------union : 중복 제거 

[ 1, 2, 3, 101, 11 ]

------intersection : 서로 중복되는 것만 

[ 1, 2 ]

------uniq : 유니크한 것만 

[ 1, 2, 3, 4, 5 ]

------zip : 각 배열의 요소끼리 2차원배열

[ [ 'a', 1, true ], [ 'b', 2, false ], [ 'c', 4, true ] ]

------object : 2개 배열의 요소를 javascript obejct형식의 {key:value}로 변환

{ a: 1, b: 2, c: 4 }

------indexOf : 앞에서 부터 지정한 위치

2

------lastIndexOf : 뒤에서 부터 지정한 위치

4

------sortedIndex : 지정한 값이 들어갈 위치 

2

------range : 지정한 길이 만큼 배열 만들기 

[ 0, 1, 2, 3 ]



5) Object Functions

  - 테스트 코드

  - 테스트 결과 

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

// coffee-script 로 작성하고 compile과 watch 옵션을 준다 

$ coffee --compile --watch object.coffee


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

// nodemon 으로 컴파일된 object.js 를 모니터링한다 

$ nodemon object.js 

11 Mar 16:40:06 - [nodemon] app crashed - waiting for file changes before starting...

11 Mar 16:40:14 - [nodemon] restarting due to changes...

11 Mar 16:40:14 - [nodemon] /Users/nulpulum/development/underscore/test/object.js


11 Mar 16:40:14 - [nodemon] starting `node object.js`

--------keys : 오브젝트의 키만

[ 'one', 'two', 'three' ]

--------values : 오브젝트의 값만

[ 1, 2, 3 ]

--------pairs : 각 오브젝트를 key:value 형태로 

[ [ 'one', 1 ], [ 'two', 2 ], [ 'three', 3 ] ]

--------invert : key:value를 거꾸로 

{ '1': 'one', '2': 'two', '3': 'three' }

--------functions : 객체의 모든 펑션 

[ '_',

  'after',

  'all',

  'any',

  'bind',

  'bindAll',

  'chain',

  'clone',

  'collect',

  'compact',

  'compose',

  'contains',

  'countBy',

  'debounce',

  'defaults',

  'defer',

  'delay',

  'detect',

  'difference',

  'drop',

  'each',

  'escape',

  'every',

  'extend',

  'filter',

  'find',

  'findWhere',

  'first',

  'flatten',

  'foldl',

  'foldr',

  'forEach',

  'functions',

  'groupBy',

  'has',

  'head',

  'identity',

  'include',

  'indexOf',

  'initial',

  'inject',

  'intersection',

  'invert',

  'invoke',

  'isArguments',

  'isArray',

  'isBoolean',

  'isDate',

  'isElement',

  'isEmpty',

  'isEqual',

  'isFinite',

  'isFunction',

  'isNaN',

  'isNull',

  'isNumber',

  'isObject',

  'isRegExp',

  'isString',

  'isUndefined',

  'keys',

  'last',

  'lastIndexOf',

  'map',

  'max',

  'memoize',

  'methods',

  'min',

  'mixin',

  'noConflict',

  'object',

  'omit',

  'once',

  'pairs',

  'partial',

  'pick',

  'pluck',

  'random',

  'range',

  'reduce',

  'reduceRight',

  'reject',

  'rest',

  'result',

  'select',

  'shuffle',

  'size',

  'some',

  'sortBy',

  'sortedIndex',

  'tail',

  'take',

  'tap',

  'template',

  'throttle',

  'times',

  'toArray',

  'unescape',

  'union',

  'uniq',

  'unique',

  'uniqueId',

  'values',

  'where',

  'without',

  'wrap',

  'zip' ]

--------extend : 두객체를 합침

{ name: 'dowon', age: 33 }

--------pick : 원하는 것만 끄집어 냄

{ age: 33 }

--------omit : 원하는 것을 삭제함 

{ name: 'dowon' }

--------defaults : 기본 값으로 대체 

{ flavor: 'chocolate', orange: 'lots' }

--------clone : 객체 복제하기 

{ name: 'dowon', age: 33 }

--------tap : 오브젝트 필터링시에 사용 

[ 2, 400 ]

--------has : 키가 존재하는지 체크 

true


** 그외  is** 관련 펑션이 존재함 (true/false 결과 리턴)



6) Utility Functions

  - 테스트 코드

  - 테스트 결과 

$ coffee --compile --watch utility.coffee

$ nodemon utility.js

1 Mar 17:07:19 - [nodemon] clean exit - waiting for changes before restart

11 Mar 17:08:06 - [nodemon] restarting due to changes...

11 Mar 17:08:06 - [nodemon] /Users/nulpulum/development/underscore/test/utility.js


11 Mar 17:08:06 - [nodemon] starting `node utility.js`

------noConflict : _ 언더바가 다른 모듈과 쫑나면 변경가능 

[Function]

------identity : 복사 

{ name: 'dowon' }

------times : 횟수만큼 수행

0

1

2

------random : min~max 사이값 랜덤 생성 

10

------mixin : 모듈에 펑션을 확장시킴

Youngsik

------uniqueId : 유니크 아이디를 만들어 줌

dowon_1

------escape 

dowon &amp; young &gt; hi &lt;

------unescape

dowon & young > hi <

------result : 지정된 키의 값 반환

hi

------template : 템플릿 엔진 <% ... %> 기본, {{ ... }} 등으로 변경가능

hello: dowon


------chain : 객첵를 여러 메소드에 걸쳐서 수행하고 싶을 경우 최초에 한번에 넣는다 

youngsik is 22


// 1) 과 2)는 동일한 표현이다 

1) _.map([1, 2, 3], function(n){ return n * 2; });

2) _([1, 2, 3]).map(function(n){ return n * 2; });



<참조>

  - Underscore.js 테스트 코드

  - PhantomJS 설치하기

  - package.json의 test 스크립트 구동하기 (Testing)


posted by Peter Note
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 Peter Note
2013. 3. 9. 17:47 Languages

Underscore.js 프레임워크를 보면 소스에 대해 왼쪽에는 주석을 오른쪽은 소스를 보여주며 설명을 한다. 이러한 문서를 자동으로 만들어 주는 툴이 Groc 이다. 또한 루트에서 수행을 하면 하위의 모든 소스에 대한 문서화를 자동으로 만들어 주고, GitHub과 통합할 수 있다 


1. Groc 설치하기 

  - 주석을 Markdown 형태로 작성한다

  - 마크다운 포멧은 배우기 쉽고 GitHub에서도 사용하므로 반드시 익혀두자 

  - GitHub의 페이지 publishing 과 통합된다 : GitHub에서 OSS(Open Source Software) 개발한 것을 공짜로 웹 서비싱 해준다

  - 검색 테이블을 제공한다 



2. 설치하기 

  - npm (Node Package Manager)가 설치되어 있어야 한다 

sudo npm install groc -g

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

npm http 304 https://registry.npmjs.org/groc

... 중략 ...

groc@0.3.2 /usr/local/lib/node_modules/groc

├── colors@0.6.0-1

├── spate@0.1.0

├── underscore@1.4.4

├── coffee-script@1.6.1

├── autorequire@0.3.4

├── showdown@0.3.1

├── optimist@0.3.5 (wordwrap@0.0.2)

├── jade@0.28.2 (commander@0.6.1, mkdirp@0.3.5)

├── uglify-js@2.2.5 (source-map@0.1.9)

├── glob@3.1.21 (inherits@1.0.0, graceful-fs@1.2.0, minimatch@0.2.11)

└── fs-tools@0.2.9 (async@0.2.6, lodash@1.0.1)


// syntax highlighting module pygments 설치하기

$ sudo easy_install Pygments

Best match: Pygments 1.6

Downloading http://pypi.python.org/packages/2.7/P/Pygments/Pygments-1.6-py2.7.egg#md5=1e1e52b1e434502682aab08938163034

... 중략 ...

Installing pygmentize script to /usr/local/bin   <== groc가 사용함



3. 문서만들기 

  - * 사용할 수 있다

  - 여러 옵션을 적용할 수 있다

  - CLI 명령으로 수행한다 : groc [js명칭]

  - github에서 groc를 다운받아서 직접 만들어 보자 

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

// groc 소스 받아 문서 생성하기 

$ git clone https://github.com/nevir/groc.git

Cloning into 'groc'...

remote: Counting objects: 1215, done.

...중 략 ...


groc index.js

publish_to_github null https://github.com/nevir/groc origin

  Generating documentation...

✓ /Users/git-repositories/groc/.git/groc-tmp/languages.html

✓ /Users/git-repositories/groc/.git/groc-tmp/project.html

..중략..

✓ /Users/git-repositories/groc/.git/groc-tmp/styles/default/docPage.html

✓ Documentation generated


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

// 디렉토리별로 .js 또는 .coffee 파일을 .html 파일로 문서화 한다

// git clone 후 

$ cd groc 디렉토리 이동후 모습 

// groc 를 수행한 후의 디렉토리 : lib 디렉토리에 있는 폴더를 상위 폴더로 올린다



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

// static 웹서버 구동 (참조)

$ static

serving "." at http://127.0.0.1:8080

17:35:09 [200]: /

17:35:09 [200]: /assets/style.css

17:35:09 [200]: /assets/behavior.js

17:35:09 [404]: /favicon.ico


  - 문서보기 : http://localhost:8080  Groc의 홈페이지 문서가 로컬에 만들어 졌다!


4. 사용 아이디어

  - GitHub에서 소스를 개발한다면 GitHub Page와 통합하여 API를 웹서비스 형태로 배포한다

  - 개발 소스에 대한 Code Review시에 Groc 문서로 만들어서 소스를 리뷰한다 

  


<참조>

  - Outsider dev 의 groc 소개

  - Pygments 설치하기

'Languages' 카테고리의 다른 글

APM 설치하기  (0) 2012.11.27
posted by Peter Note
2013. 2. 28. 11:29 Git, GitHub/Git Lec02

rebase를(참조) 통하여 다른 브랜치의 전체 commit 내역을 복사해오지 않고 특정 commit 내역만을 가져오고 싶을 경우 cherry-pick을 사용한다


1) 언제 사용

  - 토픽이나 패치 브랜치에서 개발된 특정 commit만을 가져오고 싶을 경우 

  - 즉, 하나의 commit만 rebase 하는 것이다 



2) 실습

  - cherry-pick을 하기전 상태

  

  [5.26 master브랜치와 별도의 토픽브랜치 ruby_client로 두개의 커밋이 존재]


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

// ruby_cleint별도 브랜치 만들어진 이후

// master 브랜치 커밋내역

git log --pretty=oneline -since="2 hours"

fatal: unrecognized argument: -since=2 hours

[nulpulum:~/git-repositories/pro_git]git log --pretty=oneline --since="2 hours"

514281f305bd001776ca41efebccf8276a6bfd98 modify dowon.js


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

// ruby_client 브랜치로 이동

$ git checkout ruby_client

Switched to branch 'ruby_client'

$ git log --pretty=oneline --since="2 hours"

0f79ccda8c4086d57a4b9ed53c87ecaf11e52ba5 modify topci.txt

40396ae5ab8a964704e0ab84809bb499f9c996b2 add topic.txt


  - check-pick 수행하기 

    + 그림에서 e43a6에 해당하는 "40396"에 대해서 master 브랜치에서 check-pick 한다

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

// master 브랜치로 토픽브랜치의 특정

// commit 내역만을 rebase = cherry-pick

$ git checkout master

Switched to branch 'master'

Your branch is ahead of 'origin/master' by 1 commit.

  (use "git push" to publish your local commits)

[nulpulum:~/git-repositories/pro_git]git branch

* master

  ruby_client


$ git cherry-pick 40396ae5ab8a964704e0ab84809bb499f9c996b2

[master 4963fef] add topic.txt

 1 file changed, 1 insertion(+)

 create mode 100644 topic.txt


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

// ruby_client의 커밋이 master 브랜치로 

// 새로운 commit을 제일 앞에 놓았다 

$ git log --pretty=oneline --since="2 hours"

4963fef54f1d6760ec4e5ff15c9684e0f5e6ad4e add topic.txt

514281f305bd001776ca41efebccf8276a6bfd98 modify dowon.js

[nulpulum:~/git-repositories/pro_git]git branch

* master

  ruby_client


  

  [5.27 e43a6 커밋내역 하나만 master의 제일 앞으로 새로운 commit이 생성]



<참조>

  - Pro Git : p127

posted by Peter Note
2013. 2. 23. 16:53 MongoDB/MapReduce

GridFS에 대하여 샘플을 돌려보자


1) 예제 다운로드 

  - git 복제한다

[~/development/mongodb]git clone https://github.com/jamescarr/nodejs-mongodb-streaming.git gridfs_mongoose

Cloning into 'gridfs_mongoose'...

remote: Counting objects: 44, done.

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

remote: Total 44 (delta 12), reused 40 (delta 8)

Unpacking objects: 100% (44/44), done.


  - 파일을 JetBrains WebStorm에서 열어보았다 

    + coffee-script 이용하여 app.js 를 app.coffee 로 작성

  


  - 실행하기전 express, mongoose, request, jade 모듈 설치

    + npm install express

    + npm install mongoose

    + npm install request


  - 실행 : http://localhost:3000 호출

    + 호출하기전 MongoDB를 start 해 놓아야 한다 

[~/development/mongodb/gridfs_mongoose]coffee app

Server running. Navigate to localhost:3000

  

    + 브라우져 호출하면 파일 업로드 화면이 나온다

  

 


2) GridFS 파일 업로드 하기 

  - 화면에서 Name을 입력하고 File 을 선택한 후 "제출" 버튼을 클릭한다 


  - MongoDB의 mongo에서 확인을 한다 : dowonFile 은 프로그램안에서 사용한 Collection 명칭이다

[~/mongodb]mongo

MongoDB shell version: 2.2.3

connecting to: test


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

//  제출전 상태

> show dbs

local (empty)


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

//  제출후 상태

> show dbs

dowonFile 0.203125GB

local (empty)

> use dowonFile

switched to db dowonFile

> show collections

applications

fs.chunks

fs.files

system.indexes

> db.applications.find();

{ "name" : "dowonGridFileSample", "_id" : ObjectId("51392f28dfa5f69404000001"), "files" : [ { "md5" : "6dda9a5cd37e113b246fd00604bf3638", "uploadDate" : ISODate("2013-03-08T00:22:01.077Z"), "chunkSize" : 262144, "length" : 7772701, "contentType" : "binary/octet-stream", "_id" : ObjectId("51392f28dfa5f69404000002") } ] }



3) 예제 분석하기 

  - *.coffee 를 컴파일하여 분석할 수도 있다 : coffee -c *.coffee 수행하면 *.js 파일 생성됨

  - 가급적 coffee-script에 익숙해 지도록 하자 (참조)

  - app.coffee 

    + 기본 환경 셋업

    + 스키마 생성

    + 호출을 위한 get/post 구성 : /new/:id 값을 RESTful 로 호출하면 파일을 다운로드 받을 수 있다 (id는 몽고디비에서 _id 참조)

  

  - gridfs.coffee

    + gridfs 전용 put, find 관련 메소드를 정의하여 모듈화 한다 


4) Mocha 테스트 

  - git clone 받은 디렉토리에서 Mocha 테스트를 수행한다 : current 디렉토리 밑으로 test 디렉토리의 테스트 파일을 자동 수행한다

  - 테스트 파일 형식

    + .js : mocha

    + .coffee : mocha --compilers coffee:coffee-script



<참조>

  - 원문 : nodejs-mongodb-streaming (Node.js mongoose+GridFS 예제)


'MongoDB > MapReduce' 카테고리의 다른 글

[MongoDB] Aggregation Framework 실습하기  (0) 2013.08.03
[MongoDB] Aggregation Framework 이해하기  (0) 2013.08.03
[MongoDB] GridFS 개념잡기  (0) 2013.02.23
posted by Peter Note
2013. 2. 23. 15:50 MongoDB/MapReduce

몽고디비가 샤딩으로 저장한 데이터들은 어떻게 조회되어 가져올 수 있을까? GridFS에 대해서 알아보자. 텐젠의 설명을 잠시 보자

GridFS is a specification for storing and retrieving files that exceed the BSON-document size limit of 16MB.

(GridFS는 16MB 넘는 사이즈의 데이터를 저장하고 조회하는 명세이다. 모든 파일을 도큐먼트로 다룬다는게 중요하겠다)


Instead of storing a file in an single document, GridFS divides a file into parts, or chunks, [1] and stores each of those chunks as a separate document. By default GridFS limits chunk size to 256k. GridFS uses two collections to store files. One collection stores the file chunks, and the other stores file metadata.

(한개의 파일로 저장하는 대신에 부분이나 청크로 나누어 분리된 도큐먼트를 청크로 저장한다. 청크사이즈는 기본 256k로 제한되어 있다. 파일 청크와 메타데이터를 저장하는 두개의 컬렉션을 사용한다)



1) 개념

  - 분산 파일 시스템 : Redis (Map-key:value- Data)

  - Redis와 같은 기능을 MongoDB에서는 GridFS에서 담당한다

  - mongoose ODM 드라이버를 통해서 GridFS를 사용할 수 있다


2) 사용하기 

  - javascript.pdf 50.3MBytes 자리 파일을 GridFS로 구성

  - 미디어 파일도 MongoDB에 컬렉션으로 관리하게 되는 것이다 

[~/mongodb]mongofiles -d dowon put javascript.pdf

connected to: 127.0.0.1

added file: { _id: ObjectId('5128625889a440df3f1359db'), filename: "javascript.pdf", chunkSize: 262144, uploadDate: new Date(1361601113683), md5: "57b836baabd09c486778e192fa6c350e", length: 53872431 }

done!


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

// 결과 

[~/mongodb]mongo

MongoDB shell version: 2.2.3

connecting to: test

> show dbs

dowon 0.203125GB

dowonDB 0.203125GB

local (empty)

> use dowon

switched to db dowon

> show collections

fs.chunks

fs.files

system.indexes

> db.fs.files.find();

{ "_id" : ObjectId("5128625889a440df3f1359db"), "filename" : "javascript.pdf", "chunkSize" : 262144, "uploadDate" : ISODate("2013-02-23T06:31:53.683Z"), "md5" : "57b836baabd09c486778e192fa6c350e", "length" : 53872431 }


  - 대용량 데이터를 그림처럼 GridFS로 저장하면

    + 맵 : 분산된 데이터를 Key=Value (map) 기반으로 찾고

    + 리듀스 : 자바스크립트 펑션을 통하여 통합한다(비즈니스 로직 구현)

  



<참조>

  - 몽구스(mongoose)를 이용하여 gridfs 구현하기 

  - 텐젠 메뉴얼 : http://docs.mongodb.org/manual/applications/gridfs/


'MongoDB > MapReduce' 카테고리의 다른 글

[MongoDB] Aggregation Framework 실습하기  (0) 2013.08.03
[MongoDB] Aggregation Framework 이해하기  (0) 2013.08.03
[MongoDB] GridFS 사용하기  (0) 2013.02.23
posted by Peter Note
2013. 2. 20. 17:36 Middleware, Cloud/Linux

로그 백업을 위하여 crontab에 등록할 Bash Shell를 작업하려 한다. 익혀간 과정을 적어보자 


1) Backup 가정

  - 3일전 로그를 압축한다.

  - 여러개의 로그파일이 다양한 위치에 존재한다

  - 압축된 로그파일은 년/월 별도 디렉토리로 이동하여 관리한다

  - 작은 업무 시스템별로 로그의 위치가 틀리다 (단, 작은 업무 시스템안에 디렉토리는 고정임)


2) 3일전 로그찾기 

  - 몇일전 날짜를 찾는 문법 (참조)

####################################################

# 1) output is 3 days ago 

# backup directory name : backup_YYYY-MM in log files

# 3일전 파일을 찾는다 

YYYYMMDD=`date +%Y%m%d --date '3 days ago'`

DATE="${YYYYMMDD:0:4}-${YYYYMMDD:4:2}-${YYYYMMDD:6:2}"

BK_DIR="backup_${YYYYMMDD:0:4}-${YYYYMMDD:4:2}"

GZIP_CNT="0"


echo ""

echo "===============================[Backup Start]============================="

echo "<< Start Time: "`date '+%F  %r'`" >>"

echo "-- Backup File Date : $DATE, Backup Dir : $BK_DIR"


3) 여러개의 로그파일이 다양한 위치에 존재함

  - 지정한 디렉토리에 파일이 있으면 gzip으로 압축한다

####################################################

# 2) run gzip for log files

# ${1} : directory full path

# ${2} : file name

function mkdir_function()

{

  if [ ! -d ${1} ]; then

    echo "  make dir : ${1}"

    mkdir ${1}

  fi

}


# backup_YYYY-MM 디렉토리가 없으면 만들고 .gz  압축파일을 월별로 관리한다 

function mv_file_function()

{

  mkdir_function "${1}/$BK_DIR"


  echo "  move : ${1}/${2}.gz to ${1}/$BK_DIR"

  mv ${1}/${2}.gz ${1}/$BK_DIR/

}


# ${1} : directory full path

# ${2} : file name

# 지정된 파일만 압축 

function gzip_function() 

{

  if [ -e ${1}/${2} ]; then

    cd "${1}"    

    echo "  gzip : ${1}/${2}"


    gzip ${1}/${2}


    mv_file_function "${1}" "${2}"  


    GZIP_CNT=`expr $GZIP_CNT + 1` 

  fi

}


# for time loop gzip

# 3일 이전의 모든 파일들 

function gzip_loop_function()

{

  cd "${1}"

  for file in `find -type f -mtime +3`; do

     local FNAME="${file:2}"

     local EXT="${FNAME##*.}"

     if [ "$EXT" != "" ] && [ "$EXT" != "gz" ] && [ "$EXT" != "sh" ]; then

        gzip_function "${1}" "${FNAME}"

     fi

  done

}


4) 업무 단위 시스템별로 로그의 위치 지정 : 로그 지정하여 압축 수행함 

  echo "-- [START] ${JDOMAIN} backup : TX.xml & Error.xml log"

  gzip_function "/tmp/logs" "Transactions.log.$DATE"

  gzip_function "/tmp/logs" "Error.log.$DATE"


  # gc old log

  echo "-- [START] ${JDOMAIN} backup : old gclog log"

  gzip_loop_function "/tmp/logs/$JDOMAIN/old/gclog"

 

  # nohup old log

  echo "-- [START] ${JDOMAIN} backup : old nohup log"

  gzip_loop_function "/tmp/logs/$JDOMAIN/old/nohup"


5) 전체 Shell Script


<참조>

  - 백업받을 디렉토리를 만들어야 하는 경우 : 하기 내용은 function을 이용한 참조 내역임 (다른 유사 참조)

  - Bash Shell 문법을 익혀보자 (참조)

  - Bash Shell 문법 : 옵션 잘 설명됨 (참조)

posted by Peter Note
2013. 2. 20. 17:01 Backbone.js

프론트앤드 자바스크립트 프레임워크의 시작은 백본의 이해가 기본이라고 생각합니다. 어떻게 배워야 할지 알아보죠


1) 이럴 때 사용하자 

  - modern single page web application 개발시 사용

  - 다른 최신의 (meteor.js, derby.js, ember.js)를 시작하기 이전에 기본으로 배우자 

  - 자바스크립트 MVC or MV* 프레임워크에 대해서 잘 이해하고 쓰자

  - Node.js와 궁합 잘 맞음 


2) 백본 기초 다지기

  - Developing Backbone.js Applications 번역서로 시작하자


3) 마스터 하기 

  - 자바스크립트를 먼저 익혀야 한다

  - 자바스크립트 생기초 개념

    + JavaScript Objects in Detail

    + JavaScript Variable Scope and Hoisting Explained

    + Understand JavaScript Closure with ease : 꼭 읽자. 설명 잘 했다

  - Model, View, Router, Collections에 대한 개념 정리

    + 모델이란

    + 뷰란

    + 라우터란

    + 컬렉션이란

  - 백본사용하여 개발된 예제 Wine Cellar 예제 시작하기 : Part 1

  - Developing Backbone.js Applications 복습 ^^;

  - 백본관련 블로깅 글 2개 읽기 

    + 백본의 MV* 각 역할에 대한 이해

    + 백본 시작하기 3단계

  - Wine Cellar CRUD 이해하기 : Part 2

  - Wine Cellar 어플리케이션 성능 개선 및 배울점 : Part 3 (꼭 읽자)

  - 마무리 블로깅 꼭 읽자 

    + 뷰와 서브뷰간의 통신 방법 이해하기1, 이해하기2

    + 페이지 변경 제어 이해하기1, 이해하기2


전체 하는데 30시간 정도 투자하시라 (하루 3시간씩 2주면 되겠네요)


4) 마무리

  - 이제 Node.js 를 배워보자 

  - 백본과 노드에 대해서 개념 잡았으면 현대적인 웹앱만들 준비 끝~~~

  - 실제 구현사례는 http://dailyjs.com/web-app.html 여기서 틈틈히 살펴보자 


5) 기타

  - 핸들바 템플릿엔진에 대한 이해

  - 백본 확장, 백본 Grunt, Unit Testing 방법등을 알아본다



<참조>

  - 원문 : http://javascriptissexy.com/learn-backbone-js-completely/

posted by Peter Note
2013. 2. 20. 16:27 Languages/JavaScript

자바스크립트 개발자가 되고 싶다면 이렇게 배우자. 


1) 이럴때 자바스크립트를 배우자

  - 모던 웹 애플리케이션을 만들고자 할때

  - Backbone.js, Node.js, MongoDB와 같은 프레임워크나 자바스크립트 인터프리터를 탑재한 곳에서 개발 할때


2) 이렇게 배우진 말자

  - 온라인에서 튜토리얼이나 동영상 보고 배우지 말자

  - 초보자에게 더글라스 클락포드의 "JavaScript: The Good Parts" 책은 적합하지 않다 


3) 1~ 3주간 이렇게 배우자 

  - 공부할 책들

    + Professional JavaScript for Web Developers

    + JavaScript: The Definition Guid 6th (번역서 : 자바스크립트 완벽 가이드)

    + 코드아카데미 강좌 이용

  - 코드아카데미 Web Fundamentals 공부

  - Professional JavaScript 책 1장에서 3장까지 공부

  - 코드아카데미 JavaScript Fundamentals 공부

  - Professional JavaScript 책 4장에서 5장까지 쭉 공부

  - Definition Guide는 6장까지 쭉 공부 (번역본 읽어보니 주옥같은 내용이다. 강추)

  - Professional JavaScript 책 18장까지 공부 (원문에 챕터를 너무 분류했다)

  - Definition Guide를 다시 12장까지 공부 (서버사이드 자바스크립트 마스터)


4) 4~5주간 이렇게 배우자 

  - 코드아카데미 jQuery 배우기

  - Professional JavaScript 책 18장부터 끝까지 공부

  - Definition Guide 13장부터 끝까지 공부 (클라이언트 사이드 자바스크립트 마스터)

  - 이후엔 애플리케이션을 만들어 본다 


5) 6주차

  - Node.js를 이용하여 서버 코딩을 한다

  - Backboen.js를 이용하여 클라이언트 코딩을 한다 


6) 이후 좋은 참조 사이트들 공부하기 

  - 자바스크립트 디자인 패턴

  - 자바스크립트 Garden (번역)



<참조>

  - 원문 : http://javascriptissexy.com/how-to-learn-javascript-properly/

posted by Peter Note
2013. 2. 16. 16:42 MongoDB/Prototyping

MongoDB 를 접속하기 위한 다양한 방법에 대해 알아보자 



1. mongodb 

  - REST API 개발하기 : 와인 저장고 요약 블로깅

  - MongoDB Native Driver for Node.js 문서

  - 당연히 mongojs 를 사용하는 것보다 복잡하다



2. mongojs

  - mongodb native를 wrapping한 모듈 

  - 설치 : npm install mongojs  

  - mongoDB에서 컬렉션 만들기 

[~/mongodb:nulpulum]./mongo

MongoDB shell version: 2.2.3

connecting to: test

Welcome to the MongoDB shell.

For interactive help, type "help".

For more comprehensive documentation, see

http://docs.mongodb.org/

Questions? Try the support group

http://groups.google.com/group/mongodb-user

> show dbs

local (empty)

> use dowonDB

switched to db dowonDB

> db

dowonDB

> db.people.save({_id:1, age:11, name: 'dowon', sex: true});

> db.people.save({_id:2, age:22, name: 'youngsik', sex: true});

> db.people.save({_id:3, age:33, name: 'taeyoung', sex: false});

> show collections

people

system.indexes


  - mongojs 코딩

  - Mongo Shell 에서 확인

> db.people.find();

{ "_id" : 1, "age" : 11, "name" : "dowon", "sex" : true }

{ "_id" : 2, "age" : 22, "name" : "youngsik", "sex" : true }

{ "_id" : 3, "age" : 33, "name" : "taeyoung", "sex" : false }

{ "_id" : 4, "age" : 27, "name" : "jaein", "sex" : false }



3. mongoose

  - 가장 많이 사용한다. MongoDB접속 ODM(Object Document Mapping) MVC framework

  - 설치하기 : npm install mongoose

  - mongolian 은 mongoose의 light weight 버전이다 

  - Backbone.js 프레임워크와 유사 : schema = controller 개념으로 사용, model = collections

    하기와 같이 schema에서 할 수 있는 일들은 일반 프레임워크의 컨트롤러 즉, 비즈니스 펑션을 제공한다 (참조)

Validators (async and sync)

Defaults

Getters

Setters

Indexes

Middleware

Methods definition

Statics definition

Plugins

pseudo-JOINs

  

  - Schema를 만들 때 사용하는 타입

String

Number

Date

Buffer

Boolean

Mixed

ObjectId

Array

  

  Functional Programming에서 함수를 인자로 넘기고 동일한 로직을 수행한다면, 인자인 함수를 바꿔가면서 동일한 로직을 DRY 하여 사용할 수 있다. 여기서 인자로 넘기는 함수를 Schema라고 생각해 볼 수 있다

  

  - mongoose 코딩

  - 결과 : save, find가 비동기로 이루어지기 때문에 이미 전에 save한 (age: 33 도큐먼트) 데이터만 나온다 

[nulpulum:~/development/mongoose]node mongoose.js 

connection successful...

{ age: 33,

  name: 'dowon',

  sex: true,

  _id: 511f3cb4c6ae3fef03000001,

  __v: 0 }



4. mongolian

  - Node.js 전용 드라이브

  - 향후 다른 layer와 연결하여 개발하려면 mongoose 또는 mongolian/skin중 하나를 선택하여 사용한다 

    (개인적으로 mongoskin framework이 편리하다)



5. mongoskin

  - 설치하기 

[nulpulum:~/development/nodejs/node_basic]npm install mongoskin

npm WARN package.json application-name@0.0.1 No README.md file found!

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

npm http GET https://registry.npmjs.org/mongoskin/-/mongoskin-0.5.0.tgz

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

npm http GET https://registry.npmjs.org/bson/0.1.8


> bson@0.1.8 install /Users/nulpulum/development/nodejs/node_basic/node_modules/mongoskin/node_modules/mongodb/node_modules/bson

> (node-gyp rebuild 2> builderror.log) || (exit 0)


xcode-select: Error: No Xcode is selected. Use xcode-select -switch <path-to-xcode>, or see the xcode-select manpage (man xcode-select) for further information.


mongoskin@0.5.0 node_modules/mongoskin

└── mongodb@1.2.13 (bson@0.1.8) 


  - 사용하기 : express 코딩

var mongoskin = require('mongoskin');

var db3 = mongoskin.db('localhost:27017/dowonDB?auto_reconnect');


app.get('/person3/list', function(req, res) {

    console.log('---start 04----');

    db3.collection('people').findOne({name: 'young'}, function (err, users) {

        // do something

        if(err || !users) throw err;


        res.json(users);

    });

});


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

// 결과 

[nulpulum:~/development/nodejs/node_basic]curl -i -X GET http://localhost:3000/person3/list

HTTP/1.1 200 OK

X-Powered-By: Express

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

Content-Length: 90

Date: Sat, 23 Feb 2013 05:54:17 GMT

Connection: keep-alive


{

  "age": "31",

  "name": "young",

  "sex": "true",

  "_id": "51282bb231ca135412000001"


  - mongoskin API 



<참조> 

  - Node.js Language Center in MongoDB

  - https://github.com/gett/mongojs

  - MongoJS 사용하기

  - Mongoose API 사용하기

  - Mongoose Homepage

  - Mongoose API 익히자

posted by Peter Note
2013. 2. 16. 14:56 Testing, TDD/Test First

JavaScript 의 Unit Test를 위하여 여러 프레임워크가 나왔고, 이중 자유도가 높은 Mocha를 사용하려 한다. Assert에 대해 변경을 하면 BDD, TDD를 할 수 있고, JavaScript Funcational 프로그래밍 테스트에 잘 어울리는 BDD를 기본으로 사용한다



1. Test Framework의 종류 

  - Mocha의 장점이 가장 많다 (5page)



2. Mocha 

  - mocha 명령을 수행하는 위치 하위로 test디렉토리에 있는 스크립트를 자동 수행한다 

  - Assertion의 종류를 선택할 수 있다

    + should.js : describe, it 의 BDD 스타일

    + chai : expect(), assert() 스타일

    + expect.js : expect() 스타일 

  - should.js 는 Object prototype에 assert 모듈을 확장하였다 

  - test/mocha.opts 옵션 파일을 놓으면 자동 테스트시에 해당 옵션을 자동 적용한다

--require should
--reporter dot
--ui bdd
--globals okGlobalA,okGlobalB
--globals okGlobalC
--globals callback*

  --timeout 200


  - Mocha의 BDD 스타일 기본형식 

describe('BDD style', function() {

  before(function() {

    // excuted before test suite

  });

 

  after(function() {

    // excuted after test suite

  });

 

  beforeEach(function() {

    // excuted before every test

  });

 

  afterEach(function() {

    // excuted after every test

  });

   

  describe('#example', function() {

    it('this is a test.', function() {

      // write test logic

    });

  });

});




3. 사용법

  - test 폴더 밑에 mocha.opts 파일 작성

    + coffee-script 지원

    + requrie('should') 할 필요 없이 should.js 모듈 첨부

--compilers coffee:coffee-script

--require should


  - 간단한 테스트 프로그램 작성 

    + should.js API 익히기  : Object prototype을 확장하였으므로 Object.should 사용한다 (직관적인 표현이 좋군)

describe('Array', function() {

describe('#indexOf()', function() {

it('should return -1', function() {

[1,2,3].indexOf(5).should.equal(-1);

})

})

})


  -test 폴더와 같은 dept 위치에서 mocha 수행

[nulpulum:~/development/mongojs] mocha


  ․


  1 test complete (1 ms)



<참조>

  - Mocha 사용법 - Outsider

  - mocha.opts

  - 공식홈페이지 http://visionmedia.github.com/mocha/

  - Test Framework Pros and Cons 비교

posted by Peter Note
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 Peter Note
2013. 2. 7. 21:28 Testing, TDD/Test First

Mocha는 Node.js를 위한 테스트 프레임워크이다. test 스크립트가 변경되었을 때 계속 감시하면서 다시 mocha 테스트를 해주도록 Continuously Testing이 가능하도록 Nodemon을 적용해 본다


1) Mocha 와  Nodemon 설치하기 

  - mocha 설치

$ npm install -g mocha

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

... 중략 ...

npm http 200 https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz

C:\Documents and Settings\UserXP\Application Data\npm\mocha -> C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\bin\mocha

C:\Documents and Settings\UserXP\Application Data\npm\_mocha -> C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\bin\_mocha

mocha@1.8.1 C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha

├── growl@1.7.0

├── commander@0.6.1

├── diff@1.0.2

├── debug@0.7.2

├── ms@0.3.0

├── mkdirp@0.3.3

└── jade@0.26.3 (mkdirp@0.3.0)


  - nodemon 설치하기 

   + node.js를 기반으로 개발할  때 사용한다 

   + hang이 걸리면 자동으로 re-running 시켜준다

   + 여러 디렉토리를 감시할 수 있다 (--watch 옵션적용하면 내용 변경시 node auto restart)

$ npm install -g nodemon

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

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

npm http GET https://registry.npmjs.org/nodemon/-/nodemon-0.7.2.tgz

npm http 200 https://registry.npmjs.org/nodemon/-/nodemon-0.7.2.tgz

C:\Documents and Settings\UserXP\Application Data\npm\nodemon -> C:\Documents and Settings\UserXP\Application Data\npm\node_modules\nodemon\nodemon.js

nodemon@0.7.2 C:\Documents and Settings\UserXP\Application Data\npm\node_modules\nodemon



2) Mocha 테스트 코드 만들기

  - mocha가 수행되는 위치의 test 디렉토리밑의 .js 파일을 자동 테스팅한다

  - BDD 테스트 코드 

  - mocha 수행 

// test 디렉토리가 존재 

$ ls

test


// mocha 명령을 수행하여 test 디렉토리의 mocha_sample.js 를 자동 수행하여 준다 

$ mocha


  .


  1 test complete (3 ms)



3) nodemon으로 mocha 수행하기 

  - nodemon을 mocha 위치를 지정하여 준다 

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

// 정상 테스트 코드

$ nodemon "C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\bin\mocha"

7 Feb 21:24:52 - [nodemon] v0.7.2

7 Feb 21:24:52 - [nodemon] watching: d:\Development\mocha

7 Feb 21:24:52 - [nodemon] starting `node C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\bin\mocha`


  .


  1 test complete (3 ms)


7 Feb 21:24:52 - [nodemon] clean exit - waiting for changes before restart


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

// 코드를 수정하며 에러 발생

// indexOf(0) 을 indexOf(1) 변경

7 Feb 21:26:00 - [nodemon] starting `node C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\bin\mocha`


  .


  × 1 of 1 test failed:


  1) Array #indexOf() should return -1 when the value is not present:


  AssertionError: -1 == 0

      at Context.<anonymous> (d:\Development\mocha\test\mocha_sample.js:6:14)

      at Test.Runnable.run (C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\lib\runnable.js:213:32)

      at Runner.runTest (C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\lib\runner.js:343:10)

      at Runner.runTests.next (C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\lib\runner.js:389:12)

      at next (C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\lib\runner.js:269:14)

      at Runner.hooks (C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\lib\runner.js:278:7)

      at next (C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\lib\runner.js:226:23)

      at Runner.hook (C:\Documents and Settings\UserXP\Application Data\npm\node_modules\mocha\lib\runner.js:246:5)

      at process.startup.processNextTick.process._tickCallback (node.js:244:9)


7 Feb 21:26:01 - [nodemon] app crashed - waiting for file changes before starting...


  - 위의 명령을 넣고 C:\Documents and Settings\UserXP\Application Data\npm\cmocha.cmd 파일을 만든다

  - cmocha.cmd를 수행하면 위와 똑같이 수행위치 하단에 test 디렉토리가 있다면 continuous mocha를 수행한다 



<참조>

  - 원문 : Automating Testing with Mocha and WebStorm

  - Mocha 소개

posted by Peter Note
2013. 2. 7. 13:51 Middleware, Cloud/Linux

Linux의 CPU 갯수를 알아내는 명령어


  - 명령어 : grep processor /proc/cpuinfo | wc -l

  - 결과 : cpu core 8개

[jboss]$ grep processor /proc/cpuinfo | wc -l

8

[jboss]$ grep processor /proc/cpuinfo

processor       : 0

processor       : 1

processor       : 2

processor       : 3

processor       : 4

processor       : 5

processor       : 6

processor       : 7


posted by Peter Note

완벽한 자바스크립트 아키텍쳐는 어떻게 구성되는지를 NodeJS, Google Chrome Extention, MongoDB를 통하여 알아보자


1) 역할

  - NodeJS : 서버 측면, 실시간 연결을 장시간 유지하기 위하여 Socket.io 사용한다

  - Google Chrome Extention : 클라이언트 측면, WebSocket, Notification과 Local Storage가 사용된다

  - MongoDB : 데이터를 저장한다 



2) 아키텍쳐

  - 트윗을 추적하여 실시간으로 클라이언트에게 브로드케스팅 한다

  - 클라이언트 "What's Next"는 Google Chrom browser extension 이다 (크롬 애플리케이션)

  - HTML5의 기능을 사용한다 

  - MongoDB에 트윗 내역을 저장하고 이벤트가 끝나면 통계를 생성한다 

  


3) Node 아키텍쳐

  - V8 JavaScrpt engine 기반의 서버사이드 애플리케이션 개발을 위한 오픈소스 툴킷이다 

  - Node 기반 API는 CommonJS 모듈 시스템을 사용하여 확장한다

  - 2009년 2월 라이언 일병 (Ryan Dahl)이 만들었고, Python의 Twisted나 Ruby의 EventMachine과 유사하다 

  - Joyent에서 no.de Node.js 호스팅 준비하면 진행하고 있다


      



4) Node의 목적

  - 쉽고 안전한 방법으로 고성능이며 확장가능한 네트워크 프로그램을 JavaScript로 만드는 것이 목적이다 

  - 목적을 위하여 취한 아키텍쳐 

    + Single Threaded : Apache 처럼 각 요청마다 thread를 띄우지 않는다

       > 단일 스레드를 사용함으로 CPU context switching일 피할 수 있다

       > 메모리상에 대량의 실행 컨텍스트를(Execution Context) 두지 않아도 된다

    + Event Loop : Marc Lehman 씨가 libev 라이브러를 C++로 작성한 것을 이용함

       > 이벤트 루프는 확장가능한 이벤트 알림 메커니즘(scalable event notification)을 위하여 epool 또는 kqueue를 사용한다 

    + Noe blocking I/O : Marc lehmann 씨가 libeio 라이브러를 작성한 것을 이용함 

       > input 또는 output response에 대해서 (예로 database, file system, web service등) 기다리면서 CPU time losss를 피한다

    

  - 위 특징들로 인해 Node는 thread에 자유로우면서 대량의 트래픽을 처리할 수 있게 한다 

  - 대부분의 프로토콜에(TCP, DNS, HTTP) 대해서 이미 내장되어 지원한다

  - 모든 I/O 관련 function 수행은 callback을 사용해야 한다 

  - Event Driven 언어인 JavaScript는 Node의 'Event Loop' 방식 개발에 적합하고, 익명함수/클로져 같은 자바스크립강점을 이용

  - 참조 PDF

  - GitHub에서 가장 인기있는 OSS 목록

  - 설치는 사이트에서 다운로드 또는 http://nodejs.org/dist 목록 파일 버전을 선택에서 wget등 여러 방법으로 설치함 



5) Node 서버 만들기 

  - Node 단순 서버 만들기


  - Socket.io 단순 서버 만들기


  - http server에 socket.io 모듈을 붙여서 기능을 첨부하는 것이다. 

    + a = b  대입연산의 변환  b(a) funcational로 표현됨 (functional lanuage는 assignment 즉, 대입문이 필요없다

    + 대입문이 없으므로 대입변수를(variable) 메모리에 생성할 필요가 없이 function이 state를 안가진다. (참조)

  - http.createSever()에서 callback function을 제거했으므로 client 요청에 대한 처리를 하지 않고

     대신 이벤트가 발생하면 데이터를 바로 push 한다

  - socket.io에 callback을 넣으면 클라이언트 요청을 처리한다 

var socket = io.listen(server, function(client) { ... new client connection ... } );



6) 트위터 추적 모듈 만들기

  - Twitter Streaming API를 사용해서 "What's Next" 이벤트 틔윗을 받는다

  - API는 설정 메션에 대한 모든 트윗을 전달해 준다 

  - Twitter API 연결 -> 새로운 트윗 발견시 매번 이벤트 발생을 모듈로 만든다 


7) 트위터 추적하기 

  - Basic Authorization을 사용모듈


8) Twitter OAuth 설정하기 

  - 원문의 Basic Authorization을 사용하지 않고(2010.8.31 종료됨) OAuth를 사용한다

  - OAuth 모듈을 설치한다 

$ npm install oauth

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

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

npm http GET https://registry.npmjs.org/oauth/-/oauth-0.9.8.tgz

npm http 200 https://registry.npmjs.org/oauth/-/oauth-0.9.8.tgz

oauth@0.9.8 node_modules\oauth

  - https://dev.twitter.com/ 에 로그인하여서 Consumer Key, Request Token, Access Token을 만든다

  - OAuth를 적용한 코드를 다시 만들어 보자 (실천과제)



<참조>

  - 원문 : A Full Javascript Architecture, Part One - NodeJS

  - Twitter OAuth 설명글

  - Node.js + Express로 Twitter 보기

  - Twitter OAuth with node-oauth for node.js+express


posted by Peter Note
2013. 2. 2. 17:22 Dev Environment/Sublime Text

Syntax에 대한 highlight 기능을 위하여 Jade와 Stylus 플로그인을 설치한다 


1) Sublime Text의 Package 디렉토리로 이동

  - 위치 : Sublime Text의 메뉴에서 Preferences > Browse Packages... 선택하면 이동한다 

  - 해당 위치에서 플러그인을 설치한다 



2) Jade 플로그인 설치 

$ git clone https://github.com/miksago/jade-tmbundle.git Jade

Cloning into 'Jade'...

remote: Counting objects: 139, done.

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

remote: Total 139 (delta 59), reused 120 (delta 44)

Receiving objects: 100% (139/139), 18.63 KiB, done.

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


  - Jade 확장자 파일을 연다 

  - ctr+shift+p 에서 jade라고 타입핑하고 'Set Syntax: Jade' 선택하면 highlighting 된다 

  



3) Stylus 플러그인 설치 

$ git clone https://github.com/LearnBoost/stylus.git Stylus

Cloning into 'Stylus'...

remote: Counting objects: 15849, done.

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

remote: Total 15849 (delta 10322), reused 15R609 (delta 10117)eceiving objects

Receiving objects: 100% (15849/15849), 2.36 MiB | 121 KiB/s, done.

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

Checking out files: 100% (658/658), done.


  - styl 확장자 파일을 연다 

  - ctr+shift+p 에서 stylus라고 타입핑하고 'Set Syntax: Stylus' 선택하면 highlighting 된다 

  


<참조>

  - 원문 : http://stackoverflow.com/questions/7666977/syntax-highlighting-for-jade-in-sublime-text-2

posted by Peter Note
2013. 1. 31. 23:06 Languages/CoffeeScript

CoffeeScript 문법중에서 꼭 알아야 할 것들에서 정리한다. 


1) Variables

  - 변수 선언을 하지 않는다 : 자동으로 var 붙음 

  - 세미콜론 ; 을 쓰지 않는다 

  - () 넣는 것은 옵션이다

 

2) Function

  - Named Function 과 Function Expression이나 둘다 coffee(); 를 호출한다 

  - Named Function을 Function Expression으로 변환하여 표현한다 (참조)

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

// Named Function

function coffee() {

  return confirm('dowon');

}


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

// Function Expression

var coffee = function() {
  return confirm('dowon');
}

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

// CoffeeScript 변환 

1) var 제거 

2) function() 을 -> 변환

3) {..} 컬리브레이스 와 ; 세미콜론 제거 


coffee = -> 

  confirm 'dowon'


4) confirm 은 1 tab 또는 2 space 로 들여쓰기를 한다 

5) CoffeeScript는 항상 return value를 갖는다 

6) 컴파일 되면 Function Expression과 동일하다 


3) String 변환

  - #{...} 사용한다 

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

// CoffeeScript

coffee = ->

   answer = confirm 'dowon'

   "hi #{answer}"


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

// Function Expression

var coffee;

coffee = function() {

  var answer;

  answer = confirm('dowon');

  return "hi " + answer;

}


4) Function Parameters

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

coffee = ->    호출 : coffee()


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

// ( ) 넣는 것은 옵션

coffee = (message) ->     

   호출 : coffee("dowon") 또는 coffee "dowon"  


coffee = (message, other) ->   

   호출 : coffee("hi", 2)  또는 coffee "hi", 2 


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

// 파라미터 기본 할당

coffee = (message = "dowon") ->

   answer = confirm message

   "hi #{answer}"


호출 : alert coffee()  또는 alert coffee("youngsik")


5) CoffeeScript CLI (Command Line)

  - coffee -c test.coffee : test.js 컴파일 

  - coffee -cw test.coffee : 내역이 업데이트 될 때마다 재컴파일 

  - coffee -c src -o js : src 디렉토리에 있는 .coffee 파일을 컴파일해서 js 디렉토리로 옮긴다 

  - coffee -wc src -o js : 파일이 업데이트 되면 재컴파일 한다 


6) jQuery 사용하기 

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

// jQuery 원본 

jQuery(function($) {

   function changeTab(e) {

     e.preventDefault();

     $(#tabs li a.active").removeClass("active");

     $(this).addClass("active")

  }


  $("#tabs ul li a").click(changeTab);

});


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

// CoffeeScript 변환   

$ ->

  changeTab = (e) ->

     e.preventDefault()

     $(#tabs li a.active").removeClass "active"

     $(@).addClass "active"


   $("#tabs ul li a").click changeTab

  


  - jQuery(function($) {   ==>   jQuery ($) -> 또는 $ -> 

  - function changeTab(e)  ==>  changeTab = (e) -> 

  - ( ) 와 ; 생략 

  - this ==> @ 변환 



7) if 문

  - ( ) 과 { } 를 제거 한다

  - 한줄 표현시 수행 문구를 앞으로 놓을 수 있다

  - 한줄 표현시 수행 문구가 뒤로 가면 then을 사용한다 

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

// JavaScript 

if (age < 18) {

  alert('dowon');

}


// 1차 변환 

if age < 18 

  alert 'dowon'


// 2차 변환 

alert 'dowon' if age < 18


// 3차 변환

if age < 18 then alert 'dowon'


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

// if else 구문 

if (age < 18) {

  alert('yun');

} else {

  alert('dowon');

}


// 1차 변환

if age < 18

  alert 'yun'

else

  alert 'dowon'


// 2차 변환 

if age < 18 then alert 'yun' else alert 'dowon'


8) Operator 

  - 주로 if문에 많이 사용

  

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

// CoffeeScript 

if paid() and coffee() is on then pour()


// JavaScript 변환 

if(paid() && coffee() === true) {

  pour();

}


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

addCaffeine() if not Decaf()   ===  addCaffeine() unless Decaf()


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

// JavaScript

if(2 < dodo && dodo < 5) {

  alert('youngsik');

}


// CoffeeScript 1차 

if 2 < dodo < 5

  alert 'youngsik'


// 2차 

if 2 < dodo < 5 then alert 'youngsik'


9) Switch 문 변환 

  - case <조건>: 을 when <조건> then 으로 변환 

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

// JavaScript 

var message = (function() {

  switch(coffee) {

    case 0:

       return 'hi';

    case 1:

       return 'haha';

    default:

       return 'dowon';

  }

})();


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

// CoffeeScript 변환

message = switch coffee

   when 0 then 'hi'

   when 1 then 'haha'

   else 'dowon'


10) undefined 와 null 체크 하기 변환 

  - ? 로 변환 

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

// JavaScript

if (typeof coffee !== "undefined" && coffee !== null) {

  alert("dowon");

}


// CoffeeScript 1차 변환 

if coffee?

  alert "dowon"


// CoffeeScript 2차 변환

alert "dowon" if coffee?


11) Existential 연산 변환

  - if not 을 unless 변환

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

// null 또는 undefined 일 때 0 으로 설정

// 1차 

if not coffee?

  coffee = 0 


// 2차

coffee = 0 unless coffee?


// 3차 

coffee ?= 0 


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

// null 또는 undefined 아니면 호출하기 

// 즉, 그것이 존재하면 function을 호출

// 1차

if coffee?

   coffee.brew()


// 2차

coffee?.brew()


12) 배열 변환 

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

// 변수 할당

range = [1..4]  ==>  var range = [1, 2, 3, 4];


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

// 변수 할당 

range = [1...4]  ==> var range = [1, 2, 3];


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

// 변수 사용

start = 5

end = 10

range = [start..end]

          값 [5, 6, 7, 8, 9, 10]


range[1..4] 

          값 [6, 7, 8, 9]


range[1...range.length]  이것은 요것과 동일 range[1..-1]

          값 [6, 7, 8, 9, 10] 


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

// 배열 콤마 제거 

locations = ['seoul', 'kyunggi', 'jeju']

또는

locations = [

  'seoul'

  'kyunggi'

  'jeju'

]


13) Loop 문 변환 

  - forEach 문 사용

  - for .. in 문 사용 

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

// CoffeeScript

// forEach 문 

locations = ['seoul', 'kyunggi', 'jeju']

locations.forEach(location, index) ->

  alert "location: #{location}"


// for .. in 문 1차 

for location in locations

  alert "location: #{location}"


// for .. in 문 2차 

alert "location: #{location}" for location in locations


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

// JavaScript

locations.forEach(function(location, index) {

  return alert("location: " + location);

});


to be continue...

posted by Peter Note
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 Peter Note

웹애플리케이션을 개발하기 위한 최신 기술셋을 알아보자. 모바일 컨버전스 솔루션 또는 서비스를 개발하기 위하여 방향전환을 시도중이다. 14년을 Java만 사용하다가 이제 다시 Reset 하는 기분으로 스터디중이랄까... 기본 언어가 자바스크립트이기 때문에 틈틈히 언어 공부도 필요하다. 하기 작성된 목록은 원문의 내용중 눈에 띄는 것을 임으로 정리한 것이다. 


1) Node.js 

  - 생태계가 잘 갖추어져 가고 있다 : modulesresources

  - 특징 : single-threaded, event-driven, asychronous I/O JavaScript Server Framework 

  - twitter list 팔로잉해서 최신 정보를 받자 

  - Logging, Error Handling, Bootup&Restart, Hosting 등의 해결책을 제시하고 있다 


2) JavaScript 

  - Node를 하려면 기본적으로 숙달해 있어야 한다 (JavaScript: The Definition Guide 추천 - 번역서 나왔음 6th)

  - DailyJS 통하여 최신 정보도 숙지한다 


3) CoffeeScript

  - .coffee 확장자로 코딩하여 .js로 컴파일 된다

  - 코드가 깔끔해 지고 유지보수성이 높아진다 

  - CoffeeScript의 스타일 가이드 참조 (참조2)

  - JavaScript를 CoffeeScript로 전환 툴

  - cake.coffee 툴 : CoffeeScript로 작성한 make 버전이다. CLI 방식 호출 (참조)


4) MongoDB

  - NoSQL : JSON방식 데이터 통신, 저장은 BSON(Binary JSON) 형태, JavaScript언어로 제어 

  - Replication Set 을 통한 High Availability 제공

  - Sharding을 통한 Scale-out을 제공

  - Aggregation Framework을 통하여 Big Data 제어 


5) Web Application 개발

  - Node에서는 Jade(Template Engine)사용, CSS는 stylus 사용함 

  - jQuery 기본 사용

  - UI MV* Framework으로 Backbone.js가 대세 - underscore.js를 기본사용함 -

  - Express : Node 에서 기본사용하는 MVC Framework - REST Web Services 개발함 - 


6) Testing 

  - Jasmine : BDD 

  - Vows : 비동기 BDD

  - QUnit : jQuery Javascript library


7) 통합 해주는 것들 

  - Express 개발할 때 : Express Wiki

  - CoffeeScript, Express, Jade, Stylus에 대한 boilerplate 코드 생성 : Cham

 

8) 추가적인 것들

  - socket.io : 실시간 구현

  - meteor : 실시간 서버 프레임워크 

  - 모바일 프레임워크 : PhoneGap


위의 내용들이 대충 눈에 들어오면 SKT의 CornerStone Framework을 내가 생각하는 모바일 컨버전스 솔루션이나 서비스에 접목 시켜 볼까 한다. 맨땅에 해딩하지 말고 이미 만들어진 것을 사용 목적에 맞게 수정하여 써보는 방향을 택한다. 실력이 된다면 기여자가 되보고 싶다. 



<참조>

  - 원문 : Getting Started With Node.js, Coffeescript, MongoDB, and More

posted by Peter Note
2013. 1. 31. 10:08 Dev Environment/Build System

Grunt의 API를 사용하여 Task를 만들어 보자. Grunt의 Task가 핵심으로 한개를 수행하거나 여러개를 동시에 수행할 수도  있다. 


1) Task 별칭 등록하기 

  - grunt.registerTask 로 Task의 별칭을 지정한다

    + api : grunt.registerTask(taskName, taskList)

    + 예 : task.registerTask('default', 'lint qunit concat min'); 

    + grunt 수행시 특정 task를 지정하지 않으면 자동으로 default 별칭의 task가 수행된다 


2) Function Task 만들기

  - grunt.regiterTask 로 Task를 신규로 만들 수 있다

    + api : grunt.registerTask(taskName, description, taskFunction)

    + description, taskFunction을 파라미터로 넘기면 새로운 task 등록됨 

    + fail이 나면 return false 를 해야 한다 

//////////////////////////////////////////////
// grunt.js 환경파일에 등록한다 
  grunt.registerTask('dowon', 'A sample task that logs stuff.', function(arg1, arg2) {
    if (arguments.length === 0) {
      grunt.log.writeln(this.name + ", no args");
    } else {
      grunt.log.writeln(this.name + ", " + arg1 + " " + arg2);
    }
  });

//////////////////////////////////////////////
// 결과
// 아규먼트 없을 때
D:\Development\testing_grunt>grunt.cmd dowon
Running "dowon" task
dowon, no args
Done, without errors.

// 아규먼트 전달 : 이용 
D:\Development\testing_grunt>grunt.cmd dowon:hello:youngsik
Running "dowon:hello:youngsik" (dowon) task
dowon, hello youngsik
Done, without errors.


3) Multi Task 만들기 

  - grunt.registerMultiTask 를 이용하여 만든다

    + api : grunt.registerMultiTask(taskName, description, taskFunction)

    + lint, concat, min task등이 multi task이다 

    + sub-properties (별칭 targets) 이 내부적으로 task가 된다

    + multi task에서는 function에서 특별히 this 키워드를 사용하여 접근한다 

  - grunt.initConfig 안에 target을 만든다 객체명칭 = multi task의 대표 명칭이다 

    + 하기 예제에서 logstuff 가 multi task의 대표명칭이다 

    + grunt.registerMultiTask의 첫번째 아규먼트인 multi task 명칭을 logstuff 로 일치시킨다 

    + 등록한 function에서 this 함에 주의*

//////////////////////////////////////////////
/*global config:true, task:true*/
grunt.initConfig({
  logstuff: {
    foo: [1, 2, 3],
    bar: 'hello world',
    baz: false
  }
});

grunt.registerMultiTask('logstuff', 'This task logs stuff.', function() {
  // this.target === the name of the target
  // this.data === the target's value in the config object
  // this.name === the task name
  // this.args === an array of args specified after the target on the command-line
  // this.flags === a map of flags specified after the target on the command-line
  // this.file === file-specific .src and .dest properties

  // Log some stuff.
  grunt.log.writeln(this.target + ': ' + this.data);

  // If data was falsy, abort!!
  if (!this.data) { return false; }
  grunt.log.writeln('Logging stuff succeeded.');
});

//////////////////////////////////////////////
// 결과
// target을 지정하지 않았을 때는 전체 target이 수행
D:\Development\testing_grunt>grunt.cmd logstuff
Running "logstuff:foo" (logstuff) task
foo: 1,2,3
Logging stuff succeeded.

Running "logstuff:bar" (logstuff) task
bar: hello world
Logging stuff succeeded.

Running "logstuff:baz" (logstuff) task
baz: false
 Task "logstuff:baz" failed. Use --force to continue. 

Aborted due to warnings.

// foo target을 지정
D:\Development\testing_grunt>grunt.cmd logstuff:foo
Running "logstuff:foo" (logstuff) task
foo: 1,2,3
Logging stuff succeeded.

Done, without errors.

// bar target을 지정 
D:\Development\testing_grunt>grunt.cmd logstuff:bar
Running "logstuff:bar" (logstuff) task
bar: hello world
Logging stuff succeeded.

Done, without errors.

// baz target에서 false return하면서 warning 발생함 
D:\Development\testing_grunt>grunt.cmd logstuff:baz
Running "logstuff:baz" (logstuff) task
baz: false
 Task "logstuff:baz" failed. Use --force to continue. 

Aborted due to warnings.


4) Init Task 만들기 

  - api : grunt.registerInitTask(taskName, description, taskFunction)

    +최초에 수행되는 init task를 수행하고 별도의 환경 설정 데이터도 필요없다 


5) Task명칭 바꾸기 

  - api : grunt.renameTask(oldname, newname)



6) Inside Tasks 알아보기 

  - grunt의 this 에는 여러 유용한 properties 와 method를 가지고 있다. grunt.task.current 로 expose 한다 

  - Task에서 구현하는 function에서 사용한다 

  - this.async / grunt.task.current.async

    + task를 비동직적으로 수행시켜 준다 

//////////////////////////////////////////////
// Tell grunt this task is asynchronous.
var done = this.async();
// Your async code.
setTimeout(function() {
  // Let's simulate an error, sometimes.
  var success = Math.random() > 0.5;
  // All done!
  done(success);
}, 1000);


  - this.requires / grunt.task.current.requires : 의존관계있는 task를 열거

  - this.requiresConfig / grunt.task.current.requiresConfig : config properties 열거 

  - this.name / grunt.task.current.name : 등록된 task 명칭 

  - this.nameArgs / grunt.task.current.nameArgs : grunt뒤의 아규먼트들 예) grunt.cmd task1:foo  -> task1:foo 

  - this.args / grunt.task.current.args : task명칭을 뺀 실제 아규먼트값을 배열로 리턴

  - this.flags / grunt.task.current.flags : 아규먼트를 만들어준다 

  - this.errorCount / grunt.task.current.errorCount : task에서 발생한 에러건수 


7) Indside Multi Tasks 알아보기 

  - this.target / grunt.task.current.target : multi task에서만 사용. config data로 등록된 key (name) 값 

  - this.data / grunt.task.current.data : multi task에서만 사용. config data로 등록된 value 값

  - this.file / grunt.task.current.file : compact format 사용시 this.file.src , this.file.dest 가 만들어진다 (template api 참조)



8) 외부에서 정의된 Task 로딩하기 

  - 큰 프로젝트에서 sub 프로젝트끼리 공유하기 위하여 task와 helper 들을 만든다 

  - 여러 디렉토리에서 task를 로딩하거나 또는 Npm-installed grunt plugin 을 로딩한다 

  - task 관련 파일들 로딩하기 

    + api : grunt.loadTasks(tasksPath)

  - task와 helper 로딩하기 

    + api : grunt.loadNpmTasks(pluginName)

  - npm module 호출 

    + api : grunt.npmTasks(npmModuleName)



9) Helper 정의하고 실행하기 

  - 이미 만들어지 helper들 존재 (참조)

  - helper 만들기 

    + api : grunt.registerHelper(helperName, helperFunction)

//////////////////////////////////////////////
grunt.registerHelper('add_two_nums', function(a, b) {
  return a + b;
});

  - helper 이름 바꾸기 

    + api : grunt.renameHelper(oldname, newname)


  - helper 호출하기 

    + api : grunt .helper(helperName, [, agruments...])



10) Warning 과 Fatal Error

  - api 호출하여 화면에 출력 한다 

  - grunt.warn(error [, errorCode])

  - grunt.fatal(error [, errorCode])



<참조>

  - Grunt API

posted by Peter Note