Ember CLI 환경 구성하기

이 글은 NVM, Node Version Manager를 사용하여 Ubuntu 15.04 환경에서 Node.js와 npm 환경을 간단하게 구성하는 과정을 정리한 글이며, 궁극적으로 npm을 이용하여 Ember-CLI 환경을 구성하고 Ember.js 프로젝트를 진행할 수 있는 환경을 완성하는 과정의 기록이다.

시대의 변화와 나의 목표

지난 겨울, 오랜만에 개발이 끼어있는 프로젝트를 진행했다. 이 과정에서 Client 영역의 역할을 강화하고, 동시에 Backend를 API Service 형태로 표준화하여 향후 “조각난 단위 서비스"의 조합으로 “통합 운영관리 환경"을 구성할 수 있는 기반을 만들고자 했고 이를 위한 표준 Client 요소로 Ember.js를 선택했다.

이 과정에서 다음과 같은 개념, Paradigm을 결합/정제하여 사용했는데, 이 구성에 대한 내용은 다음에 기회가 되면 정리를 하려고 한다.

  • Backend as a Service API
  • API-First Design
  • Client-side MVC
  • Micro-Service Architecture

Ember, Ember-CLI 그리고 Node.js

Ember.js는 홈페이지에 “A framework for creating ambitious web applications"라는 표어를 걸고 있다. 말 그대로 Web Application을 개발하기 위한 프레임워크다. 다만, 기존에 익숙한 “프레임워크” 개념과 대비되는 내용은, 이것이 Server 측에 Runtime과 함께 구성되는 형태의 것이 아니라 Client 측에서 동작하는 MVC 모델을 제공한다는 점이다. 즉, 서버로부터 App을 Download한 후 Ember.js App이 동작하게 되면, App 내부에 존재하는 Adapter에 의해 Server가 제공하는 Data를 내려받아 App 내부의 Model로 재구성한 후, 각종 Control에 의해 Client 측에서 업무를 수행하게 되는 것이다. 물론, 보존되어야 하는 결과는 다시 Adapter를 통해 Server 측으로 전송/저장된다.

Ember-CLI는 이러한 Ember.js Application을 쉽게 구성할 수 있도록 돕는 개발환경이다. 개인적인 경험으로 보면, 이런 유형의 개발환경은 Ruby on Rails가 처음이었던 것 같은데, Rails에 대한 경험이 있다면 Ember-CLI의 역할을 쉽게 이해할 수 있을 것 같다.

RoR 프로젝트를 시작할 때 rails new와 같은 명령을 이용하여 App Skeleton을 쉽게 구성하고, 역시 rails generate 명령을 이용하여 Model, Controller, 그리고 View의 기본 골격을 표준 코드와 함께 만들어낼 수 있었다.
Ember-CLI 역시, 이와 유사하게 Ember App을 시작하기 위한 골격을 만들어주고, App 안에서 Model, Controller 등 구성요소를 쉽게 생성할 수 있도록 도와준다. RoR과 차이가 있다면 Ember-CLI는 간단한 시험용 Web Server가 내장되어 있을 뿐, 별도의 Runtime이 제공되지 않는다.

앞서 잠깐 얘기한 바와 같이, Ember는 최종적으로 만들어진 App이 Client 쪽에 Download가 된 후 Javascript가 지원되는 Browser 위에서 구동되기 때문에, Server 측에서는 단지 Static한 파일을 제공할 뿐, 별도의 Runtime이라는 것이 존재하지 않는 것이다.

npmNode.js에 포함되어 있는 패키지 관리도구이다. 이름을 풀면, Node.js Package Manger 쯤 될 것 같은데, 홈페이지 머릿글에는 “npm is the package manager for A,B,C,D,… javascript.” 라고 표현하고 있다. 어쩌면 Node.js의 기세를 알려주는 부분인데, 2015년 12월 8일 오늘의 설명은 213,112개의 패키지를 제공한다고 한다.
20만 패키지 중의 하나인 Ember-CLI는 Node.js 기반으로 동작하는 도구로, 바로 이 npm을 통하여 설치를 하게 된다.

Node.js는 뭐 말이 필요없을 것 같다.

Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js’ package ecosystem, npm, is the largest ecosystem of open source libraries in the world.

