[Javascript] Babel & Webpack

Isabel·2023년 8월 11일
0

CS 및 기술 정리

목록 보기
5/5

Babel, Webpack ?

이제 취업 준비를 하다보면 공고에서 이런 글을 확인할 수 있을 것입니다.

webpack, esbuild 등 모듈 번들러 활용 경험이 있는 분
Babel을 이용한 ES6+ 스펙의 사용 경험이 있는 분

또 쉽게 우리는 React 앱을 시작할 때, create-react-app 이라는 명령어를 통해 시작하죠? 이 때 webpack, babel이 자동으로 설치됩니다. Vue도 마찬가지에용. vue-cli를 통해 설치하면 webpack, babel이 자동으로 설치됩니다.

💡 학습 목표 : 바벨과 웹팩이 뭔지 알고 가시길!

1. Webpack이란?

💡 webpack: 모던 Javascript 애플리케이션을 위한 정적 모듈 번들러 (webpack 정의)

Webpack: 여러 개의 파일들을 하나로 묶어주는 번들러

  • 모듈 번들러 : 웹 어플리케이션을 구성하는 자원(HTML, CSS, Javascript, Images 등)을 각각 모듈로 보고 이를 병합해서 하나의 결과물을 만드는 도구

모듈 ****

  • 프로그래밍 관점
    • 특정 기능을 갖는 작은 코드 단위
  • Webpack에서는?
    • 웹 애플리케이션을 구성하는 모든 자원 하나하나가 모두 모듈
  • 모듈 번들링: 웹 애플리케이션을 구성하는 여러 자원들을 하나의 파일로 병합 및 압축 해주는 동작

Webpack은 왜 사용하나요?

  • 모듈화의 필요성
    • 파일 단위의 자바스크립트 모듈 관리
      • 자바스크립트의 변수의 유효 범위는 기본적으로 global → 어디에서든지 접근하기 용이함
      • 하지만 위 특성이 어플리케이션을 생성할 때는 문제점으로 작용
        <!-- index.html -->
        <html>
          <head>
            <!-- ... -->
          </head>
          <body>
            <!-- ... -->
            <script src="./app.js"></script>
            <script src="./main.js"></script>
        		<script>
              getNum();  // main.js의 var num 값이 출력됨
            </script>
          </body>
        </html>
        • 위 두 파일들에서 동일한 이름의 변수를 선언하고 활용한다고 가정했을 때, (예를 들면 var num) 내가 원하는 대로 결과값이 도출되지 않을 수 있음
      • 하지만 파일 단위로 변수를 관리할 수 있게 된다면? → 웹팩은 파일 단위로 모듈화하여 관리
  • 번들러를 사용하면 여러 파일을 하나로 묶어주기 때문에 네트워크 접속의 부담을 줄여 더 빠른 서비스를 제공할 수 있음
  • 브라우저의 HTTP 요청 제약을 피할 수 있음 (한 번에 보낼 수 있는 HTTP 요청 수 : 6~8개, 2개 이런 브라우저도 있음)

but, 하나의 파일로 모듈화된 파일들을 요청하게 되면 첫 로딩시 속도가 너무 느려질 수 있음

Code Splitting, 캐시 등의 방법으로 문제를 해결한다고 함


Code Splitting

웹팩에서 번들링 한 코드를 분할하고, 요청에 따라 로드할 수 있도록 해주는 방법

  • Code Splitting을 하지 않은 경우, 애플리케이션을 실행시켰을 때 모든 코드가 한번에 요청이 되어서 로딩 시간이 길어질 수 있음
  • Code Splitting을 하게 되면, 필요한 순간 필요한 코드만 불러오기 때문에 우선 순위를 제어할 수 있고, 로딩 시간도 줄일 수 있음

2. Babel이란?

💡 Babel: Javascript compiler

Babel: 입력된 코드를 Javascript로 변환해주는 트랜스파일러

  • Transplier: 특정 언어로 작성된 코드를 비슷한 다른 언어로 변환

Babel은 왜 사용하나요?

모든 브라우저가 최신 문법, 기술(ES6)을 지원하는 것은 아니기 때문에 구 기능(ES5)으로 변환하는 작업이 필요

  • ES6의 화살표 함수와 ES7의 지수 연산자
[1, 2, 3].map(n => n ** n);
  • Transpiled
// ES5
"use strict";

[1, 2, 3].map(function (n) {
  return Math.pow(n, n);
});

