[Spring Junit] Transaction Rollback with Junit

[Spring Junit] Transaction Rollback with Junit
JUnit 테스트시에 DB설정은 다음과 같다.


  1. DataSource 설정
  2. Transaction 설정 
  3. Junit 테스트 수행. 

이때 DB에 입력 및 삭제 테스트를 진행하면 실제로 데이터가 DB로 입력되거나, 삭제가 발생한다.
이를 선택적으로 수행할 수 있는 방법은 다음과 같다.

@Log4j
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {
DBConfiguration.class
})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional
Bla... Bla... TestCodes.....

상기 코드에서 @TransactionConfiguration 부분의 프로퍼티 값으로 2가지 설정을 해준다.

  • transactionManager : 어느 트랜잭션매니저를 이용할 것인지 기술한다. 
  • defaultRollback : 기본 롤백 정책을 입력한다. (true : 롤백진행, false : 롤백없이 바로 CUD진행)
그리고 중요한 것은 @Transactional을 꼭 입력해야한다는 사실..
이 어노테이션은 해당 테스트가 트랜잭션 하에서 수행하게 할 것인지 지정해주는 것이니...
당. 연. 히 넣어주는 쎈스. 


[Java] Static Import 즉, 정적 import를 왜 하는가?

[Java] Static Import 즉, 정적 import를 왜 하는가?

Static Import

from : http://docs.oracle.com/javase/1.5.0/docs/guide/language/static-import.html

static 멤버에 접근하기 위해서 우리는 Qualify 하게 레퍼런스를 참조해야한다. 이 멤버가 어디에서 왔는지 지정하기 위해서 필요하다.
예를 들면 다음과 같다.
double r = Math.cos(Math.PI * theta);
이를 위해서 사람들은 정적 멤버를 인터페이스에 기술하고, 이 인터페이스를 상속 받는다. 그러나 이것은 좋은 방법이 아니다. 사실 이런 나쁜 방법들에는 그것을 위한 이름이 있다. Constant Interface Antipattern( Effective Java Item 17참조). 이 문제가 되는 것은 다른 클래스의 정적 멤버를 사용하는 클래스는 상세 구현의 일부라는 것이다. 클래스가 인터페이스를 구현할때 이것은 클래스의 public API의 부분이 된다. 구현의 상세는 공개 API에 노출 되어서는 안된다.

static import 생성자는 정적 멤버에 대해서 qualified 하지 않아도 되며, 정적 멤버를 포함하고 있는 타입으로 부터 상속을 받지 않아도 된다. 대신에 프로그램은 멤버를 임포트 할 수 있다.

import static java.lang.Math.PI;
혹은
import static java.lang.Math.*;
를 이용할 수 있다.
그리고 정적 임포트를 통해서 정적 멤버에는 다음과 같이 qualification을 사용하지 않고 이용가능하다.
double r = cos(PI * theta);
정적 import 선언은 일반적인 import와 유사하다.
normal import 선언은 클래스를 package로 부터 임포트한다. 이는 패키지의  qualification없이 사용가능하도록 해준다.

정적 import선언은 클래스로 부터 정적 멤버를 임포트 한다. 이는 클래스의 qualification없이 사용 가능하도록 해준다.

언제 static import를 이용할까? 매우 드물게 (Very sparingly!). 오직 상수의 로컬 복사를 시도하는 경우 혹은 상속을 통해서 어뷰징 하고 있을때 (the Constant Interface Antipattern) 사용한다. 다른  말로 하나 혹은 두개의 클래스에서 정적 멤버를 빈번하게 접근해야할때 이용한다. 만약 static import 기능을 남용하면 코드를 매우 읽기 어렵게 하고, 유지보수 하기 어렵게 한다. namespace를 오염 시켜버리게 된다.
코드를 읽는 독자들은 정적 멤버들이 어디서 왔는지 알지 못하게 될 것이다. 클래스로 부터 정적 멤버 전체를 임포트 하는 것은 읽기를 어렵게 할 수 있다. 만약 하나 혹은 2개의 멤버를 이용하고자 한다면 그것들을 각각 이용하기 바란다.

적절하게만 사용한다면 static import는 당신을 코드를 더 읽기 쉽게 할 수 있으며, 클래스 이름을 중복으로 쓰는 boilerplate한 코드를 제거할 수 있다.

















[IntelliJ] IntelliJ에서 정적 Import 설정하기.

InttlliJ 정적 Import 설정 


테스트 코드를 작성하다보면 정적 import처리에서 애를 먹는다.
주로 등록해서 사용하는 패키지를 나열해본다.

org.hamcrest.Matchers
org.hamcrest.CoreMatchers
org.junit
org.junit.Assert
org.junit.Assume
org.junit.matchers.JUnitMatchers
IntelliJ에서는 어떻게 설정하는지 찾아보자.
참고로 Eclipse에서는 링크 참조.

설정방법 : 

Cmd + , 혹은 상단 메뉴인 IntelliJ IDEA > Preference 를 클릭한다.

검색창에서 "Code Style" 로 검색한다.
그러면 Editor > Code Style 가 검색이 된다. (직접 찾아가도 된다.)

Java를 클릭하고. Package to Use Import with '*' 부분에서 '+' 버튼을 클릭한다.

상기 나열된 패키지를 하나씩 등록한다.
(이때 Static 체크 박스를 체크하면 정적 import가 된다.)

이제 소스에서 자동완성을 클릭하면 원하는 정적 import가 자동으로 삽입된다.


끝 ~




[Sublime Text] Babel Package 추가하기

Install Babel Syntext Package on Sublime Text

React를 사용할때 간단한 에디터 툴로 Sublime Text를 이용하는 경우가 많다.
테스트를 할때든, 공부를 할때든 Sublime Text는 좋은 툴이다.

React 문법을 이쁘게 보여주거나, 자동완성을 위한 Sublime Text 패키지가 있어 설치방법을 소개한다.
설치방법은 다음과 같이 선택할 수 있다.

  • Sublime React
  • Babel Sublime
여기서는 Babel Sublime만을 설치한다. 사실 Babel이 더 보기가 이쁘고 좋다. 


Sublime Text에서 패키지 Controller 설치하기. 

패키지 컨트롤러를 설치하는 가잔 간단한 방법은 Sublime Text console에서 명령어를 이용하여 설치하는 방법이 있다.

