번들링과 Webpack(웹팩)

moono·2023년 3월 19일
0

JavaScript

목록 보기
22/23

번들링

🧐 프론트엔드 개발자에게 번들이란?

현대 웹 개발에서, 사용자에게 웹 애플리케이션을 제공하기 위한 파일 묶음
사용자가 브라우저를 열고 주소를 입력하면 해당 주소에서 프론트엔드 개발자가 번들링한 여러 파일을 받는다.
이 파일을 브라우저가 실행해서 웹 애플리케이션을 사용자에게 제공하게 된다.
⇒ 여러 제품이나 코드 프로그램을 묶어서 패키지로 제공하는 행위

👍 번들링의 필요성

HTML, CSS, JavaScript 파일을 그대로 전송하는 것은 무슨 문제가 있을까?

  • 문제 1) 두개의 .js 파일에 같은 변수를 사용하고 있어서, 변수 간 충돌이 일어났다.
  • 문제 2) 딱 한 번 불러오는 프레임 워크 코드가 8MB라서 인터넷 속도가 느린 국가의 모바일 환경에서 사용자가 불편을 호소
  • 문제 3) 배포 코드가 너무 읽기 쉬워 개발을 할 줄 아는 사용자가 프론트엔드 애플리케이션을 임의로 조작해 피해가 발생한다.

번들링 작업에서는 필연적으로 용량을 줄이고 파일을 통일하는 툴링작업 이 필요하게 된다.
⇒ 소프트웨어를 잘 만들어도 사용자에게 배포하기 위해 번들링이 꼭 필요하다


Webpack(웹팩)

웹팩은 프론트엔드 애플리케이션 배포를 위해 가장 많이 사용하는 번들러(프론트엔드 애플리케이션을 대규모 유저에게 제공하기 위해 가장 많이 사용하는 방법)
⇒ 개발자 경험(DX) 개선에도 기여하고, 사용자 경험(UX) 개선에도 기여한다.
⇒ 코드 관리 용이 / 렌더 금방!

🏁 Webpack(웹팩)이란?

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

  • ➰ 모듈 번들러(Module Bundler) 의 등장

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

  • ➰ Webpack 에서의 모듈

    JS 뿐 아니라 HTML, CSS, 이미지 파일들도 포함한 포괄적인 개념
    따라서 Webpack은 주요 구성 요소인 로더(loader)를 통해 다양한 파일도 번들링이 가능하다.

  • ➰ 빌드와 번들링

    빌드 : 개발이 완료된 앱을 배포하기 위해 하나의 폴더 로 구성하여 준비하는 작업
    ⇒ 예) React앱 기준 npm run build 실행하면 React build 작업이 진행되고, index.html 파일에 압축되어 배포에 최적화된 상태를 제공해준다.
    번들링 : 묶음의 개념, 파일을 묶는 작업 그자체를 말하는데 모듈간의 의존성 관계를 파악해 그룹화 하는 작업
    ⇒ 파일은 의존적 관계에 있는 파일들(import, export) 자체 혹은 내부적으로 포함되어 있는 모듈을 의미

🏁 Webpack(웹팩)의 필요성

웹 애플리케이션의 빠른 로딩 속도와 높은 성능을 위함!!
코드의 양이 많은 것을 무겁다 고 표현하는데, 무거울수록 로딩 속도와 성능은 저하된다.(일반 유저는 3초 이내에 페이지가 뜨지 않으면 이탈을 선택)
⇒ 로딩 속도를 개선하기 위한 많은 노력이 필요했는데 대표적으로 브라우저에서 서버로 요청하는 파일의 숫자를 줄이는 것이 있다.

Webpack(웹팩) 이 없다면 각각 알아서 서버에 요청해 얻어와야 했지만,
Webpack(웹팩) 이 있다면 같은 타입의 파일들은 묶어서 요청 및 응답을 받을 수 있기 때문에 네트워크 코스트가 많이 줄어든다.

Webpack4 버전 이상부터는 Development , Production 두가지의 모드를 지원한다.
Production 모드로 번들링할 경우, 코드 난독화, 압축, 최적화 작업을 지원한다.
⇒ 상용화 된 프로그램을 사용자에게 더 쾌적한 환경 및 보안까지 신경쓰면서 노출시킬 수 있다.


Webpack(웹팩) 핵심 개념

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

