본문 바로가기
Front-end Framework

[최신 웹 프론트엔드 개발환경 세팅] 5. 예제 구현

by kellis 2020. 11. 15.

5) 예제 구현

 

예제 소스 

 

es6-demo.zip
0.07MB

 를 다운로드하여 사용하시면 됩니다. 

이 파일은 babel과 webpack 설정이 모두 완료된 상태로, 압축을 풀고 npm install을 하신 뒤 바로 사용이 가능합니다. 소스로 사용된 예제는 mdn의 module example을 활용하였습니다.

프로젝트 구조는 아래와 같습니다. 

이제 실제로 트랜스파일링과 번들링을 위해 필요한 작업을 수행하고, 브라우저상에서 정상적으로 동작하는지 확인해 보도록 하겠습니다.

 

(1) Babel로 Transpiling

먼저, plugin-proposal-class-properties을 설치해주어야 합니다.

preset-env는 현제 제안 단계에 있는 사양의 플러그인의 경우 트랜스파일링이 되지 않기 때문에, 이를 보완해주는 플러그인이 필요하기 때문입니다. 이 글에서 사용된 예제에서는 Class field를 정의하는 것이 여기에 해당됩니다. 이와 같이 설치가 필요한 플러그인은 바벨 홈페이지에서 검색할 수 있습니다. 

npm install --save-dev @babel/plugin-proposal-class-properties

설치가 완료되면 .babelrc 파일에 plugins 정보를 추가해줍니다.

{
  "presets": ["@babel/preset-env"],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}

그럼 이제 트랜스파일링 실행을 위해  package.json 파일을 조금 수정해보겠습니다. scripts에 build를 추가하여 babel로 빌드한다는 것을 지시해주는 것입니다. 

{
  "name": "es6-demo",
  "version": "1.0.0",
  "scripts": {
    "build": "babel src/js -w -d dist/js"
  },
  "devDependencies": {
    "@babel/cli": "^7.7.0",
    "@babel/core": "^7.7.2",
    "@babel/preset-env": "^7.7.1",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10"
  }
}

이전 글에서 생성한 package.json에 build를 추가한 내용입니다. 보기 쉽게 하기 위해서 일부 필요 없는 내용(description 등)을 제거하였습니다.

  • -w : --watch 옵션의 축양형. 타깃 폴더(src/js)에 있는 모든 파일들의 변경을 감지하여 자동으로 트랜스파일링 
  • -d : --out-dir 옵션의 축양형. 트랜스파일링된 결과물이 저장될 폴더 지정.

 

프로젝트 루트 위치에서 트랜스파일링을 실행하면 아래와 같이 출력됩니다. 

npm run build
 
> es6-demo@1.0.0 build {프로젝트 루트}
> babel src/js -w -d dist/js
 
Successfully compiled 5 files with Babel

또한 프로젝트 루트에 dist 폴더가 생성됩니다. dist에 생성된 js 파일을 열어보시면, 아래와 같이 기존의 es6코드가 정상적으로 es5으로 변환된 것을 보실 수 있습니다. 


여기까지 되었다면, babel을 위한 설정은 완료되었습니다. webpack이 필요하지 않거나, 트랜스파일링만 필요하다면 여기까지의 내용으로 충분합니다.

 

(2) Webpack Bundling 

그러나 우리는 여러 모듈이 존재하기 때문에 번들링이 필요합니다.  이를 위해 webpack 설정을 해주도록 하겠습니다. 

 

먼저 추가적으로 필요한 패키지를 설치하겠습니다. 

npm install --save-dev babel-loader
 
npm install webpack-dev-server --save-dev
  • babel-loader : webpack이 모듈을 번들링할 때, babel 트랜스파일링 작업을 수행하도록 하는 패키지. 만약 트랜스파일링이 필요하지 않다면 필요 없음
  • webpack-dev-server : webpack 빌드를 테스트하기 위해 사용하는 http 서버. 메모리에서 빌드하여 테스트할 수 있도록 하는 패키지. express의 심플 버전이라고 볼 수 있음.

 

