toggle menu

[Gulp.js] Gulp 입문 ② - 한단계씩 따라하며 gulp.js 익히기

2015.09.08 23:06 Gulp.js

사내에 gulp.js를 소개하는 강의를 준비하며 단계별로 gulp의 사용방법을 익힐 수 있도록 예제를 만들어 보았다. 아주 기초적인 부분만 짚고 있지만 처음 접하는 사람이 한단계씩 따라가다보면 기본적으로 많이 사용되는 수준까지는 어렵지 않게 도달할 수 있도록 준비했다.



들어가며


gulp 는 node.js 기반의 task runner 다. 반복적인 귀찮은 작업들이나 아래와 같이 프론트엔드 빌드에 필요한 작업들을 gulp 통해 쉽게 처리해줄 수 있다.






또한 gulp 는 스스로를 stream 기반의 build system 이라고 소개하고 있다.


node.js의 특징인 event-driven, non-blocking I/O 를 바탕으로, 요청 후 한번에 결과를 받는 것이 아니라 이벤트로 중간중간 전달받는 방식을 stream이라고 하는데, 이 stream 을 기반으로 하고 있기 때문에 실제로 작업 속도도 비교적 더 빠른 것으로 알려져 있다.



gulp 의 task 는 pipe 로 연결되는데(node.js stream의 그 pipe가 맞다), 작업 대상 파일들이 pipe 를 따라 흘러가며(stream) 병렬로 동시에 여러 task를 수행하게 된다. '꿀꺽 삼키다' 라는 뜻의 gulp 라는 이름과 빨대가 꽂힌 컵모양의 심볼이 gulp 의 특징을 잘 반영하고 있다고 볼 수 있다.





gulp 설치하기


gulp 를 사용하기에 앞서 node.js 와 npm 이 먼저 미리 설치되어 있어야 한다. 우분투 환경에서 node.js 를 설치하는 방법은 이 포스팅을 참고하면 된다. node.js 와 npm 이 설치되었다면, 먼저 아래와 같이 package.json 파일을 생성해준다.


$ npm init



package.json 파일이 생성되었다면, 아래와 같이 gulp 를 global 과 local 모두 설치해준다.


$ npm install gulp --global
$ npm install gulp --save-dev


--save-dev 옵션으로 설치해주는 이유는, 대부분 gulp 가 production 이 아닌 개발 과정에서만 필요하기 때문에, 환경 변수 상의 NODE_ENV 의 값이 production 인 경우 gulp가 설치되지 않도록 하기 위해서 이다.


이제 이어서 gulp의 설정 파일인 gulpfile.js 을 step1부터 차근차근 따라가며 만들어가보자.


앞으로 이어질 각 단계에 대한 설명 및 예제 소스는 https://github.com/eu81273/gulp-step-by-step 에 올려두었다.




STEP 1. Hello World


무언가 새로운 것을 배울 때는 가장 단순한 기본 형태를 보는 것이 가장 빠르게 이해하는 길이다.

gulp의 설정파일인 gulpfile.js 의 가장 단순한 형태는 아래와 같다. 특별한 기능은 하지 않고 Hello World 라는 내용만 콘솔에 찍어주는 하나의 task로만 구성되어 있다.


var gulp = require('gulp');

// hello world 라고 콘솔에 찍는 task
gulp.task('hello', function () {
    return console.log('Hello World!');
});


gulp.task

gulp.task 메서드는 새로운 gulp task 를 등록해주는 역할을 한다. 가장 기본적인 형태에서는 첫번째 파라메터에 task 이름, 두번째 파라메터에 실제 작업할 내용이 함수가 위치하게 된다.


이제 gulpfile.js 파일에 설장한 hello 라는 task는 아래와 같이 실행할 수 있다.


$ gulp hello


hello 라는 task 를 실행하면 아래와 같이 'Hello world!' 라는 메시지만 출력하고 종료되는 것을 볼 수 있다.







STEP 2. Default Task


앞서 step 1에서 gulp hello 로 hello task 를 실행했는데, 항상 hello task를 실행한다면 hello task를 기본값으로 설정해줄 수 있다.


var gulp = require('gulp');

// hello world 라고 콘솔에 찍는 task
gulp.task('hello', function () {
    return console.log('Hello World!');
});

//gulp를 실행하면 default 로 hello task 실행
gulp.task('default', ['hello']);