아무튼, Node.js는 Javascript가 바로 지금 IT의 화두로 다시 떠오르는 현상의 일등공신이며, 일단 이 글에서는 Ember-CLI를 동작하기 위한 기반환경이다.

NVM은 Node.js Version Manager를 줄인 이름으로, Ember.js, Ember-CLI, 또는 Node.js 환경구성을 위한 필수요소는 아니다. 단지, RedHat, Ubuntu 등의 OS 제공자에 의해 OS와 함께 배포되는 (아마도 오래된) 버전이 아닌 Node.js가 직접 제공하는 최신버전 또는 공식버전을 OS의 패키지 관리체계와 독립적으로 설치하고 활용하기 위한 도구이다.

Node.js 환경을 구성하는 방식은 여러가지가 있는데, 간략하게 보았을 때, 각각 다음과 같은 특성을 갖고 있다.

방식버전장점
OS 표준 패키지 사용OS 제공자가 정한 버전설치가 간단하고 익숙함
NodeSource Node.js Binary Distributions최신 버전역시 익숙함
NodeSource Docker Images최신 버전쉽게 Docker와 연계
Node.js Version Manager다양한 버전동시에 다양한 버전 활용

필요에 따라, NVM외에도 다음의 추가 옵션을 고민해볼 수 있다.

길었는데, 이제 실제의 설치과정이다.

Ember-CLI 환경 구성

Ember-CLI의 설치는 다음과 같은 순서로 진행된다.

  1. nvm 설치
  2. nvm을 통하여 Node.js 설치 (npm이 함께 제공됨)
  3. npm을 통하여 Ember-CLI 설치

기본 환경 준비

먼저, 다음과 같은 명령으로 기본적인 Build가 가능한 환경을 구성해준다.

$ sudo apt-get install build-essential libssl-dev

nvm의 설치

nvm은 github repository를 통하여 설치스크립트를 내려받아 실행하는 형태로 설치가 진행되며, 설치 과정에서 repository cloning을 하는 구조로 되어있다.

다음과 같은 명령으로, 최신 버전의 nvm을 설치해준다.

$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  7731  100  7731    0     0  25393      0 --:--:-- --:--:-- --:--:-- 25430
=> Downloading nvm from git to '/home/sio4/.nvm'
=> Cloning into '/home/sio4/.nvm'...
remote: Counting objects: 4168, done.
remote: Compressing objects: 100% (23/23), done.
remote: Total 4168 (delta 10), reused 0 (delta 0), pack-reused 4145
Receiving objects: 100% (4168/4168), 1.05 MiB | 226.00 KiB/s, done.
Resolving deltas: 100% (2418/2418), done.
Checking connectivity... done.
* (detached from v0.29.0)
  master

=> Appending source string to /home/sio4/.bashrc
=> Close and reopen your terminal to start using nvm
$ 

위와 같이, curl 명령으로 내려받은 스크립트를 실행시키면, 실행시킨 사용자 Home아래의 .nvm 경로에 repository cloning이 이루어진다.

설치된 내용을 확인해보면 다음과 같다.

$ nvm --version
0.29.0
$ du -sh .nvm
2.2M	.nvm
$ nvm version-remote node
v5.1.1
$ nvm ls-remote node|tail -5
         v4.2.2
         v4.2.3
         v5.0.0
         v5.1.0
         v5.1.1
$ 

맨 처음의 --version 옵션으로 설치된 nvm 명령의 버전확인이 가능하다. 두 번째 명령으로 확인한 바와 같이, 이 패키지가 시스템에 차지하는 footprint는 약 2MB 정도이다.
세 번째 명령과 네 번째 명령으로, 원격 저장소에서 제공하는 Node.js의 최신 버전과 제공하는 모든 버전을 각각 확인할 수 있다.

추가로, 위의 설치과정의 맨 끝을 보면, .bashrc에 뭔가 추가했다는 내용이 나온다. 그 내용은 아래와 같으며, nvm 환경 초기화를 위한 구문이다.

export NVM_DIR="/home/sio4/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"  # This loads nvm

node.js의 설치

