웹팩 - 가장 사랑받는 번들러

Ryu·2022년 9월 26일
0
post-thumbnail

webpack은 2022년 7월 현재 프론트엔드 애플리케이션 배포를 위해서 가장 많이 사용하는 번들러입니다. 실리콘벨리나 국내 IT 대기업을 막론하고 프론트엔드 애플리케이션을 대규모 유저에게 제공하기 위해 가장 많이 사용하는 방법입니다. 많은 웹 개발자에게 사랑받고 있고, 이제는 Node.js 백엔드 개발자도 배포를 위해서도 많이 사용합니다. - 웹팩 한글화 문서

가장 많이 사용하는 번들러답게 공식문서도 한글로 번역이 되어있고, 자료도 쉽게 찾을 수 있어 처음 번들링에 대해서 학습할 때 참고하기 좋습니다.

Webpack이란

여러 개의 파일을 하나의 파일로 합쳐주는 모듈 번들러를 의미합니다. 모듈 번들러란 HTML, CSS, JavaScript 등의 자원을 전부 각각의 모듈로 보고 이를 조합해 하나의 묶음으로 번들링(빌드)하는 도구입니다.

1. 모듈 번들러(Module Bundler)의 등장

모던 웹으로 발전하면서 JavaScript 코드의 양이 절대적으로 많이 증가했고, 또 대규모의 의존성 트리를 가지고 있는 대형 웹 애플리케이션이 등장하므로써 세분화된 모듈 파일이 폭발적으로 증가했습니다. 이 모듈 단위의 파일들을 호출을 해 브라우저에 띄워야 하는데, JavaScript 언어의 특성에 따라 발생하기 쉬운 각 변수들의 스코프 문제를 해결해야 하고, 각 자원을 호출할 때에 생겨나는 네트워크 쪽의 코스트도 신경써줘야만 했습니다.

각 모듈에서 쓰이는 변수의 이름의 종속성과 순서 문제/ 네이밍 충돌 / 비효율적일정도로 많은 통신

그래서 이런 복잡성에 대응하기 위해 하나의 시작점(Ex. React App의 index.js 등)으로부터 의존성을 가지는 모듈을 모두 추적하여 하나의 결과물을 만들어내는 모듈 번들러가 등장하게 되었습니다.

네트워크 코스트 해결
위 사진에서 8번의 requests와 305ms의 시간이 소요된 반면3번의 requestsfh 184ms가 걸린 것을 확인할 수 있다.

2. Entry, Output, Loader, Plugin 설정

웹팩의 4가지 핵심 개념

1)Target

2)Entry

3)Output

4)Loader

5)Plugin

2-1. Target 설정

Webpack은 다양한 환경과 target을 컴파일합니다. target의 기본값은 web입니다. 적용하지 않으면 해당 기본 값으로 적용됩니다. 이 부분에는 web 외에도 다양한 환경을 컴파일 할 수 있는데, esX를 넣으면 지정된 ECMAScript 버전으로 컴파일할 수 있습니다.

module.exports = {
  target: ["web", "es5"],
};

해당 config 파일에서는 es5를 배열 안에 넣었습니다. 따라서 이 config 파일은 브라우저와 동일한 환경에서 사용하기 위하여 컴파일할 것이며, 작성된 코드를 es5 버전으로 컴파일 하겠다고 지정한 것임을 알 수 있습니다. Browser Compatibility와 연관된 속성으로 볼 수 있습니다.

2-2. Entry 설정

webpack은 번들링 과정에서 '디펜던시 그래프(dependency graph)'를 그린다. 특정 지점에서 출발해서, 애플리케이션에 필요한 모든 모듈을 포함하는 그래프를 재귀적으로 완성해 나간다. 한 파일이 다른 파일을 필요로 하면 이를 '디펜던시(dependency)'가 있다고 해석하는데, 이 방식으로 웹팩은 이미지 또는 웹 글꼴과 같이 코드가 아닌 리소스도 디펜던시로 관리할 수 있게 된다. 그래프를 모두 그리고 나면 이 모든 모듈을 소수의 번들로 묶어서 (보통 하나의 번들로 묶는다) 브라우저에 로드될 준비를 마친다.

