Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

bower : 웹 프론트앤드 패키지 관리자

bower를 알게 된 것은 Dani님의 포스팅을 보고 나서였지만 본격적으로 쓰기 시작한 것은 최근의 일이다. bower는 트위터에서 만든 프론트앤드용 패키지 매니저이다. node.js를 사용한다면 npm을 생각하면 이해하기 가장 쉬울것이고(실제로도 비슷하다.) 보통 언어별로 있는 의존성 라이브러리 관리자(메이븐, 루비젬 등등)이지만 bower는 프론트엔드 전용이라는 점이 다르다.


bower
bower를 처음 봤을 때의 시기나 지금이나 웹 프로젝트를 할 때마다 반복적으로 해야하는 jQuery를 다운받고 Bootstrap을 다운받는 등의 일을 어떻게 줄일까 고민하고 있고 일부는 grunt-init을 사용해서 해결하고 있다. bower를 처음 봤을 때 '오오~ 이거야~'라는 생각을 했음에도 불구하고 사용하지 않았던 것은 실제 필요에 비해서 좀 거추장스럽게 느껴진다는 점과(지금도 좀 그렇게 느낀다.) 그 이전에는 사용해 보지 않았던 components라는 어색한 이름때문이었다. 이런 부분이 크게 달라지진 않았지만 프론트앤드쪽도 이젠 의존성 관리가 거추장스러워져서 쓰기 시작했다.

Bower 홈페이지

bower는 기존에는 저장소는 twitter하단에서 사용했지만 프로젝트가 커져서 그런지 이제는 bower라는 계정으로 분리되었다. 그래서 검색으로 찾을 경우 일부 검색결과는 현재 깨지고 있다.

npm install -g bower

bower는 node.js로 만들어진 도구 이므로 npm을 이용해서 설치하고 커맨드라인 명령어로 사용하기 때문에 글로벌로 설치한다. 정상적으로 설치가 되면 bower -v로 버전정보를 확인할 수 있다.


bower 사용
bower는 npm과 매우 유사하므로 npm에 익숙하다면 bower도 쉽게 사용할 수 있다.

$ bower install jquery

위와 같이 실행하면 jquery를 다운받는다. bower는 기본적으로 components라는 폴더를 사용하므로 현재 위치에 components 폴더가 생성되고(npm 처럼 하위폴더에서 실행하더라도 상위의 bower 컴포넌트 위치를 찾아서 설치하는 기능은 없어보인다.)그 아래 jquery 폴더가 생성되고 이 아래 jquery관련 파일들을 다운받는다. 최초 다운로드시에는 시간이 걸리지만 로컬에 캐싱하므로(~/.bower) 이후부터는 빨라진다. 한번에 여러 컴포넌트를 설치하고 싶다면 bower install jquery bootstrap과 같이 사용하면 된다.(여전히 컴포넌트라는 이름이 어색하기는 하지만 자바스크립트와 CSS등을 한꺼번에 다루기 때문에 이런 이름을 정한 것으로 생각된다.) 다만 이때 설치는 해당 파일 하나만(jquery.js나 jquery.min.js 등) 받아오는 것이 아닌 bower 저장소에 패키징되서 저장된 내용을 모두 내려받는다. 설치한 bootstrap의 폴더 내용을 보면 다음과 같다.

$ ll components/bootstrap/
total 168
drwxr-xr-x  16 outsider  staff    544  4 29 19:57 .
drwxr-xr-x   4 outsider  staff    136  4 29 19:57 ..
-rw-r--r--   1 outsider  staff    344  4 28 20:25 .gitignore
-rw-r--r--   1 outsider  staff     34  4 28 20:25 .travis.yml
-rw-r--r--   1 outsider  staff  25120  4 28 20:25 CHANGELOG.md
-rw-r--r--   1 outsider  staff   3488  4 29 19:56 CONTRIBUTING.md
-rw-r--r--   1 outsider  staff  10172  4 28 20:25 LICENSE
-rw-r--r--   1 outsider  staff   4561  4 28 20:25 Makefile
-rw-r--r--   1 outsider  staff   4599  4 28 20:25 README.md
-rw-r--r--   1 outsider  staff   5308  4 29 19:57 component.json
-rw-r--r--   1 outsider  staff    297  4 28 20:25 composer.json
drwxr-xr-x  14 outsider  staff    476  4 28 20:25 docs
drwxr-xr-x   4 outsider  staff    136  4 28 20:25 img
drwxr-xr-x  17 outsider  staff    578  4 28 20:25 js
drwxr-xr-x  44 outsider  staff   1496  4 28 20:25 less
-rw-r--r--   1 outsider  staff    700  4 28 20:25 package.json