이제 node.js를 설치할 차례이다. 다음과 같이, 원하는 버전을 인수로 주고 install 부명령을 사용하게 되면 해당 버전의 node.js를 설치할 수 있다.

$ nvm install v4.0.0
Downloading https://nodejs.org/dist/v4.0.0/node-v4.0.0-linux-x64.tar.xz...
######################################################################## 100.0%
WARNING: checksums are currently disabled for node.js v4.0 and later
Now using node v4.0.0 (npm v2.14.2)
$ nvm version
v4.0.0
$ nvm ls
->       v4.0.0
         system
node -> stable (-> v4.0.0) (default)
stable -> 4.0 (-> v4.0.0) (default)
iojs -> N/A (default)
$ 

설치 과정은 위와 같이, 바이너리 버전을 공식 사이트로부터 내려받아서 풀어주는 행태로 진행된다.

앞서 ls-remote 부명령이 원격지의 제공 가능한 모든 버전을 보여준 것과 같이, ls 부명령은 현재 시스템에 설치된 사용 가능한 모든 버전의 목록을 보여준다. 여기서 system은 시스템에 설치된 OS 제공자의 버전을 말하며 앞에 화살표가 붙은 v4.0.0nvm에 의해 설치한 버전이며 현재 선택된 버전임을 뜻한다.

이제 실제의 명령을 실행해서 적용된 버전을 확인해보자.

$ node --version
v4.0.0
$ npm --version
2.14.2
$ which node
/home/sio4/.nvm/versions/node/v4.0.0/bin/node
$ which npm
/home/sio4/.nvm/versions/node/v4.0.0/bin/npm
$ 

이렇게, node 명령을 실행했을 때, 원했던 바와 같이 4.0 버전이 실행되는 것을 볼 수 있고, npm 역시 같이 사용 가능한 상태로 있음을 볼 수 있다. 또한, which 명령을 이용하여 어떤 경로의 실행파일이 실행되는지도 확인이 가능하다.

ember-cli의 설치, 맛보기 (따라하지 말자)

npm install 명령을 사용하여 다음과 같이 ember-cli를 설치할 수 있다. 이 작업은 nvm과는 별개의 npm 세상의 기능이다. 아래와 같은 명령을 수행하여 패키지를 설치하게 되면, 현재경로 아래node_modules 라는 이름의 경로가 생성되고 이 안에 ember-cli가 설치된다.

$ npm install ember-cli
npm WARN deprecated lodash-node@2.4.1: This package is no longer maintained. See its readme for upgrade details.
npm WARN deprecated lodash@2.4.2: lodash@<3.0.0 is no longer maintained. Upgrade to lodash@^3.0.0
npm WARN deprecated lodash-node@3.10.1: This package is no longer maintained. See its readme for upgrade details.
npm WARN deprecated lodash@2.3.0: lodash@<3.0.0 is no longer maintained. Upgrade to lodash@^3.0.0
ember-cli@1.13.13 node_modules/ember-cli
├── ember-cli-is-package-missing@1.0.0
├── ember-cli-path-utils@1.0.0
├── ember-cli-test-info@1.0.0
├── ember-cli-string-utils@1.0.0
├── ember-cli-get-dependency-depth@1.0.0
<...>
$ 

설치 후, 디스크 사용량을 보면 아래와 같다.

$ du -sh ~/.nvm ~/.npm node_modules
43M	/home/sio4/.nvm
42M	/home/sio4/.npm
143M	node_modules
$ 

위에서 보는 바와 같이, ~/.nvm에는 nvm 자체와 내려받은 버전의 node.js가 차지하는 용량 만큼이 사용되며, ~/.npmnpm에 의해 내려받아진 패키지가 사용하는 만큼 크기가 증가한다. 최종적으로, 내려받아진 패키지는 사용 가능한 형태로 풀려서 node_modules에 저장되게 된다.

문제는, 이렇게 설치된 ember-cli 패키지는 현재의 프로젝트, 현재 경로에 고립되게 되며 Ember-CLI의 특성과는 다른 구성이 된다. (ember-cli 명령은 프로젝트 내부에서도 자주 실행되지만, 그에 앞서 프로젝트 자체를 생성하는 용도가 매우 크기 때문에…)

Global 옵션으로 ember-cli 설치