step 1과는 다르게 'default' 라는 task가 추가되었고, 이 default task의 두번째 파라메터에 배열 형태로 'hello'가 추가되어 있는 것을 볼 수 있다. gulp 는 기본적으로 default 라는 이름의 task를 찾기 때문에 이제 gulp hello 라고 입력할 필요없이, 아래와 같이 gulp 라고만 하면 hello task 를 실행할 수 있다.


$ gulp


hello 라는 task 를 실행하면 아래와 같이 'Hello world!' 라는 메시지만 출력하고 종료되는 것을 볼 수 있다.







STEP 3. Tasks in Series


기본적으로 gulp는 여러개의 task들을 동시에 병렬로 수행하도록 설계되어 있지만, 다른 task가 먼저 수행된 이후에 수행이 되어야하는 task가 있을 수 있다. 이러한 task 간의 dependency는 생각보다 간단하게 해결할 수 있다.


var gulp = require('gulp');

// hello 라고 콘솔에 찍는 task
gulp.task('hello', function () {
    return console.log('Hello');
});

// world 라고 콘솔에 찍는 task, hello 라는 task가 먼저 완료된 뒤에만 실행된다.
gulp.task('world', ['hello'], function () {
    return console.log('World!');
});

//gulp를 실행하면 default 로 world task를 실행
gulp.task('default', ['world']);



이번에는 task 가 총 두 개인데, 하나는 'Hello' 라는 메시지를 출력하는 hello task 이고, 또 하나는 'World!' 라는 메시지를 출력하는 world task 이다.


world task 보다 hello task 가 먼저 실행되도록 하는 것은 간단하다. world task 를 선언한 부분을 보면, 두번째 파라메터에 ['hello'] 가 추가되어 있는데, 이렇게 두번째 파라메터에 먼저 수행되어야할 task들의 이름을 배열 형태로 넣어두면 해당 task들을 먼저 수행한 후에 해당 task를 수행하게 된다.


$ gulp


기본값으로 world 라는 task 를 실행하도록 했지만, 실제로 실행될 때는 dependency 설정으로 hello task가 먼저 실행되고 world task가 이후에 실행되는 것을 볼 수 있다.






STEP 4. JavaScript Minify(Uglify)


프론트엔드 빌드 과정 중에 가장 빈번하게 하는 작업 중 하나는 JavaScript 파일을 Minify(혹은 Uglify, 난독화)하는 작업이다. JavaScript 파일에 포함된 주석, 공백 등을 제거하고 변수명 등을 짧게 바꾸는 등의 작업을 거쳐 용량을 줄이고 JavaScript Engine 이 보다 빠르게 JavaScript 파일을 해석할 수 있도록 도와주게 된다.


이러한 JavaScript Minify 작업을 해주는 많은 Gulp 플러그인 들이 존재하는데, 여기에서는 그 플러그인들 중 gulp-uglify 라는 플러그인을 사용해서 해당 작업을 수행할 예정이다. 먼저 npm 을 사용해서 gulp-uglify 플러그인을 설치해준다.


$ npm install gulp-uglify --save-dev


이제 본격적으로 플러그인을 사용해서 직접 파일을 다루는 빌드 작업을 시작해보자.


var gulp = require('gulp');
var uglify = require('gulp-uglify');

//자바스크립트 파일을 minify
gulp.task('uglify', function () {
    return gulp.src('src/*.js') //src 폴더 아래의 모든 js 파일을
        .pipe(uglify()) //minify 해서
        .pipe(gulp.dest('dist')); //dist 폴더에 저장
});

//gulp를 실행하면 default 로 uglify task를 실행
gulp.task('default', ['uglify']);


이번에는 앞의 예제들과는 다르게 'gulp.src' 와 'pipe', 'gulp.dest' 라는 키워드들이 추가된 것을 볼 수 있다.


gulp.src

gulp.src 는 해당 task의 대상이 되는 파일들을 지정해주는 역할을 한다. 파일을 선택하는 방식은 node-glob 의 문법을 따른다.


//src 하위의 모든 디렉토리의 js 확장자를 가진 파일
'src/**/*.js'
//foo 디렉토리와 bar 디렉토리에서 js 확장자를 가진 파일
['foo/*.js', 'bar/*.js']



gulp.dest

gulp.dest 는 해당 task의 결과물이 저장될 경로를 지정한다.



pipe

