본문 바로가기

React/Babel과 WebPack 을 이용한 ES6 환경 구축

Babel과 Webpack을 이용한 ES6 환경 구축(2) - Webpack 이란?

WebPack5는 build콘솔에 여러 warning이 발생, 각종 plugin에서 아직 webpack5대응이 완벽하게 되어 있지 않은 것 같습니다.

 

[ WebPack 이란? ]

 

모듈 번들링이라고 한다. 모듈 번들링이란 html 파일에 들어가는 필요한 다수의 의존관계에있는 모듈들을 하나의 Javascript 파일로 만들어주는 방식이다.

 

[ WebPack을 사용하는 이유 ]

 

1. 여러개의 파일을 하나로 묶어줌

Webpack을 사용하면 의존 모듈이 하나의 파일로 번들링되므로 별도의 모듈 로더가 필요없다. 그리고 다수의 Javascript  파일을 하나의 파일로 번들링하므로 html 파일에서 script 태그로 다수의 자바스크립트 파일을 로드해야 하는 번거로움도 사라진다.

 

옛날에는 페이지마다 새로운 html을 요청해서 뿌려주는 방식이었다면, 요새는 SPA 하나의 html 페이지에 여러개의 Javascript 파일들을 포함한다. 이 여러개의 Javascript파일들을 하나로 묶어주어 관리가 편하고, 컴파일 시간이 줄어들며 웹페이지 성능을 최적화 해준다. 

 

2. http 요청이 비효율적이기 때문에

다운로드 할 파일이 많아지게 되면 네트워크 커넥션이 많아지므로 네트워크에 부하가 많아져 느려진다.

웹페이지는 html, css, js 등 수 많은 구성요소로 이루어져 있다. 이 외에도 이미지, json 데이터 등등 수 많은 파일들을 받아와야 하는데 http/1.1에서는 커넥션 하나를 열어 하나씩 요청을 보내야 한다. (요청이 많을수록 비효율적)

때문에 하나의 파일로 합쳐주어 요청 횟수도 줄이고 속도도 향상된다. (하나의 파일로 합치기에 파일이 크다면 여러개로 나눌 수도 있다.)

 

하단의 그림처럼 WebPack 은 여러 파일들을 하나로 합쳐주면서 크로스브라우징 이슈도 대응한다.

 

[ 설정 파일 구분 ]

WebPack4 가 나오면서 개발시 사용하는 Development 모드와 파일을 압축하여 변수 이름 들을 읽기 어렵게 축약해 놓은 Production 모드가 생겼다. 한개의 설정파일을 생성하고 공유하면서 각 빌드 별로 분기를 만들어 설정해줄 수도 있지만 파일을 개발용, 배포용으로 나누어 사용하는걸 권장한다고 한다. 

WebPack파일을 3가지로 나누어 개발용, 배포용, 공용으로 만들어준다. 나눈 후 공통으로 쓰이는 부분을 WebPack Merge를 사용해 분리하여 사용한다.

  • webpack.common.js
  • webpack.dev.js
  • webpack.prod.js

[ 설치 ]

 

# 웹팩 merge를 설치

$ npm i webpack-merge 

# 웹팩 설치 (웹팩4 부터는 webpack core와 webpack-cli 패키지가 분리되었기 때문에 두 패키지를 각각 설치해야 한다.)

$ npm i --save-dev webpack webpack-cli

[ babel-loader ]

Webpack이 모듈을 번들링할 때 babel을 사용하여 ES6+ 코드를 ES5 코드로 트랜스파일링하도록 babel-loader를 설치한다.

# babel-loader 설치

$ npm install --save-dev babel-loader

 

[ webpack.common.js 생성 ]

webpack.config.js 는 Webpack이 실행될 때 참조하는 설정 파일이다. 프로젝트 루트에 webpack.config.js 파일을 생성하고 아래와 같이 작성한다. (최종작성을 먼저 보여주고있다.)