다음과 같이, npm install 명령을 -g 옵션과 함께 실행해주면 패키지의 설치 Scope을 “프로젝트"에서 “Global"로 옮겨가게 할 수 있다. 즉, 설치되는 파일의 저장 위치가 현재 경로로부터 Node.js 설치 Tree 아래로 옮겨가게 되고 특정 프로젝트에 종속적인 것이 아닌 시스템(nvm 개념 하에서는 특정 버전) 전역에서 사용 가능하도록 설치를 할 수 있게 된다. (output이 길지만 기록을 위해…)

$ npm -g install ember-cli
npm WARN deprecated lodash-node@2.4.1: This package is no longer maintained. See its readme for upgrade details.
npm WARN deprecated lodash-node@3.10.1: This package is no longer maintained. See its readme for upgrade details.
/home/sio4/.nvm/versions/node/v4.0.0/bin/ember -> /home/sio4/.nvm/versions/node/v4.0.0/lib/node_modules/ember-cli/bin/ember
ember-cli@1.13.13 /home/sio4/.nvm/versions/node/v4.0.0/lib/node_modules/ember-cli
├── ember-cli-is-package-missing@1.0.0
├── ember-cli-path-utils@1.0.0
├── ember-cli-test-info@1.0.0
├── ember-cli-string-utils@1.0.0
├── ember-cli-get-dependency-depth@1.0.0
├── clean-base-url@1.0.0
├── ember-cli-normalize-entity-name@1.0.0
├── silent-error@1.0.0
├── amd-name-resolver@0.0.2
├── fs-monitor-stack@1.1.0
├── escape-string-regexp@1.0.3
├── pleasant-progress@1.1.0
├── is-git-url@0.2.3
├── isbinaryfile@2.0.4
├── ember-cli-copy-dereference@1.0.0
├── broccoli-source@1.1.0
├── exists-sync@0.0.3
├── promise-map-series@0.2.2
├── diff@1.4.0
├── node-modules-path@1.0.1
├── broccoli-viz@2.0.1
├── through@2.3.8
├── bower-endpoint-parser@0.2.2
├── walk-sync@0.1.3
├── broccoli-merge-trees@1.0.0
├── inflection@1.8.0
├── node-uuid@1.4.7
├── exit@0.1.2
├── broccoli-sane-watcher@1.1.4 (broccoli-slow-trees@1.1.0)
├── symlink-or-copy@1.0.1 (copy-dereference@1.0.0)
├── temp@0.8.1 (rimraf@2.2.8)
├── debug@2.2.0 (ms@0.7.1)
├── nopt@3.0.6 (abbrev@1.0.7)
├── http-proxy@1.12.0 (eventemitter3@1.1.1, requires-port@0.0.1)
├── findup@0.1.5 (commander@2.1.0, colors@0.6.2)
├── semver@4.3.6
├── chalk@1.1.0 (supports-color@2.0.0, ansi-styles@2.1.0, has-ansi@2.0.0, strip-ansi@3.0.0)
├── glob@5.0.13 (path-is-absolute@1.0.0, inherits@2.0.1, once@1.3.3, inflight@1.0.4)
├── readline2@0.1.1 (mute-stream@0.0.4, strip-ansi@2.0.1)
├── morgan@1.6.1 (on-headers@1.0.1, basic-auth@1.0.3, depd@1.0.1, on-finished@2.3.0)
├── rsvp@3.1.0
├── findup-sync@0.2.1 (glob@4.3.5)
├── minimatch@2.0.10 (brace-expansion@1.1.2)
├── broccoli-kitchen-sink-helpers@0.2.9 (mkdirp@0.5.1)
├── resolve@1.1.6
├── git-repo-info@1.1.2
├── portfinder@0.4.0 (async@0.9.0, mkdirp@0.5.1)
├── configstore@1.2.1 (os-tmpdir@1.0.1, object-assign@3.0.0, graceful-fs@4.1.2, uuid@2.0.1, osenv@0.1.3, xdg-basedir@2.0.0, write-file-atomic@1.1.4, mkdirp@0.5.1)
├── cpr@0.4.2 (graceful-fs@4.1.2, mkdirp@0.5.1, rimraf@2.4.4)
├── sane@1.3.0 (watch@0.10.0, minimist@1.2.0, exec-sh@0.2.0, walker@1.0.7, minimatch@0.2.14, fb-watchman@1.6.0)
├── compression@1.6.0 (bytes@2.1.0, on-headers@1.0.1, vary@1.1.0, compressible@2.0.6, accepts@1.3.0)
├── broccoli-funnel@1.0.1 (array-equal@1.0.0, blank-object@1.0.1, path-posix@1.0.0, fs-tree-diff@0.3.1, fast-ordered-set@1.0.2, walk-sync@0.2.6, mkdirp@0.5.1, rimraf@2.4.4)
├── broccoli-plugin@1.2.1 (rimraf@2.4.4)
├── fs-extra@0.22.1 (jsonfile@2.2.3, graceful-fs@4.1.2, rimraf@2.4.4)
├── broccoli-config-replace@1.1.0 (broccoli-kitchen-sink-helpers@0.3.1, fs-extra@0.24.0)
├── yam@0.0.18 (lodash.merge@3.3.2, fs-extra@0.16.5)
├── broccoli-config-loader@1.0.0 (broccoli-caching-writer@2.2.1)
├── express@4.13.3 (escape-html@1.0.2, merge-descriptors@1.0.0, array-flatten@1.1.1, cookie@0.1.3, utils-merge@1.0.0, cookie-signature@1.0.6, parseurl@1.3.0, methods@1.1.1, fresh@0.3.0, range-parser@1.0.3, vary@1.0.1, path-to-regexp@0.1.7, content-type@1.0.1, etag@1.7.0, content-disposition@0.5.0, serve-static@1.10.0, depd@1.0.1, on-finished@2.3.0, qs@4.0.0, finalhandler@0.4.0, proxy-addr@1.0.9, send@0.13.0, accepts@1.2.13, type-is@1.6.10)
├── ember-cli-preprocess-registry@1.1.0 (process-relative-require@1.0.0, broccoli-clean-css@0.2.0)
├── quick-temp@0.1.3 (mktemp@0.3.5, rimraf@2.2.8, underscore.string@2.3.3)
├── tiny-lr@0.2.0 (parseurl@1.3.0, qs@5.1.0, livereload-js@2.2.2, faye-websocket@0.10.0, body-parser@1.14.1)
├── merge-defaults@0.2.1 (lodash@2.4.2)
├── ember-router-generator@1.1.1 (recast@0.9.18)
├── markdown-it@4.3.0 (uc.micro@1.0.0, linkify-it@1.2.0, mdurl@1.0.1, entities@1.1.1, argparse@1.0.3)
├── lodash@3.10.1
├── bower-config@0.6.1 (osenv@0.0.3, graceful-fs@2.0.3, optimist@0.6.1, mout@0.9.1)
├── broccoli@0.16.8 (broccoli-slow-trees@1.1.0, copy-dereference@1.0.0, mime@1.3.4, commander@2.9.0, rimraf@2.4.4, connect@3.4.0, handlebars@3.0.3)
├── core-object@0.0.2 (lodash-node@2.4.1)
├── broccoli-sourcemap-concat@2.0.2 (mkdirp@0.5.1, broccoli-caching-writer@2.2.1, lodash.uniq@3.2.2, fast-sourcemap-concat@0.2.6, lodash-node@2.4.1)
├── inquirer@0.5.1 (mute-stream@0.0.4, async@0.8.0, chalk@0.4.0, lodash@2.4.2, cli-color@0.3.3)
├── markdown-it-terminal@0.0.2 (ansi-styles@2.1.0, cli-table@0.3.1, cardinal@0.5.0, lodash-node@3.10.1)
├── leek@0.0.18
├── testem@0.9.11 (styled_string@0.0.1, did_it_work@0.0.6, growl@1.8.1, printf@0.2.3, fileset@0.2.1, charm@1.0.0, xmldom@0.1.19, commander@2.9.0, mustache@2.2.0, async@1.5.0, mkdirp@0.5.1, rimraf@2.4.4, backbone@1.2.3, cross-spawn-async@2.1.1, tap-parser@1.2.2, consolidate@0.13.1, js-yaml@3.4.6, fireworm@0.6.6, npmlog@1.2.1, socket.io-pure@1.3.11)
├── broccoli-babel-transpiler@5.5.0 (clone@0.2.0, json-stable-stringify@1.0.0, broccoli-persistent-filter@1.1.6, babel-core@5.8.34)
├── npm@2.14.10
└── bower@1.7.0
$ 