Webpack 은 다양한 환경과 target을 컴파일한다. (기본값은 web)
web 외에도 다양한 환경을 컴파일 할 수 있는데, esX를 넣으면 지정된 ECMAScript 버전으로 컴파일 할 수 있다.

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

⇒ 이 config 파일은 브라우저와 동일한 환경에서 사용하기 위해 컴파일할 것이며,
작성된 코드를 es5버전으로 컴파일 하겠다고 지정한 것. (Browser Compatibility와 연관된 속성)

Entry

시작점
React 도 index.js에서 HTML 엘리먼트 하나에 React 코드를 적용하는 것 부터 시작한다.( 실제 webpack을 사용하기도 했음)

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

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

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

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

Output(출력)

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

const path = require('path')

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

기본 출력 파일의 경우에는 ./dist/main.js 로, 생성된 기타 파일의 경우에는 ./dist 폴더로 설정된다.
output.filename : webpack 에 번들의 이름을 알려준다.
output.path : webpack 에 내보낼 위치를 알려준다. path 속성을 사용할 때는 path 모듈을 사용해야만 한다.

Loader(로더)

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

module.exports = {
  ...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
        exclude: /node_modules/,
      },
    ],
  },
};
  • test(필수속성) : 변환이 필요한 파일들을 식별하기 위한 속성
  • use(필수속성) : 변환을 수행하는데 사용되는 로더를 가리키는 속성
  • exclude : 바벨로 컴파일하지 않을 파일이나 폴더를 지정
    (반대로 include 속성을 이용해 반드시 컴파일해야 할 파일이나 폴더 지정이 가능하다.)

이런 속성을 넣어 규칙을 정하기 위해선 module.rules 아래에 정의해야 한다.
그냥 rules에 정의하면 webpack 은 경고를 함

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

⇒ 위 예제에서 html-webpack-plugin 은 생성된 모든 번들을 자동으로 삽입하여 애플리케이션용 HTML 파일을 생성해준다.
mini-css-extract-plugin 은 CSS를 별도의 파일로 추출해 CSS 를 포함하는 JS 파일당 CSS 파일을 작성해주게끔 지원한다.

  1. 플러그인을 사용하기 위해서는 require() 를 통해 플러그인을 먼저 요청해야한다.
  2. plugins 배열에 사용하고자 하는 플러그인을 추가해야 한다.
    대부분의 플러그인은 사용자가 옵션을 통해 지정할 수 있다.
    다른 목적으로 플러그인을 여러 번 사용하도록 설정할 수 있기 때문에 new 연산자로 호출해 플러그인의 인스턴스를 만들어줘야 한다.

Optimization(최적화)

webpack 버전 4부터 선택한 항목에 따라 최적화를 실행한다.

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

최적화하기 위해 다양한 옵션이 지원되는데, 대표적으로 minimize minimizer 등을 사용한다.

  • minimize : TerserPlugin 또는 optimization.minimize 에 명시된 plugins로 bundle 파일을 최소화(=압축) 시키는 작업 여부를 결정
  • minimizer : defualt minimizer 을 커스텀된 TerserPlugin 인스턴스를 제공해 재정의할 수 있다.

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


Webpack tutorial

➰ 기본 (CLI로만 작동하는)

  • npm 준비하기 npm i 또는 npm init -y

✔️ 웹팩 설치하기

npm install -D webpack webpack-cli

✔️ index.js 파일 만들기

우선 src 폴더를 만들고 그 안에 index.js 파일을 만든다.
매개변수를 console.log 하는 간단한 함수를 만들고, underbar.js 라는 파일도 만들어서
그 안에 once 를 구현해본다.(webpack 작동원리 파악을 위한 예시)

✔️ 웹팩 config 파일 작성

const path = require('path') 를 상단에 꼮!!! 입력해주고
module.exports={} 안에 entryoutput 을 입력해준다.

👊 시행착오
처음에 webpack.config.js 파일을 src 폴더 안에 만들었는데, 번들링을 하면
계속 dist 폴더 안에 내가 설정한 filename에 app.bundle.js 가 안 생기고 main.js 가 생겼다.
⇒ 왜냐면 entry 위치를 잘못해줬으니까.. index.jswebpack.config.js 가 같은 파일안에 있으니까
./src/index.js 라고 하면 안됐따!!! webpack.config.js 파일은 꼭 src 폴더 밖에 두도록 하자

