[TIL] 번들링과 웹팩

ansmeer008·2022년 11월 23일
1

Today I learn

목록 보기
59/65
post-thumbnail

번들링

번들링 자체는 여러 제품이나 코드, 프로그램을 묶어서 패키지로 제공하는 행위를 의미한다.


what is 번들링?

프론트엔드 개발에서 번들링은 사용자가 더 쉽고 빠르게 프론트엔드 애플리케이션에 접근할 수 있도록 용량을 줄이거나 파일을 최소화하여 유저에게 전달하는 과정을 말함.

“사용자에게 웹 어플리케이션을 제공하기 위한 파일 묶음”


번들링의 필요성

작성한 HTML, CSS, JavaScript 파일을 그대로 전송하는 것은 용량이나 조작에 관한 문제를 발생시킬 수 있다.

<번들링 없이 배포했을 때 생길 수 있는 문제점들>

- 두 개의 .js 파일에서 같은 변수를 사용하고 있어서, 변수 간 충돌이 일어난 경우.
- 딱 한 번 불러오는 프레임워크 코드가 8MB라서, 인터넷 속도가 느린 국가의 모바일 환경에서 사용자가 불편을 호소함.
- 번들 파일 사이즈를 줄이기 위해서 파일의 공백을 모두 지웠는데, 가독성이 너무 떨어져서 코딩하기가 어렵다. 결국 그대로 공백을 되돌려서 코딩함.
- 배포 코드가 너무 읽기 쉬워 개발을 할 줄 아는 사용자가 프론트엔드 애플리케이션을 임의로 조작하여 피해가 발생함.




Webpack

프론트엔드 애플리케이션 배포를 위해 가장 많이 사용하는 번들러.

공식문서도 한글로 잘 번역되어 있는 편.


What is Webpack?

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

모듈 번들러의 등장 배경 🤔
: Js 코드 양의 절대적 증가, 대규모의 의존성 트리를 가지고 있는 대형 웹 애플리케이션의 등장으로 세분화된 모듈 파일이 폭발적으로 증가함. 이 모듈 단위의 파일들을 호출을 해 브라우저에 띄워야 하는데, JavaScript 언어의 특성에 따라 발생하기 쉬운 각 변수들의 스코프 문제를 해결해야 하고, 각 자원을 호출할 때에 생겨나는 네트워크 쪽의 코스트도 신경써줘야 함. 이런 복잡성에 대응하기 위해 하나의 시작점(Ex. React App의 index.js 등)으로부터 의존성을 가지는 모듈을 모두 추적하여 하나의 결과물을 만들어내는 모듈 번들러가 등장했다.


웹팩에서 모듈

Js의 모듈에만 국한되지 않고 HTML, CSS, .jpg, .png와 같은 이미지 파일들도 전부 포함한 포괄적인 개념으로 웹팩의 주요 구성 요소인 로더(loader)를 통해 다양한 파일도 번들링이 가능.


빌드와 번들링

  • 빌드 : 개발이 완료된 앱을 배포하기 위해 하나의 폴더(directory)로 구성하여 준비하는 작업.
    (ex: React 기준으로 설명하면 npm run build 실행하면 React build 작업이 진행되고, index.html 파일에 압축되어 배포에 최적화된 상태를 제공해줌.)

  • 번들링 : 모듈간 의존성 관계를 파악해 그룹화하는 작업으로 파일을 묶는 작업 그 자체. (파일은 의존적 관계에 있는 파일들(import, export) 그 자체 혹은 내부적으로 포함되어 있는 모듈을 의미)


웹팩의 필요성

웹 애플리케이션의 빠른 로딩 속도와 높은 성능을 위함.

  • 같은 타입의 파일들은 묶어서 요청 및 응답을 받을 수 있기 때문에 네트워크 코스트가 획기적으로 줄어들게 된다.

  • Webpack loader를 사용하면 일부 브라우저에서 지원하지 않는 JavaScript ES6의 문법들을 ES5로 번환해주는 babel-loader를 사용할 수 있음.

  • Webpack4 버전 이상부터는 Develoment, Production 두 가지의 모드를 지원하는데, Production 모드로 번들링을 진행할 경우, 코드 난독화, 압축, 최적화(Tree Shaking) 작업을 지원.



