ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 웹팩(Webpack)
    간단정리 2020. 12. 9. 13:21

    웹팩 너란 녀석


    프로젝트를 진행 하다 보면 어떤 이유에서인지 결국 webpack(이후 웹팩)을 만나게 된다. 웹팩이 파일들을 bundle.js로 export해주는 것은 이해하고 있지만 정확한 개념과 동작방식을 알아볼 필요가 있을 것 같다.

    내가 너를 만나게 된 이유

     파일 압축은 방법에 따라 달라지지만 우리가 흔히 사용하는 기본 압축은 파일 용량을 줄이는 압축이 아니다. 파일 이동, 다운로드를 경험한적 있는가? 3만개의 파일을 이동하는 것압축 된 1개의 파일을 이동하는 것은 같은 용량이여도 큰 시간 차이를 만들어낸다.

     

     서비스를 개발 하며 확장성, 재사용성을 위하여 각 기능별로 파일을 분리하고 성격에 따라 경로도 달라진다. 하지만 위의 압축의 예시와 같이 여러개의 파일을 서버에서 내려 받고 로딩하는 것은 그만큼의 비용이 들어간다.

     

     위와 같은 문제를 해결할 방법이 필요했고, 그 해결책이 각각의 모듈을 번들링 해주는 웹팩이다.

    그래서 웹팩 이란

     웹팩이란 최신 프론트엔드 프레임워크에서 가장 많이 사용되는 모듈 번들러(Module Bundler)이다. 모듈 번들러란 웹 애플리케이션을 구성하는 자원(HTML, CSS, Javscript, Images 등)을 모두 각각의 모듈로 보고 이를 조합해서 병합된 하나의 결과물을 만드는 도구를 의미한다. (참고: 웹팩 핸드북)

    모듈 (참고)

     모듈이란 프로그래밍 관점에서 특정 기능을 갖는 작은 코드 단위를 의미한다. 웹팩에서의 모듈은 해당 애플리케이션을 구성하는 HTML, CSS, Javascript, Images, Font 등 모든 파일들을 모듈이라 의미한다.

     

    모듈 번들링

     아래 그림과 같이 웹 애플리케이션을 구성하는 수 많은 파일들을 하나의 파일로 병합 및 압축 해주는 것을 모듈 번들링이라 한다.

     

    정리

    파일을 하나 하나 다운 받는 것은 비용이 너무 많이 들어가니, 그것을 좀 더 깔끔하게 정리하여 압축하는 것을 모듈 번들링이라고 하고 그것을 세팅하는 것이 웹팩이다.

     

    주요 속성


     웹팩의 번들링 과정을 이해하기 위해서는 4가지의 속성을 알아야 한다. 그것을 차근차근 살펴 보자.

     

    [1] entry

    [2] output

    [3] loader

    [4] plugin

     

    entry

     entry는 아래의 의존성 그래프의 시작점을 의미한다.

    애플리케이션에서 사용 될 자바스크립트의 시작점은 ./path/to/my/entry/file.js이다.

    // webpack.config.js
    // Usage: entry: { <entryChunkName> string | [string] } | {}
    module.exports = {
      entry: {
        app: './src/app.js',
        adminApp: './src/adminApp.js'
      }
    };

     

    entry는 환경, 빌드 대상 및 런타임별로 확장 가능하다.

    // webpack.config.js
    // Usage: entry: { <entryChunkName> string | [string] } | {}
    module.exports = {
      entry: {
        app: './src/app.js',
        adminApp: './src/adminApp.js'
      }
    };

     

    output

     output은 웹팩에서 번들링 된 번들 파일의 경로를 의미 한다.

    아래 Product와 같이 해시값을 지정해주는 이유는 동일한 콘텐츠 해시일 경우 브라우저가 캐시를 유지 시켜주므로 성능 향상에 도움이 되기 때문이다. (이는 단일 entry를 갖고 있을 때는 의미가 없을 것이다. 단일 시작점을 가지고 있고 번들링을 한다는 자체가 파일이 수정 되었음을 의미할테니. 그러므로 여러 번들러가 존재할 때, 의미 있는 것 같다.)

    // webpack.prod.js
    module.exports = {
      output: {
        filename: '[name].[contenthash].bundle.js'
      }
    };
    
    // webpack.dev.js
    module.exports = {
      output: {
        filename: '[name].bundle.js'
      }
    };

     

    loader

    loader는 웹팩이 번들링을 할 때, 자바스크립트 파일 외 다른 파일(HTML, CSS, Images, 폰트 등)들을 변환할 수 있도록 도와주는 속성이다.

    - test : 로더를 적용할 파일 유형

    - use : 해당 파일에 적용할 로더의 이름

    // webpack.config.js
    module.exports = {
      module: {
        rules: [
          {
            test: /\.css$/,
            use: [
              // [style-loader](/loaders/style-loader)
              { loader: 'style-loader' },
              // [css-loader](/loaders/css-loader)
              {
                loader: 'css-loader',
                options: {
                  modules: true
                }
              },
              // [sass-loader](/loaders/sass-loader)
              { loader: 'sass-loader' }
            ]
          },
    			{ test: /\.ts$/, use: 'ts-loader' }
        ]
      }
    };

     

    로더는 오른쪽에서 왼쪽순으로 적용 된다.

    (1) scss를 로드

    (2) scss를 css로 변환

    // 배열 방식
    module: {
      rules: [
        {
          test: /\.scss$/,
          use: ['css-loader', 'sass-loader']
        }
      ]
    }
    
    // 옵션을 표기하고 싶으면 아래와 같은 방식
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            { loader: 'style-loader' },
            {
              loader: 'css-loader',
              options: { modules: true }
            },
            { loader: 'sass-loader' }
          ]
        }
      ]
    }

     

    plugin

     plugin은 웹팩의 기본적인 동작에 추가적인 기능을 제공하는 속성이다. 로더는 파일을 해석하고 변화한다면 plugin은 결과물의 형태를 바꾸는 역할을 수행 한다.

     

    사용법은 굉장히 쉽다. (하단)

    const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
    const webpack = require('webpack'); //to access built-in plugins
    const path = require('path');
    
    module.exports = {
      entry: './path/to/my/entry/file.js',
      output: {
        filename: 'my-first-webpack.bundle.js',
        path: path.resolve(__dirname, 'dist')
      },
      module: {
        rules: [
          {
            test: /\.(js|jsx)$/,
            use: 'babel-loader'
          }
        ]
      },
      plugins: [
        new webpack.ProgressPlugin(),
        new HtmlWebpackPlugin({template: './src/index.html'})
      ]
    };

     

    플러그인 종류

     

    Plugins | webpack

    webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

    webpack.js.org

     

    생각


     생각보다 웹팩의 구성요소는 간단했다. 하지만 구성요소와 다르게 그 요소 안에 숨어있는 여러 loader들과 plugin들은 너무나도 다양한 것 같다. 하지만 언제나 그렇듯 필요할 때 마다 잘 찾아서 꺼내 사용하면 될 것 같다. 확실히 차근차근 docs를 보며 이해하고 글을 쓰니 정리가 되어 좋다.

    다음은 babel을 알아보고 babel과 eslint에서 가끔 중복되는 옵션들이 있었던 것 같은데 그것에 대하여 알아보아야겠다.

    댓글

Developer RyuK