pipe 는 gulp.src 에서 대상으로 지정된 각 파일들을 stream 형태로 읽어들여서 다음으로 거쳐야할 플러그인 등으로 연결할 때 사용하게 된다. 아래의 이미지에서 초록색 라인이 pipe의 기능이라고 보면 좀더 이미지화하는데 도움이 될 수 있다. 우리가 알고 있는 node.js stream의 pipe와 같다.





default task 로 uglify 를 지정했기 때문에 아래와 같이 gulp 라고만 입력해도 uglify task가 실행되게 된다.


$ gulp


gulp-uglify 플러그인을 사용하면 아래와 같이 각 파일들이 minify 되어서 dist 디렉토리에 동일한 파일명으로 생성된 것을 볼 수 있다.







STEP 5. Watch


앞서 gulp-uglify 플러그인을 사용해서 JavaScript 파일을 Minify 하는 방법에 대해서 살펴 보았다. 그런데 한 두번은 괜찮지만, 개발 과정에서는 자잘한 변경이 많을 수 밖에 없는데, 매번 JavaScript 파일을 수정할 때마다 gulp 를 타이핑해서 task 를 실행하는 것은 비효율적이고 귀찮은 일이다.


gulp는 이런 경우를 위해, 파일에 변경이 있을 때마다 변경을 감지해서 task 를 실행할 수 있는 기능을 gulp.watch 라는 메서드로 제공해주고 있다.


var gulp = require('gulp');
var uglify = require('gulp-uglify');

//자바스크립트 파일을 minify
gulp.task('uglify', function () {
    return gulp.src('src/*.js') //src 폴더 아래의 모든 js 파일을
        .pipe(uglify()) //minify 해서
        .pipe(gulp.dest('dist')); //dist 폴더에 저장
});

// 파일 변경 감지
gulp.task('watch', function () {
    gulp.watch('src/*.js', ['uglify']);
});

//gulp를 실행하면 default 로 uglify task와 watch task를 실행
gulp.task('default', ['uglify', 'watch']);



앞서 살펴본 소스에서 watch 라는 task가 추가되었는데, 이 task를 자세히 살펴보면, gulp.watch 메서드를 어떻게 사용해야하는지 알 수 있다.


gulp.watch

gulp.watch 의 첫번째 파라메터에서는 변경 감지를 해야하는 대상을 지정한다. 파일을 선택하는 방식은 node-glob 의 문법을 따른다.

두번째 파라메터는 변경이 감지되었을 때 실행할 task 를 지정한다. 배열 형태로 여러개의 task 명을 넣어주면 변경이 일어날 때마다 해당 task 들을 자동으로 실행해주게 된다.


gulp.task('watch', function () {
    //src 디렉토리 안에 js 확장자를 가진 파일이 변경되면 uglify task 실행
    gulp.watch('src/*.js', ['uglify']);
});



default task 로 uglify 와 watch task 를 지정했기 때문에 아래와 같이 gulp 라고만 입력하면 uglify 와 watch task가 실행되게 된다.


$ gulp


이번에는 watch task 도 실행했기 때문에, gulp 가 바로 종료되지 않고 변경 감지를 위해 대기하고 있는 것을 볼 수 있다. 이때 src 디렉토리 아래의 js 파일 하나를 수정하면 바로 변경을 감지해서 uglify task를 수행하는 것을 확인할 수 있다.







마치며


지금까지 단계별로 gulp.js 의 사용방법에 대해서 살펴보았다. 여기에서는 설명을 위해 gulp-uglify 플러그인 하나만 사용했지만, 지금까지 다룬 내용을 잘 이해했다면  2015년 9월 현재 약 1800 여개에 이르는 gulp 플러그인들을 필요에 따라 적용하는데 큰 어려움이 없으리라 본다.


각 단계에 해당하는 예제들과 설명은 https://github.com/eu81273/gulp-step-by-step 에 올려두었다. 이 포스팅에서 설명하지 않은 예제들도 몇 가지 더 올려두었고, 앞으로도 gulp.js 를 처음 사용할 때 알아두어야할 내용이 있다면 지속적으로 추가해갈 예정이다.


자신에게 꼭 필요한 것 같지 않아서 gulp 사용하는 것을 미뤄두고 있었다면, 지금 잠깐 시간을 내서 5개의 예제만 돌려보는 것을 추천한다. 그 후에는 언제든지 필요에 따라 gulp 플러그인들을 찾아서 적절하게 활용하고 있는 자신을 발견할 수 있을 것이다.




Gulp.js 관련 포스팅 더보기