Jaeilit

번들러 웹팩 본문

TIL

번들러 웹팩

Jaeilit 2023. 9. 7. 10:05
728x90

웹 페이지의 서비스들이 규모가 커지기 시작하고 SPA 의 프레임워크/라이브러리 들이 등장함에 따라서 번들러의 역할도 중요해졌습니다. 

 

또한 최근 트렌드 중 Nexjts 는 리액트의 Server Components 를 활용하여 번들 용량을 최대한 줄여 사용자 경험과 성능을 더 최적화 하려고 하고 있기 때문에 번들이 무엇인가에 대해 한번 공부해보려고 했습니다.

 

모듈 번들러란

브라우저가 필요한 리소스들(html, css, js 기타 Img file font 등)을 병합 및 압축을 해주는 동작입니다.

번들러중에서도 가장 많이 사용되는 모듈 번들러는 Webpack 웹팩 입니다.

그 외에도 Rollup, Parcel, 최근 Vite 도 있습니다.

 

번들러 사용 이전에는 JS 파일을 사용하기 위해서 기능/페이지 단위 모듈화 한 script 를 추가하는 방법이 있었습니다. 이 방식은 너무 많은 스크립트로 인해 네트워크의 병목을 유발하는 원인이 될 수 있어서 확장이 어렵습니다. 두번째 방법은 모든 프로젝트에 하나의 거대한 .js 파일을 만들어서 사용하는 것입니다. 이 방법은 유효범위와 크기, 가독성, 유지보수에 문제를 발생시킬 수 있습니다.

 

웹팩은 JS 애플리케이션을 위한 정적 모듈 번들러입니다. 웹팩은 애플리케이션을 처리할 때, 내부적으로 프로젝트에 필요한 모든 모듈을 매핑하고 하나 이상의 번들을 생성하는 의존성 그래프를 만듭니다.

 

의존성 그래프는 하나의 파일이 다른 파일에 의존할때마다 웹팩은 이것을 의존성으로 취급합니다. 이를 통해 웹팩은 이미지 또는 웹 폰트와 같은 코드가 아닌 다른 리소스를 가져와, 애플리케이션에 의존성으로 제공할 수 있습니다.

 

아래 개념들을 이해하는게 웹팩 사용에 도움이 됩니다.

 

- Entry (엔트리)

- Output (출력)

- Loaders (로더)

- Plugins (플러그인)

- Mode (모드)

- Browser Compatibility (브라우저 호환성)

 

1. Entry

webpack.config.js 의 entry 부터 시작하여 웹팩은 애플리케이션에서 필요한 모든 모듈을 포함하는 의존성 그래프를 재귀적으로 빌드한 다음, 모든 모듈을 브라우저에 의해 로드 되는 작은수(미니멀 1개)의 번들로 묶습니다.

 

기본 경로는 ./src/index.js 입니다. 하지만 여러의 엔트리 포인트를 지정할수도 있습니다.

const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js',
  },
};

// entry 는 의존성 그래프를 생성하기 위해 사용해야하는 모듈입니다. (시작지점)
// output 은 번들을 내보낼 위치와 파일 이름을 지정합니다.

 

웹팩 모듈은 다양한 방식으로 의존성을 표현할 수 있습니다. ES2015 의 import 문, CJS require()문과 AMD define, require 문 css/sass/less 파일의 @import 문 stylessheet url과 이미지 url html img src 까지 의존성을 관리하고 있습니다.

 

 

2. Loaders

위와 같이 ESM, CJS, AMD, icons, font, Webassembly Module 을 기본적으로 지원하며 이외에 여러 언어로 작성된 모듈과 로더를 지원합니다. 

 

웹팩은 기본적으로 JS와 JSON 파일만 이해합니다.  Loader 를 사용하면 파일을 전처리 할 수 있습니다. 이렇게하면 JS 를 넘어 모든 정적 리소스를 번들링하여 의존성 그래프에 추가할 수 있습니다.

 

로더에는 두 가지의 속성이 있습니다.

 

- test 변환이 필요한 파일들을 식별하는 정규식을 지원합니다.

- use 변환을 수행하는데 사용되는 로더를 가리킵니다.

 

const path = require('path');

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js',
  },
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
};

로더의 종류로는 babel, esbuild, html, styles-loader, 등등 다양한 로더들이 있습니다.

https://webpack.kr/loaders

 

Loaders | 웹팩

웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.

webpack.kr

 

3. Plugins

