Webpack 이란?

이짜젠·2021년 6월 24일
0

번들러가 하는 가장 크고 중요한 일은 모듈스펙을 사용하는 Javascript의 구문들을 해석해서 하나의 파일로 합쳐주는 것이다.

말 그대로 Web application을 구성하는 파일들을 최적화하여 packaging 해주는 프로그램이다.

번들러라고도 불리는데, bundle 이라는 단어가 "묶음"과 비슷한 의미를 갖고있기때문에, 웹 애플리케이션을 구성하는 파일들을 "묶어주는" 프로그램이라고 생각하면 된다.


왜 사용하는가?

모듈스펙을 사용해 개발한 웹 애플리케이션을 (모듈스펙을 지원하지않는) 브라우저에서 동작시킬 수 있게된다.

기존의 Web Application이 서버가 렌더링 해준 HTML page + 간단한 JS로 구성되던 형태에서 점점 발전해가면서 브라우저 자체에서 다양한 프레임워크, 모듈, 라이브러리를 가져다 쓰기 시작했다.

Web Application이 사용하는 파일이 많아지다보니 파일관리의 필요성이 대두되었고, 그 결과로 자바스크립트의 모듈시스템 도입되었다.

그러나 다양한 브라우저마다 지원하는 javascript의 버전이 다르기에, 호환성 문제로 몇몇 브라우저에서는 모듈시스템을 사용할 수 없다.

모듈시스템을 사용하고있는 웹 애플리케이션을 브라우저에서 동작할 수 있도록 하기 위한 도구로 웹팩이 등장하게되었다.


기능

  • javascript의 모듈들을 모든 브라우저에서 실행이 가능하도록 하나의 파일로 합친다.
    (브라우저에서 사용하지 못하는 모듈 시스템을 사용 가능하도록 변환해준다.)
  • javascript 뿐만아니라 css/scss, image 등 다양한 파일들도 최적화된 형태로 합쳐준다.
  • browser가 이해할 수 없는 파일들을 이해할 수 있는 형태로 변환해준다.
  • 파일을 합치는 과정에서, 사용자가 원하는 형태로 파일을 변환
    ( ex. 특정 문구(console.log) 주석 처리 등 ..) 
  • 파일을 합치는 과정에서, 다양한 최적화작업을 수행한다.
    ( ex. 이미지 압축 )

환경설정

웹팩은 webpack.config.js 파일에 설정값들을 저장하고, 실행시 파일을 읽고 설정값에 맞춰 packaging(or bundling)을 수행한다.

create-react-app이나, vue-cli와 같은 툴체인 프로그램들이 자동으로 생성해주는 webpack.config.js 파일을 보면 너무나 복잡해보인다. 그러나 결국 필수적으로 필요한 뼈대는 4가지다.

entry: 패키징의 시작점 설정

웹팩이 패키징을 수행 할 시작점을 설정해주는 곳이다. 

module.exports = (env, options) => {
  return {
    //...
    entry: {
      app: [path.join(srcPath, '/index')]
    },
    //...
  }
}

output: 패키징의 종단점(출력) 설정

웹팩이 패키징을 완료한 파일을 저장할 종료점을 설정해주는 곳이다.

module.exports = (env, options) => {
  return {
    //...
	output: {
      path: distPath,
      filename: 'app.js',
    },
    //...
}

module: 패키징의 방법, 규칙을 정의

웹팩이 패키징을 수행하는 과정에서 각 파일별로 패키징할 방법과 규칙을 설정해주는 곳이다.
패키징은 "로더"라고 하는 프로그램을 이용해 진행된다.
파일별로 사용할 로더에 대한 규칙과 방법을 정의한다.

ex) babel

module.exports = (env, options) => {
  return {
    //...
    module: {
      rules: [
        { test: /\.tsx?$/, loader: 'ts-loader' },
        { test: /\.s[ac]ss/, use: [ MiniCssExtractPlugin.loader, 'css-loader' ] }
      ]
    }
    //...
  }
}

plugins: 패키징된 파일의 후처리와 관련된 설정

웹팩이 패키징을 완료 한 후, 후처리로 작업할 내용들을 정의
사용할 플러그인 소프트웨어들을 정의/적용한다.

ex) 이미지 최적화 플러그인

module.exports = (env, options) => {
  return {
    //...
    plugins: [
      new MiniCssExtractPlugin({ filename: 'assets/css/app.css' }),
      new webpack.DefinePlugin({}),
      (options.mode !== 'production') && new ReactRefreshWebpackPlugin(),
      new HtmlWebpackPlugin({
        template: path.join(srcPath, '/index.html'),
      }),
      new CopyPlugin({
        patterns: [
          { from: path.resolve(srcPath, 'assets'), to: 'assets' }
        ],
      }),
    ].filter(Boolean),
    //...
  }
}

예시코드

다양한 구조의 환경설정파일들이 있다.
아래는 토이프로젝트로 진행중인 React App에서 사용하는 설정파일이다.
webpack boilerplate를 검색하여 다양한 설정 템플릿을 얻을 수 있다.

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyPlugin = require("copy-webpack-plugin");

const path = require('path');
const srcPath = require('path').resolve(__dirname, 'src');
const distPath = require('path').resolve(__dirname, 'dist');

module.exports = (env, options) => {
    return {
        name: 'opgc',

        entry: {
            app: [path.join(srcPath, '/index')]
        },

        module: {
            rules: [
                {
                    test: /\.jsx?/,
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            ['@babel/preset-env', {
                                targets: {
                                    browsers: ['last 2 chrome versions']
                                }
                            }], 
                            '@babel/preset-react'
                        ],
                        plugins: [
                            '@babel/plugin-proposal-class-properties',
                            (options.mode !== 'production') && require.resolve('react-refresh/babel'),
                        ].filter(Boolean)
                    }
                },
                { test: /\.tsx?$/, loader: 'ts-loader' },
                { test: /\.s[ac]ss/, use: [ MiniCssExtractPlugin.loader, 'css-loader' ]}
            ]
        },

        plugins: [
            new MiniCssExtractPlugin({ filename: 'assets/css/app.css' }),
            new webpack.DefinePlugin({}),
            (options.mode !== 'production') && new ReactRefreshWebpackPlugin(),
            new HtmlWebpackPlugin({
                template: path.join(srcPath, '/index.html'),
            }),
            new CopyPlugin({
                patterns: [
                    { from: path.resolve(srcPath, 'assets'), to: 'assets' }
                ],
            }),
        ].filter(Boolean),

        output: {
            path: distPath,
            filename: 'app.js',
        },
    }
};

대안

Webpack 말고도 다양한 번들러들이 있다.

  • Parcel
  • Gulp
  • rollup (라이브러리같은 소프트웨어를 만들때)

그러나 webpack에서 detail한 설정이 가능하기때문에 실무에서 많이 사용한다.

https://stackshare.io/stackups/gulp-vs-parcel-vs-webpack

profile
오늘 먹은 음식도 기억이 안납니다. 그래서 모든걸 기록합니다.

0개의 댓글