그래서 html페이지에서 참조할 때도 components/bootstrap/docs/assets/css/bootstrap.css나(bootstrap은 빌드된 파일이 좀 특이한 위치에 있다.) components/jquery/jquery.js로 참조해야 한다. 이는 일반적으로 정적파일 폴더 아래 js, css, images 등으로 구분해 놓고 사용하던 관례에 맞지 않고 경로도 상당히 복잡해 지지만(components 하위의 경로는 바꿀 수 없다.) bower를 쓰려면 어쩔 수 없어 보인다. bower는 단순 팩키지 매니저일 뿐이므로 배포시에 이런 파일들이 함께 배포되는 것이 싫다면 별도로 배포과정에서 처리를 해주어야 할 것 같다.

$ bower install jquery#1.9.1

버전을 지정해서 설치하고 싶다면 뒤에 #과 함께 버전번호를 붙혀준다.

$ bower uninstall jquery

설치한 컴포넌트를 제거하고 싶다면 uninstall 명령어를 사용한다. 사실 이는 그냥 components 폴더 아래 해당 폴더를 삭제해 준 것과 동일하다.
 

$ bower list
bower discover Please wait while newer package versions are being discovered
example
├─┬ bootstrap#2.3.1
│ └── jquery#1.8.3 (2.0.0 now available)
└── jquery#1.8.3 (2.0.0 now available)

bower list 혹은 bower ls로 현재 폴더 하위에 설치된 컴포넌트들의 목록을 확인할 수 있고 최신버전이 아닌 경우 옆에 최신버전이 표시된다. 계층 구조라서 보기는 쉽지만 여기서 약간 조심해야 할 점이 있는데(npm에 익숙하다면 특히) 위와 같이 계층 구조로 나오기는 하지만 최상위의 jquery와 bootstrap하위의 jquery는 사실 같은 폴더이다. 그러므로 jquery의 버전을 올리면 양쪽이 모두 올라가게 된다. 저렇게 계층으로 표시되는 이유는 bootstrap안에서 jquery에 대한 의존성이 표시되어 있기 때문인데 실제로 node.js 처럼 폴더의 계층으로 의존성을 갖지 않으므로 두 jQuery는 사실상 같다. 이는 프론트앤드에서는 각 파일이 자신만의 의존성을 갖는것이 아니라 html에서 제어를 하게 되므로 당연한 선택으로 생각된다.

$ bower search d3
Search results:

    d3 git://github.com/mbostock/d3.git
    nvd3 git://github.com/novus/nvd3
    d3-plugins git://github.com/d3/d3-plugins.git
    github-d3 git://github.com/github/d3.git
    d3cloud git://github.com/rajenms/d3-cloud.git
    d3-tip git://github.com/Caged/d3-tip.git
    d3-treelayout git://github.com/MfgLabs/d3-treelayout.git

원하는 컴포넌트가 존재하는지 찾고 싶다면 search 명령어를 사용하면 된다. 패키지명에 검색어가 들어간 패키지를 모두 찾아준고 검색어를 생략하면 모든 패키지가 다 출력된다.

$ bower lookup d3
d3 git://github.com/mbostock/d3.git

패키지명으로 검색하고 싶다면 lookup 명령어를 사용하고 이는 일치하는 패키지명만 출력된다. 일치하는 이름이 없는 경우에는 비슷한 패키지를 추천해준다.

$ bower info jquery
jquery

  Versions:
    - 2.0.0
    - 1.9.1
    - 1.8.3
    - 1.8.2
    - 1.8.1
    - 1.8.0
    - 1.7.2
    - 1.7.1
    - 1.7.0
    - 1.6.4
    - 1.6.3
    - 1.6.2
    - 1.6.1
    - 1.6.0
    - 1.5.2
    - 1.5.1
    - 1.5.0
    - 1.4.4
    - 1.4.3
    - 1.4.2
    - 1.4.1
    - 1.4.0
    - 1.3.2
    - 1.3.1
    - 1.3.0
    - 1.2.6
    - 1.2.3

패키지의 버전 정보를 알고 싶다면 info 명령어를 사용한다. npm과는 달리 간단히 버전 정보의 목록만 나타난다.


