웹팩 기본 사용법 (1)

처음 접해보는 웹팩의 원리와 기본 사용 방법

2023-11-30

웹팩(기본)배경

예를들어 아래와 같은 덧셈 함수는

// math.js
function add(a,b){
    return a+b;
}
// app.js
add(10,20);

모두 하나의 HTML 파일안에서 로딩해야만 실행된다. math.js가 로딩되면 app.js는 add 함수를 찾고 실행시키는데, add 함수가 전역으로 사용되기 때문에 다른 파일에서 같은 이름의 함수를 사용하면 충돌이 발생할 수 있다.


이런 문제를 예방하기위해 IIFE(즉시실행함수) 방식의 스코프를 사용했다.

var math = math || {}

;(function () {
  function add(a, b) {
    return a + b
  }
  math.add = add
})();

함수 스코프를 만들어 외부에서 접근할 수 없도록해 충돌을 막을 수 있었고, 전역에 선언한 math라는 이름만 사용하면 된다.


자바스크립트 모듈을 구현하는 대표적인 명세는 AMD와 CommonJS가 있다.

CommonJS

//math.js
export function add(a,b){
    return a+b;
}
//app.js
const math = require('./math.js');
math.add(10,20);

ES2015 표준 모듈 시스템

//math.js
export function add(a,b){
    return a+b;
}
//app.js
import {add} from './math.js';
add(10,20);

export 구문으로 모듈을 만들고 import 구문으로 가져올 수 있다.

이러한 방식은 모든 브라우저에서 지원하지 않는다. 따라서 웹팩과 같은 모듈 번들러를 사용해야한다.


웹팩사용방법

웹팩은 여러개의 파일을 하나로 합쳐주는 번들러(bundler)이다. 웹팩을 사용하면 자바스크립트뿐만 아니라 css, html, 이미지 등 모든 파일을 모듈로 관리할 수 있다.

웹팩으로 간단하게 작업을 해보자.

먼저 웹팩과 웹팩 터미널 도구인 cli를 설치한다.

npm install -D webpack webpack-cli

root 디렉토리에 webpack.config.js 파일을 생성한다.

//webpack.config.js
const path = require('path');

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

package.json에 빌드 스크립트를 추가한다.

//package.json
{
    "scripts": {
        "build": "webpack"
    }
}

이제 npm run build 명령어를 실행하면 웹팩이 빌드를 시작한다.


웹팩 로더

웹팩은 자바스크립트 파일 뿐만 아니라 css, html, 이미지 등 모든 파일을 모듈로 관리할 수 있다. 하지만 웹팩은 자바스크립트 파일만 이해할 수 있기 때문에 css나 html, 이미지 파일을 자바스크립트 파일로 변경해야한다. 이때 사용하는 것이 로더이다.

자주 사용하는 로더

css-loader

npm install -D css-loader

웹팩은 모두 모듈로 바라보기 때문에 자바스크립트 뿐만 아니라 스타일시트도 import 구문으로 불러올 수 있다.

import './style.css';
// style.css
body {
    background-color: red;
}
//webpack.config.js
module.exports = {
    {...}
  module: {
    rules: [
      {
        test: /\.css$/, // .css 확장자로 끝나는 모든 파일
        use: ["css-loader"], // css-loader를 적용한다
      },
    ],
  },
};

웹팩은 entry에서 모듈을 검색하다가 css 파일을 찾으면 css-loader를 적용한다.


style-loader

모듈로 변경된 스타일 시트는 돔에 추가되어야 브라우저가 해석한다. css-loader는 css 파일을 자바스크립트 파일로 변경할 뿐 돔에 추가하지는 않는다. 따라서 style-loader를 추가해야한다.

npm install -D style-loader
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

style-loader를 css-loader보다 앞에 적용한다. 로더는 배열로 설정하면 뒤 -> 앞 순서대로 로더가 작동한다.


file-loader

css 뿐만 아니라 소스코드에서 사용하는 모든 파일들을 모듈로 사용할 수 있게 할 수 있다.

npm install -D file-loader
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif)$/i, // i는 대소문자 구분없이, 확장자들
        loader: "file-loader",
        options: {
          publicPath: "./dist/", // prefix를 아웃풋 경로로 지정
          name: "[name].[ext]?[hash]", // 파일명 형식
        },
      },
    ],
  },
};

