Client-side에서 패키지 관리를 위해서 bower를 자주 사용하는 편인데 bower는 module loader가 아니라 정말 말 그대로 패키지만 받아서 bower_components 에 넣어주는 정도의 역할만 하기 때문에 부수적인 작업이 많이 필요한 편이다. jspm은 module loader인 SystemJS를 기반으로 모듈을 불러온다. Traceur이나 Babel도 쉽게 적용할 수 있어 ES6 기준으로 개발하는데 편리하다.

jspm-cli를 먼저 설치한다.

$ npm install --global jspm/jspm-cli

프로젝트 폴더에서 jspm init로 프로젝트를 초기화 한다. 초기화 과정에서 프롬프트로 기본적인 사항들을 입력 받는데 ES6를 위해 어떤 transpiler를 사용할지 정할 수 있다. 여기서 설정한 모든 내용은 package.json에 저장되며 SystemJS를 위한 config.js 파일도 자동으로 생성된다.

$ jspm init

jspm으로 npm과 github에 있는 라이브러리를 쉽게 설치할 수 있다. (jspm install registry:package@version) 또한 alias로 등록되어 있는 라이브러리는 registry를 입력하지 않고도 설치할 수 있다. 그 목록은 registry 리포지터리에서 확인할 수 있다.

$ jspm install github:github/fetch
$ jspm install fetch

위에는 github의 fetch 구현을 사용했지만 whatwg-fetch를 사용할 수도 있다. 패키지를 사용할 때 패키지명을 다음과 같이 맵핑해서 사용할 수 있다. 다시 말하면 fetch에 맵핑하면 import "whatwg-fetch" 대신 import "fetch"로 불러오는 것이 가능하다.

$ jspm install fetch=npm:whatwg-fetch

다음 코드대로 index.html을 작성한다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Hello World</title>
    <script src="jspm_packages/system.js"></script>
    <script src="config.js"></script>
    <script>
        System.import('app/main'); // 진입점이 되는 js 경로
    </script>
</head>
<body></body>
</html>

app/main.js를 작성한다. github에서 haruair의 리포지터리 갯수를 구해 console.log로 출력한다.

import 'fetch'

fetch('https://api.github.com/users/haruair/repos')
  .then(response => response.json())
  .then(repos => console.log(repos.length))

이제 결과를 확인해보자. php -S localhost:8000 또는 python -m SimpleHTTPServer 8000으로 간단하게 서버를 띄워 console을 확인한다.

jspm의 장점은 js 뿐만 아니라 css와 같은 파일도 import 할 수 있어 컴포넌트 형태로 개발하기 쉽다. Webpack에서도 각 확장별로 loader를 지정해주면 알아서 처리해주지만 jspm은 설정 파일을 조작할 필요 없이 단순히 jspm의 systemjs/plugin-css만 설치하면 되는 편리함이 있다.

$ jspm install css

app/style.css를 간단하게 추가해서 확인해보자.

body {
  background: #0dd0dd;
}

방금 작성한 css 파일을 js에서 import 하는 것이 가능하다. 다음 코드를 app/main.js에 추가하면 페이지에서 css를 불러오는 것을 확인할 수 있다.

import './style.css!'

css 외에도 less도 가능하다. sass는 아직 systemJS을 지원하는 플러그인이 없는 것으로 보인다.

패키지 묶기 (bundle)

jspm은 bundle도 지원한다. 간단하게 jspm bundle 명령어로 묶을 수 있고 app/main과 같이 진입점을 사용하고 있는 경우 jspm bundle-sfx app/main -o <outfile> 식으로 묶을 수 있다.

Jack Franklin의 London React Meetup, ES6 Modules & React with SystemJS에서는 uglifyjs와 html-dist 패키지를 함께 활용해 다음과 같은 Makefile을 만들어 make build로 묶을 수 있도록 만들었다.

먼저 uglifyjs와 html-dist를 npm으로 설치해야 한다.

$ npm install --save-dev uglifyjs html-dist

다음 내용으로 Makefile을 만든다. 2행 이후의 내용은 모두 스페이스가 아닌 탭으로 시작해야 한다.

build:
    -rm -r dist/
    mkdir dist
    jspm bundle-sfx app/main -o dist/app.js
    ./node_modules/.bin/uglifyjs dist/app.js -o dist/app.min.js
    ./node_modules/.bin/html-dist index.html --remove-all --minify --insert app.min.js -o dist/index.html

이제 make build로 dist 폴더 내에 minify된 index.html과 번들된 app.js, app.map, 그리고 uglifyjs로 변환된 app.min.js를 확인할 수 있다.