✔️ 번들링하기

CLI 에 npx webpack 으로 번들링하기
번들링이 잘 됐다면 이전에 node src/index.js 로 나온 출력 결과물과 node dist/app.bundle.js 가 같아야한다. 만약 잘 나왔다면 성공

✔️ npm run build 설정하기

추후에 다른 개발자와 협업할 때, 지금까지의 여정을 간단하게 대신할 수 있는 스크립트를 만드는 것
CLI에 npm run build 를 입력했을 때 바로 npx webpack 이 실행될 수 있게
package.json"script" 안에 "build":"webpack", 을 추가한다.
그러면 npm run build 이걸로 번들링을 할 수 있다.


➰ CSS 번들에 포함하기

✔️ index.html 만들기

src 폴더 안에 index.html 만들고, <body> 안에 <script src="index.js"></script> 추가하고 확인하면 에러가 나옴.
⇒ 그럼 이 파일은 dist 폴더로 옮겨서 번들 파일과 연결 시킨 후에 script src 를 app.bundle.js 로 바꾸기

index.js 코드를 바꿨다면 npm run build 로 번들링을 진행하고 dist/index.html 을 열면 바뀐 확인 가능

✔️ index.css 만들기

index.html 을 꾸며줄 index.css 를 dist 파일 안에 만든 후
index.html <title> 위에 <link rel="stylesheet" href="style.css"> 추가하면
CSS가 적용된 index.html 을 확인할 수 있다.

✔️ index.css 옮기고 loader 추가하기

webpack 은 JS와 CSS를 함께 배포해야할 때 더 쉽게 배포할 수 있게 loader를 제공!
dist/index.css 를 src 로 옮기고, 해당 파일을 src/index.js 에서 require('./style.css'); 로 불러오면
node src/index.js 명령어로 확인했을 때 CSS를 읽을 수 없어서 문법 에러가 발생한다.
npm run build 를 해도 오류가 설정
이 에러 없애고 webpack에서 css 를 제대로 불러오게하기 위해
로더 설치하고 불러온다!

CLI 에 npm i -D css-loader style-loader 로 설치하고
webpack.config.jsmodule.exports ={} 안의 output 아래에 module:{rules:[]} 의 배열 안에 test, use, exclude 추가한다.

  • test: \/.css$/ : .css 인 파일들을 변환하겠다.
  • use: ['style-loader', 'css-loader'] : style-loader , css-loader 를 사용해서
    아래에서 위로 읽고 왼쪽에서 오른쪽으로 읽어서 css-loader 가 끝에 있어야 함
  • exclude: /node_modules/ : 근데 node_modules 라는게 들어간 애들은 컴파일하지 않을거야
🧐 궁금증 exclude: /node_modules/ 이게 무슨 뜻이지?ㅇㅅㅇ?

npm run build 명령어로 번들링이 잘 됐는지 확인하고(경고 있어도 에러 없으면 성공)
dist/index.html 파일 라이브서버로 열면 CSS 가 잘 적용된 걸 볼 수 있고
<link rel="stylesheet" href="style.css"> 이 코드는 필요없다.

➰ HTML 번들에 포함하기

  • dist/index.html 을 다시 src 폴더 안으로 옮기고!

✔️ HTML 웹팩 플러그인 설치

CLI 에 npm i -D html-webpack-plugin 로 플러그인 설치하기

✔️ webpack 에 플러그인 적용하기

webpack.config.js 파일 제일 상단에 있는 path 밑에
const HtmlWebpackPlugin = require('html-webpack-plugin') 추가하기(변수명은 뭐든 상관 없음!)

그리고 module.exports={} 안에 module:{} 밑에 plugins:[] 안에 new HtmlWebpackPlugin({template: path.resolve(__dirname, "src", "index.html")}) 추가하기
⇒ src 폴더 안에 index.html 파일 선택

✔️ 번들링하기

CLI에 npm run build 입력하면, dist 폴더 안에 index.html 이 생성된다.
⇒ CSS는 app.bundle.js 파일에 넣어주고(CSS loader로), JS는 html-webpack-plugin이 자동으로
dist/index.html 파일 안에 <script defer="defer" src="app.bundle.js"></script> 를 추가해준다.

0개의 댓글