sublime에서 Ctrl + ` 를 누르거나
View > Show Console 메뉴를 선택한다.

창이 열리면 다음 설치 명령어를 입력한다.
Sublime Text 3용  :
import urllib.request,os,hashlib; h = '2915d1851351e5ee549c20394736b442' + '8bc59f460fa1548d1514676163dafc88'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)
Sublime Text 2용 : 
import urllib2,os,hashlib; h = '2915d1851351e5ee549c20394736b442' + '8bc59f460fa1548d1514676163dafc88'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None; urllib2.install_opener( urllib2.build_opener( urllib2.ProxyHandler()) ); by = urllib2.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); open( os.path.join( ipp, pf), 'wb' ).write(by) if dh == h else None; print('Error validating download (got %s instead of %s), please try manual install' % (dh, h) if dh != h else 'Please restart Sublime Text to finish installation')
설치가 자동으로 완료 된다.

문제가 있다면 다음 사이트에서 설치 명령어를 다시 확인하자.

만약 오류가 있다면 Sublime Text를 닫았다가 다시 열고 명령어를 한번더 입력해보자.

Babel Sublime 설치하기. 

Cmd + Shift + P를 선택한다.
입력창에서 Package Controll: Install Package 를 선택한다.



여기서 Babel을 찾아서 설치한다.

설치 이후에는 다음과 같이 Babel 신텍스를 선택한다.


변경된 내용을 확인해보자.
신텍스가 정상으로 동작함을 확인할 수 있다.



더 자세한 설정을 원하면 다음 사이틀르 찾아가자.
https://github.com/babel/babel-sublime










[handlebars] Reference

[handlebars] Reference

Base

from : http://handlebarsjs.com/reference.html

Handlebars.compile(template, options)

template 을 컴파일 하는 작업은 다음과 같이 수행하면 즉시 수행된다.
var template = Handlebars.compile('{{foo}}');
template({});

  • template : 를 수행할때 어떻게 수행할지에 대한 다양한 옵션들이 다음과 같이 있다. 
  • data : false로 설정하면 @data 트래킹을 disable한다. 
  • compat : true로 설정하면 recursive 필드 룩업을 수행한다. 
  • knownHelpers : Hash로 헬퍼의 리스트를 포함하고 있다. 이는 템플릿이 실행되는 타임에 존재하는지 파악하게 된다. 이때 이 값을 전달하면 옵티마이즈된 결과로 컴파일러가 컴파일한다. 내부 헬퍼는 자동적으로 포함되어진다. 값을 false로 설정하는 것으로 제거 할 수 있다. 
  • knownHelpersOnly : true로 설정하면 알려진 헬퍼의 리스트를 기반으로 최적화 한다. 
  • noEscape : true로 설정하면 어떠한 내용도 escape하지 않는다. 
  • strict : strict모드로 실행한다. 이 모드에서는 템플릿은 유실된 필드에 대해서 무시하지 않고 오류를 던진다. 이것은 {{^foo}}{{/foo}} 와 같은 inverse오퍼레이션을 disable하는 사이드 이펙트가 있다. 그렇지 않으면 소스 객체내에서 명시적으로 포함된다. 
  • assumeObjects : path를 트래버싱 할때 체크된 객체를 제거한다. 이는 strict모드의 서브셋이며, 데이터 입력들이 안전하다고 판단되면 옵티마이즈된 템플릿을 생성한다. 
  • preventIndent : 기본적으로 인덴트된 partial콜을 수행한다. 이는  pre태그를 patial이 작성할때 기대하지 않는 행동을 하는 것을 막아준다. 이 옵션을 true로 지정하면 auto-indent 기능이 disable된다. 
  • ignoreStandalone : true로 지정하면 standalone태그를 제거하는 작업을 disable하게 한다. block과 partial에 설정하면 이는 해당 라인에서 공백을 제거하지 않는다. 
  • explicitPartialContext : partial을 위한 컨텍스트를 disable한다. enabled된 경우 partial은 컨텍스트 값이 전달되지 않으며 비어있는 객체로 실행이 된다. 

Handlebars.precompile(template, options) 

주어진 템플릿을 precompile한다. 이를 통해서 클라이언트에 전달하게 되면 클라이언트는 컴파일 없이 수행된다.
var templateSpec = Handlebars.precompile('{{foo}}');
이는 Handlebars.compile에서 제공하는 모든 옵션을 이용할 수 있다. 추가적으로 다음 값을 전달할 수 있다.

  • srcName : 입력 파일을 위한 소스 맵을 생성하기 위해 전달한다. 이 방법으로 수행이 되면 반환되는 구조는 {code, map}으로 code에는 템플릿 정의가, map에는 소스 맵이 들어간다. 
  • destName : 선택적인 파라미터로 srcName과 결합된다. 이는 소스 맵을 생성할때 목적지 파일 이름을 제공한다. 

Handlebars.template(templateSpec)

Handlebars.precompile와 함께 precompile된 템플릿을 설정한다. 
var template = Handlebars.template(templateSpec);
template({});

Handlebars.registerPartial(name, partial)

environment 에서 특정 템플릿에 의해 접근 가능한 partial을 등록한다.
Handlebars.registerPartial('foo', partial);

또한 한번에 복수개의 partial을 등록할 수 있다.
Handlebars.registerPartial({
    foo: partial,
    bar: partial
});
전체 라이브러리가 모두 로딩되면 partial은 필요한경우 컴파일 될 것이다. 만약 실행타임에 로딩하는 경우라면 partial은 사전에 컴파일된 템플릿 이어야한다. 이는 Handlebars.template 메소드를 이용하여 적절하게 설정할 수 있다.

Handlebars.unregisterpartial(name)

이전에 등록한 partial을 등록 해제한다.
Handlebars.unregisterPartial('foo');

Handlebars.registerHelper(name, helper)

environment에서 특정 템플릿에 의해서 접근할 수 있는 헬퍼를 등록한다.
Handlebars.registerHelper('foo', function() {
});
또한 복수개의 헬퍼를 한번에 등록할 수 있다.
Handlebars.registerHelper({
    foo: function() {
    },
    bar: function() {
    }
});

Handlebars.unregisterHelper(name)

사전에 등록된 헬퍼를 등록 해제한다.
Handlebars.unregisterHelper('foo');

Handlebars.registerDecorator(name, helper)

environment에서 특정 템플릿에서 접근이 가능한 decorator를 등록한다.
Handlebars.registerDecorator('foo', function() {
});
또한 한번에 decorator를 여러개 등록할 수 있따.
Handlebars.registerDecorator({
    foo: function() {
    },
    bar: function() {
    }
});

Handlebars.unregisterDecorator(name)

이전에 등록된 decorator를 해제한다.
Handlebars.unregisterDecorator('foo');

Handlebars.SafeString(string)

template가 렌더된경우 스트링이 escape되는 것을 막는다.
new Handlebars.SafeString('<div>HTML Content!</div>')
스트링이 생성될때 safe로 마크된다. 다른 외부 컨텐츠는 handlebars.escapeExpression메소드를 이용하여 escape된다. 이는 잠재적인 보안적인 문제를 회피한다.

Handlebars.escapeExpression(string)

전달된 스트링의  HTML을 escape한다. 이는 HTML컨텐츠에서 text렌더링시 안전하게 수행한다.
 Handlebars.Utils.escapeExpression(string)
 &<>"'`=
상기 엔티티는 적합한 값으로 변경이 된다. SafeString 값은 수정되지 않고 남아 있는다.

triple braced 표현식 {{{ }}} 을 제외하고 모든 표현식은 이 메소드를 통과하게 되어 있다. 추가적으로 헬퍼들은 이 메소드를 이용하여 SafeString  을 통과한 HTML컨텐츠를 안전하게 처리한다. 이는 code injection 가능성을 막아준다.

이 메소드는 Handlebars.Utils.escapeExpression 로 alias되어 있다.

Handlebars.createFrame(data)

block helper에 의해서 사용되며, 자식 데이터 객체를 생성한다.
if (options.data) {
    var data = Handlebars.createFrame(options.data);
    data.foo = 'bar';
    options.data = data;
}
헬퍼들은 데이터 스테이트를 변경하며 이때 새로운 프레임을 생성한다. 이때 그 자체로 고립된 상태로 그리고 다른 부모의 상태를 깨트리지 않고자 하는경우 새로운 프레임을 생성한다. 일반적으로 하나의 헬퍼가 수행될때 오직 하나의 프레임만 생성될 필요가 있다. each iterator은 오직 하나의 프레임을 생성하며 이는 모든 자식들이 수행될때 재사용 된다.

Handlebars.create()

고립된 핸들바스 환경을 생성한다.
var OtherHandlebars = Handlebars.create();
각 환경은 자신의 헬퍼들과 partials를 가진다. 이것은 구별되는 헬퍼와 partials가 필요한 케이스에서 사용하기 위해 필요하다. 대부분의 유즈케이스는 root Handlebars 환경을 직접적으로 사용할 수 있다.

주어진 환경에 대해서 생성된 템플릿은 해당 환경에 연결이 된다. 이 의미는 복수의 환경에서 수행될 필요가 있는 템플릿들은 Handlebars.template 를 이용하여 매 환경마다 새롭게 컴파일하고 생성되어야할 필요가 있다는 의미이다. 이것은 partial에도 동일하게 적용된다.

Handlebars.noConflict()

Handlebars 인스턴스를 글로벌 스페이스에서 제거하고, 이전에 등록되어진 다른 라이브러리를 저장한다.
var myHandlebars = Handlebars.noConflict();
이는 버젼 충돌에 대한 고민없이 글로벌에 로드된 라이브러리의 구분되는 버젼을 이용하도록 해준다.

Handlebars.log(level, message)

log헬퍼에 의해서 로거 기능을 사용하도록 해준다.
필요하다면 오버라이드 된다.

Utilities

Handlebars는 다양한 유틸리티 메소드를 제공하며 Handlebars.Utils객체를 통해서 사용가능하다.

Handlebars.Utils.isEmpty(value)

주어진 값이 비어있는지 확인한다.
Handlebars.Utils.isEmpty(value)
이는 if와 with헬퍼에서 사용되며 해당 컨틀로 플로우를 결정하기 위해 사용된다. Handlebar의 empty에 대한 정의는 다음과 같다.

  • 길이가 0인 배열
  • false성격의 값이나 0

Handlebars.Utils.extend(obj, value)

단순한 유틸리티 메소드로 아규먼트 obj 객체에 특정 키와 값으로 구성된 value를 적용한다.
Handlebars.Utils.extend(foo, {bar: true})
이는 객체 foo에 키가 bar인 값을 세팅하며 그 값은 true이다.

Handlebars.Utils.toString(obj)

일반적인 toString메소드이다.

Handlebars.Utils.isArray(obj)

객체가 배열인지 검사한다.

Handlebars.Utils.isFunction(obj)

객체가 함수인지 검사한다.

@data Variable

다음 @data 변수는 Handlebars와 내장된 헬퍼에 의해서 구현되었다.

@root