설치가 끝면 list 명령으로 원하는 패키지가 의존성 관계에 있는 다른 패키지와 함께 설치된 계층 구조를 확인할 수 있다. 눈여겨 볼 부분은, 설치 위치가 현재 구동 중인 Node.js 버전 아래인 ~/.nvm/versions/node/v4.0.0/lib 라는 점이다.

$ npm -g list
/home/sio4/.nvm/versions/node/v4.0.0/lib
├─┬ ember-cli@1.13.13
│ ├── amd-name-resolver@0.0.2
│ ├─┬ bower@1.7.0
│ │ ├── abbrev@1.0.7
│ │ ├── archy@1.0.0
│ │ ├─┬ bower-config@1.3.0
<...>
$ 

각 경로 별 사용량은 아래와 같다. (현재경로에 설치되는 것은 없다.)

$ du -sh ~/.nvm ~/.npm 
185M	/home/sio4/.nvm
42M	/home/sio4/.npm
$ 

또하나 확인할 부분은, 설치 중 출력의 맨 윗부분에 있는 다음 줄이다.

/home/sio4/.nvm/versions/node/v4.0.0/bin/ember -> /home/sio4/.nvm/versions/node/v4.0.0/lib/node_modules/ember-cli/bin/ember

이 줄이 설명하고 있는 내용은, ember-cli 패키지에서 제공하는 ember라는 명령어가 Node.js 버전의 bin 안으로 Link되었다는 점이다. 이 과정을 통해서 이제 사용자는 ember 명령을 Direct로 실행할 수 있게 되었다.
오예! 그럼 드디어 Ember를 시작할 차례?