그리고 프로젝트 루트에 webpack.config.js 파일을 생성합니다. 

const path = require('path');
 
module.exports = {
  // enntry file
  entry: './src/js/main.mjs',
  output: {
    path: path.resolve(__dirname, 'dist/js'),
    filename: 'bundle.js'
  },
  devServer: { contentBase: "./" },
  module: {
    rules: [
      {
        test: /\.js$/,
        include: [
          path.resolve(__dirname, 'src/js')
        ],
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
            plugins: ['@babel/plugin-proposal-class-properties']
          }
        }
      }
    ]
  },
  mode: 'development'
};
  • entry : webpack의 진입점. 
  • output : webpack의 결과물
    • path : 컴파일한 번들을 저장할 위치
    • filename : 번들명으로 지정할 이름
  • module : 모듈 관련 설정
    • loader : 적용할 로더. 대체로 babel과 많이 사용하므로 babel-loader가 들어갑니다.
    • options : 플러그인을 사용하기 때문에 이를 사용함을 기재해 주어야 합니다. 

 

마지막으로 package.json에서 build를 babel이 아닌 webpack을 수행하도록 변경해주겠습니다. 아래가 최종적인 package.json의 형태입니다. 

{
  "name": "es6-demo",
  "version": "1.0.0",
  "scripts": {
    "start": "webpack-dev-server --open",
    "build": "webpack -w"
  },
  "devDependencies": {
    "@babel/cli": "^7.7.0",
    "@babel/core": "^7.7.2",
    "@babel/plugin-proposal-class-properties": "^7.7.4",
    "@babel/preset-env": "^7.7.1",
    "babel-loader": "^8.0.6",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.9.0"
  }
}
  • --open 옵션 : webpakc-dev-server 실행 시 localhost:8080이 브라우저에서 열림

 

이제 webpack 설정도 모두 끝났습니다. webpack을 실행하여 트랜스파일링 및 번들링을 실행하면 아래와 같이 출력됩니다. 

npm run build
 
> es6-demo@1.0.0 build {프로젝트 루트}
> webpack -w
 
 
webpack is watching the files…
 
Hash: d64d0739af01d7f6ac7c
Version: webpack 4.41.2
Time: 151ms
Built at: 2019-11-29 18:15:42
    Asset    Size  Chunks             Chunk Names
bundle.js  12 KiB    main  [emitted]  main
Entrypoint main = bundle.js
[./src/js/main.mjs] 874 bytes {main} [built]
[./src/js/modules/canvas.mjs] 1.11 KiB {main} [built]
[./src/js/modules/circle.mjs] 1.04 KiB {main} [built]
[./src/js/modules/square.mjs] 883 bytes {main} [built]
[./src/js/modules/triangle.mjs] 1.21 KiB {main} [built]

성공젹으로 번들링이 실행되고 나면 dist/js 아래에 bundle.js가 생성됩니다. 이렇게 생성된 bundle.js를 사용하고자 하는 html에 script로 심어주면, es6 문법도 정상적으로 동작하게 됩니다. 

<!DOCTYPE html>
<html>
<body>
  <script src="./dist/js/bundle.js"></script>
</body>
</html>

 

(3) Webpack-dev-server를 이용한 예제 실행 확인

 

트랜스파일링과 번들링 작업이 모두 끝났습니다. 이제 예제가 실제로 정상 동작하는지 확인해보도록 하겠습니다. webpack-dev-server를 띄워줍니다. 

npm start
 
> es6-demo@1.0.0 start {프로젝트 루트}
> webpack-dev-server --open
 
i 「wds」: Project is running at http://localhost:8080/
i 「wds」: webpack output is served from /
i 「wds」: Content not from webpack is served from ./dist
i 「wdm」: Hash: a0d5788fc8725de20873
Version: webpack 4.41.2
Time: 667ms
Built at: 2019-11-29 18:19:49
    Asset     Size  Chunks             Chunk Names