webpack.common.js 
webpack.common.js 

entry

웹팩은 기본적으로 여러 개의 자바스크립트 모듈을 하나의 파일로 묶어내는 번들러입니다. 따라서 웹팩은 다른 모듈을 사용하고 있는 최상위 자바스크립트 파일이 어디에 있는지 알아야 하며, 설정 파일에서 이를 Entry 속성으로 명시한다. 웹팩은 이 Entry 속성에 명시된 파일을 기준으로 의존성 트리를 만들어 하나의 번들 파일을 만들어 내게 된다. Entry 설정의 기본값은 ./src/index.js 이다. 

 

output

위 섹션에서 웹팩이 번들링 결과를 dist/main.js 파일로 묶어내는 이유는 설정이 dist/main.js이기 때문입니다. 설정 파일의 Output 속성을 통해서 이 값을 다른 디렉터리와 파일로 변경할 수 있습니다.

Entry 설정은 항상 프로젝트 디렉터리 내부이기 때문에 상대 경로로 하는 반면에, Output 설정은 항상 프로젝트 디렉터리 내부라는 보장이 없으므로 절대 경로로 한는 점에 주의 바랍니다.

※ HtmlWebpackPlugin을 사용하면 html 파일을 자동으로 생성해 주기 때문에 output을 입력하지 않아도 번들 파일이 dist에 생성된다. 파일의 이름이나 경로를 따로 지정해 줄 필요가 없으면 입력하지 않아도 된다.

 

resolve 

Webpack이 알아서 경로나 확장자를 처리할 수 있게 도와주는 옵션이다. 

modules에 node_modules를 넣어야 디렉토리의 node_modules를 인식할 수 있다. 

resolve.alias를 사용하명 경로를 줄일 수 있다. 

 

공식문서를 보면 Babel 7.4.0부터 더이상 사용하지 않고 core-js와 regenerator-runtime을 직접 사용하는 방식을 제안하고 있다.

또한 전역을 오염시키지 않고 웹팩 번들에 포함하여 번들 내부에 가두는 방법이 있어 그방법을 사용하기로 했다. 이러한 방식은 코드에서 사용한 polyfill 메서드만 번들에 포함된다. 방법은 아래와 같다.

 

$ npm install --save-dev @babel/plugin-transform-runtime

$ npm install --save @babel/runtime @babel/runtime-corejs3

 

module의 rules아래 plugins에 아래 코드를 추가해준다.

webpack.common.js 

Promise, Object.assign, Array.from 등과 같이 ES5 이하로 대체할 수 없는 기능은 트랜스파일링이 되지 않는다.

따라서 오래된 브라우저에서도 ES6+에서 새롭게 추가된 객체나 메소드를 사용하기 위해서는 @babel/polyfill을 설치해야 한다. babel-polyfill은 개발 환경에서만 사용하는 것이 아니라 실제 환경에서도 사용하여야 하므로 --save-dev 옵션으로 개발 설치를 하지 않도록 한다.

 

# babel polyfill 설치

$ npm install @babel/polyfill

 

설치 후 webpack.config.js 에 entry에 추가해준다. 

webpack.config.js

loader 

loader는 babel loader를 사용할 것이다. 

 

optimization

성능 최적화를 위한 것이라 webpack.prod.js 에만 추가한다. 

[ plugin 및 코드분리 ]

로더는 특정 유형의 모듈을 변환하는 데 사용되지만 플러그인을 활용하여 번들 최적화, 자산 관리 및 환경 변수 주입과 같은 광범위한 작업을 수행 할 수 있다.

플러그인을 사용하려면 플러그인이 필요하고 require()이를 plugins어레이에 추가해야한다 . 대부분의 플러그인은 옵션을 통해 사용자 정의 할 수 있다. 다른 목적으로 구성에서 플러그인을 여러 번 사용할 수 있으므로 new연산자 로 호출하여 플러그인의 인스턴스를 만들어야한다.

 

