LHJ

I'm a FE developer.

직접 작성한 gulp 및 grunt, gulp, webpack 관련

12 Nov 2020 » node_gulp

직접 작성한 gulp 및 grunt, gulp, webpack 관련

N 업무에서 새로운 페이지를 만들어야되는 작업이 있었습니다.
그래서 gulp로 N 업무를 진행해봤습니다.

N 업무용 걸프

N 업무용 걸프를 위해 지켜야할 사항을 다음과 같이 정했습니다.

  1. CSS 컴파일 결과는 한줄 \n 한줄 \n <- 이런 형식으로 나와야됩니다.
  2. CSS 컴파일될 때 sourcemaps 기능이 적용되어선 안됩니다.

그리고 추가 규칙도 정했습니다.

  1. JS도 컴파일될 때 sourcemaps 기능이 적용되어선 안됩니다.
  2. JS는 min 파일로 압축 및 난독화해서 내보냅니다.
  3. 최신 문법으로 작성해도 최소 IE9~10 버전까지 적용될 수 있도록 컴파일되게 합니다.

위와 같은 규칙을 정해놓고 Gulp를 구성했습니다.
이전에도 공유드린 적이 있지만, Gulp를 실행할 때 환경변수를 전달해 현재 ‘개발중’인지 아니면 고객에게 전달해줄 빌드중(Production)인지를 구분하였습니다.

{
  "scripts": {
    "start": "gulp",
    "build": "NODE_ENV=production gulp build"
  }
}

package.json에 위와 같이 Custom 명령어를 작성합니다.
환경변수 인식 오류를 대비해

npm i -D win-node-env

win-node-env 모듈도 설치해줍니다.
위와 같이 작성한 후에 npm start 명령어를 입력하면 gulp 명령어가 실행되고, npm run build 명령어를 입력하면 NODE_ENV=production gulp build 명령어가 실행됩니다.

start는 npm start이고 build는 npm run build인 이유는
start는 npm에 기본 내재되어있는 명령어이고 build는 사용자가 추가한 명령어이기 때문입니다.

npm start - SCSS

npm start로 해당 걸프를 실행하면 위와 같이 (개발용)이란 메시지가 붙습니다.

그리고 위와같이 sourcemaps 기능이 활성화되도록 했습니다.
그 이유는 개발중일 때는 sourcemaps 기능이 켜져있어야 어디 sass 파일에 작성된 내용인지를 쉽게 알 수 있기 때문입니다.

npm run build - SCSS

반대로 npm run build 명령어를 통해 build를 하면 다음과 같이 결과물이 출력됩니다.

아까완 다르게 (개발용) 텍스트가 붙어있지 않습니다.

그리고 sourcemaps 기능도 없어진 것을 확인할 수 있습니다.

npm start - JavaScript

JavaScript도 마찬가지입니다.
npm start로 실행하면

어느 파일에서 작성된 코드인지를 보여줍니다.

npm run build - JavaScript

하지만 npm run build 명령어를 통해 빌드하면,

위와 같이 sourcemaps 기능이 없어져 컴파일된 결과물을 가리키고 어디서 작성되어있는지 알 수 없게됩니다.
또한 1줄로 min 파일화되었고 난독화되었음도 확인할 수 있습니다.


원리

아까 위에서 말씀드렸듯이 package.json에 커스텀한 명령어를 통해 각 명령어마다 다른 환경변수를 전달한다고 했습니다.
해당 환경변수는 다음과 같이 gulp 코드에 전달됩니다.

위 코드를 보시면 상수 sourcemapsprocess.env.NODE_ENV === “production” ? false : true; 이런 코드로 값을 부여하는 것을 알 수 있습니다.
위 코드로 현재 개발용 실행인지 아니면 빌드하는 것인지를 구분하는 것입니다.
그렇게 구분되어진 값이 sourcemaps 상수에 담기게되고,

