들어가며
2015년 12월에 Gulp 4.0에서 추가되고 변경된 4개의 기능 정리 라는 제목으로 Gulp 4.0에서 추가된 주요 기능들에 대해 포스팅했었는데, 이번에 실무에 4.0을 적용해보며 3.x과 어떤 부분에서 체감적으로 차이가 있는지 또 어떻게 마이그레이션 할 수 있는지에 대해 정리해보려고 한다.
Gulp 4.0은 무려 2014년 8월부터 릴리즈 이야기가 나왔고... 오랜 기간 Alpha 2 상태에서 크게 변화한 부분은 없었기 때문에 앞으로 4.0이 정식 출시되더라도 공식 문서 정도만 추가될 뿐 아래에서 설명하는 구조는 변함이 없을것으로 보인다.
Gulp 4.0 설치
기존에 Gulp 3.x 버전을 사용 중이었다면, 기존 버전을 제거하는 것부터 시작해야 한다.
# 전역에 설치한 Gulp 제거
$ npm uninstall gulp --global
# 프로젝트에 설치한 Gulp 제거
$ npm uninstall gulp --save-dev
Gulp 4.0 부터는 기존 Gulp 모듈에서 CLI가 분리되었다. 따라서 Gulp CLI 는 전역에 설치해주고, Gulp 는 프로젝트별로 설치해주면 된다.
# Gulp CLI 설치
$ npm install gulpjs/gulp-cli --global
# 프로젝트에 Gulp 4.0 설치
$ npm install gulpjs/gulp.git#4.0 --save-dev
기존 3.9 버전에서는 설치할 때 deprecated 된 디펜던시들이 많아서 설치과정에서 주의가 많이 발생했지만, 4.0 버전에서는 deprecated 된 디펜던시가 모두 변경된 것을 볼 수 있다. 4.0 릴리즈 준비가 끝난 탓인지 3.9 버전은 거의 업데이트를 하지 않고 있는데 때문에 deprecated 된 디펜던시가 3.x 버전대에서 개선되는 것은 기대하지 않는 것이 좋다.
기본적으로 task 가 아니라 function
Gulp 의 상징과도 같았던 task 에도 큰 변화가 생겼다. Gulpfile 을 작성한다면 기본적으로 Gulp.task
메서드를 선언하는 것을 떠올리게 되는데, 4.0부터는 task 메서드는 오직 CLI 에서 호출이 필요할 때만 사용하는 것을 권장하고 기본적으로 모든 task 는 function
으로 작성하도록 유도하고 있다.
익숙한 기존의 task 선언을 살펴보자.
gulp.task('mytask', ['first', 'second'], function () {
//task 내용
});
gulp.task('first', function () {
//task 내용
});
gulp.task('second', function () {
//task 내용
});
task 의 이름을 정해주고, 이 task 가 실행되기전 먼저 실행되어야 하는 task 들의 목록을 배열로 선언한뒤, task 의 실제 코드가 위치하는 아주 익숙한 구조이다. 하지만 4.0 에서 이렇게 task 를 선언하면 안된다. 굳이 위의 3.0 방식을 4.0 방식으로 바꿔보자면 아래와 같다.
function first () {
//task 내용
}
function second () {
//task 내용
}
function last () {
//task 내용
}
var mytask = gulp.series(gulp.parallel(first, second), last);
task들을 조합하기 위한 새로운 메서드
이전 포스팅 에서도 다루었지만, Gulp 4.0 에서는 task 들을 직렬 또는 병렬로 실행되도록 조합하는데 사용되는 gulp.series
와 gulp.parallel
메서드가 추가되었다. 위의 예에서도 일단 기본적으로 직렬로 실행하지만, 먼저 병렬로 first 와 second 를 실행하고 이 두개가 마치면 last 를 실행하도록 선언된 것을 볼 수 있다. 다소 낯설지 모르겠지만, 조금 시간이 지나면 4.0의 방식이 훨씬 명시적이고 직관적으로 task 들의 관계를 나타내고 정리할 수 있음을 알 수 있다. 굉장히 마음에 드는 변화다.
위의 예에서 gulp.series
가 리턴하는건 function
이다. 따라서 위의 코드에서는 mytask()
로 실행하면 해당 task 들이 실행된다. 이전에는 task 를 임의로 실행하려면 숨겨진 메서드인 gulp.start
나 혹은 gulp.run
을 사용해서 등록된 task 를 실행했었다. 이 숨겨진 메서드를 이용해서 만들어진 runSequence
라는 플러그인도 존재했었다.
하지만 4.0 에서 gulp.start
와 gulp.run
이 모두 제거되었다. task 는 기본적으로 function
이니 function 을 실행하면 된다는 것이 Gulp 4.0의 컨셉이기 때문이다. (이 부분이 제일 낯설어서 적응하는데 어려움이 있었다...)
어쨌든 gulp.start
와 gulp.run
이 모두 제거된 만큼 runSequence
같은 플러그인은 더이상 사용할 수 없다. 물론 runSequence
가 필요했던 부분은 gulp.series
와 gulp.parallel
메서드로 완전히 대체할 수 있기 때문에 문제가 되지는 않지만, runSequence 처럼 gulp.start
와 gulp.run
를 내부적으로 사용하고 있던 Gulp 3.0 의 플러그인들은 4.0 에서 제대로 동작하지 않을 수도 있다.
여기까지 정리해보면, 기존에 gulp.task
메서드를 사용해서 task 를 선언했다면, 이제는 function
으로 선언하면 되고, CLI 로 실행할 필요가 있는 task 들만 gulp.task
메서드로 등록시켜주면 된다는 것과 또 task들 간의 디펜던시는 gulp.series
와 gulp.parallel
메서드를 사용해서 조합해 주면 된다로 정리할 수 있다.
이제 임의로 task를 실행할 수 없는걸까?
4.0 에서 gulp.start
와 gulp.run
이 모두 제거되었다고해서 task 를 직접 실행할 수 있는 방법이 모두 사라진 것은 아니다. 아래와 같이 task 를 실행하는 오히려 다양한 방법이 존재한다.
function myTask () {
//task 내용
}
gulp.task('myTaskName', myTask);
//당연히 myTask 를 직접 실행할 수 있다.
myTask();
//혹은 gulp.task 메서드로 등록했다면, gulp.task 메서드 자체를 실행할 수도 있다.
gulp.task('myTaskName')();
//gulp.series 나 gulp.parallel 메서드를 사용할 수도 있다.
gulp.series(myTask)();
//gulp.task 메서드로 등록했다면, 함수가 아니라 task명을 string 형태로 호출해도 된다.
gulp.series('myTaskName')();
개인적으로는 gulp.series('task명').call()
과 같이 사용하는 것을 추천하는데, 이렇게 실행하면 Gulp 가 실행할때와 유사한 화면 결과가 나오기 때문이다.
task 는 function 이다
지금까지 반복되는 맥락은 task 가 function
이라는 점이다. 이전에도 물론 function
이었지만 task 로 등록해야만 동작했다면 이제는 정말 function 인 것이다. 때문에 좀더 명확하게 아래 중의 하나의 형태를 가져야 한다.
- stream 을 리턴한다.
- callback 을 호출한다.
- Promise 를 리턴한다.
- child process 를 리턴한다.
- observable 을 리턴한다.
이중에서 하나의 형태가 아니라면 Gulp 4.0 은 task 실행을 제대로 하지 않고 중단시키거나 아니면, gulp.series
와 gulp.parallel
메서드를 사용해서 조합해도 다음 task 로 제대로 넘어가지 못하게 된다. 따라서 이전에는 좀 느슨하게 task 를 작성했다면 이제는 위의 형태 중 한가지 형태로 반드시 작성해야 한다.
또 task 는 function 이기 때문에 task의 이름은 function 의 이름과 같다. task를 익명함수로 선언하게 되면 실행했을 때 Anomymous 로 task 이름이 뜨는 것을 보게 된다. 따라서 되도록 익명함수 사용을 자제하고 반드시 function name 을 지정하도록 한다.
그 외 나머지..
gulp.tree
메서드로 전체 task 의 목록을 배열 형태로 취할 수 있다. 또 커스텀 레지스트리를 위해 gulp.registry
메서드가 추가되었다. gulp.dest
와 동일한 기능을 하지만 symlink
를 생성하는 gulp.symlink
추가되었다.
gulp.src
메서드의 경우 성능이 향상되었고 파라메터로 전달된 glob
패턴이 순서대로 평가되도록 바뀌었다.
Gulp 4.0부터 Vinyl Object
에 소스맵이 내장되어 있지만 실제 코드를 작성하다보니 기존 소스맵 플러그인을 사용하는게 아직까지는 더 명시적이란 생각이 들었다.
마치며
지금까지 Gulp 4.0을 적용해보며 3.x과 어떤 부분에서 체감적으로 차이가 있는지 또 어떻게 마이그레이션 할 수 있는지에 대해 살펴보았다. 처음에는 낯설고 적응이 안되는 부분들이 있었지만, 4.0 에서 제안하고 있는 바대로 gulpfile 을 작성하다보니 좀더 더 명시적인 형태가 된다고 할까? Gulp 메인테이너들이 꽤 고민한 흔적이 느껴진다.
이번 포스팅에서는 Gulp 4.0 에서 개념적으로 변화한 부분과 마이그레이션 위주로 글이 진행되었는데, 4.0 에서 추가된 API 에 대해 궁금하다면 이전 포스팅 Gulp 4.0에서 추가되고 변경된 4개의 기능 정리 를 읽어보길 권한다.