bower.json
보통 프로젝트의 의존성은 동일하게 가져가므로 설치한 패키지에 대한 정보를 명시해야 하는데 npm에서는 package.json에 명시하고 Maven에서는 pom.xml에 명시한다. bower에서는 bower.json을 사용하는데 이전 버전에서는 component.json을 사용하다가 0.9.0 버전부터는 bower.json을 사용하고 있다.

$ bower init
name: [example]
version: [0.0.0] 0.1.0
main file: []
add commonly ignored files to ignore list? (y/n): [y] y

bower init을 사용하면 다음과 같은 bower.json을 생성할 수 있다

{
  "name": "example",
  "version": "0.1.0",
  "ignore": [
    "**/.*",
    "node_modules",
    "components"
  ]
}

bower.json에서 각 값의 의미는 아래와 같다.

  • name: (필수값) 팩키지명
  • version: 버전 정보
  • main: 패키지의 엔드포인트
  • ignore: 패키지를 설치할 때 bower가 무시할 파일 목록
  • dependencies : 프로덕션에서 사용할 패키지 의존성 정보
  • devDependencies : 개발용 패키지 의존성 정보

작성한 프로젝트를 bower에 배포할 것이 아니라면 dependenciesdevDependencies외이는 큰 의미는 없다.

{
  "dependencies": {
    "jquery": "~2.0.0"
  },
  "devDependencies": {
    "qunit": "~1.11.0"
  }
}

의존성은 위와 같이 작성하면 되고 버전 표기 방식은 npm과 동일해 보인다("package.json으로 npm 의존성 모듈 관리하기" 참고) bower.json에 의존성이 명시되어 있다면 bower install 만 실행하면 자동으로 bower.json에 명시된 컴포넌트들을 다운받아서 설치한다. 참고로 bower update 명령어도 있는데 예상과 달리 새로운 버전이 있어도 update 명령어로는 새로운 버전을 설치하지 않는다.(명령어가 좀...) 좀 테스트를 해봤는데 잘 모르겠다...(이건 나중에..)

$ bower install jquery --save
$ bower install qunit --save-dev

bower.json에 일일이 버전을 표기하는 것이 귀찮다면 --save--save-dev 옵션을 사용하면 설치하면서 자동으로 bower.json 파일의 의존성 부분에 설치버전으로 추가를 해준다.


.bowerrc
bower에 전체적으로 적용할 설정을 사용자의 홈디렉토리에 .bowerrc 파일을 만들어서 지정할 수 있다. .bowerrc파일은 다음과 같은 JSON 형식이다.

{
  "directory": "bower_components",
  "endpoint": "https://bower.mycompany.com",
  "json": "bower.json",
  "searchpath": [
    "https://bower.herokuapp.com"
  ],
  "shorthand_resolver": "git://example.com/{{{ organization }}}/{{{ package }}}.git"
}

  • directory : 컴포넌트를 설치할 기본 디렉토리
  • endpoint: 커스텀 등록 엔드포인트
  • json: 의존성을 처리할 때 사용할 기본 JSON 파일
  • searchpath: 추가적으로 검색할 읽기전용 Bower 저장소
  • shorthand_resolver: 간단하게 지정할 패키지명의 템플릿
shorthand_resolver의 경우 기본 값이 github이므로 account/repository 처럼 지정할 수도 있다.


bower의 장점
초반에 bower를 접했을 때 느꼈던 것처럼 약간 거추장스럽게 느껴질 수도 있다.
하지만..

  • 프론트앤드쪽 라이브러리도 많이 복잡해 졌기 때문에 의존성 관리가 필요하다. 경로가 좀 복잡해 지지만 부트스트랩같은 경우 안에 css, js, img등이 있으므로 일일이 나눠서 복사해주거나 어차피 전체를 하나의 폴더안에 넣어야 한다.)
  • 변경사항을 추적할 필요가 없는 의존성 라이브러리를 저장소에 추가하는 것은 낭비다.(프론트앤드라서 익숙치 않아서 그렇지 개념은 서버와 동일하다. 물론 서버는 보통 바이너리라는 차이가 있지만)
  • json 파일만 공유하고 의존성 라이브러리는 각자 설치해서 사용하는 것이 더 좋은 접근으로 보인다.(물론 프론트앤드에서는 아직 익숙치 않으므로 불필요한 과정이 늘어난 것으로 보일수도 있다.)

2013/04/29 23:57 2013/04/29 23:57