DevOps/Optimization

webpack이란? 설정파일 파헤치며 알아보기

닝닝깅 2024. 3. 18. 19:09

말로만 들어본 웹팩.

평소에 CRA를 통해 프로젝트를 만드는데, 이 CRA설치에 웹팩이 포함되어있어 웹팩파일을 직접 설정하는 경우가 없었다. 이번에 VSCode 익스텐션을 만들어보며 웹팩 설정도 같이 해보게 되어 기록!

 

🌟 Webpack이란?

 

웹의 규모가 커질 수록 파일 간의 관계가 복잡하고 무거워져서 브라우저 로딩 시간이 길어지는 현상이 나타난다.

 

이때 웹팩을 사용하여 파일 정리 및 최적화를 해줄 수 있다.

웹팩은 여러개의 파일을 하나로 합쳐주는 자바스크립트 모듈 번들러이다.

쉽게 말해 웹팩을 통해 여러개로 나눠진 파일을 하나의 번들로 모듈화하여 로딩 속도도 줄이고 가독성과 유지보수성도 향상시키는 역할을 한다.

 

만약 번들의 크기가 너무 커질 경우 초기 로딩 속도는 저하될 수 있는데 이땐 웹팩에 코드 스플리팅, 캐시 등의 기능을 통해 해결할 수 있다.

 

🌟 Webpack 설정파일

webpack을 설치하고 webpack.config.js 파일을 생성하여 웹팩 설정을 해준다.

웹팩 4부터는 설정파일이 필요하지 않다고 한다. 하지만 설정 파일을 통해 기본 설정 이외의 설정을 할 수 있기 때문에 알아두는 것이 훨씬 좋다!

 

나의 익스텐션을 패키징하기 위한 설정 내용은 다음과 같다. 웹 애플리케이션이 아니기 때문에 웹 애플리케이션을 위한 설정과는 다소 차이가 있을 수 있다.

const path = require("path");

const extensionConfig = {
  target: "node",
  mode: "none",
  entry: "./src/extension.ts",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "extension.js",
    libraryTarget: "commonjs2",
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        use: [
          {
            loader: "ts-loader",
          },
        ],
      },
    ],
  },
  externals: {
    vscode: "commonjs vscode",
  },
  resolve: {
    mainFields: ["browser", "module", "main"],
    extensions: [".ts", ".js"],
  },
  devtool: "nosources-source-map",
  infrastructureLogging: {
    level: "log",
  },
};
module.exports = [extensionConfig];

 

요소를 하나하나씩 뜯어보자!~~

Target

특정 환경에 대한 런타임 코드를 생성하도록 웹팩에 지시하는 역할을 한다.

 

node로 지정하면 Node.js에서 실행되는 번들을 생성할 수 있다.

 target: "node"

 

Mode

웹팩에 내장된 환경별 최적화를 가능하게 한다.

 

옵션에는 3가지가 있다.

development - 개발모드를 의미하며 코드가 압축되지 않고, 난독화가 되지 않은 상태이다.

production - 배포모드를 의미하며 코드가 압축된 상태로 js파일을 난독화해준다. (번들링 파일의 크기가 확 줄어든다)

none - 기본 최적화 옵션에서 제외되는 상태로 development와 비슷한 상태이다.

mode: "none"

 

 

Entry

웹팩에서 웹 자원을 변환하기 위한 최초 진입점을 알려주는 역할을 한다.

 

최초 진입점이란 애플리케이션의 전반적인 구조와 내용이 담겨져있는 파일이다. 웹팩이 이 파일을 토대로 다른 모듈과의 의존성을 그리는 디펜던시 그래프를 생성하곤한다. 디펜던시 그래프를 사용하여 모듈에 필요한 스크립트가 순서대로 실행되는 최적화된 번들을 생성한다.

 

만약 진입점이 두 가지로 나누어질 경우 다중 엔트리 구문을 사용하면 된다.

entry: "./src/extension.ts"

 

Output

결과물인 번들파일을 내보낼 위치와 파일의 이름을 웹팩에 알려주는 역할을 한다.

 

기본적인 프로퍼티는 다음과 같다.

path : 해당 파일의 경로를 나타낸다. Node.js API를 사용하여 인자로 받은 경로로 유효한 파일 경로를 만들어내는 것이 일반적인 방법이다.

filename : 파일의 이름을 나타낸다.

 

기본설정 이외에 다른 여러 옵션을 추가할 수도 있다.

libraryTarget : 라이브러리를 내보내는 방식을 나타낸다. 

output: {
    path: path.resolve(__dirname, "dist"),
    filename: "extension.js",
    libraryTarget: "commonjs2",
},

 

Loader

웹팩은 기본적으로 js와 JSON파일만 이해하기 때문에 다른 유형의 파일을 변환시켜줘야한다.

 

test - 로딩에 적용할 파일들의 패턴을 정규표현식으로 명시한다.

exclude - 파일 중 제외할 파일을 명시한다.

use - 이 파일에 적용할 로더를 설정한다. 

 

자주 사용되는 로더의 종류는 ts-loader, css-loader 등 여러가지가 있다. 이외에도 직접 커스텀 로더를 생성하여 적용할 수도 있다. 

 

loader은 의존성 트리 내의 모듈 처리 방식을 설정하는 것이기 때문에 module.rules 배열 내부에 추가해주어야 한다.

module: {
    rules: [
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        use: [
          {
            loader: "ts-loader",
          },
        ],
      },
    ],
  },

 

 

여기서는 사용하지 않았지만 그외의 알아두어야 할 설정 중 하나인 플러그인!

plugin

웹팩의 기본적인 동작에 추가적인 기능을 제공하는 역할을 한다. 들 최적화, 에셋 관리, 환경변수 주입 등 광범위한 작업 수행이 가능하다.

 

loader와 비슷해보일 수 있지만 차이점이 명확하다.

loader은 함수로 정의되어 파일을 해석하고 변환하는 처리과정에 관여하는 반면 plugin은 클래스로 정의되어 번들링된 결과물을 처리한다.

 

플러그인의 예시는 다음과 같다.

html-webpack-plugin - 생성된 모든 번들을 자동 삽입하여 애플리케이션용 HTML 파일을 생성

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

 

플러그인 사용을 위해서는 require()을 통해 플러그인을 요청하고, new 연산자를 통해 플러그인의 인스턴스를 만들어 사용한다.

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

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

 

 

🌟 번들링 (빌드)

간편한 명령어 사용을 위해 script에 명령어를 등록하고 실행하면 output의 dist경로에 설정파일을 토대로 번들된 파일이 생성된다.

 

🌟 끝으로.. 

어떻게 웹팩을 잘 활용하여 번들링을 해야 하는 지 아직 정확하게는 모르겠다. 기본 요소와 동작에 대해서 익혔으니 앞으로는 활용법에 대해 더 알아보려고 한다.

다양한 로더의 활용법도 궁금하고, 평소 코드 스플리팅을 할 때 리액트의 내장 함수인 react.lazy + suspense 기능만 사용했었는데 webpack으로 하는 코드 스플리팅은 또 어떤 차이가 있을 지도 궁금하다.

 

다음번엔 리액트 개발 환경 세팅을 처음부터 끝까지 직접 해볼 예정이다. 얼른 해보고 싶다!

 


참고

https://webpack.kr/concepts/

https://velog.io/@gusdh2/Webpack%EC%9D%B4%EB%9E%80-%EC%99%9C-%ED%95%84%EC%9A%94%ED%95%A0%EA%B9%8C%EC%9A%94#loader

https://heropy.blog/2017/10/28/webpack_term/