Gulp 사용법 #2 (gulp-concat)
Syntax Gulp
이전 포스팅에서는 gulp 의 설치방법 및 간단한 task 에 대해 알아보았습니다.
이제 본격적으로 gulp 사용방법에 대해 알아봅니다.
만약 gulp 설치가 되어 있지 않다면 Gulp #1 설치를 참고하시기 바랍니다.
Determining Folder Structure(폴더 구조 생성하기)
gulp 의 workflow(작업흐름) 방식을 이해하기 위해서 전체적인 맥락을 짚어보며 진행하도록 하겠습니다.
gulp 설치를 완료한 후 package.json 과 gulpfile.js가 준비되었다면 사용자 프로젝트에 디렉터리 구조를 구성할 필요가 있습니다.
먼저, src (source) 폴더와 dist (distribution) 폴더를 먼저 만들어두로록 합니다.
scr 폴더는 어떠한 처리도 하지 않은 JavaScript와 압축하지 않은 (s)css, 그리고 최적화하지 않은 이미지들로 구성될 것이고 dist 폴더는 Gulp 에 의해서 빌드된 파일들이 이 디렉터리에 포함되게 될 것입니다.
다시 말해, 빌드된 파일들이 포함될 dist 폴더는 애플리케이션을 서비스할 때 최적화 처리된 파일들을 포함하게 될 것입니다.
일반적으로 dist 디렉터리 네이밍을 많이 사용하지만 사용자에 기호에 맞게 생성해도 상관은 없습니다.
여기서는 디렉터리 구성을 다음과 같이 하도록 합니다.
gulpfile.js
앞선 포스팅에서 gulpfile.js 를 간단히 작성해 보았습니다.
gulpfile.js 파일은 Gulp가 수행할 일을 작성하게 되며 Grunt 와는 다르게 Gulp의 문법은 매우 쉽고 다루기 쉽다는 평이 지배적입니다..
아래는 자바스크립트 파일을 조합하는 task 에 대한 문법입니다.
// Gulp 모듈 호출
var gulp = require('gulp');
// Gulp 의 concat 패키지 모듈 호출
var concat = require('gulp-concat');
// ...
// Gulp.task() 를 사용해 combine:js 테스크를 정의
gulp.task('combine:js', ['lint-js'], function () {
return gulp.src('/project/js/**/*.js')
.pipe(concat('scriptAll.js'))
.pipe(gulp.dest('project/dist/js'));
});
//...
gulp.task('default', ['combine:js']);
위의 문법에 대해 차근차근 살펴보도록 하겠습니다.
// Gulp 모듈 호출
var gulp = require('gulp');
// Gulp 의 concat 패키지 모듈 호출
var concat = require('gulp-concat');
gulpfile 에서 사용하기 위해서는 jQuery 객체를 사용하기 위해 jQuery 객체를 호출하듯이 require 해야할 필요가 있습니다.
그리고 다음 행의 gulp-concat 패키지 모듈을 사용하기 위해서는 이전에 반드시 npm 으로 (--save-dev 옵션을 주어서) 사용하려는 gulp 모듈 패키지를 설치해야합니다.
다음과 같이 gulp-concat를 설치할 수 있으며, npmjs.com 에서 모듈 패키지들을 참고하시기 바랍니다.
$ mpm install gulp-concat --save-dev
gulp.task()
gulp.task(name, deps, func)
앞서 말했듯이 gulp.task() 는 Gulp 가 수행할 일을 정의하고, 이 메소드는 세 개의 전달인자를 받습니다.
그리고 3개의 파라미터 중에 두번째 파라미터는 생략할 수 있습니다.
- name - task의 이름을 지정하고, 이름에는 공백이 포함되어서는 안됩니다.
- deps - 현재 선언하고 있는 task를 수행하기 전에 먼저 실행되어야하는 task들의 배열 목록을 작성할 수 있습니다. 위의 예제에서는 JavaScript 파일을 병합하는 task를 진행하기 전에 JavaScript Lint(자바스크립트 문법 검사)를 먼저 수행하도록 정의되어 있습니다. (물론 그 전에 lint-js task를 이 task보다 앞에 작성해주어야 먼저 수행할 수 있을 것입니다.)
- func - 실제 수행할 업무 프로세스를 정의하는 function 입니다.(처리해야할 일을 정의)
만약 선행되어야하는 task 가 없다면 굳이 gulp.task('name', [], fn); 의 형태로 두번재 파라메터를 줄 필요가 없고 gulp.task('name', fn); 로 정의해도 정상적으로 task 를 수행하게 됩니다.
gulp.src(files)
gulp.src(files)
gulp.src(files) 메소드 줄은 gulp 객체의 src() 에 파일이나 파일의 경로를 배열 데이터 형식(배열 또는 string)으로 작성하도록 합니다.
즉, gulp.src 는 해당 task의 대상이 되는 파일들을 지정해주는 역할을 합니다.
파일을 선택하는 방식은 node-glob 의 문법을 따르고 있습니다.
위의 예제에서는 js/**/*.js 로 되어 있는데, 이렇게 와일드카드 형태로 표현해줄 수도 있습니다.
이렇게 표현할 경우, Gulp 는 js/ 폴더와 내부폴더의 .js 파일들을 모두 찾아서 파일을 가져오게 됩니다.
와일드카드 형태 말고도 배열을 사용해서 원하는만큼 여러 개의 파일들과 폴더들을 가져올 수도 있습니다.
gulp.src([
'project/src/js/navigation.js',
'project/src/js/slider/*.js',
'!project/src/js/slider/slider-beta.js'
]);
바로 위 코드에서는 "navigation.js" 파일과, slider 폴더 안의 모든 .js 파일들을 가져오게 됩니다.
그리고 배열의 마지막 아이템 앞에 '!' 표시 되어 있는 것은 이 파일은 포함하지 말라는 의미입니다.
이 느낌표는 바로 앞의 와일드카드 형태에서 이 파일을 포함하고 있을 경우에만 이것을 사용해야 합니다.
gulp.pipe(...)
gulp.pipe(...)
gulp.pipe(...) 는 Gulp의 스트리밍 기능으로 "pipe" 는 gulp.src 에서 대상으로 지정된 각 파일들을 stream 형태로 읽어들여서 다음으로 거쳐야할 플러그인 등으로 연결할 때 사용하게 됩니다.
다시말해, pipe 메소드를 사용해서 task들의 결과물을 function 에게 전달해 줄 수 있으며 pipe가 하는 일은, pipe로 stream 간에 read 와 write event 들을 연결해 주는 것입니다.
그리고 pipe 는 체이닝으로 여러개의 pipe를 서로 연결하여 사용할 수도 있습니다.
아래의 예제를 통해 좀더 살펴보도록 합니다.
gulp.src('project/src/js/*.js')
.pipe(stripDebug())
.pipe(concat('scriptAll.js'))
.pipe(gulp.dest('project/dist/js'));
위 예제 코드는 stripDebug와 concat 을 사용하고 있습니다.
먼저, Gulp는 project/src/js 폴더의 모든 js 파일들을 가져온 후에 stripDebug 에게로 파이핑(piping) 해주게 되는데, stripDebug는 모든 console.log 들과 alert 들을 제거해주는 gulp 모듈 패키지입니다.
그 후에 체이닝으로 이 파일들을 concat('scriptAll.js') 로 파이핑해주는데, 이건 console.log와 alert이 제거되고 압축된 모든 파일들을 scriptAll.js 파일 하나로 병합해 줄 것입니다.
gulp.dest()
gulp.dest
는 해당 task의 결과물이 저장될 경로를 지정하게 됩니다.
위 task에서 gulp 는 이 파일을 gulp.dest() 로 보내게 되는데, 이를 통해 실제로 우리가 사용하게 될 output 파일로 떨궈지게 될 것입니다.
즉, dest()
는 전달받은 인자(문자열)을 토대로 파일이 출력될 목적지(Destination)을 설정하는 역할을 합니다.
위의 task 를 수행하게 되면 불필요한 콘솔 로그와 alert 가 제거되고 여러개의 js파일이 하나로 병합된 js 파일을 얻게 될것입니다.(project/dist/js/scriptAll.js).
gulp.task('default', [])
gulp.task('default', []) 는 CLI 에서 아무런 argument 없이 glup 명령어만을 타이핑하여 실행했을 때 기본값으로 실행되는 task 입니다.
만약 특정 task를 실행하고 싶다면 아래와 같이 할 수 있습니다.
$ gulp task-name
이제 gulpfile.js 전반적인 문법구조를 알아보았습니다.
지금부터는 실제로 gulpfile.js 를 작성해 보도록 하겠습니다.
Preprocessing with Gulp(걸프 전처리기 작성하기)
앞에서 Gulp를 사용할 최소한의 준비 과정을 마쳤다면 이제 본격적으로 Gulp 플러그인을 활용하여 웹 개발에 유용한 업무를 등록하는 과정(task)을 알아보도록 하겠습니다.
여기서 다룰 gulp 플러그인은 gulp-concat 입니다.
이 플러그인은 여러 개의 자바스크립트 파일을 하나의 파일로 병합해 주는 플러그인입니다.
먼저 npm 을 이용하여 플러그인을 아래와 같이 다운로드 받도록 합니다.
$ npm install gulp-concat --save-dev
참고로 여러 개의 플러그인을 다운로드할 경우에는 빈 공백을 사용하여 여러 개의 플러그인을 구분하여 한꺼번에 내려받을 수도 있습니다.
$ npm install gulp-concat gulp-uglify gulp-sass gulp-livereload --save-dev
CLI 에서 위 명령어를 실행하면 gulp-concat, gulp-uglify, gulp-sass, gulp-livereload 총 네 개의 플러그인을 한 번에 내려받을 수 있을 것 입니다.
여기서는 gulp-concat 만 다운로드 받습니다.
설치가 끝나면 [node_modules] 디렉터리에 gulp-concat 모듈 패키지가 생성된 것을 확인하실 수 있습니다.
이제 gulpfile.js 파일에 gulp-concat 모듈을 호출하는 코드와 gulp.task() 메소드에 업무 이름을 부여, 정의하도록 하겠습니다.
// Modules 호출
var gulp = require('gulp');
// Gulp 의 concat 패키지 모듈 호출
var concat = require('gulp-concat');
// Gulp.task()를 사용해 gulp-concat 업무 수행을 정의
// task 의 이름은 가능하면 플러그인과 연관성있는 이름을 정의하는 것이 좋습니다.
// 여기서는 concat:js 라고 task 이름을 정의함.
gulp.task('concat:js', function () {
return gulp.src(['project/src/js/script-01.js', 'project/src/js/script-02.js'])
.pipe( concat('conbined.js') )
.pipe( gulp.dest('project/dist/js') );
});
// gulp.task('default', ['concat:js']);
필자의 디렉터리 구조는 아래와 같습니다.
두 개의 스크립트 파일이 있으며 이 파일을 병합하려고 합니다.
그리고 gulp.task() 의 업무 이름을 concat:js 라고 정의했으며 gulp 객체의 src() 에 병합하려는 자바스크립트 파일 경로를 배열 데이터 형식으로 추가하였습니다.
그리고 다음 줄의 pipe 에서 gulp-concat 모듈을 호출하여 참조한 concat() 함수에 병합한 후 생성할 파일 이름을 문자열로 전달했습니다.
마지막 pipe() 에서는 gulp.dest() 메소드가 수행되는데 윗라인에서의 pipe가 수행한 결과물이 출력될 목적지를 설정했습니다.
그리고 마지막 라인의 glup.task 는 주석처리되어 있는데 이는 나중에 설명하도록 하겠습니다.
일단 위와 같이 되었다면 CLI 에서 아래와 같이 gulp 를 실행합니다.
$ gulp concat:js
gulp 를 실행하면 아마 아래와 같이 dist/js 폴더 내에 병합된 파일이 생성되었을 것입니다.
dist 디렉터리는 gulp.dest() 내에서 문자열을 자동으로 디렉터리까지 구성해 줍니다.
그래서 미리 디렉터리 구조를 구성할 필요는 없지만 사용자의 기호에 따라 목적지 디렉터리를 생성해 둔 후 작성하여도 무방합니다.
그리고 gulpfile.js 의 마지막 줄이 주석처리되어 있는데 주석을 제거한 후 gulp 명령어만 실행해 보시기 바랍니다.
다시 실행하여 확인하려면 dist 폴더를 지운 후 다음의 명령어를 실행해 보시기 바랍니다.
$ gulp
위와 같이 실행하면 앞서 실행했던 gulp concat:js 처럼 실행하지 않아도 gulp 가 수행될 것입니다.
이는 앞서 설명했듯이 두번째 파라미터는 의존 모듈을 정의할 수 있는데, task('default')는 gulp 기본 명령어를 의미하고 다른 task 네이밍을 배열로 전달함으로써 gulp default 인 gulp 를 실행하게 될 때 의존성을 가진 task 들을 먼저 수행하기 때문에 명시적으로 gulp concat:js 를 작성하실 필요가 없습니다.
즉, 'default' 이름으로 정의된 task 를 수행하게 됩니다.
또한 gulp 명령어를 실행하면 concat:js 업무가 시작(starting)해서 종료(Finished)할 때 까지 **밀리초(ms) 소요되었다고 CLI 화면 창에 출력합니다.
즉, 자바스크립트 파일들을 병합한 파일을 목적지에 생성하는데 ** 밀리초가 소요된 것이라 할 수 있습니다.
위의 코드는 병합할 파일 개수가 늘어날 때마다 매번 배열 아이템을 추가해줘야 하는 번거로움이 발생할 것입니다.
예를 들어 script-03.js, script-04.js 가 추가되었다면 또 다시 gulp.src() 에 추가해야 하므로 유지보수 측면에서 위에서 사용한 배열 방식을 불편할 것입니다.
이러한 불편함을 해소하려면 다음과 같이 모든 자바스크립트 파일을 의미하는 문자열(*.js)로 변경할 수 있습니다.
// Modules 호출
var gulp = require('gulp');
// Gulp 의 concat 패키지 모듈 호출
var concat = require('gulp-concat');
// Gulp.task()를 사용해 gulp-concat 업무 수행을 정의
gulp.task('concat:js', function () {
return gulp.src(['project/src/js/*.js']) // *.js 로 변경
.pipe( concat('conbined.js') )
.pipe( gulp.dest('project/dist/js') );
});
gulp.task('default', ['concat:js']);
위와 같이 gulpfile.js 를 변경하고 또 다른 script 파일을 하나 더 생성하여 CLI에서 gulp 명령어를 실행하면 모든 스크립트 파일이 병합된 하나의 스크립트 파일을 얻을 수 있을 것입니다.
이렇게 하면 수십 개의 파일을 편리하게 병합할 수 있습니다.
하지만 앞서 설명한 방법은 유지보수를 할 때는 편리하지만, 파일 간의 병합이 알파벳 순서대로 병합되기 때문에 스크립트 처리 순서에 이슈가 발생할 수 있을 것입니다.
그러므로 특정 파일을 우선적으로 병합할 필요성이 있는데 아래와 같이 우선적으로 병합할 파일 경로를 먼저 제공한 다음 모든 파일을 의미하는 문자열을 배치하면 특정파일을 우선적으로 병합시킬 수 있습니다.
// Modules 호출
var gulp = require('gulp');
// Gulp 의 concat 패키지 모듈 호출
var concat = require('gulp-concat');
// Gulp.task()를 사용해 gulp-concat 업무 수행을 정의
gulp.task('concat:js', function () {
return gulp.src(['project/src/js/script-03.js','project/src/js/*.js']) // 우선적으로 병합할 특정 파일을 먼저 작성
.pipe( concat('conbined.js') )
.pipe( gulp.dest('project/dist/js') );
});
gulp.task('default', ['concat:js']);
필자는 script-03.js 라는 파일을 생성하여 스크립트 작성을 하였고 이 파일을 우선적으로 병합시키려고 합니다.
그리고 gulp 를 수행합니다.
$ gulp
필자의 gulp 를 수행한 결과는 다음과 같습니다.
그리고 프로젝트 디렉터리 구조상 하위 디렉터리까지 있는 경우가 다반사입니다.
이러한 모듈 관리 목적으로 만든 하위 디렉터리 내의 자바스크립트 파일까지 병합해야 할 때는 합쳐야 할 파일 경로를 **/*.js
로 표기할 수 있습니다.
필자의 [src] 디렉터리에 [js/libs] 하위 디렉터리를 생성한 후 임의의 자바스립트 파일을 추가하도록 하겠습니다.
그런 다음 gulfile.js 를 아래와 같이 수정하도록 합니다.
// Modules 호출
var gulp = require('gulp');
// Gulp 의 concat 패키지 모듈 호출
var concat = require('gulp-concat');
// Gulp.task()를 사용해 gulp-concat 업무 수행을 정의
gulp.task('concat:js', function () {
return gulp.src(['project/src/js/**/*.js']) // js 하위 디렉터리 내의 모든 자바스크립트 파일을 가져온다.
.pipe( concat('conbined.js') )
.pipe( gulp.dest('project/dist/js') );
});
gulp.task('default', ['concat:js']);
CLI 에서 gulp 명령어를 수행하도록 합니다.
그럼 다음과 같은 결과를 얻을 수 있을 것입니다.
지금까지 gulp-concat 플러그인을 설치하고 gulpfile.js 를 작성하는 방법에 대해 알아보았습니다.
이 포스팅에서는 한 가지 플러그인을 다뤘지만 다음 포스팅에서는 여러 개의 플러그인을 설치하고 다뤄보기 위해 다수의 gulp 모듈을 호출하고 gulp.task() 를 정의해 보면서 gulp 의 좀 더 나은 활용방법에 대해 알아보도록 하겠습니다.