Babel이 하는 일

  1. Transform syntax 구문 변환

    • 최신 자바스크립트 문법을 오래된 브라우저가 이해할 수 있도록 오래된 문법 ES5으로 변환
  2. JSX and React

    • React에서 사용되는 JSX 문법을 Javascript로 트랜스파일링
    • JSX는 브라우저에서 바로 실행될 수 없기 때문에, Javascript로 변환해주어야 함
    • 바벨로 컴파일된 JSX는 React.createElement를 호출하여 리액트 엘리먼트를 반환한다.
    • JSX 문법을 사용하는 컴포넌트 파일에는 React를 import해줘야 한다.
    import React from 'react';

Babel과 Webpack을 활용한 간단 ES6 환경 구축!

Webpack

  1. Webpack 설치 및 초기 설정

    1-1. npm 초기화

    npm init -y
    //package.json
    {
      "name": "test",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }

    1-2. 로컬에서 webpack, webpack-cli (커맨드-라인에서 webpack을 실행할 때 사용되는 도구) 설치

    npm install webpack webpack-cli --save-dev

    devDependecies에 아래와 같이 추가됨

    //package.json
    {..., 
    
    "devDependencies": {
        "webpack": "^5.87.0",
        "webpack-cli": "^5.1.4"
      }
    }
  2. 번들 생성

    • lodash 설치 (build 정상적으로 되는지 테스트 하기 위해 설치)
    npm i lodash
    • index.html 파일 생성
    <html>
      <head>
        <title>Webpack Demo</title>
        <script src="https://unpkg.com/lodash@4.16.6"></script>
      </head>
      <body>
        <script src="src/index.js"></script>
      </body>
    </html>
    • src 폴더 생성 > 폴더 안에 index.js 파일 생성
    function component() {
      var element = document.createElement('div');
    
      /* lodash is required for the next line to work */
      element.innerHTML = _.join(['Hello','webpack'], ' ');
    
      return element;
    }
    
    document.body.appendChild(component());
  1. **웹팩 빌드를 위한 구성 및 빌드**

    • 웹팩 빌드 및 빌드 결과물로 실행하기 위해 각 파일에 아래 내용 반영
    import _ from 'lodash';
    • lodash를 Import하고 html 파일에서 lodash cdn import 관련 코드 삭제
    <html>
      <head>
        <title>Webpack Demo</title>
        <!-- <script src="https://unpkg.com/lodash@4.16.6"></script> -->
      </head>
      <body>
        <!-- <script src="src/index.js"></script> -->
        <script src="dist/main.js"></script>
      </body>
    </html>
    • 웹팩 빌드 명령어를 실행하기 위해 package.json 파일에 아래 내용 추가
    "scripts": {
      "build": "webpack --mode=none"
    }
    • npm run build 명령어 실행
    npm run build
    
    > test@1.0.0 build
    > webpack --mode=none
    
    asset main.js 536 KiB [emitted] (name: main)
    runtime modules 1.25 KiB 6 modules
    cacheable modules 532 KiB
      ./src/index.js 268 bytes [built] [code generated]
      ./node_modules/lodash/lodash.js 531 KiB [built] [code generate

    정상 빌드 됨 → dist 폴더 가 생성되고 해당 폴더 안에 main.js라는 파일의 결과물이 생김

  1. Using Configuration
  • 버전 4부터 webpack은 어떠한 설정도 필요하지 않으나 복잡한 설정이 필요한 경우를 위해 설정파일을 작성할 수 있음
  • webpack.config.js가 있으면 webpack은 이 파일을 기본으로 작동
  • 프로젝트 폴더 루트 레벨에 webpack.config.js 파일 생성 후 아래 내용 추가
// webpack.config.js
// `webpack` command will pick up this config setup by default
var path = require('path');

module.exports = {
  mode: 'none',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  }
};

  • entry
    : 웹팩이 빌드할 파일의 시작 위치
    : default [./src/index.js]

  • output
    : 웹팩에 의해 생성된 번들을 내보낼 위치와 이름 지정
    : default [./dist/main.js]

  • module

  • loaders
    : JS가 아닌 파일들도 유효한 모듈로 변환

  • plugins
    : 번들화된 JS를 난독화하거나 특정 텍스트를 추출
    : 번들된 css, js 파일들을 html 파일에 주입(html-webpack-plugin 사용)하는 역할
    : 번들을 최적화하거나, asset을 관리하고, 또 환경 변수 주입등과 같은 광범위한 작업 수행

  • mode
    : production(최적화 빌드), development(빠른 빌드), none(그냥 빌드)
    : 웹팩 설정 모드로 3가지 중 선택 가능

  1. NPM Scripts

    • 편리하게 사용하기 위해 단축 명령어를 사용할 수 있음
    • package.json 파일 수정
    "scripts": {
      "build": "webpack"
    }
  2. npm run build 정상 작동

    npm run build
    
    > test@1.0.0 build
    > webpack
    
    asset main.js 536 KiB [compared for emit] (name: main)
    runtime modules 1.25 KiB 6 modules
    cacheable modules 532 KiB
      ./src/index.js 268 bytes [built] [code generated]
      ./node_modules/lodash/lodash.js 531 KiB [built] [code generated]
    webpack 5.87.0 compiled successfully in 116 ms