여기서 Production 모드에서 사용할 plugin과 Development 모드에서 사용할 plugin이 나뉘기 때문에 파일을 분리해야 한다.

우선 공동으로 필요한 webpack.common.js 를 생성한다.

 

$ npm i --save-dev html-webpack-plugin dotenv-webpack

 

htmlWebpackPlugin을 사용해 output파일을 생성하기위해 공통으로 사용했다.
dotenv는 개발 모드와 배포 모드를 따로 만들고 경로도 따로 줄 수 있지만 우리 프로젝트에서는 하나의 파일이기 때문에 따로 경로 지정은 생략하고 공통 파일에 넣었다.

 

Development 모드

Development에서는 webpack-dev-server, Hot Module Replacement(HMR), 소스맵을 사용할 것이다.

 

webpack-dev-server : express로 만들어진 간단한 web server이다. 변경 사항을 감지해 리컴파일을 한뒤 브라우저를 빠르게 실시간 리로드한다. 디스크에 저장되지 않는 메모리 컴파일을 사용하기 때문에 컴파일 속도가 빨라진다.

 

htmlWebpackPlugin : 서버를 띄울 때마다 임시 index.html 파일을 만들어 사용한다. //동영상강의본 뒤 내용추가

 

Hot Module Replacement(HMR) : 코드에 변경이 생겨 다시 빌드할 때 매번 브라우저를 리로드 할 필요 없이 변경된 모듈만 바로 교체하는 기능이다. 그래서 현재 테스트 중인 스테이트가 계속 유지된다는 장점도 있다.

 

소스맵 : 배포시 파일들을 압축하여 코드를 알아보기 힘들기 때문에 에러가 난다면 디버깅이 힘들다. 소스맵은 배포용으로 빌드한 파일과 원본 파일을 연결시켜주기 때문에 배포용 파일의 특정 부분이 원본 소스의 어떤 부분인지 쉽게 확인가능하다.

 

inline-source-map : 개발용에서는 로그, 디버깅, 번들링 타임을 고려하여 옵션 선택

 

우선 webpack-dev-server 를 설치한다.

 

$ npm i --save-dev webpack-dev-server react-hot-loader

[ webpack.dev.js 생성 ]

webpack.dev.js

Production 모드

프로덕션 모드에서 고려해야 할 것은 코드 미니파이지만 위에서 보다시피 웹팩 4에서는 UglifyWebpackPlugin 이 내장되어 추가 설치나 설정 없이 미니파이가 가능하다.

  • 만약 Uglify를 필요한 사항에서만 적용하려면 optimization의 minimize를 false로 주고 terser-webpack-plugin을 활용하면 된다.
  • 때문에 Production 모드에서는 빌드마다 기존 dist 디렉터리를 초기화 해주는 플러그인과 위에서 언급한 optimization 정도만 적용했다.

$ npm i --save-dev clean-webpack-plugin

[ webpack.prod.js 생성 ]

webpack.prod.js

[Sass를 컴파일한 결과물인 css를 bundle.js 파일에 포함시키는 방법]

$ npm i node-sass style-loader css-loader sass-loader --save-dev

설치 후 wepack.common.js 파일에서

entry 안에 

wepack.common.js 

moudle -> rules 안에 아래 rule를 추가한다.

wepack.common.js 

[ package.json ]

package.json
package.json

터미널에서 npm start로 실행

 

[ 주의사항 ] 

webpack , webpack-cli 등 버전이 안맞으면 오류가 난다. webpack5로 업데이트 되고 난 뒤 호환이 안되는 경우가 있다.

필자는 현재 

  • webpack : 4.43.0
  • webpack-cli : 3.3.11
  • webpack-dev-server : 3.11.0
  • webpack-merge : 4.2.2 

인 상태이다. 

 

참고:

https://velog.io/@lllen/Webpack-z1tdfqep

https://dev-yakuza.posstree.com/ko/react/typescript/