Ember-CLI로 Ember App 시작하기

앞서 얘기했듯이, Ember-CLI의 사용 방식과 개발 흐름은 RoR의 그것과 유사하다. 다음과 같이 new 부명령을 이용하여 Application의 Skeleton을 만들 수 있다.

$ ember new hardened-layer --skip-git 
version: 1.13.13
Could not find watchman, falling back to NodeWatcher for file system events.
Visit http://www.ember-cli.com/user-guide/#watchman for more info.
installing app
  create .bowerrc
  create .editorconfig
  create .ember-cli
  create .jshintrc
  create .travis.yml
  create .watchmanconfig
  create README.md
  create app/app.js
  create app/components/.gitkeep
  create app/controllers/.gitkeep
  create app/helpers/.gitkeep
  create app/index.html
  create app/models/.gitkeep
  create app/router.js
  create app/routes/.gitkeep
  create app/styles/app.css
  create app/templates/application.hbs
  create app/templates/components/.gitkeep
  create bower.json
  create config/environment.js
  create ember-cli-build.js
  create .gitignore
  create package.json
  create public/crossdomain.xml
  create public/robots.txt
  create testem.json
  create tests/.jshintrc
  create tests/helpers/destroy-app.js
  create tests/helpers/module-for-acceptance.js
  create tests/helpers/resolver.js
  create tests/helpers/start-app.js
  create tests/index.html
  create tests/integration/.gitkeep
  create tests/test-helper.js
  create tests/unit/.gitkeep
  create vendor/.gitkeep
Installed packages for tooling via npm.
Installed browser packages via Bower.
$ 

명령행을 보면 --skip-git 옵션을 준 것을 볼 수 있는데, Ember-CLI는 App을 만들자마자 App Tree 전체를 Git로 관리하도록 구성해버린다. 이게 편할 수도 있겠지만 나는 직접 버전 관리를 하는 것을 좋아하기 때문에 이 과정을 Skip할 수 있도록 했다.

출력의 마지막 두 줄을 보면, npm과 Bower를 이용하여 패키지 설치를 한다는 구문이 있다. Ember-CLI는 App 구성에 필요한 다양한 Node.js 패키지와 Bower로 관리되는 Javascript 요소들을 함께 설치해준다.

