Webpack 이란 ?

Posted by Juri on May 16, 2022

참고

웹팩 핸드북 웹팩 공식홈페이지 Serverless Webpack

Webpack

웹팩이란?

웹팩은 모듈 번들러로 웹 애플리케이션을 구성하는 자원(HTML, CSS, Javascript, Images 등)을 각각의 모듈로 보고 이를 조합해 병합된 하나의 결과물로 만드는 도구 중 하나이다.

웹팩에서의 모듈은 웹 애플리케이션을 구성하는 모든 자원을 의미하며 파일 하나하나가 모두 모듈이 된다. 많은 자원들을 하나의 파일로 병합 및 압축 해주는 동작을 모듈 번들링이라고 한다.

웹팩의 등장배경

  1. 파일 단위의 자바스크립트 모듈 관리
  2. 웹 개발 작업 자동화 도구
  3. 웹 애플리케이션의 빠른 로딩 속도와 높은 성능

웹팩의 주요 속성

entry

엔트리는 웹팩에서 웹 자원을 변환하기 위해 필요한 최초 진입점이자 자바스크립트 파일 경로이다.

1
2
3
module.exports = {
    entry: "./src/index.js"
};

웹팩에서 위의 코드를 실행하면 src폴더 밑의 index.js을 대상으로 웹팩이 빌드를 수행한다.

output

아웃풋은 웹팩을 돌리고 난 결과물의 파일 경로다.

1
2
3
4
5
6
7
8
const path = require("path");

module.exports = {
    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "./dist")
    }
};

filename은 웹팩으로 빌드한 파일의 이름을, path는 해당 파일의 경로를 의미한다.

Loader

로더는 웹팩이 애플리케이션을 해석할 때 자바스크립트 파일이 아닌 웹 자원(HTML, CSS, Images, Fonts 등)들을 변환할 수 있도록 도와준다.

1
2
3
4
5
6
7
8
9
10
module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ["css-loader"]
            }
        ]
    }
};

test는 로더를 적용할 파일 유형 (정규표현식 사용), use는 해당 파일에 적용할 로더의 이름을 입력한다. 위의 코드는 해당 프로젝트의 모든 CSS파일에 대해 CSS 로더를 적용하겠다는 의미로 볼 수 있다.

plugin

플러그인은 웹팩의 기본적인 동작에 추가적인 기능을 제공한다. 로더는 파일을 해석하고 변환하는 과정에 관여하는 반면, 플러그인은 결과물의 형태를 바꾸는 역할을 한다.

1
2
3
4
5
const webpack = require("webpack");

module.exports = {
    plugins: [new webpack.ProgressPlugin()]
};

플러그인 종류

  • split-chunks-plugin
  • clean-webpack-plugin
  • image-webpack-loader
  • webpack-bundle-analyzer-plugin

Developter Tools

Webpack Dev Server

웹팩 데브 서버는 웹 애플리케이션을 개발하는 과정에서 유용하게 쓸 수 있다. 웹팩의 빌드 대상 파일이 변경되었을 때 매번 웹팩 명령어를 실행하지 않아도 코드만 변경하고 저자하면 웹팩으로 빌드한 후 브라우저를 새로 고침해준다.

Source Map

소스맵은 배포용으로 빌드한 파일과 원본 파일을 서로 연결해준다. 압축해 배포한 파일에서 에러가 난다면 소스맵을 이용해 배포용 파일의 특정 부분이 원본 소스의 어떤 부분인지 확인할 수 있다.

Serverless Webpack

Serverless plugin to bundle your lambdas with Webpack

람다함수들을 웹팩으로 묶어주는 플러그인이다. 웹팩은 여러 개의 모듈을 하나의 자바스크립트 코드로 압축하는 라이브러리다.

webpack configuration file

아래와 같이 webpack 경로를 따로 지정하지 않으면 webpack.config.js를 찾는다.

1
2
3
4
5
6
7
custom:
  webpack:
    webpackConfig: ./src/my-webpack.config.js
    includeModules: true
      forceExclude:
        - aws-sdk

1
2
3
4
5
6
7
8
9
10
11
12
13
// my-webpack.config.js
const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
const path = require("path");

module.exports = {
    mode: slsw.lib.webpack.isLocal ? "development" : "production",
    entry: slsw.lib.entries,
    outputs: {
        path: path.join(__dirname, ".webpack")
    },
    externals: [nodeExternals()]
};
  • mode: 모드 (production, development)에 따라 최적화 혹은 빠르게 빌드된다.
  • entry: webpack이 빌드할 파일의 시작위치를 나타낸다.
  • output: 생성된 번들을 내보낼 위치와 파일이름을 지정한다.
  • externals: 번들에서 제외할 모듈을 지정한다. 위의 코드는 외부모듈을 지정하고 있다.

실습

개발환경과 배포환경에서 빌드 목표가 달라 환경에 따라 webpack configuration을 분리하는 게 좋다. 중복된 부분이 많아 common 부분을 유지하면서 각각의 설정을 새로 생성했다. 이후, 설정을 합치기 위해 webpack-merge를 사용한다.

webpack.common.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const path = require("path");
const nodeExternals = require("webpack-node-externals");
const webpack = require("webpack");
const slsw = require("serverless-webpack");

module.exports = {
    entry: slsw.lib.entries,
    output: {
        libraryTarget: "commonjs",
        path: path.resolve(__dirname, ".webpack"),
        filename: "[name].js"
    },
    resolve: {
        extensions: [".ts", ".js", ".json"]
    },
    externals: [nodeExternals()],
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: ["ts-loader"]
            }
        ]
    },
    target: "node"
};

common에서 entry 와 output을 설정한다.

webpack.dev.js

1
2
3
4
5
6
7
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");

module.exports = merge(common, {
    mode: "development",
    devtool: "source-map"
});

webpack.prod.js

1
2
3
4
5
6
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");

module.exports = merge(common, {
    mode: "production"
});

환경에 맞게 mode를 설정하고 development환경에는 devtool 설정을 추가했다. webpack-merge를 사용해 common을 중복해서 설정하지 않아도 된다.