세 번의 프로젝트동안 프론트엔드 개발자로서 개발을 진행했음에도 웹팩에 대해 이해하고 넘어가지 않아서 정리해보는 시간을 가지려고 합니다. React 같은 경우 CRA(create-react-app)으로 프로젝트 빌드 시에 개발 환경을 자동으로 설정해주기 때문에 큰 관심을 가지지 않은 점이 깊은 이해에 방해되었다고 생각합니다. 그래서 나름의 정리를 통해 webpack을 이해하고자 합니다.

webpack

공식문서에서 설명하는 webpack은 모던 JavaScript 애플리케이션을 위한 정적 모듈 번들러(module-bundler) 입니다.

 자바스크립트는 변수 유효 범위를 전역으로 가지게 됩니다. 이는 접근성은 좋지만, 웹 어플리케이션을 개발하다보면 각 스크립트에서 활용하는 변수명이 중복되는 등의 문제가 발생할 수 있습니다. 이를 해결하기 위한 방법으로 JS의 즉시호출함수(IIFE) 기능을 이용한 CommonJSAMDUMD등이 있습니다. (자바스크립트 모듈화의 변화 IIFE => CommonJS, AMD, UMD => ES6)

 

 또한, 웹 페이지는 html, css, js, 이미지, 웹 폰트, json 데이터 등 정말 많은 파일들이 모여 하나의 웹 페이지가 구성이 되며, 요청해야 할 파일의 수가 많아져 그만큼 비효율적이게 됩니다. 이런 문제를 해결하고자 요청의 수를 줄이는 번들러가 필요하게 됩니다.

 

따라서 웹팩은 CommonJS, AMD, ES6Module 포맷을 모두 지원하며, 자바스크립트 모듈에만 국한되지 않고 웹 애플리케이션을 구성하는 모든 자원을 하나의 파일로 병합 및 압축 해주는 동작을 수행하게 됩니다.

 

 

webpack의 4가지 속성

웹팩의 빌드(파일 변환) 과정을 이해하기 위해서는 4가지 주요 속성(entry, output, loader, plugin)에 대해서 알고 있어야 합니다.

entry

webpack은 모든 것을 module로 관리합니다. javascript, css, img 등 모든 것을 JS 모듈로 로딩하여 사용합니다.

여러 module의 관계(의존성)를 파악하여 하나로 묶기 위해서는 기준점이 필요하고 그 기준점이 entry입니다. 

// webpack.config.js

module.exports = {
  entry: './src/index.js'
}

위 코드는 웹팩을 실행했을 때 src 폴더 밑의 index.js 을 대상으로 웹팩이 빌드를 수행하는 코드입니다.

// index.js
import LoginView from './LoginView.js';
import HomeView from './HomeView.js';
import PostView from './PostView.js';

function initApp() {
  LoginView.init();
  HomeView.init();
  PostView.init();
}

initApp();

 지정된 파일에는 웹 애플리케이션의 전반적인 구조와 내용이 담겨져 있어야 합니다. 웹팩이 해당 파일을 가지고 웹 애플리케이션에서 사용되는 모듈들의 연관 관계를 이해하고 분석하기 때문에 애플리케이션을 동작시킬 수 있는 내용들이 담겨져 있어야 합니다.

entry: {
  login: './src/LoginView.js',
  main: './src/MainView.js'
}

 entry는 여러 개가 될 수 있으며, 위와 같이 엔트리 포인트를 분리하는 경우는 싱글 페이지 애플리케이션이 아닌 특정 페이지로 진입했을 때 서버에서 해당 정보를 내려주는 형태의 멀티 페이지 애플리케이션에 적합합니다.

 

output

Output은 Webpack을 통해 만들어진 결과물이 반환될 경로를 지정하는 부분이며 이는 객체 형태로 작성되어야 합니다.

// webpack.config.js
var path = require('path');

module.exports = {
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist')
  }
}

 빌드한 파일명인 filename은 필수로 지정해야하며, path는 파일의 경로를 나타냅니다.

(예시 코드는 Node.js API인 path.resolve() 코드로 인자로 넘어온 경로들을 조합하여 유효한 파일 경로를 지정합니다.)

 

loader

앞서 살펴본 것처럼 모듈에는 여러 종류의 파일이 존재하지만, 웹팩은 자바스크립트 하나만 이해합니다. 

그렇기 때문에 Loader는 자바스크립트가 아닌 언어로 구성된 파일을 Webpack이 이해할 수 있게 만드는 기능입니다.

 

CSS로더 같은 경우는 다음과 같이 사용합니다.

npm i css-loader -D

일단 npm명령어를 사용하여 css 로더를 설치합니다. 

// webpack.config.js
module.exports = {
  entry: './app.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['css-loader']
      }
    ]
  }
}
  • test : 로더를 적용할 파일 유형 (일반적으로 정규 표현식 사용)
  • use : 해당 파일에 적용할 로더의 이름

 

여러 개의 로더를 사용할 경우에는 rules에 옵션을 추가해주면 됩니다.특정 파일에서 여러 개의 로더를 사용할 경우에는 로더가 적용되는 순서를 주의해야합니다.로더는 기본적으로 오른쪽에서 왼쪽 순으로 적용됩니다.

 

 자주 사용되는 로더의 종류는 다음과 같습니다.

 

TypeScript | 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

 

plugin

Loader가 파일을 해석하고 변환하는 과정에 관여하는 반면,  Plugin은 해당 결과물의 형태를 바꾸는 역할을 합니다.

// webpack.config.js
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

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

플러그인의 배열에는 생성자 함수로 생성한 객체 인스턴스만 추가될 수 있습니다.

위의 두 플러그인은 각각 아래와 같은 역할을 합니다.

  • HtmlWebpackPlugin : 웹팩으로 빌드한 결과물로 HTML 파일을 생성해주는 플러그인
  • ProgressPlugin : 웹팩의 빌드 진행율을 표시해주는 플러그인

 

자주 사용하는 플러그인의 종류

 

속성의 한줄요약

  1. Entry 속성은 웹팩을 실행할 대상 파일. 진입점
  2. Output 속성은 웹팩의 결과물에 대한 정보를 입력하는 속성. 일반적으로 filename과 path를 정의
  3. Loader 속성은 CSS, 이미지와 같은 비 자바스크립트 파일을 웹팩이 인식할 수 있게 추가하는 속성. 로더는 오른쪽에서 왼쪽 순으로 적용
  4. Plugin 속성은 웹팩으로 변환한 파일에 추가적인 기능을 더하고 싶을 때 사용하는 속성. 웹팩 변환 과정 전반에 대한 제어권을 갖고 있음

 

장점과 단점

장점

  • 코드를 제거하는 tree shaking과 같은 최적화를 수행하여 HTTP 요청을 줄여 성능을 향상시킨다.
  • Loader를 통해 다양한 리소스를 Javascript에서 사용할 수 있는 여러 형태로 변환 가능하다.
  • CLI, 간단한 명령어로 조작이 가능하다.
  • 대부분의 기능을 커스터마이징할 수 있다.

단점

  • 러닝커브가 존재한다. 다양한 값을 설정해야 하기 때문에 익숙해지기 전까지 작업 시간이 길다.
  • 초기에 많은 리소스를 하나의 파일로 병합하기 때문에 초기 로딩 비용이 커진다.

+ Recent posts