설치된 모습을 보면,

$ ls -F
README.md   bower_components/   node_modules/  testem.json
app/        config/             package.json   tests/
bower.json  ember-cli-build.js  public/        vendor/
$ du -sh *
4.0K	README.md
52K	app
4.0K	bower.json
14M	bower_components
8.0K	config
4.0K	ember-cli-build.js
218M	node_modules
4.0K	package.json
12K	public
4.0K	testem.json
44K	tests
4.0K	vendor
$ 

이렇게 bower_componentsnode_modules가 부풀어 있는 것을 볼 수 있고, 그 안에 아래와 같은 다양한 패키지가 설치된 것을 확인할 수 있다.

$ ls node_modules
broccoli-asset-rev/                    ember-cli-inject-live-reload/
ember-cli/                             ember-cli-qunit/
ember-cli-app-version/                 ember-cli-release/
<...>
$ ls bower_components
ember/                  ember-load-initializers/    jquery/
ember-cli-shims/        ember-qunit/                loader.js/
ember-cli-test-loader/  ember-qunit-notifications/  qunit/
<...>
$ 

마지막으로, 구성한 App을 시험해본다. Ember-CLI는 serve 부명령을 이용해서 개발 과정에서 시험용으로 사용할 수 있는 내장 Web Server를 구동할 수 있다.

$ ember serve
version: 1.13.13
Could not find watchman, falling back to NodeWatcher for file system events.
Visit http://www.ember-cli.com/user-guide/#watchman for more info.
Livereload server on http://localhost:49152
Serving on http://localhost:4200/

Build successful - 4329ms.

Slowest Trees                                 | Total               
----------------------------------------------+---------------------
ConcatWithMaps: Concat: Vendor                | 3300ms              

Slowest Trees (cumulative)                    | Total (avg)         
----------------------------------------------+---------------------
ConcatWithMaps: Concat: Vendor (1)            | 3300ms              
Babel (6)                                     | 527ms (87 ms)       

^C$

위의 출력을 보면, 4200 포트를 이용하여 서비스를 제공하면서, Livereload를 위한 포트가 함께 열리는 것을 확인할 수 있다. 또한, 이 App을 빌드하는 과정에 소요된 시간 정보를 사용자에게 알려줘서 개발 과정에서 도움이 될 수 있도록 하고 있다.

이제 Web Browser를 이용하여 위의 http://localhost:4200/로 접속해보자.

떳다!

화면 아래쪽에 표시된 Ember Inspector 부분은 별도로 구성한 Firefox Addon 이니까 나타나지 않더라도 실망하지 않아도 된다. (그러나 이게 있으면 개발이 휠씬 편해질테니, 필수로 설치하길 바란다.)

끝.

참고

참고 1: 링크로 구성하기

앞서 얘기했던 프로젝트 단위의 설치를 할 경우, install 부명령 대신 link 부명령을 사용하게 되면 프로젝트 경로 아래의 node_modules는 실제 패키지가 아닌 중앙에 설치된 패키지의 link로 채워지게 된다. (동일한 패키지를 여러 프로젝트에서 사용한다면 이런 방식으로 용량을 아낄 수 있다.)

$ mkdir project-a
$ cd project-a
$ npm link ember-cli
<...>
$ ls -l node_modules
합계 4
lrwxrwxrwx 1 sio4 61 12월  8 13:12 ember-cli -> ../../../.nvm/versions/node/v4.0.0/lib/node_modules/ember-cli
$ 

이런 상황에서 각 경로의 사용량을 확인해보면, 위의 Global 설치와 유사한 것을 확인할 수 있다.

$ du  -sh ~/.nvm ~/.npm node_modules/
185M	/home/sio4/.nvm
45M	/home/sio4/.npm
12K	node_modules/
$ 

참고 2: 디렉터리 내용 보기

Global 모드나, Link 모드로 설정된 경우, 각 경로에는 아래와 같은 형태로 파일들이 저장되어 있음을 확인할 수 있다.

  • npm 경로: 내려받은 패키지 파일
  • nvm 아래 버전 경로: 패키지의 실행 가능한 설치본

설명보다 명령의 결과가 깔끔하다.