초기화된 컨텍스트로 템플릿이 수행된 것이다.
{{#each array}}
    {{@root.foo}}
{{/each}}
명시적으로 변경하지 않는한 이 값은 모든 페이지 렌더링에서 일관적으로 동작한다. 이 의미는 사용된 partials가 depth로된 파라미터를 통해서 그들의 부모 템플릿을 참조 할 수 없다는 것이다.

@first

각 iteration이 첫번째 엘리먼트인경우에만 해당 헬퍼가 수행된다.
{{#each array}}
    {{#if @first}}
        First!
    {{/if}}
{{/each}}

@index

0기반의 인덱스이며 이는 현재 스텝의 인덱스를 나타난다. 이는 each헬퍼에 의해서 설정한다.
{{#each array}}
    {{@index}}
{{/each}}

@key

현재 반복 스텝의 엘리먼트의 키 이름을 나타낸다. 이는 each헬퍼에 의해서 설정된다.
{{#each array}}
    {{@key}}
{{/each}}

@last

each헬퍼에 의해서 설정하며 iteration스텝의 마지막 스텝을 의미한다.
{{#each array}}
    {{#if @last}}
        Last :(
    {{/if}}
{{/each}}

@level

로그 레벨을 할당한다.
template({}, {data: {level: Handlebars.logger.WARN}})
 로그레벨은 다음과 같다.

  • Handlebars.logger.DEBUG
  • Handlebars.logger.INFO
  • Handlebars.logger.WARN
  • Handlebars.logger.ERROR

로거를 통한 로그 출력은 Handlebars.logger.level에 설정된 값 이상인경우에 출력된다.
기본값은 error모드로 설정된다.











[Tabata Training] 타바타 트레이닝이란?

[Tabata Training] 타바타 트레이닝이란?
일반적으로 운동은 지속적으로 오랫동안 해야한다고 알려져 있다.

아마도 운동을 함으로써 힘의 증가, 살 빼기, 유연성 증가, 근육 키우기 등을 목표로 할 것이다.
대부분의 운동 프로그램은 가능한 오랫동안 고정적인 플랜으로 운동을 하라고 한다.
그러나 이러한 운동은 오랜 시간 그리고 지루함, 무엇보다 지속적으로 하기가 어려운 단점이 있다.

연구끝에 Tabata라는 새로운 운동 방법이 등장하였고, 이는 high-intensity interval training (HIIT)로 불리는 운동이다.

Tabata의 역사 : 

Tataba트레이닝은 일본의 과학자 Izumi Tabata와 그의 연구팀에 의해서 도쿄에 있는 National Insitute of Fitness and Sport 연구소에서 탄생하였다.

Tabata와 그의 팀은 2개의 팀으로 나누어 연구를 하였고
첫번째 그룹은 평이한 강도의 운동을 하고, 두번째 그룹은 고강도의 운동을 하도록 나누었다.

첫번째 그룹

  • 매주 5일 운동, 6주간 수행
  • 평이한 강도의 운동
  • 매 운동은 1시간 수행

두번째 그룹

  • 매주 4일 운동, 6주간 수행
  • 고강도 운동
  • 매 운동은 4분동안 수행하며 20초 운동 10초 휴식을 반복.

운동의 결과
첫번째 그룹

  • 에어로빅 시스템 향상 (cardiovascular 심폐)
  • 비 에어로빅 시스템 (muscle 근육)은 작거나 변화 없음


두번째 그룹

  • 첫번재 그룹보다 더 향상된 에어로빅 시스템
  • 비 에어로빅 시스템 28% 향상

즉 결론은  HIIT (고강도 인터벌 트레이닝)이 에어로빅 시스템과 비 에어로빅 시스템 둘다에 더 큰 효과가 있음을 보였다.

Tabata 프로그램

각 훈련은 오직 4분간만 수행한다. 그러나 주어진 4분동안 최대한 극복하여 운동을 수행해야한다.
타바다 프로그램은 다음과 같다.

  • 20초동안 고강도로 운동
  • 10분 휴식
  • 8라운드 반복

20초동안은 본인이 생각하기에 가능하면 더 힘들고 어렵게 운동을 하고, 10초를 쉰다 이것이 한 세트이다. 이렇게 해서 8세트를 수행한다.

그리고 이러한 훈련에서 원하는 어떠한 운동이든 상관없다.
스쾃, 푸시업, 버핏 혹은 다른 대근육을 키우는 운동을 수행한다. 케틀벨 운동역시 매우 좋다.

Tabata 프로그램 운동은 다음과 같이 할 수 있다. 

  1. Push-ups (4분)
  2. Bodyweight Squats (4분)
  3. Burpeets (4분)
  4. Mountain Climbers (4분)

푸시업을 시작으로 20초동안 수행하고 10초 쉬기를 한다. 그리고 다시 20초동안 푸시업을 한다. 8세트를 끝내고 나면 1분을 쉰다.

다음으로 스쾃을 동일하게 반복한다. 끝나고 나면 1분을 쉬고, 다시 버핏을 한다. 그리고 마운틴 클라이밍을 수행한다.

Tabata는 짧은 시간에 매우 신속하게 수행하는 운동이다. 인내성과 스피드를 향상시키기를 원한다면 루틴을 변경하면 된다.

Tabata Workouts and Exercises 샘플 : 




[handlebars] Built-In Helpers

[handlebars] Built-In Helpers
from : http://handlebarsjs.com/builtin_helpers.html

The if block helper

if헬퍼를 이용하여 조건에 따라 블록을 렌더할 수 있다. 만약 아규면트가 false, undefined, null, "", 0혹은 []을 반환하는 경우 Handlebars는 블록을 렌더하지 않는다.
<div class="entry">
    {{#if author}}
        <h1>{{firstName}} {{lastName}}</h1>
    {{/if}}
</div>
비어있는 ( {} )컨텍스트를 이용하였다면 author은 undefined로 되며 결과는 다음과 같다.
<div class="entry">
</div>
block expression을 이용하는경우 expression이 false와 같은 값을 반환하는 경우 특정 템플릿 섹션을 실행할수 있다. 섹션은 {{else}}로 된 부분이며 이는 "else section"이라 부른다.
<div class="entry">
    {{#if author}}
        <h1>{{firstName}} {{lastName}}</h1>
    {{else}}
        <h1>Unknown Author</h1>
    {{/if}}
</div>

The unless block helper

unless블록을 이용하여 if헬퍼의 inverse 처리를 할 수 있다. 이 블록은 만약 표현식이 false 값인경우 렌더링한다.
<div class="entry">
    {{#unless license}}
    <h3 class="warning">WARNING: This entry does not have a license!</h3>
    {{/unless}
</div>
만약 현재 컨텍스트에서 license를 살펴보고 결과가 false 값이라면 핸들바스는 warning을 렌더링한다. 그렇지 않은경우 렌더링 하지 않는다.

The each block helper

each를 이용하여 반복을 처리할 수 있다. 블록 내부에서는 this를 이용하여 각 엘러먼트를 레퍼런스 할수 있다.
<ul class="people_list">
    {{#each people}}
        <li>{{this}}</li>
    {{/each}}
</ul>
컨텍스트는 다음과 같다.
{
    people: [
        "Yehuda Katz",
        "Alan Johnson",
        "Charles Jolley"
    ]
}
결과는 다음과 같다.
<ul class="people_list">
    <li>Yehuda Katz</li>
    <li>Alan Johnson</li>
    <li>Charles Jolley</li>
</ul>
this 표현식을 이용하여 특정 컨텍스트를 현재 컨텍스트를 기준으로 참조할 수 있다.

또한 선택적으로 {{else}} 섹션을 제공하여 리스트가 비어있는경우 처리를 할 수 있다.
{{#each paragraphs}}
    <p>{{this}}</p>
{{else}}
    <p class="empty">No content</p>
{{/each}}
 추가적으로 객체를 위한 iteration은 {{@key}} 를 통해서 현재 key를 참조할 수 있다.
{{#each object}}
    {{@key}}: {{this}}
{{/each}}
iterator의 첫번째와 마지막 스텝은 @first와 @last를 통해서 접근이 가능하다.

중첩된 each블록은 path를 기반으로 깊이값을 통해서 반복에 접근할 수 있다. parent인덱스에 접근하기 위해서는 {{@../index}}를 이용할 수 있다.

each헬퍼는 또한 block parameters를 제공한다. 이는 이름 지어진 참조를 블록 내부 어디서든지 접근하게 해준다.
{{#each array as |value key|}}
    {{#each child as |childValue childKey|}}
        {{key}} - {{childKey}}. {{childValue}}
    {{/each}}
{{/each}}
이는 key와 value변수를 생성하고 자식은 depth 변수를 참조하지 않고서도 접근이 가능하다. 이 예제에서는 {{key}}는 {{@../key}}를 나타낸다. 그러나 많은 케이스에서 더 읽기 쉽다.

The with Block Helper

보통 핸들바스 템플릿은 컴파일된 메소드로 전달된 컨텍스트에 대해서 처리를 수행한다.
var source = "<p>{{lastName}}, {{firstName}}</p>";
var template = Handlebars.compile(source);
template({firstName: "Alan", lastName: "Johnson"});
결과는 다음과 같다.
<p>Johnson, Alan</p>
내장된 with블록 헬퍼를 이용하여 template의 섹션을위한 컨텍스트를 옮길 수 있다.
<div class="entry">
    <h1>{{title}}</h1>
    {{#with author}}
        <h2>By {{firstName}} {{lastName}}</h2>
    {{/with}}
</div>
컨텍스트는 다음과 같다.
{
    title: "My first post!",
    author: {
        firstName: "Charles",
        lastName: "Jolley"
    }
}
결과는 다음과 같다.
<div class="entry">
    <h1>My first post!</h1>
    <h2>By Charles Jolley</h2>
</div>
with는 또한 block parameters와 함께 사용된다. 이는 현재 블록내의 참조를 정의한다.
다음 예제는 위 예제를 변형한 것이다.

<div class="entry">
    <h1>{{title}}</h1>
    {{#with author as |myAuthor|}}
        <h2>By {{myAuthor.firstName}} {{myAuthor.lastName}}</h2>
    {{/with}}
</div>
이 코드는 ../와 같은 깊이 참조자를 이용하는 것보다 잠재적으로 복잡한 템플릿을 이용할때 더 명확하게 해준다.

전달된 값이 비어있는 경우를 위해서 선택적으로 {{else}}를 이용할 수 있다.
{{#with author}}
    <p>{{name}}</p>
{{else}}
    <p class="empty">No content</p>
{{/with}}

The lookup helper

lookup 헬퍼는 handlebars변수를 이용하여 동적 파라미터를 참조하기 위한 헬퍼이다. 이는 배열의 인덱스를 해석하기 위해 유용하다.
{{#each bar}}
    {{lookup ../foo @index}}
{{/each}}

The log block helper

log 헬퍼는 템플릿이 수행될때 컨텍스트의 상태를 로깅하기 위한 목적으로 사용된다.
{{log "Look at me!"}}
Handlebars.logger.log를 위임하여 커스텀 로깅을 오버라이딩 할 수 있다.
여러개의 아규먼트를 이 메소드에 전달하여 로거를 찍을 수 있다.

{{log "This is logged" foo "And so is this"}}
log level은 해시 파라미터를 이용하여 지정이 가능하며 debug, info, warn, error를 지정할 수 있다. 이 값이 없으면 기본적으로 warn으로 설정된다.

{{log "Log!" level="error"}}
로깅은 선택적으로 Handlebars.logger.level에 설정한 값에 따라 출력이 된다. 기본값은 info이다. 모든 로그 스테이트먼트는 현재 레벨을 출력시 설정할 수 있다.

The blockHelperMissing helper

environment's helpers hash에서 직접적으로 resolve할 수 없는 경우에 암묵적으로 호출된다.
{{#foo}}{{/foo}}
이것은 이 헬퍼를 호출하며 현재 컨텍스트 상에서 foo의 값을 해석한다. 그리고 options.name 필드에 "foo"를 설정한다.

이것은 사용자에 의해서 오버라이드 될것이다. 다음과 같이 블록 실행을 통해 변경이 가능하다.
Handlebars.registerHelper('blockHelperMissing', function(context, options) {
    throw new Handlebars.Exception('Only if or each is allowed');
});
이는 mustache-style블록 실행의 사용을 막기위해 사용될 수 있다. 이는 더 효과적인 if와 each 헬퍼들을 위한 목적이다.

The helperMissing helper

내부적 헬퍼는 특정 황경에서 헬퍼가 발견되지 못하는 경우 혹은 현재 컨텍스트 내에서 발견되지 못하는 경우에 호출된다. 양쪽 케이스에서 이것은 blockHelperMissing 헬퍼를 우선적으로 수행한다.
{{foo}}
{{foo bar}}
{{#foo}}{{/foo}}
각각은 이 헬퍼를 호출하고, 특정 아규먼트들을 전달한다. 이 헬퍼는 knownHelperOnly모드에서는 호출되지 않는다.

이것은 어플리케이션에서 오버라이딩 될수 있다.
Handlebars.registerHelper('helperMissing', function(/* [args, ] options */) {
    var options = arguments[arguments.length - 1];
    throws new Handlebars.Exception('Unknown field: ' + options.name);
});
































[handlebars] Partials 알아보기

[handlebars] Partials 알아보기
from : http://handlebarsjs.com/partials.html

Handlebars는 partials를 이용하여 템플릿을 재사용 가능하게 한다. Partials는 일반적인 Handlebars 템플릿으로 다른 템플릿을 직접적으로 호출할 수 있다.

Basic Partials

partials를 이용하기 위해서 반드시 Handlebars.registerPartial로 등록이 되어야 한다. 
Handlebars.registerPartial('myPartial', '{{name}}')
이는 myPartial이라는 partial을 등록한다. Partial들은 사전에 컴파일 되며 사전에 컴파일된 템플릿에 두번째 파라미터로 전달된다. 

partial을 호출하는 것은 partial 문법을 이용하여 호출할 수 있다. 
{{> myPartial }}
이는 myPartial로 이름지어진 partial을 렌더링한다. partial을 실행하면 이는 현재 수행되는 컨텍스트 하위에 존재하게 된다.

Dynamic Partials

sub expression문법을 이용하연 선택된 partial을 동적으로 실행할 수 있다.
{{> (whichPartial) }}
이것은 whichPartial을 실행하고 이 함수에 의해서 반환된 이름으로 된 partial을 렌더링한다.

subexpression은 변수들을 resolve하지 않는다. 그러므로 whichPartial은 반드시 함수이어야한다. 만약 단순 변수가 partial이름을 가니면 lookup 헬퍼를 이용하여 resolve할 수 있다.
{{> (lookup . 'myVariable') }}

Partial Contexts 

partial을 custom context에서 수행이 가능하며 이는 partial call을 위한 컨텍스트를 전달함으로 해서 가능하다.
{{> myPartial myOtherContext }} 

Partial Parameters

커스텀 데이터는 해시 파라미터를 통해서 partial에 전달될 수 있다.
{{> myPartial parameter=value }}
이는 parameter를 parar이 실행될때 value 값으로 전달한다.
이는 부모 컨텍스트의 데이터를 partial로 전달해서 노출하고자 할때 유용하다.

{{> myPartial name=../name }}

Partial Blocks 

partial을 렌더하기 위한 시도를 할때 보통의 행동은 not found는 error를 throw 하기 위한 구현을 하는 것이다. 만약 failover가 필요한경우, partial은 블록 구문을 이용하여 해당 처리를 한다.
{{#> myPartial }}
    Failover content
{{/myPartial}}
이것은 만약 myPartial에 대한 partial이 등록되지 않은경우 Failover content가 렌더될 것이다.

이 블록 문법은 partial에 템플릿을 전달하기 위해서 사용된다. 이는 @partial-block으로 이름지어진 특별한 partial에 의해서 실행될 수 있다.
{{#> layout }}
    My Content
{{/layout}}
layout partial은 다음을 포함한다.
Site Content
{{> @partial-block }}
이런경우 다음을 렌더한다.
Site Content
My Content
이러한 방식으로 호출될때 블록은 호출되는 시점에 partial의 컨텍스트 하위에서 수행이 된다. 깊어진 path와 블록 파라미터들은 partial템플릿 대신에 partial block에 연관되어 수행이 된다.
{{#each children as |child|}}
    {{#> childEntry}}
        {{child.value}}
    {{/childEntry}}
{{/each}}
 이것은 이 템플릿으로 부터 child.value를 렌더링한다. partial이 아니다.

Inline Partials

템플릿들은 inline 데코레이터를 통해서 블록으로 스콥된 partial들을 정의할 것이다. 
{{#*inline "myPartial"}}
    MyContent
{{/inline}}
{{#each children}}
    {{> myPartial}}
{{/each}}
이것은 myPartial 로 이름지어진 partial을 렌더링 한다. 각 child마다.

각 inline partial은 현재 블록과 모든 자식에 가능하며 이는 다른 partial의 실행을 포함한다. 이것은 레이아웃 템플릿을 포함하며 기능적으로 유사하다.
{{#> layout}}
    {{#*inline "nav"}}
        My Nav
    {{/inline}}
    {{#*inline "content"}}
        My Content
    {{/inline}}
{{/layout}}

layout partial은 다음과 같을 것이다. 
<div class="nav">
    {{> nav}}
</div>
<div class="content">
    {{> content}}
</div>

[handlebars] Block Helper

[handlebars] Block Helper
from : http://handlebarsjs.com/block_helpers.html

Block Helper는 커스텀 iterator를 정의하고 다른 기능을 수행할 수 있도록 해준다. 그리고 새로운 컨텍스트함께 전달된 블록을 호출할 수 있다.

Basic Blocks

보여주기를 목적으로 블록 헬퍼를 정의해보다. 이는 블록을 호출하며 이는 헬퍼가 존재하지 않는다. 
<div class="entry">
    <h1>{{title}}</h1>
    <div class="body">
        {{#noop}}{{body}}{{/noop}}
    </div>
</div>

noop 헬퍼 (줄임말로 no operation이다.) 옵션 해시를 받는다. 이 옵션 해시는 (options.fn)함수를 가지고 있으며 이는 일반적인 컴파일된 Handlebars template와 같은 행동을 한다. 특히 이 함수는 컨텍스트를 받고 스트링을 반환한다. 

Handlebars.registerHelper('noop', function(options) {
    return options.fn(this);
});
Handlebars는 항상 this와 같은 현재 컨텍스트 포함하는 헬퍼를 호출한다. 그래서 this를 블록에서 호출할 수 있다. 이는 현재 컨텍스트를 의미한다. 

어떤 헬퍼들은 이러한 방법으로 컨텍스트에 전의된 전체 필드들을 획득할 수 있다. 필드에 접근하는 것은 helper에 의해서 씌여진다. 이때 패스 레퍼런스가 사용될 것이다. 상단 예제어서 noop 는 컨텍스내의 필드이며 다음과 같이 레퍼런싱 된다. 
{{./noop}}

Basic block Variation

더욱 낳은 문법을 살펴보기 위해서 다른 블록 헬퍼 정의를 살펴보자. 이는 몇가지 마크업으로 둘러쌓인 텍스트를 추가하는 것이다. 
<div class="entry">
    <h1>{{title}}</h1>
    <div class="body">
        {{#bold}}{{body}}{{/bold}}
    </div>
</div>

bold헬퍼는 텍스트를 볼드로 만들어주는 마크업을 추가할 것이다. 이때 함수는 컨텍스트를 받아 들이고 스트링을 반환한다. 
Handlebars.registerHelper('bold', function(options) {
    return new Handlebars.SafeString(
        '<div class="mybole">'
        + options.fn(this)
        + '</div>');
});

The with helper

with 헬퍼는 헬퍼에게 파라미터를 어떻게 전달하는지 보여준다. 헬퍼가 호출될때 파라미터를 전달하기 위해서는 context와 함께 전달한다. 
<div class="entry">
    <h1>{{title}}</h1>
    {{#with story}}
        <div class="intro">{{{intro}}}</div>
        <div class="body">{{{body}}}</div>
    {{/with}}
</div>
아마도 JSON객체 섹션에서 깊게 중첩된 프로퍼티 부분이 있고 반복적인 부모 이름을 피하여 사용할 것이다. 
{
    title: "First Post",
    story: {
        intro: "Before the jump"
        body: "After the jump"
    }
}
이러한 헬퍼의 구현은 noop헬퍼의 구현과 매우 많이 닮았다. 헬퍼들은 파라미터를 받을 수 있다. 그리고 파라미터들은 내부적으로 {{mustache}}블록을 통해서 직접적으로 사용할 수 있다. 
handlebars.registerHelper('with', function(context, options) {
    return options.fn(context);
});
파라미터들은 헬퍼에 전달되며 기술한 순서대로 전달된다. 

Simple Iterators

block 헬퍼의 공통적인 유즈케이스는 커스텀 iterator를 정의하는 것이다. 사실 모든 핸들바스의 내장 헬퍼들은 일반적인 핸들바스 블록 헬퍼로 정의 되어 있다. each 헬퍼가 어떻게 동작하는지 보자. 

<div class="entry">
    <h1>{{title}}</h1>
    {{#with story}}
        <div class="intro">{{{intro}}}</div>
        <div class="body">{{{body}}}</div>
    {{/with}}
</div>
<div class="comments">
    {{#each comments}}
        <div class="comment">
            <h2>{{subject}}</h2>
            {{{body}}}
        </div>
    {{/each}}
</div>
이 케이스에서 우리는 comments의 배열의 각 엘리먼트가 each에 전달된 블록을 호출하기를 원할 것이다. 

Handlebars.registerhelper('each', function(context, options) {
    var ret = '';
    for (var i=0, j=context.length; i<j; i++) {
        ret = ret + options.fn(context[i]);
    }
    return ret;
});
이 예제에서 우리는 전달된 파라미터를 iterate를 통해서 접근하며 각 아이템들을 한번씩 호출한다. 우리는 스트링을 만들고 그것을 반환한다. 

이 패턴은 더 향상된 iterator를 구현을 사용할 수 있도록 한다. 예를 들어 <ul>로 래핑된 내용을 만들고, 내부의 각 결과는 <li>로 래핑하고자 할수도 있다. 
{{#list nav}}
    <a href="{{url}}">{{title}}</a>
{{/list}}
컨텍스트는 다음과 같다. 
{
    nav: [
        {url: "http://www.yehudakatz.com", title: "Katz Got Your Tongue" },
        {url: "http://www.sproutcore.com/block", title: "SproutCore Blog" },
    ]
}
헬퍼는 원래 each헬퍼와 유사하다. 

Handlebars.registerHelper('list', function(context, options) {
    var ret = "<ul>";
    for (var i=0, j=context.length; i<j; i++) {
        ret = ret + "<li>" + options.fn(context[i]) + "</li>";
    }
    return ret + "</ul>";
});
라이브러리는 underscore.js 혹은 SproutCore의 런타임 라이브러리와 같이 이용하며 이는 쫌 이쁘게 만들어 준다. 예를 들어 여기에는 SproutCore의 런타임 라이브러리와 같다. 

Handlebars.registerHelper('list', function(context, options) {
    return "<ul>" + context.map(function(function(item) {
        return "<li>" + options.fn(item) + "</li>";
    }).join("\n") + "</ul>";
});

Conditionals

다른 일반적인 유즈케이스는 조건문을 수행하는 것이다.  iterator 과 같이 핸들바스는 내장된 if와 unless 컨트롤 구조를 가지고 있으며 이는 일반적인 핸들바스 헬퍼이다. 

{{#if isActive}}
    <img src="start.gif" alt="Active">
{{/if}}
컨트롤 구조는 일반적으로 현재 컨텍스트를 변경하지 않는다. 대신에 이는 몇가지 변수에 대해서 어떠한 블록을 수행해야할지를 결정하게 된다. 

Handlebars.registerHelper('if', function(conditional, options) {
    if (conditional) {
        return options.fn(this);
    }
});
조건을 작성할때 조건에 만족하지 않을때 다른 구문을 실행하고자 할 수 있다. 이럴때는 else 블록 헬퍼를 이용할 수 있다. 

{{#if isActive}}
    <img src="star.gif" alt="Active">
{{else}}
    <img src="cry.gif" alt="Inactive">
{{/if}}
Handlebars는 options.inverse와 같은 else를 위한 프라그먼트 블록을 제공한다. else 프라그먼트의 존재여부를 위한 체크를 할 필요가 없다. Handlebars는 자동적으로 찾아낼 것이며, "noop" 함수를 등록한다.

Handlebars.registerHandler('if', function(conditional, options) {
    if (conditional) {
        return options.fn(this);
    } else {
        return options.inverse(this);
    }
});
Handlebars는 추가적인 메타데이터를 제공하여 블록헬퍼에게 전달할 옵션 헬퍼 프로퍼티를 추가할 수 있도록 해준다.

조건은 else mustache에 추가적으로 검사를 진행 할 수 있다.
{{#if isActive}}
    <img src="star.gif" alt="Active">
{{else if isInactive}}
    <img src="cry.gif" alt="Inactive">
{{/if}}
이후 처리를 위한 헬퍼와 동일하게 unless 헬퍼는 else위치에 사용할 수 있다. 헬퍼 값들이 다른경우 닫는 mustache는 여는 헬퍼의 이름과 매치 시켜주면 된다.

Hash Arguments

보통의 헬퍼와 같이 블록 헬퍼는 옵셔널 해시를 final 아규먼트로 전달 할 수 있다. 이전의 list헬퍼를 살펴보고 다른 선택적인 속성을 추가해보나. 이는 <ul>엘러먼트가 생성될 것이다.

{{#list nav id="nav-bar" class="top"}}
    <a href="{{url}}">{{title}}</a>
{{/list}}
handlebars final hash로 options.has형태로 제공한다. 이것은 다양한 개수의 파라미터를 수용할 수 있도록 해준다. 이는 또한 optional해시를 받아들일 수 있다. 만약 템플릿이 hash 아규먼트를 제공하지 않는다면 Handlebars는 자동적으로 빈 객체를 전달하며 ( {} )으로 전달한다.  그러므로 해시 아규먼트가 존재하는지 여부를 검사할 필요가 없다.

Handlebars.registerHelper('list', function(context, options) {
    var attrs = Em.keys(options.hash).map(function(key) {
        return key + '="' + options.hash[key] + '"';
    }).join(" ");
    return "<ul " + attrs + ">" + context.map(function(item) {
        return "<li>" + options.fn(item) + "</li>";
    }).join("\n") + "</ul>";
});
Hash 아규먼트들은 강력한 초가적인 파라미터들을 제공할 방법을 가지고 있다. 이는 위치 멪가 아규먼트를 제공해야하는 복잡함 없이 제공한다.

Block 헬퍼들은 또한 자식 템플릿에 private 변수를 인젝트 할 수 있다. 이것은 원래 컨텍스트에 들어있지 않는 데이터와 같은 추가적인 정보를 추가하기 위한 매우 유용한 방법이다.

예를 들어 list에 작업을 할때현재 엔덱스의 값을 제공할 수 있다.
{{#list array}}
    {{@index}}. {{title}}
{{/list}}
Handlebars.registerHelper('list', function(context, options) {
    var out = "<ul>", data;
    if(options.data) {
        data = Handlebars.createFrame(options.data);
    }
    for(var i=0; i<context.length; i++) {
        if(data) {
            data.index = i;
        }
        out += "<li>" + options.fn(context[i], { data: data }) + "</li>";
    }
    out += "</ul>";
    return out;
});
private변수는 data옵션을 이용하여 제공된다. 이것은 모든 파생된 스콥에서 지정이 가능하다.

부모 스콥에서 정의된 Private변수는 path된 쿼리를 통해 접근되어진다. index필드를 접근하기 위해서 @../index가 사용되어진다.

각 헬퍼에서 새로운 데이터 프레임을 생성하는 것을 보장하는 것은 자신의 데이터에 assign하는 것이다. 그렇지 않으면 다운스트림 헬퍼는 의도하지 않은 업스트림 변수를 변경할 것이다.

또한 데이터 필드는 이전에 존재하는 데이터 객체와 상호작용 하기 위해서 추가된 것임을 보장한다. private 변수의 행동은 조건적으로 컴파일 되고 몇몇 템플릿들은 이 필드로 생성되지 않는다.

Block Parameters

Handlebars 3.0에서는 제공하고 있는 헬퍼로 부터 이름있는 파라미터를 수신받을 수 있다.
{{#each users as | user userId}}
    Id : {{userId}} Name: {{user.name}}
{{/each}}
이 예제에서 user는 현재 컨텍스트와 같은 동일한 값을 가진다. 그리고 userId는 iteration을 위한 인덱스 변수를 가진다.

이는 중첩된 헬퍼를 제공하여 이름 충돌을 회피한다. 이는 private변수들에 발생할 수 있다.
{{#each users as |user userId}}
    {{#each user.book as |book bookId}}
        User Id: {{userId}} Book Id: {{bookId}}
    {{/each}}
{{/each}}
내장 헬퍼의 넘버는 블록 파라미터들을 젝오하고 다른 커스텀 헬퍼는 blockParams옵션 필드를 통해서 제공된다.
Handlebars.registerHelper('block-params', function() {
    var args = [],
        options = arguments[arguments.length - 1];
    for(var i=0; i < argument.length - 1; i++) {
        args.push(arguments[i]);
    }
    return options.fn(this, {data: options.data, blockParams: args});
});
{{#block-params 1 2 3 as |foo bar baz|}}
    {{foo}} {{bar}} {{baz}}
{{/block-params}}
 헬퍼의 구현은 주어진 블록의 이름지어진 변수의 선언을 허용한다. 이 예제는 출력으로 1, 2, 3을 렌더시에 수행한다.

헬퍼들은 블록 파라미터들의 number를 결정할 수 있다. 이는 options.fn.blockParams 필드 템플릿을 통해서 가능하며 이는 정수 카운터이다. 이 값은 블록 파라미터의 수를 표현하며 자식 템플릿에 의해서 참조될 수 있다. 이 카운트 뒤에 있는 파라미터들은 절대 참조되지 않는다. 그리고 필요한경우 헬퍼에 의해서 안전하게 제거된다. 이것은 선택적이고 다른 추가적인 파라미터들이며 이는 템플릿에 전달된 파라미터들로 조용히 무시된다.

Raw Blocks

Raw 블록들은 처리되지 않는 mustache블록들을 처리하기 위해 필요한 템플릿으로 이용가능하다.
{{{{raw-helper}}}}
    {{bar}}
{{{{/raw-helper}}}}
이것은 컨텐츠의 인터프리터를 수행하지 않고 raw-helper 헬퍼를 실행할 것이다.
Handlebars.registerHelper('raw-helper', function(options) {
    return options.fn();
});
이는 다음과 같이 렌더링된다.
{{bar}}

[handlebars] precompiler이용하기.

[handlebars] precompiler이용하기.
from : http://handlebarsjs.com/precompilation.html

Handlebars프리컴파일러를 이용하면 핸들바 컴파일이 클라이언트 브라우저에서 컴파일되는 시간을 줄여주며, 필요한 핸들바스 라이브러리를 처리하는 시간을 감소 시켜 준다.

Getting Started

우선 OS X에서 node를 인스톨 하거나, npm을 인스톨 할 필요가 있다.
$ brew install node
이 가정은 Homebrew가 미리 설치 되어 있다는 것을 가정한다. 설치를 위해서는 다음을 보자.

다음으로 npm패키지로 핸들바스를 설치하자.
$ npm install handlebars -g
-g옵션을 이용하면 패키지를 글로벌 속성으로 설치하겠다는 의미이다. 이러게 하면 어떠한 프로젝트에서든지 사용이 가능하다.

이제 precompiler를 사용할 준비가 되었다.
$handlebars <input> -f <output>
컴파일러는 Handlebars.template에 템플릿을 인서트 할 것이다. 만약 입력 파일이 person.handlebars라면 컴파일러는 Handlebars.template.person에 추가한다. 이 템플릿은 다음과 같은 장식으로 직접 호출 될 수 있다.

Handlebars.templates.person(context, options);
만약 precompile된 template로 작업을 한다면 디플로이된 어플리케이션에 컴파일러를 추가할 필요가 없다. 대신에 더 가벼운 "runtime" 빌드를 이용할 수 있다.
<script src="/libs/handlebars.runtime.js"></script>
추가적으로 다운로드 사이즈를 줄여주기 위해서는 클라이언트 사이드의 컴파일을 제거하면 된다. 이러면 부트 타임을 극적으로 줄여준다. 컴파일 타임은 핸들바의 사용에 있어 매우 비싼 작업이다.

Optimizations

precompile를 수행할때 몇가지 최적화를 수행할 수 있다.
첫번째로 알려진 헬퍼 리스트를 지정할 수 있다.
handlebars <input> -f <output> - each -k if -k unless
handlebars 컴파일러는 이러한 헬퍼에 접근하기 위한 최적화를 할 수 있도록 해준다.

그리고 컴파일 타임에 알려진 헬퍼만 필요하다면 --knownOnly 옵션을 추가하여 최소한의 코드를 생성하도록 할 수 있다. 이는 더 빠르게 수행되도록 해준다.

Usage

Usage: node ./bin/handlebars [template|directory]...

Options:
  -f, --output         Output File
  --map                Source Map File                                                    [string]  [default: undefined]
  -a, --amd            Exports amd style (require.js)
  -c, --commonjs       Exports CommonJS style, path to Handlebars module                                 [default: null]
  -h, --handlebarPath  Path to handlebar.js (only valid for amd-style)                                     [default: ""]
  -k, --known          Known helpers
  -o, --knownOnly      Known helpers only
  -m, --min            Minimize output
  -n, --namespace      Template namespace                                              [default: "Handlebars.templates"]
  -s, --simple         Output template function only.
  -N, --name           Name of passed string templates. Optional if running in a simple mode. Required when operating
                       on multiple templates.
  -i, --string         Generates a template from the passed CLI argument.
                       "-" is treated as a special value and causes stdin to be read for the template value.
  -r, --root           Template root. Base value that will be stripped from template names.
  -p, --partial        Compiling a partial template
  -d, --data           Include data when compiling
  -e, --extension      Template extension.                                                       [default: "handlebars"]
  -b, --bom            Removes the BOM (Byte Order Mark) from the beginning of the templates.
  -v, --version        Prints the current compiler version
  --help               Outputs this message

precompiler의 노멀 모드를 이용한다면 결과 템플릿은 Handlebars.templates객체에 저장된다. 이 템플릿들은 동일한 템플릿 호출 방법으로 이용이 가능하다.

만약 단순 모드 프리컴파일을 한다면 이는 단일 자바 스크립트 메소드를 생성해낸다. 이는 Handlebars.template메소드를 거쳐야 하며, 결과 객체는 노멀로 이용될 수 있다.




[handlebars] Expression 알아보기.

[handlebars] Expression 알아보기.
from : http://handlebarsjs.com/expressions.html
Handlebars 의 expression은 Handlebars 템플릿의 기본유닛이다.
{{mustache}}를 이용할 수 있으며, 헬퍼에 이를 전달할 수 있으며 또는 해시 아규먼트에서 값처럼 사용할 수 있다.

기본사용법 : 

다음은 가장 단순한 표현식이다.
<h1>{{title}}</h1>
이 표현식의 의미는 현재 컨텍스트 내에서 title라는 프로퍼티를 찾아서 대체하라는 의미이다.
Block helper들은 현재 컨텍스트를 다룬다. 그러나 표현식의 기본적인 의미는 변경하지 않는다.

Handlebars표현식은 dot 로 분리된 표현식으로 경로 탐색을 할 수 있다.
<h1>{{article.title}}</h1>
이 표현식은 현재 컨텍스트에서 article를 찾고, title속성을 찾아서 대체하라는 의미이다.
Handlebars는 / 문법을 이용할 수 있다.  이를 이용하여 위 코드를 다음과 같이 기술 할 수 있다.
<h1>{{article/title}}</h1>
식별자는 다음에 열거된 유니코드 문자를 제외하고 어떤것이든 될 수 있다.
Whitespace ! " # % & ' ( ) * + , . / ; < = > @ [ \ ] ^ ` { | } ~

프로퍼티를 참조하는 것은 유효한 식별자가 아니다. 세그먼트 리터럴을 이용하기 위해서 [ 표기를 이용할 수 있다.
{{#each articles.[10].[#comments]}}
    <h1>{{subject}}</h1>
    <div>
        {{body}}
    </div>
{{/each}}
상단 예에서 templage는 each파라미터를 통해서 자바스크립트의 다음 고드와 같이 처리된다.
articles[10]['#comments']
Handlebars HTML escapes 값은 {{expression}}에 의해서 반환된다. 만약 이를 원하지 않는다면 "triple-stash" {{{ 를 이용하자.
{{{foo}}}

Helpers

Handlebars의 헬퍼 콜은 단순한 식별자이며, 0개 이상의 파라미터를 받을 수 있다. 이는 공백으로 나누게 된다.  Handlesbars는 상단에 기본 사용법과 완전히 동일한 방법으로 사용된다.
Handlebars.registerHelper('link', function(object) {
    var url = Handlebars.escapeExpression(object.url),
        text = Handlebars.escapeExpression(object.text);
    return new Handlebars.SafeString(
        "<a href='" + url +"'>" + text + "</a>"
    );
 });
헬퍼로 부터 HTML을 반환할때, Handlebars의 SafeString을 이용하여 기본적으로 escape하지 않을 수 있다. SafeString을 이용하면 모든 unknown 혹은 unsafe한 데이터들은 수동으로 escape된다. 이는 escapeExpression메소드를 이용한다.

또한 단순 스트링, number, boolean과 같은 타입의 파라미터를 Handlebars helper에 전달 할 수 있다.

{{{lilnk "See more..."" story.url}}
이 케이스에서 Handlebars는 2개의 파라미터를 전달한다. "See more..."와 현재 컨텍스트에서 store.url의 처리결과 값이 전달된다.

Handlebars.registerHelper('link', function(text, url) {
    url = Handlebars.escapeExpression(url);
    text = Handlebars.escapeExpression(text);
    return new Handlebars.SafeString(
        "<a href='" + url + '''>" + text + "</a>"
    );
});
이는 story.text의 값을 기반으로 동적 텍스트 값을 헬퍼에 이용할 수 있다.

{{{link story.text story.url}}}
Handlebars헬퍼는 선택적인 시퀀스인 key-value쌍들을 받을수 있다. 이는 final파리미터로 사용되며 (도큐먼테이션에서 해시 아규먼트와 같이 참조된다.)

{{{link "See more..." href-story.url class="story"}}}
해시 아규먼트에서 키들은 단순 식별자이어야 한다. 그리고 값은 Handlebars의 표현식이어야 한다.
이 의미는 값은 단순 식별자, paths, String이 될 수 있다는 의미이다.

Handlebars.registerHelper('link', function(text, options) {
    var attrs = [];
    for(var prop in options.hash) {
        attrs.push(
            Handlebars.escapeExpression(prod) + '="' + Handlebars.escapeExpression(options.hash[prop]) + '"');
    }
 
    return new Handlebars.SafeString (
        "<a " + attrs.join(" ") + ">" + Handlebars.escapeExpression(text) + "</a>"
    );
});
Handlebars는 추가적인 메타데이터를 제공한다. Hash argument와 같은 것으로 final parameter과 같이 helper에 제공된다.

Handlebars또한 템플릿의 블록과 함께 헬퍼를 호출하기 위한 메커니즘을 제공한다. 블록 헬퍼는 어떠한 컨텍스트에서든지 선택된 블록을 0번 이상 호출할 수 있다.

Subexpressions

Handlebars 는 subexpression을 제공한다. 이는 단일 mustache를 이용하여 복합 헬퍼를 호출할 수 있다. 그리고 내부 헬퍼의 결과를 외부 헬퍼 아규먼트로 전달 할 수 있다. Subexpression은 ( )로 구분한다.
{{outer-helper (inner-helper 'abc') 'def' }}
이 케이스에서 inner-helper는 스트링 아규먼트 'abc'를 받는 헬퍼로 호출이 되며 이 결과는 outer-helper의 첫번째 아규먼트로 전달된다. 그리고 'def'는 두번째 아규먼트로 전달된다.

Whitespace Control

템플릿의 공백은 특정 mustache스테이트먼트의 각 부분에서 ~ 문자를 브레이스{의 의해서 생략이 될 수 있다.
{{#each nav ~}}
    <a href="{{ur}}">
        {{~#if test}}
            {{~title}}
        {{~^~}}
            Empty
        {{~/if~}}
    </a>
{{~/each}}
컨텍스트 :
{
    nav: [
        {url: 'foo', test: true, title: 'bar'},
        {url: 'bar'}
    ]
}

출력결과 뉴라인과 포매팅된 공백처리 결과이다.
<a href="foo">bar</a><a href="bar">Empty</a>
이 확장은 라인 처리의 기본적인 동작이며 "standalone"헬퍼이다.
{{#each nav}}
    <a href="{{url}}">
        {{#if test}}
            {{title}}
        {{^}}
            Empty
        {{/if}}
    </a>
{{~/each}}
결과는 다음과 같다.
<a href="foo">
    bar
</a>
<a href="bar">
    Empty
</a>

Escaping

Handlebars컨텐츠는 하나 혹은 두개의 방법으로 이스케이프 될 수 있다. 이는 인라인 이스케이프 혹은 raw block helpers이다. 인라인 escape는 prefixing mustache블록으로 \으로 시작하는 블록이다. Raw block은 {{{{ mustache 브레이스로 생성된다.

\{{escaped}}
{{{{raw}}}}
    {{escaped}}
{{{{/raw}}}}



























 


[handlebars] Getting Started

[handlebars] Getting Started

Getting Started handlebars

from : http://handlebarsjs.com/

Getting Started

Handlebars는 아래와 같이 일반 HTML과 같이 보인다.
내부에는 내장된 handlebars 표현식 {{ 와 }}로 표현하고 있다.

<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{body}}
  </div>
</div>
그리고 <script>태그 안에 포함시켜 브라우저로 전달할 수 있도록 한다.
다음과 같다.

<script id="entry-template" type="text/x-handlebars-template">
  <div class="entry">
    <h1>{{title}}</h1>
    <div class="body">
      {{body}}
    </div>
  </div>
</script>
JavaScript에서 컴파일 하기 위해서 Handlebars.compile를 이용할 수 있다.
var source   = $("#entry-template").html();
var template = Handlebars.compile(source); 
또한 미리 컴파일 해 둘 수 있다.

- 실행시 필요한 라이브러리 최소화
- 브라우저에서 컴파일 하는 자원낭비를 막을 수 있다.
- 모바일 디바이스에서 수행할때 꼭 필요한 작업이라고 할 수 있다.

context 값을 이용하여 template를 실행하는 방법은 다음과 같다.
var context = {title: "My New Post", body: "This is my first post!"};
var html    = template(context);
결과는 다음과 같다.
<div class="entry">
  <h1>My New Post</h1>
  <div class="body">
    This is my first post!
  </div>
</div>
즉 {{ }} 표현식으로 된 내용이 context의 내용으로 변환되었다.

HTML Escaping

Handlebars HTML-escapes값은 {{표현식}} 으로 반환된다. 만약 escape를 원하지 않는다면 {{{ }}} 표현식을 이용하면 된다. 이는 triple-stash라고 부른다.
<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{{body}}}
  </div>
</div>
context는 다음과 같다.
{
  title: "All about <p> Tags",
  body: "<p>This is a post about &lt;p&gt; tags</p>"
}
결과는 다음과 같다.
<div class="entry">
  <h1>All About &lt;p&gt; Tags</h1>
  <div class="body">
    <p>This is a post about &lt;p&gt; tags</p>
  </div>
</div>
Handlebars.SafeString을 이용하면 escape하지 않는다. 만약 helper를 작성하고 이것이 HTML을 생성하는 것이라면 new Handlebars.SafeString(result)를 이용하면 된다.
이런 환경에서 수동적으로 파라미터를 이스케이프 할 수 있다.
Handlebars.registerHelper('link', function(text, url) {
  text = Handlebars.Utils.escapeExpression(text);
  url  = Handlebars.Utils.escapeExpression(url);
  var result = '<a href="' + url + '">' + text + '</a>';
  return new Handlebars.SafeString(result);
});
이 코드는 파라미터로 전달된 내용을 이스케이프 할 것이다. 그러나 결과 값으로 safe로 마크하게 된다. 그러므로 Handlebars는 "triple-stash"를 기술하지 않더라도 이스케이프 처리를 하지 않게 된다.

Block Expressions

Block Expressions는 헬퍼를 지정하도록 해준다. 이것은 현재와 다른 서로다른 컨텍스트에서 템플릿 섹션을 invoke하게 해준다.
이 블록 헬퍼들은 # 시작하고 마지막으로는 /로 끝이 나는 블록을 가진다.

다음 HTML내용을 살펴보자. 이는 HTML리스트를 생성하게 된다.
{{#list people}}{{firstName}} {{lastName}}{{/list}}
context : 
{
  people: [
    {firstName: "Yehuda", lastName: "Katz"},
    {firstName: "Carl", lastName: "Lerche"},
    {firstName: "Alan", lastName: "Johnson"}
  ]
}
이 헬퍼 이름을 list로 생성하고자 한다고 하자.
헬퍼는 people을 첫번째 파라미터로 받는다. 그리고 옵션들의 해시는 두번째 파라미터로 받는다.
옵션 해시는 fn으로 이름된 속성을 가지고 있다. 이는 컨텍스트와 함께 호출할 수 있으며, 일반적으로 Hanglebars template처럼 invoke하게 된다.

Handlebars.registerHelper('list', function(items, options) {
  var out = "<ul>";
  for(var i=0, l=items.length; i<l; i++) {
    out = out + "<li>" + options.fn(items[i]) + "</li>";
  }
  return out + "</ul>";
});
템플릿을 실행하면 다음과 같은 결과가 나온다.
<ul>
  <li>Yehuda Katz</li>
  <li>Carl Lerche</li>
  <li>Alan Johnson</li>
</ul> 
Block helper는 더 많은 기능이 있다. else섹션 생성 등...
options.fn(context)를 호출할때 블록헬퍼의 컨텐츠는 escape된다. 그리고 Handlebars는 블록헬퍼의 결과를 escape하지 않는다. 만약 Handlebars가 escape 처리를 하게 된다면 두번 escape되기 때문이다.

Handlebars Paths

Handlebars는 단순 패스를 지원한다. Mustache와 같이..
<p>{{name}}</p>
다음과 같은 중첩 path도 지원한다. 
<div class="entry">
  <h1>{{title}}</h1>
  <h2>By {{author.name}}</h2>
  <div class="body">
    {{body}}
  </div>
</div>
context :
var context = {
  title: "My First Blog Post!",
  author: {
    id: 47,
    name: "Yehuda Katz"
  },
  body: "My first post. Wheeeee!"
};
이는 Handlebars가 좀더 raw한 JSON 객체와 함게 템플릿을 처리할 수 있다는 것을 의미한다.

또한 ../세그먼트를 포함할 수 있으며, 이는 부모로 부터 상대적인 경로를 나타낸다.
<h1>Comments</h1>
<div id="comments">
  {{#each comments}}
  <h2><a href="/posts/{{../permalink}}#{{id}}">{{title}}</a></h2>
  <div>{{body}}</div>
  {{/each}}
</div>
../ 는 호출하는 블록마다 다르게 해석이 될 것이다.
../를 이용하는 것은 컨텍스트가 변경될때 필요하다. 그러므로 each와 같은 헬퍼들의 자식은 ../의 사용이 if와 같은 헬퍼의 자식에 따라 사용하거나 하지않게 작업이 필요할 것이다.

{{permalink}}
{{#each comments}}
  {{../permalink}}
  {{#if title}}
    {{../permalink}}
  {{/if}}
{{/each}}
이 예제에서 서로다른 블록에서 permalink 값이 존재하더라도 같이 사용될 것이다.
이러한 행위는 Handlebars4에서 지원이 된다.

Handlebars는 this키워드를 이용하여 helpers와 data fields에 대해서 이름 충돌을 해결할 수 있도록 해준다.

<p>{{./name}} or {{this/name}} or {{this.name}}</p>
상기 예제는 각각 방식 모두 헬퍼에 있는 동일한 name을 이용하지 않고, 현재 컨텍스트의 name 필드를 이용하게 된다. 

Template comments with {{!-- --}} or {{! }}.

커멘트는 다음과 같이 사용할 수 있다. 
<div class="entry">
  {{!-- only output author name if an author exists --}}
  {{#if author}}
    <h1>{{firstName}} {{lastName}}</h1>
  {{/if}}
</div>
커멘트는 출력에 나타나지 않는다.

<div class="entry">
  {{! This comment will not be in the output }}
  <!-- This comment will be in the output -->
</div>
어떠한 커멘트든 반드시 }} 을 포함하거나 다른 핸들바스의 토큰들은 {{!-- --}}을 사용해야한다.

Helpers

Handlebars의 헬퍼는 템플릿의 어떠한 컨텍스트로 부터든 접근이 가능하다. 헬퍼는 Handlebars.registerHelper 메소드를 이용하여 등록 가능하다.
<div class="post">
  <h1>By {{fullName author}}</h1>
  <div class="body">{{body}}</div>
  <h1>Comments</h1>
  {{#each comments}}
  <h2>By {{fullName author}}</h2>
  <div class="body">{{body}}</div>
  {{/each}}
</div>
컨텍스트와 헬퍼 사용
var context = {
  author: {firstName: "Alan", lastName: "Johnson"},
  body: "I Love Handlebars",
  comments: [{
    author: {firstName: "Yehuda", lastName: "Katz"},
    body: "Me too!"
  }]
};
Handlebars.registerHelper('fullName', function(person) {
  return person.firstName + " " + person.lastName;
});
결과는 다음과 같다.
<div class="post">
  <h1>By Alan Johnson</h1>
  <div class="body">I Love Handlebars</div>
  <h1>Comments</h1>
  <h2>By Yehuda Katz</h2>
  <div class="body">Me Too!</div>
</div>
헬퍼들은 함수내에서 this를 통해서 현재 컨텍스트에 접근이 가능하다.
<ul>
  {{#each items}}
  <li>{{agree_button}}</li>
  {{/each}}
</ul>
컨텍스트와 헬퍼의 사용
var context = {
  items: [
    {name: "Handlebars", emotion: "love"},
    {name: "Mustache", emotion: "enjoy"},
    {name: "Ember", emotion: "want to learn"}
  ]
};
Handlebars.registerHelper('agree_button', function() {
  var emotion = Handlebars.escapeExpression(this.emotion),
      name = Handlebars.escapeExpression(this.name);
  return new Handlebars.SafeString(
    "<button>I agree. I " + emotion + " " + name + "</button>"
  );
});
결과는 다음과 같다.
<ul>
  <li><button>I agree. I love Handlebars</button></li>
  <li><button>I agree. I enjoy Mustache</button></li>
  <li><button>I agree. I want to learn Ember</button></li>
</ul> 
만약 헬퍼가 HTML을 반환하는 경우 escape처리 되지 않기를 원할수 있다. 이때에는 Handlebars.SafeString을 이용하자.

Literals

Helper는 또한 자신들에거 전달된 literal values 를 가질 수 있을 것이다. 이것이 파리미터 아규먼트이든지, 해시 아규먼트이든지. 지원된 리터럴은 numbers, strings, true, false, null 그리고 undefined 를 포함한다.

{{agree_button "My Text" class="my-class" visible=true counter=4}}

Partials

Handlebars partials는 공유 템플릿을 생성하여 코드를 재사용 할 수 있다. 이 템플릿을 렌더링은 다음과 같이 한다.
<div class="post">
  {{> userMessage tagName="h1" }}
  <h1>Comments</h1>
  {{#each comments}}
    {{> userMessage tagName="h2" }}
  {{/each}}
</div>
partial과 context를 시용하는 경우는 다음과 같다.
Handlebars.registerPartial('userMessage',
    '<{{tagName}}>By {{author.firstName}} {{author.lastName}}</{{tagName}}>'
    + '<div class="body">{{body}}</div>');
var context = {
  author: {firstName: "Alan", lastName: "Johnson"},
  body: "I Love Handlebars",
  comments: [{
    author: {firstName: "Yehuda", lastName: "Katz"},
    body: "Me too!"
  }]
};
결과는 다음과 같다.
<div class="post">
  <h1>By Alan Johnson</h1>
  <div class="body">I Love Handlebars</div>
  <h1>Comments</h1>
  <h2>By Yehuda Katz</h2>
  <div class="body">Me Too!</div>
</div>

1. handlebars 설치
















[handlebars] 핸들바스 설치

[handlebars] 핸들바스 설치
핸들바스 설치 방법 :

NPM 

Handlebars의 npm 패키지는 CommonJS 감지 시스템을 위한 라이브러리와 내장 브라우저 라이브러리 둘다 포함하고 있다.

npm install --save handlebars

Require 감지 시스템은 Node와 Webpack등의 시스템에서는
require('handlebars');
 혹은 런타임에서 바로 사용
require('handlebars/runtime');

# 참고 :
브라우저 빌드는 node_modules/handlebars/dist/ 디렉토리에 위치한다.
이 방식은 precompiler를 이용하여 프리컴파일된 템플릿을 이용할때 매우 유용한 방법이다. 이는 항상 동일한 버젼에서 동작하도록 해준다.

Bower

Handlebars 는 bower compoment를 관리한다. 다음과 같이 설치가 가능하다.
bower install --save handlebars 
기본 bower 라이브러리는 UMD 스타일이며 이는 global, CJS 그리고 AMD 모듈 시스템에 적합하게 돌아간다. handlebars.js와 handlebars.runtime.js는 주요 소스 파일이다. 그러나 이 컴포넌트에는 다른 옵션들도 있다.

Manual Download

모든 handlebars릴리즈 버젼과 CI빌드들은 S3인 builds page에서 다운로드 받을수 있다.
가장 마지막에 빌드된 handlebars버젼은 handlebars-latest.js이다.

노트 : S3 빌드버젼은 커뮤니티를 위해서 제공되는 기능이다. 이것을 실제 제품에 이용하는 것은 좋지않다.

CDN

Handlebars는 CDN에서 받을수 있다.


2. handlebars 체험하기

















[NPM] npm install시 package.json 사용하기.

[NPM] npm install시 package.json 사용하기.
npm 의존성 패키지를 설치하는 방법으로 package.json을 생성하여 이용하는 방법이 있다.

package.json 파일을 사용하면 얻는 이점
1. package.json 자체로 프로젝트에서 어떠한 의존성을 이용하고 있는지 설명해준다.
2. semantic version rules를 이용하여 프로젝트의 패키지 버젼을 지정할 수 있다.
3. 빌드를 다시 수행할 수 있다. 이는 다른 개발자와 협업을 쉽게 해준다.

필수사항 : 

package.json의 최소 요건은 다음과 같다.

1. "name"
- 모두 소문자로 작성 되어야한다.
- 공백 없이 한단어가 되어야한다.
- 대쉬(-), 언더스코어(_) 는 허용된다.

2. "version"

예제 :
{
  "name": "test-package",
  "version": "1.0.0"
}

package.json 생성하기

package.json을 생성하는 2가지 방법은 다음과 같다.

1. 대화형 
// 대화형식으로 물어보면서 package.json 파일을 생성한다.
npm init
대화형 패키지 생성 과정 :
KIDOui-iMac:~ KIDO$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible 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: (KIDO) test-package
version: (1.0.0)
description: my_test_package
git repository:
author: test_author
license: (ISC) ISC
About to write to /Users/KIDO/package.json:
{
  "name": "test-package",
  "version": "1.0.0",
  "description": "my_test_package",
  "main": "index.js",
  "dependencies": {
    "connect": "^3.4.1"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "test_author",
  "license": "ISC"
}

Is this ok? (yes) yes 

 2. 기본 생성형 
// 디폴트 값을 이용하여 package.json파일을 생성한다.
npm --yes
npm -y

디폴트 생성결과
KIDOui-iMac:~ KIDO$ cat package.json
{
  "name": "KIDO",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {
    "connect": "^3.4.1"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"

필드 설명 : 

name
- 기본적으로 author의 이름이며, 지정하지 않는경우 git의 리포지토리 이름이 세팅된다.

version
- 항상 1.0.0이다.

main
- 항상 index.js이다.

scripts
- 입력하지 않으면 기본적으로 test 스크립트를 생성한다.

keywords
- 빈값이 기본으로 들어간다.

author
- CLI가 제공된경우 해당 내용이 표시된다.

license
- ISC이다.

repository
- git등이 존재하면 현재 디렉토리의 정보를 뽑아올 것이다.

bugs
- 현재 디렉토리로 부터 정보를 뽑아온다.

homepage
- 현재 디렉토리로 부터 정보를 뽑아온다.

기본적으로 몇가지 설정 옵션을 init command에 설정할 수 있다.
> npm set init.author.email "wombat@npmjs.com"
> npm set init.author.name "ag_dubs"
> npm set init.license "MIT"

패키지 의존성 지정하기. 

패키지 의존성을 지정하는 타입은 2가지가 있다.
"dependencies" : 이 패키지들은 프로덕션에서 당신의 어플리케이션에 의해 필요한 패키지를 나열한다.
"devDependencies" : 이 패미지들은 오직 개발과 테스팅에서만 필요한 패키지를 나열한다.


수동으로 의존성 지정하기. 

- 수동으로 의존성을 지정하기 위해서는 package.json 파일을 열고 dependencies와 devDepencencies 영역을 추가하면 된다.
{
  "name": "my_package",
  "version": "1.0.0",
  "dependencies": {
    "my_dep": "^1.0.0"
  },
  "devDependencies" : {
    "my_test_framework": "^3.1.0"
  }
}

자동으로 의존성 지정하기.

1. depencencies 영역에 추가하기.
npm install <package_name> --save
2. devDepencencies 영역에 추가하기.
npm install <package_name> --save-dev

참고 : https://docs.npmjs.com/getting-started/using-a-package.json