toggle menu

[Gulp.js] Gulp 4.0, 어떤 것들이 달라졌을까?

2016. 7. 12. 07:30 Gulp.js

들어가며


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.seriesgulp.parallel 메서드가 추가되었다. 위의 예에서도 일단 기본적으로 직렬로 실행하지만, 먼저 병렬로 first 와 second 를 실행하고 이 두개가 마치면 last 를 실행하도록 선언된 것을 볼 수 있다. 다소 낯설지 모르겠지만, 조금 시간이 지나면 4.0의 방식이 훨씬 명시적이고 직관적으로 task 들의 관계를 나타내고 정리할 수 있음을 알 수 있다. 굉장히 마음에 드는 변화다.


위의 예에서 gulp.series 가 리턴하는건 function 이다. 따라서 위의 코드에서는 mytask() 로 실행하면 해당 task 들이 실행된다. 이전에는 task 를 임의로 실행하려면 숨겨진 메서드인 gulp.start 나 혹은 gulp.run 을 사용해서 등록된 task 를 실행했었다. 이 숨겨진 메서드를 이용해서 만들어진 runSequence 라는 플러그인도 존재했었다.


하지만 4.0 에서 gulp.startgulp.run 이 모두 제거되었다. task 는 기본적으로 function 이니 function 을 실행하면 된다는 것이 Gulp 4.0의 컨셉이기 때문이다. (이 부분이 제일 낯설어서 적응하는데 어려움이 있었다...)


어쨌든 gulp.startgulp.run 이 모두 제거된 만큼 runSequence 같은 플러그인은 더이상 사용할 수 없다. 물론 runSequence가 필요했던 부분은 gulp.seriesgulp.parallel 메서드로 완전히 대체할 수 있기 때문에 문제가 되지는 않지만, runSequence 처럼  gulp.start 와 gulp.run 를 내부적으로 사용하고 있던 Gulp 3.0 의 플러그인들은 4.0 에서 제대로 동작하지 않을 수도 있다.


여기까지 정리해보면, 기존에 gulp.task 메서드를 사용해서 task 를 선언했다면, 이제는 function 으로 선언하면 되고, CLI 로 실행할 필요가 있는 task 들만 gulp.task 메서드로 등록시켜주면 된다는 것과 또 task들 간의 디펜던시는 gulp.seriesgulp.parallel 메서드를 사용해서 조합해 주면 된다로 정리할 수 있다.





이제 임의로 task를 실행할 수 없는걸까?


4.0 에서 gulp.startgulp.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 인 것이다. 때문에 좀더 명확하게 아래 중의 하나의 형태를 가져야 한다.


  1. stream 을 리턴한다.
  2. callback 을 호출한다.
  3. Promise 를 리턴한다.
  4. child process 를 리턴한다.
  5. observable 을 리턴한다.


이중에서 하나의 형태가 아니라면 Gulp 4.0 은 task 실행을 제대로 하지 않고 중단시키거나 아니면, gulp.seriesgulp.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개의 기능 정리 를 읽어보길 권한다.



Gulp.js 관련 포스팅 더보기