$ ls ~/.npm/ember-cli/1.13.13/
package  package.tgz
$ ls ~/.nvm/versions/node/v4.0.0/lib/node_modules/ember-cli/
ADDON_HOOKS.md      CONTRIBUTING.md  TRANSITION.md  blueprints  node_modules
ARCHITECTURE.md     LICENSE.md       appveyor.yml   dev         package.json
CHANGELOG.md        README.md        assets         docs        tests
CODE_OF_CONDUCT.md  RELEASE.md       bin            lib
$ ls ~/.nvm/versions/node/v4.0.0/lib/node_modules/ember-cli/node_modules/
amd-name-resolver                findup-sync
bower                            fs-extra
bower-config                     fs-monitor-stack
<...>
$ 

참고 3: 사용할 버전 고르기

nvm를 이용한 설치의 특성 중 하나는, 이것이 단순히 하나의 환경을 위한 패키지 관리가 아니라 다양한 환경을 위한 실행 버전 관리라는 점이다.

모든 설치가 끝났음에도 불구하고 새롭게 쉘을 열어주면, 그 창에서 다시 node를 실행하면 OS 제공자에 의해 설치된 system 버전이 실행되게 되는 것을 알게 될 것이다.

$ node --version
v0.10.25
$ nvm ls
         v4.0.0
->       system
node -> stable (-> v4.0.0) (default)
stable -> 4.0 (-> v4.0.0) (default)
iojs -> N/A (default)
$ 

위와 같이, node --version 명령으로 확인해보면 새 세션에서는 시스템에 기본 설치된 것이 작동하게 된다. nvm ls 명령으로 확인해보면 역시, system 버전이 선택되어 있는 것을 볼 수 있다. 이 상태라면, 아래와 같이 use 부명령을 사용하여 이 세션에서 사용할 node.js 버전을 고를 수 있다.

$ nvm use v4.0.0
Now using node v4.0.0 (npm v2.14.2)
$ nvm ls
->       v4.0.0
         system
node -> stable (-> v4.0.0) (default)
stable -> 4.0 (-> v4.0.0) (default)
iojs -> N/A (default)
$ node --version
v4.0.0
$ npm --version
2.14.2
$ 

간단하지만 성가신 일이다. 이런 상황에서 새 세션에 대하여 기본적으로 사용할 버전을 지정하려면 alias 부명령을 사용하면 된다.

기본값 설정 전 상태

$ nvm ls
         v4.0.0
->       system
node -> stable (-> v4.0.0) (default)
stable -> 4.0 (-> v4.0.0) (default)
iojs -> N/A (default)
$ 

현재 존재하는 alias 확인

$ nvm alias
node -> stable (-> v4.0.0) (default)
stable -> 4.0 (-> v4.0.0) (default)
iojs -> N/A (default)
$ 

새로운 alias 생성 및 확인

$ nvm alias default node
default -> node (-> v4.0.0)
$ nvm alias
default -> node (-> v4.0.0)
node -> stable (-> v4.0.0) (default)
stable -> 4.0 (-> v4.0.0) (default)
iojs -> N/A (default)
$ 

그리고 새 쉘 세션을 시작했을 때의 결과

$ nvm ls
->       v4.0.0
         system
default -> node (-> v4.0.0)
node -> stable (-> v4.0.0) (default)
stable -> 4.0 (-> v4.0.0) (default)
iojs -> N/A (default)
$ 

참고 4: Ubuntu의 기본 node.js는 명령어가 node가 아닌 nodejs

Ubuntu는 Debian을 기반으로 하는 배포본인데, Debian 자체가 워낙 거인이다. 이미 node라는 이름의 패키지가 있기 때문에 Node.js의 명령어 이름은 원래 패키지 이름을 따라 nodejs 인데… 이게, Node.js의 명령어가 node임을 가정하고 제작된 다른 패키지들에게 혼선을 준다.

다음과 같은 명령을 통하여 node라는 명령을 내렸을 때 Node.js가 실행되도록 해줄 수 있다.

$ sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 99
update-alternatives: using /usr/bin/nodejs to provide /usr/bin/node (node) in auto mode
$ 

정말 끝!


더 보기

comments powered by Disqus