그 값을 위와 같이 전달함으로써 상황에 맞게 on/off 할 수 있는 것입니다. JavaScript 컴파일도 마찬가지 원리입니다.

환경변수를 받아와 gulp-if 모듈로 true인지 false인지를 구분해 terser() 메서드를 실행할지 말지를 결정했습니다.

CSS 한줄 컴파일

sass 컴파일할 때 outputStyle 옵션으로는 4가지가 있습니다.

  1. nested : 기본값입니다. 옵션을 적용하지 않았을 때 해당 스타일로 컴파일 됩니다.

     /* 컴파일 결과물 */
     ul {
       font-family: Georgia;
       color: #333333; }
       ul li {
         display: inline-block; }
    
  2. expanded

     /* 컴파일 결과물 */
     ul {
       font-family: Georgia;
       color: #333333;
     }
     ul li {
       display: inline-block;
     }
    
  3. compact

     /* 컴파일 결과물 */
     ul { font-family: Georgia; color: #333333; }
     ul li { display: inline-block; }
    
  4. compressed

     ul{font-family:Georgia;color:#333333}ul li{display:inline-block}
    

N 업무용 스타일은 3번 compact입니다.
하지만 gulp-sass 컴파일할때 compact 옵션을 줘서 컴파일하면

/* 컴파일 결과물 */
ul { font-family: Georgia; color: #333333; }

ul li { display: inline-block; }

.class { display: block}

위와 같이 한줄씩 더 개행되어 컴파일됩니다.
위와 같이 컴파일되면 곤란합니다.
그래서 gulp-clean-css 라이브러리의 도움을 받았습니다.

compact 형식으로 컴파일되게하고 gulp-clean-css 라이브러리의 도움을 받아 한번더 개행처리된 부분을 제거했습니다.

JS 파일 정리방법

src/js 폴더에 파일, 폴더트리는 다음과 같습니다.

script.js 파일엔 apps 폴더에 정의되어있는 파일들을 import 시켰습니다.

import './apps/common';

caseView.js 파일엔 caseView 폴더에 정의되어있는 파일들을 import 시켰습니다.

import './caseView/guide';
import './caseView/search';
import './caseView/brand';
import './caseView/main';
import './caseView/brand-main';

위와 같이 작성하고 컴파일하면 import 된 파일들의 내용이 불러와져 컴파일됩니다.
저희가 gulp로 scss 파일 컴파일 하는 원리와 똑같다고 생각하면 됩니다.

JavaScript Polyfill

자바스크립트 폴리필도 적용했습니다.
폴리필이란 쉽게 말해 코드조각입니다.
스니펫과 비슷한 개념이라고 생각하시면 됩니다.

하지만 스니팻과는 차이점이 있습니다.
스니팻은 개발자가 개발을 편하게 하기위해 자주 쓰는 코드조각 모음입니다.
젠코딩에 주로 많이 사용됩니다.

폴리필은 크로스브라우징을 위한 코드조각이라고 보시면 됩니다.
예를 들면 Promise와 같은 ES6 이후에 생긴 새로운 객체는 IE에서는 전혀 지원이 안됩니다.
이를 IE에서도 작동하게끔 만들어주는 코드 조각들이 바로 폴리필입니다.

프로젝트를 진행하시다보면, 혹은 작업하시다보면 특정 플러그인을 사용했을시 IE10에서 확인해보면

indexOf가 정의되어있지 않습니다.

위와 같은 에러메시지를 접할때가 있습니다.
이런 경우에 특정 코드를 추가하면 해결되는 경험을 해보셨을 수도 있습니다.
그 특정 코드를 바로 폴리필이라고 부릅니다.

하지만 이렇게 에러가 생길때마다 직접 폴리필을 찾아 추가하는 것은 개발자에게 아주 귀찮은 일입니다.
이러한 일을 자동으로 해주는 라이브러리가 있습니다.

Gulp에선 바로 browserify 라이브러리가 이 역할을 해줍니다.

위와 같이 자바스크립트 파일을 컴파일 합니다.
위와 같이 하면 자바스크립트를 작성할 때 최신 문법과 최신 개념을 사용해서 작업해도 알아서 브라우저 저버전에서도 작동하도록 컴파일해줍니다.


Grunt, Gulp, Webpack, parcel .. 자동화툴 역사

FE 개발자들은 Grunt, Gulp, Webpack, parcel 등 많은 종류의 자동화 툴을 사용합니다.

이 중에서 Grunt와 Gulp는 웹 테스크 매니저 또는 웹 테스크 러너라 불리고 Webpack, parcel 등은 모듈 번들러라고 불립니다.
등장 순서로보면 Grunt가 2011년, Gulp가 2013년에 나왔고 Webpack과 parcel는 그 이후에 나왔습니다.

이러한 자동화 도구는 같은 철학을 가지고 있습니다.

  1. 개발자 편의성
  2. 사용자 접근성

이러한 자동화 툴은 공통적으로 귀찮고 반복적이고 번거로운 일이면서도 개발자의 실수를 유발하기 쉬운 작업들을 자동화했습니다.
개발자가 그러한 일들을 직접 처리하는 것이 아닌 컴퓨터가 자동으로 처리해 개발자의 실수를 최소화하고 작업시간을 단축시켰습니다.

그리고 결과물을 최적화해 사용자의 접근성을 높였습니다.
최적화엔 압축, min 파일화, 번들링 등 많은 방법이 있습니다.

개발자들이 Grunt에서 Gulp로 옮겨간 이유

저희 회사만 보더라도 대부분 작업에서 Gulp를 더 많이 사용합니다.
라인만해도 옛날 레포에서만 Grunt를 가끔 볼 수 있고 대부분 Gulp를 사용합니다.
왜 Grunt에서 Gulp로 옮겨갔는지 이유를 알아보기 전에 Grunt와 Gulp의 차이점을 짚고 넘어가는 게 좋을 것 같습니다.

겉으로만 보면 Grunt와 Gulp는 같은 작업을 수행합니다.

Grunt, Gulp 수행방법

하지만 수행하는 방법에서 차이가 있습니다.

Grunt는 아래와 같이 설정하는 형태로 작성합니다.
특정 기능을 구현하기 위해 미리 정해져있는 규칙에 의해 설정파일을 작성하면 되는 방식입니다.
프레임워크와 라이브러리 개념으로 보자면 프레임워크에 더 가깝다고 볼수도 있을 것 같습니다.

// Grunt는 JSON 형태의 config를 구성하는 방식으로 구현됩니다.
imagemin:{
   jpgs:{
	options:{
		progressive: true
	},
	files:[{
		expand:true,
		cwd: 'src/img',
		src: ['*.jpg'],
		dest: 'images/'
	}]
   }
}

반대로 Gulp는 아래와 같이 JavaScript 코드를 다룰 줄 안다면 JavaScript로 쉽게 작성할 수 있습니다.

// Gulp는 Javascript를 사용합니다.
function jpgs() {
   return gulp.src()
	.pipe(imagemin({ progressive: true}))
	.pipe(gulp.dest('optimized_images'))
}

속도

Grunt와 Gulp는 속도면에서도 차이가 있습니다.

Gulp는 스트림을 기반으로하는 빌드 시스템입니다.
스트림을 이용해서 데이터를 읽고 출력하며 작업들을 ‘메모리’에서 처리합니다.
즉, 요청 후 한번에 결과를 받는 것이 아니라 이벤트 중간중간 전달받아 작업을 하기 때문에 비교적 작업속도가 빠릅니다.

스트림이란?
데이터 입,출력시 비동기적으로 처리될 수 있는 데이터의 연속적 흐름으로써, NodeJS에서는 이 스트림을 읽고 쓸 수 있습니다.

…이건 다른 카테고리에서 정리했으므로 여기까지.