옵션으로 경로를 지정할 수 있다. publicPath는 파일을 참조하는 경로를 지정한다. name은 파일명 형식을 지정한다.


url-loader

파일을 base64로 인코딩하여 문자열 형태로 변환한다. 파일 크기가 작은 파일들은 문자열로 변환하여 파일을 요청하는 횟수를 줄일 수 있다.

npm install -D url-loader
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif)$/i,
        loader: "url-loader",
        options: {
          publicPath: "./dist/",
          name: "[name].[ext]?[hash]",
          limit: 5000, // 5kb 미만 파일만 data url로 처리
        },
      },
    ],
  },
};

file-loader와 url-loader는 v5부터 기본적으로 제공하며, asset이라는 키워드로 사용할 수 있다.

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif)$/i,
        type: "asset/resource", // file-loader
        generator: {
          filename: "[name][ext]?[hash]", // [name]은 파일명, [ext]는 확장자
        },
      },
      {
        test: /\.(png|jpe?g|gif)$/i,
        type: "asset/inline", // url-loader
        generator: {
          filename: "[name][ext]?[hash]",
        },
      },
      {
        test: /\.(png|jpe?g|gif)$/i,
        type: "asset", // 기본값은 8kb 미만은 inline, 8kb 이상은 resource
        generator: {
          filename: "[name][ext]?[hash]",
        },
      },
    ],
  },
};

웹팩 플러그인

로더는 파일을 해석하고 변환하는 과정에 관여하지만 플러그인은 해당 결과물의 형태를 바꾸는 역할을 한다. 로더는 파일 단위로 처리하는 반면 플러그인은 번들된 결과물을 처리한다. 번들된 자바스크립트를 난독화 한다거나, 특정 텍스트를 추출할 수 있는 용도로 사용한다.

자주 사용하는 플러그인


BannerPlugin

const webpack = require("webpack");

module.exports = {
  plugins: [
    new webpack.BannerPlugin({
      banner: () => `빌드 날짜: ${new Date().toLocaleString()}`,
    }),
  ],
};

DefinePlugin

개발환경과 운영환경으로 나누어서 작업할 때 환경변수를 설정할 수 있다. 환경에 의존적인 정보를 소스가 아닌 환경 변수로 관리하면 소스코드를 더욱 안전하고 편리하게 관리할 수 있다.

const webpack = require("webpack");

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      VERSION: JSON.stringify("v.1.2.3"),
      PRODUCTION: JSON.stringify(false),
      MAX_COUNT: JSON.stringify(999),
      "api.domain": JSON.stringify("http://dev.api.domain.com"),
    }),
  ],
};

HtmlWebpackPlugin

npm install -D html-webpack-plugin
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: 'index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index_bundle.js',
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html", // 템플릿 경로를 지정
      minify:
        process.env.NODE_ENV === "production"
          ? {
              // 빌드 모드가 production일 때만 사용
              collapseWhitespace: true, // 빈칸 제거
              removeComments: true, // 주석 제거
            }
          : false,
    }),
  ],
};
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>webpack App</title>
  </head>
  <body>
    <script src="index_bundle.js"></script>
  </body>
</html>

script 태그에 번들링된 결과물을 자동으로 추가해준다. 웹팩 엔트리가 여러개일 경우 여러개의 script 태그를 추가해준다.


CleanWebpackPlugin

npm install -D clean-webpack-plugin
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
  plugins: [new CleanWebpackPlugin()],
};

MiniCssExtractPlugin

스타일 시트가 점점 많아짐에 따라 하나의 자바스크립트로 만들면 부담이 될 수 있다. 번들 결과물에서 스타일시트 코드만 따로 분리하여 별도의 css파일로 만들어주는 플러그인이다.

npm install -D mini-css-extract-plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
    }),
  ],
};

운영 환경에서는 MiniCssExtractPlugin.loader를 사용해 스타일시트를 별도의 파일로 분리한다. 개발 환경에서는 style-loader를 사용해 동적으로 돔에 추가한다.


웹팩의 로더와 플러그인의 원리, 사용방법에 대해서 알아보았다.

우리가 편리하고 쉽게 사용하는 Create-React-App는 웹팩으로 빌드된 결과물을 제공해준다. 하지만 기본적인 웹팩으로 설정되어있고, 직접 커스텀하려면 eject를 해야한다.

이번 기회에 웹팩의 원리와 기본적인 사용방법을 알아보았다.