jspm의 아쉬운 점은 아직 브라우저에서만 명확하게 동작한다는 점이다. registry에 등록되지 않은 패키지도 npm이나 github에서 직접 받을 수 있도록 지원하고 있지만 브라우저에서 제대로 지원하지 않는 라이브러리의 경우 사용할 수 없다. 또한 isomorphic한 방식으로 접근할 때 nodejs가 jspm으로 설치한 라이브러리를 불러오지 못하기 때문에 pre-rendering을 하려 한다면 중복되는 패키지를 다시 받아야 하는 불편함이 있다. 하지만 jspm은 무엇보다 설정을 배우는 것에 시간을 많이 쓰지 않고서도 ES6를 바로 사용할 수 있다는 장점이 있다. 또한 cli도 상당히 단순해서 다른 도구과 달리 바로 써먹을 수 있는 즐거움이 있다. 이 jspm이 서버측, 클라이언트측 모두 사용할 수 있도록 나온다면 말 그대로 강력함을 뽐내지 않을까 상상해본다. 🙂

AngularJS{{}} 방식의 인터폴레이션 마크업을 사용하는데 flask(jinja)django 등에서 {{ foo }} 형태의 템플릿 마크업을 이미 사용하고 있어서 문제가 된다. 이런 경우를 위해 AngularJS에서 $interpolateProvider를 지원하는데 이를 이용해 문제를 회피할 수 있다.

var customInterpolationApp = angular.module('customInterpolationApp', []);

customInterpolationApp.config(function($interpolateProvider) {
    $interpolateProvider.startSymbol('{@');
    $interpolateProvider.endSymbol('@}');
});

자세한 내용은 AngularJS의 $interpolateProvider 문서에서 확인할 수 있다.

2014년 4월 추가 : 에디터 적용을 위해 이 글을 보고 있다면 Summernote를 확인하자. http://hackerwins.github.io/summernote/


에디터 문제로 늘 골머리를 썩히고 있는데 naver smart editor를 적용하자니 jindo라는 프레임워크를 하나 더 올리는게 부담스러워서 사용하지 않았었습니다. 한동안 열심히 에디터를 찾아봤지만 적당한 대안이 없어 …그냥 도입하기로 했습니다.

적용하려고보니 약간 문제가 있었습니다. jindo 에서 jQuery랑 동일하게 $를 사용하고 있는 문제로 jquery에 네임스페이스(namespace)를 지정해서 사용해야 했는데 jindo를 에디터에만 사용하기 때문에 스마트 에디터를 수정해서 jindo의 네임스페이스를 사용하는 편이 낫다는 판단을 했습니다. 앗, 절대 jindo가 별로라거나 나쁘다는 의미가 아닙니다…ㅎㅎ 사내에서 이미 jQuery를 많이 사용하고 있어서 교차로 사용하기엔 교육 문제도 있으니까요.

  1. 먼저 nforge에서 smart editor, jindo(namespace)를 내려받습니다.
  2. jindo를 js 폴더에 넣고 js 폴더에 있는 js 파일들을 열어 아래의 정규식으로 치환해줍니다.
> (\$\$\(|\$\$\.|\$A\(|\$A\.|\$Agent\(|\$Agent\.|\$Ajax\(|\$Ajax\.|\$Class\(|\$Class\.|\$Cookie\(|\$Cookie\.|\$Date\(|\$Date\.|\$Document\(|\$Document\.|\$Element\(|\$Element\.|\$ElementList\(|\$ElementList\.|\$Event\(|\$Event\.|\$Fn\(|\$Fn\.|\$Form\(|\$Form\.|\$H\(|\$H\.|\$Jindo|\$Json\(|\$Json\.|\$S\(|\$S\.|\$Template\(|\$Template\.|\$Window\(|\$Window\.)
> jindo.\1

내용은 jindo 레퍼런스에서 긁어와서 무식하게 만들었습니다; 저는 에디터 플러스에서 했습니다. 정규표현식으로 치환이 가능한 도구를 사용하시면 되겠습니다.

차기 네이버 스마트 에디터에서는 네임스페이스 버전을 제공한다고 개발자센터에 써져 있는 것 보면 얼른 업데이트 되길 기대해봅니다. 근데 최종이 2009년 9월이네요.

Cufon은 font를 js 데이터로 변환해 canvas로 출력하는 방식으로, 기존 iFR, FIR, sFIR 처럼 텍스트를 그래픽 폰트로 변경해주는 도구다. canvas 기반이라 플래시보다 무겁진 않지만 글꼴의 끝부분이 다소 뭉개지는 현상이 있다. 한국어 폰트는 여전히 글자수가 많기 때문에 용량상 이득은 크게 없는 편이다.

Cufon에서 :hover를 사용하기 위해서는 다음과 같은 방법으로 작성해야 한다.

Cufon.replace('#navlist li a', { hover: true, fontFamily: 'MyFont' });
Cufon.replace('h2, h3, h4', { hover: true,  fontFamily: 'MyOtherFont'});

다음과 같이 작성하면 내용이 덮어져 :hover가 동작하지 않는다는 점을 유의하자.

Cufon.replace('#navlist li a', {hover: true});
Cufon.replace('#navlist li a', {fontFamily: 'MyFont'});

색상을 바꿔요

눈에 편한 색상을 골라보세요 :)

Darkreader 플러그인으로 선택한 색상이 제대로 표시되지 않을 수 있습니다.