Babel

  1. 패키지 설치
npm install --save-dev @babel/core @babel/cli @babel/preset-env
  • @babel/core : 바벨의 핵심 기능이 있는 모듈 (parsing(코드를 추상 구문 트리로 파싱), traverse(추상 구문 트리를 오래된 문법으로 변환), generator(새로 생성된 추상 구문 트리를 바탕으로 새로운 코드 생성)를 한꺼번에 처리할 수 있는 함수를 제공 => transformSync)
  • @babel/cli : @babel/core를 터미널에서 커맨드를 입력해서 사용하기 위한 패키지
  • @babel/preset-env : 모던 자바스크립트를 지원하기 위한 모든 플러그인의 집합 : ES6 이상(ES2015+)의 문법으로 작성된 코드를 ES5 문법의 코드로 변환해주는 모든 규칙을 정의’
  1. 전체 구성 파일 생성
  • 프로젝트의 루트에 babel.config.json 파일을 생성한 후, 아래 예시 코드로 설정한다.
    {
      "presets": [
        [
          "@babel/preset-env",
          {
            "targets": {
              "edge": "17",
              "firefox": "60",
              "chrome": "67",
              "safari": "11.1"
            },
            "useBuiltIns": "usage",
            "corejs": "3.6.5"
          }
        ]
      ]
    }
  1. 아래 코드를 package.json에 적용한 후, npm run compile을 터미널에 입력

    • src 폴더에 있는 모든 JavaScript 파일을 구문 분석(parse) 하고 설정한 변환을 적용하여 각 파일을 dist 폴더로 출력한다.
    npm run compile
    
    > test@1.0.0 compile
    > babel src -d dist
    
    Successfully compiled 1 file with Babel (210ms).

  • compile 전 원본
import _ from "lodash";

function component() {
  var element = document.createElement("div");
  const a = () => {
    console.log("a");
  };

  /* lodash is required for the next line to work */
  element.innerHTML = _.join(["Hello", "webpack"], " ");

  return element;
}

document.body.appendChild(component());
  • compile 후
"use strict";

var _lodash = _interopRequireDefault(require("lodash"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function component() {
  var element = document.createElement("div");
  const a = () => {
    console.log("a");
  };

  /* lodash is required for the next line to work */
  element.innerHTML = _lodash.default.join(["Hello", "webpack"], " ");
  return element;
}
document.body.appendChild(component());
  • but, 화살표함수는 ES5에서 안되지 않나요?
  1. plugin 사용하여 코드 변환 수행하기

    • ES2015+ 구문을 ES5로 변환하고자 한다면 @babel/plugin-transform-arrow-functions 플러그인을 사용하여 적용
    npm install --save-dev @babel/plugin-transform-arrow-functions
    • babel.config.json 파일에 도 설정
    {
      "presets": [
        ...
      ],
      "plugins": ["@babel/plugin-transform-arrow-functions"]  // 추가
    }

    이제는 화살표 함수도 선언형 함수 형태로 컴파일 해줄 수 있다.

    "use strict";
    
    var _lodash = _interopRequireDefault(require("lodash"));
    function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
    function component() {
      var element = document.createElement("div");
      const a = function a() {
        console.log("a");
      };
    
      /* lodash is required for the next line to work */
      element.innerHTML = _lodash.default.join(["Hello", "webpack"], " ");
      return element;
    }
    document.body.appendChild(component());
  • 그 외에도 추가적으로 preset, polyfill, configuration을 활용하여 더 다양하게 사용할 수 있다.

한 줄 요약

💡 웹팩은 자바스크립트 어플리케이션을 위한 모듈 번들러!
바벨은 자바스크립트 컴파일러! (or 트랜스파일러)


참고
webpack
Babel · Babel
웹팩이 필요한 이유 | 웹팩 핸드북
Babel 직접 적용하며 이해하기

0개의 댓글