Webpack의 핵심개념들

웹팩을 설치하고 나서 작성해줄 config 파일 예시를 보면서 핵심 개념들을 알아보자!

module.exports = {
  target: ["web", "es5"],
  entry: "./src/script.js",
  output: {
    path: path.resolve(__dirname, "docs"),
    filename: "app.bundle.js",
    clean: true
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "src", "index.html"),
    }),
    new MiniCssExtractPlugin(),
  ],
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(),
    ]
  }
};

❄️ Target

: 웹팩은 다양한 환경과 타겟을 컴파일한다.(타겟의 기본값 web)

위 config 파일 예시에서는 브라우저와 동일한 환경(web)에서 사용하기 위해 컴파일 할 것이며, 작성된 코드를 es5 버전으로 컴파일하겠다고 지정한 것. (타겟은 Browser Compatibility = 브라우저 호환성과 연관된 속성으로 볼 수 있음)


❄️ Entry

: 프론트엔드 개발자가 작성한 코드의 ‘시작점’

Entry point라고도 하며, 웹팩이 내부 디펜던시 그래프 생성하기 위해 사용해야하는 모듈. 앤트리 포인트를 기반으로 직간접적으로 의존하는 다른 모듈과 라이브러리를 찾아낼 수 있음.

기본값은 ./src/index.js 이고, 지정하고 싶은 값을 지정할 수도 있음 (여러개도 가능)

module.exports = {
		...
	entry: "./src/script.js"
};

❄️ Output

생성된 번들을 내보낼 위치와 이 파일의 이름을 지정하는 방법을 웹팩에서 알려주는 역할.

기본 출력 파일의 경우 ./dist/main.js로, 생성된 기타 파일의 경우 ./dist 폴더로 설정됨.

아래 코드에서는 output.filename과 output.path 속성 이용해 웹팩에 번들 이름과 내보낼 위치 알려주고 있음. (path 속성 사용할 때는 path 모듈 사용해야 함.)

const path = require('path');//path 모듈 사용

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

❄️ Loader

웹팩은 기본적으로 Js와 JSON 파일만 이해하지만 loader를 사용하면 다른 유형 파일을 처리하거나, 유효한 모듈로 변환해 애플리케이션에 사용하거나, 디펜던시 그래프에 추가할 수 있음.

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

Loader가 가진 웹팩 설정 속성

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

test, use 속성은 필수로 입력해야함. 


❄️ Plugins

플러그인 사용하면 번들을 최적화하거나 에셋을 관리하고, 환경변수 주입 등 광범위한 작업 할 수 있음.

플러그인 사용을 위해서는 require() 통해 플러그인을 요청
⇒ plugins 배열에 사용하고자 하는 플러그인 추가

대부분의 플러그인은 사용자가 옵션을 통해 지정할 수 있는데, 다른 목적으로 플러그인을 여러 번 사용하도록 설정할 수 있기 때문에 new 연산자를 사용해 호출하여 플러그인의 인스턴스를 만들어줘야 함.

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(),
  ],
};

위 예시에서 html-webpack-plugin은 생성된 모든 번들을 자동으로 삽입하여 애플리케이션용 HTML 파일을 생성해준다.

mini-css-extract-plugin은 CSS를 별도의 파일로 추출해 CSS를 포함하는 JS 파일 당 CSS 파일을 작성해주도록 지원.



❄️ Optimization (최적화)

웹팩은 버전4부터는 선택한 항목에 따라 최적화를 실행함.

최적화 위해서 minimize, minimizer등을 사용함.

minimize : TerserPlugin 또는 optimization.minimize에 명시된 plugins로 bundle 파일을 최소화(=압축)시키는 작업 여부를 결정.

minimizer : defualt minimizer 를 커스텀된 TerserPlugin 인스턴스를 제공해서 재정의할 수 있음.

module.exports = {
  ...
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(),
    ]
  }
};

위 예시에서는 mini-css-extract-plugin에 관련된 번들을 최소화하도록 지시하고 있음.

profile
예술적인 코드를 짜는 프론트 엔드 개발자가 꿈입니다! (나는야 코드 아티스트! 🤭)

0개의 댓글