이때 우리는 webpack이 어디를 출발지점으로 해서 그려나가면 좋을지 알려주어야 한다. config파일에서 entry 속성을 설정해서 웹팩이 어떤 모듈로부터 시작해서 디펜던시 그래프를 그려나갈지 명시해줄 수 있다. 'entry' 속성의 기본값은 './src/index.js'이지만 다른 Entry Point를 지정할 수도 있다. (여러 개도 지정 가능)

//기본 값
module.exports = {
	...
  entry: "./src/index.js",
};

//지정 값
module.exports = {
	...
  entry: "./src/script.js",
};

기본 값은 ./src/index.js이지만 webpack 설정에서 이런 식으로 Entry 속성을 설정하여 다른 (또는 여러 entry point)를 지정할 수 있습니다.

2-3. Output 설정

Output 속성은 생성된 번들을 내보낼 위치와 이 파일의 이름을 지정하는 방법을 webpack에 알려주는 역할을 합니다.

const path = require('path');

module.exports = {
	...
  output: {
    path: path.resolve(__dirname, "docs"), // 절대 경로로 설정을 해야 합니다. 
    filename: "app.bundle.js",
    clean: true
  },
};

기본 출력 파일의 경우에는 ./dist/main.js로 , 생성된 기타 파일의 경우에는 ./dist 폴더로 설정됩니다. 위의 예제에서는 output.filename과 output.path 속성을 사용하여 webpack에 번들의 이름과 내보낼 위치를 알려주고 있습니다. path 속성을 사용할 때는 path 모듈을 사용해야만 합니다.

2-4. Loader 설정

이제까지 자바스크립트 외의 리소스도 번들링할 수 있다고 했지만, 사실 웹팩은 기본적으로 JavaScript와 JSON 파일만 이해할 수 있다. 이 때 필요한 것이 Loader이다. 사용하려는 포맷에 대응하는 Loader를 설정해주면 다른 포맷의 리소스도 디펜던시 그래프에 추가할 수있게 된다.

Loader를 설정하려면 'test'와 'use' 두 가지 필수 속성을 적어주어야 한다. 'test'는 어떤 파일을 변환할지 지정하는 속성으로, 보통 /.txt/과 같이 정규표현식으로 작성한다. 이 때, /\.txt/ 과 같이 따옴표 없이 작성해야한다. '/.txt/' 또는 "/\.txt/"와 같이 따옴표를 넣으면 빌드가 제대로 안될 것이다,,, 'use'는 파일을 변환할 때 어떤 로더를 사용해야하는지 명시하는 속성이다.
이렇게 Loader를 설정해주면 포맷에 얽매이지 않은 자유로운 import가 가능하다. 예를 들어 js파일에서 import '../css/index.css';과 같이 해당 모듈에서 필요한 css파일을 import해올 수 있다. 웹팩을 사용하기 전에는 상상할 수 없었던 일이다! 이 기능은 다른 번들러에서는 지원되지 않을 수도 있다고 한다.

module.exports = {
	...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
        exclude: /node_modules/,
      },
    ],
  },
};

상위 수준에서 loader는 webpack 설정에 몇 가지 속성을 가집니다.

test: 변환이 필요한 파일들을 식별하기 위한 속성
use: 변환을 수행하는데 사용되는 로더를 가리키는 속성
exclude: 바벨로 컴파일하지 않을 파일이나 폴더를 지정. (반대로 include 속성을 이용해 반드시 컴파일해야 할 파일이나 폴더 지정 가능)

2-5. Plugin 설정

Plugins를 사용하면 번들을 최적화하거나 에셋을 관리하고, 또는 환경변수 주입 등의 광범위한 작업을 수행할 수 있게 됩니다.

const webpack = require('webpack');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  ...
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "src", "index.html"),
    }),
    new MiniCssExtractPlugin(),
  ],
};

로더가 파일단위로 처리하는 반면 플러그인은 번들된 결과물을 처리한다.
로더가 변환하는 동안 플러그인은 bundle optimization, asset management and injection of environment과 같은 일을 진행할 수 있다

profile
호기심이 많은 사람입니다.

0개의 댓글