bundle.js  369 KiB    main  [emitted]  main
Entrypoint main = bundle.js
[0] multi (webpack)-dev-server/client?http://localhost:8080 ./src/js/main.mjs 40 bytes {main} [built]
[./node_modules/webpack-dev-server/client/index.js?http://localhost:8080] (webpack)-dev-server/client?http://localhost:8080 4.29 KiB {main} [built]
[./node_modules/webpack-dev-server/client/overlay.js] (webpack)-dev-server/client/overlay.js 3.51 KiB {main} [built]
[./node_modules/webpack-dev-server/client/socket.js] (webpack)-dev-server/client/socket.js 1.53 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/createSocketUrl.js] (webpack)-dev-server/client/utils/createSocketUrl.js 2.89 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/log.js] (webpack)-dev-server/client/utils/log.js 964 bytes {main} [built]
[./node_modules/webpack-dev-server/client/utils/reloadApp.js] (webpack)-dev-server/client/utils/reloadApp.js 1.59 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/sendMessage.js] (webpack)-dev-server/client/utils/sendMessage.js 402 bytes {main} [built]
[./node_modules/webpack-dev-server/node_modules/strip-ansi/index.js] (webpack)-dev-server/node_modules/strip-ansi/index.js 161 bytes {main} [built]
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
[./src/js/main.mjs] 874 bytes {main} [built]
[./src/js/modules/canvas.mjs] 1.11 KiB {main} [built]
[./src/js/modules/circle.mjs] 1.04 KiB {main} [built]
[./src/js/modules/square.mjs] 883 bytes {main} [built]
[./src/js/modules/triangle.mjs] 1.21 KiB {main} [built]
    + 22 hidden modules
i 「wdm」: Compiled successfully.
  • 꼭 webpack-dev-server를 사용할 필요는 없습니다. 다른 http 서버, 예를 들어 express 등을 사용하셔도 무방합니다. 

 

localhost:8080으로 접속해보면, 정상적으로 브라우저에서 동작하는 것을 확인할 수 있습니다. 

 

 

 

참고. babel-polyfill

ES6에서 추가된 Promise나 Object.assign, Array.from 등은 ES5로 트랜스파일링하여도, 대체할 수 있는 ES5의 기능이 없어 변경되지 않고 그대로 남아 있게 됩니다. 마찬가지로 브라우저는 이 기능들을 지원하지 않기 때문에 이럴 때에는 babel-polyfill 패키지를 설치해 주어야 합니다.

트랜스파일링만 수행한다면, main.js와 같이 진입점에서 @babel/polyfill을 import 해주어야 하고,

webpack을 사용한다면, webpack.config.js 파일의 entry에 진입점과 함께 @babel/polyfill를 기재해 주어야 합니다.  

const path = require('path');
 
module.exports = {
  // entry files
  entry: ['@babel/polyfill', './src/js/main.js'],
   
  //...이하 생략

 

 

mjs vs js

mjs 확장자?

예제 소스를 보시면 자바스크립트 파일인데 mjs 확장자를 사용하는 것을 보실 수 있습니다. mjs는 EcmaScript의 모듈을 위한 확장자로서, 이 자바스크립트 파일이 모듈로 구성되었다는 것을 명시합니다. js와 달리 정의상 use strict 한 등의 약간의 차이가 있습니다. 

 

 

 

references

 

Babel과 Webpack을 이용한 ES6 환경 구축 1

 

Babel | PoiemaWeb

현재 브라우저는 ES6를 완전하게 지원하지 않는다. ES6+(ES6 이상의 버전)를 사용하여 프로젝트를 진행하려면 ES6+로 작성된 코드를 IE를 포함한 모든 브라우저에서 문제 없이 동작시키기 위한 개발

poiemaweb.com

Babel과 Webpack을 이용한 ES6 환경 구축 2

 

Webpack | PoiemaWeb

앞에서 테스트해 본 바와 같이 ES6 모듈을 현재의 브라우저에서 사용하려면 [RequireJS](http://requirejs.org/) 또는 [SystemJS](https://github.com/systemjs/systemjs)와 같은 모듈 로더가 필요하다. [Webpack](https://webpac

poiemaweb.com

 

댓글