로더는 특정 유형의 모듈을 변환하는데 사용되지만 플러그인을 활용하여 번들을 최적화하거나 assert, 환경변수 주입 등 광범위한 작업을 수행할 수 있습니다.

const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); // 내장 plugin에 접근하는 데 사용

module.exports = {
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, 'public/index.html'),
            favicon: './public/favicon.ico',
            minify: true,
            meta: {
                'ui-version': git_hash,
            },
        }),
    ],
};

플러그인들은 new 연산자를 호출하여 인스턴스를 만들어야합니다.

예제에서 HtmlWebpackPlugin 은 생성된 모든 번들을 자동으로 삽입하여 애플리케이션용 HTML 파일을 생성합니다.

index.html HTML 파일에 meta 태그를 주입한다거나, favicon 등을 주입할 수 있습니다.

 

이외에도 많은 플러그인들이 있습니다.

https://webpack.kr/plugins

 

Plugins | 웹팩

웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.

webpack.kr

 

4. Mode

mode 파라미터는 production development none 3가지 옵션을 사용하여 webpack에 내장 된 최적화 기능을 사용할 수 있습니다.

 

옵션에 따라 최적화의 내용이 달라집니다.

 

development 

- procees.env.NODE_ENV 가 developent 로 설정됩니다.

- 개발 환경에 적합한 설정을 사용합니다.

- 코드를 최적화 하지않고 디버깅을 용이하게 합니다.

- 빠른 빌드 시간을 제공하고, 가독성이 높은 번들 파일을 생성합니다.

- 개발용 소스맵을 생성하여 오류 추적 및 디버깅을 용이하게 합니다.

- 모듈 번들링 시 주석과 디버깅 관련 정보를 포함한 번들 파일을 생성합니다.

 

production

- deve 모드와 마찬가지로 procees.env.NODE_ENV 가 production 로 설정됩니다.

- 코드를 최적화하여 번들 크기를 줄이고 성능을 최대화 합니다.

- 최소화된 코드를 생성하고 사용하지 않는 코드를 제거합니다.

- 소스맵을 새성하지 않거나 필요한 경우에만 생성을 설정할 수 있습니다.

 

module.exports = {
  mode: 'production',
};

 

+@ Under The Hood 

모듈은 서로를 사용하여 모듈 그래프를 형성합니다. 번들링 과정 중에 모듈은 청크로 결합됩니다. 청크는 청크 그룹으로 합쳐지고 모듈을 통해 서로 연결된 그래프 (ChuckGraph)를 형성합니다. 내부적으로 엔트리 포인트를 설명할때는 하나의 청크로 청크 그룹을 만드는 것을 말합니다.

 

module.exports = {
  entry: './index.js',
};

main 이라는 이름으로 하나의 청크 그룹이 생성됩니다. main 은 entry 포인트의 기본 이름입니다. 이 청크 그룹에 index.js 모듈이 포함되어있습니다.

module.exports = {
  entry: {
    home: './home.js',
    about: './about.js',
  },
};
청크를 다음과 같이 home, about 이라는 이름고 Path 로 분리할수 있습니다.
 
chunks 청크는 두가지 형태로 제공됩니다.
 
- 초기 청크 
엔트리 포인트의 메인청크입니다. 이 청크는 엔트리 포인트에서 명시 된 모든 모듈과 의존성을 포함합니다.
- 비초키 청크
lazy loading, 동적 import, SplitChunksPlugin 사용 중에 나타날 수 있습니다.
 
+++ 
리액트의 lazy loading 이 이 부분을 활용한 부분입니다. lazy loading 이 chuck 파일을 비동기 청크로 나눠 main 의 초기 청크의 크기를 줄여 spa 에서 단점으로 꼽히던 초기 로딩을 좀 더 빠르게 하기 위함이고 lazy loaidng 으로 나눠놓은 해당 라우터에 진입 시 비동기로 chuck 파일을 가져와서 로딩하게 됩니다.
 
마찬가지로 dymanic import 도 리액트적인 요소인 lazyloading, suspence 를 제외하고는 같은 원리입니다. import 가 필요한 시점에 해당 chuck 파일을 불러오게 됩니다.

 

중간에 suspensce 를 활용하여 척 로딩시 로딩 UI 를 꾸며줄수도 있습니다.
 

참고글

https://webpack.kr/concepts/

 

Concepts | 웹팩

웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.

webpack.kr

https://webpack.kr/concepts/under-the-hood/

 

Under The Hood | 웹팩

웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.

webpack.kr

 

728x90