WebPack(웹팩) 주요 속성

Minho Yoo·2022년 11월 2일
1

WebPack

목록 보기
2/3
post-thumbnail

웹팩의 4가지 주요 속성

웹팩의 빌드 (파일 변환) 과정을 이해하기 위해서는 아래 4가지 주요 속성에 대해서 알고 있어야 한다.

  • entry
  • output
  • loader
  • plugin

각 주요 속성에 대해서 자세히 살펴보자.

Entry

entry 속성은 웹팩에서 웹 자원을 반환하기 위해 필요한 최초 진입점이자 자바스크립트 파일 경로이다.

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

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

Entry 파일에는 어떤 내용이 들어가야 하나?

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

예를 들어, 블로그 서비스를 웹팩으로 빌드한다고 했을 때 코드의 모양은 아래와 같을 수 있다.

// 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();

위 코드는 해당 서비스가 싱글 페이지 애플리케이션이라고 가정하고 작성한 코드이다.
사용자의 로그인화면, 로그인 후 진입하는 메인화면, 그리고 게시글을 작성하는 화면 등 웹 서비스에 필요한 화면들이 모두 index.js 파일에서 불러져 사용되고 있기 때문에 웹팩을 실행하면 해당 파일들의 내용까지 해석하여 파일을 빌드해줄 것이다.

위와 같이 모듈 간의 의존 관계가 생기는 구조를 디펜던시 그래프(Dependency Graph) 라고 한다.

Entry 유형

앞에서 살펴본 것처럼 엔트리 포인트는 1개가 될 수도 있지만 아래와 같이 여러 개가 될 수도 있다.

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

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

Output

output 속성은 웹팩을 돌리고 난 결과물의 파일 경로를 의미한다.

// webpack.config.js
module.exports = {
  output: {
    filename: 'bundle.js'
  }
}

앞에서 배운 entry 속성과는 다르게 객체 형태로 옵션들을 추가해야 한다.

Output 속성 옵션 형태

최소한 filename은 지정해줘야 하며 일반적으로 아래와 같이 path 속성을 함께 정의한다.

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

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

여기서 filename 속성은 웹팩으로 빌드한 파일의 이름을 의미하고, path 속성은 해당 파일의 경로를 의미한다.
그리고 path 속성에서 사용된 path.resolve() 코드는 인자로 넘어온 경로들을 조합하여 유효한 파일 경로를 만들어주는 Node.js API이다.

이 API가 하는 역할을 좀 더 이해하기 쉽게 표현하면 아래와 같다.

output: './dist/bundle.js'

Output 파일 이름 옵션

앞에서 살펴본 filename 속성에 여러 가지 옵션을 넣을 수 있다.

  1. 결과 파일 이름에 entry 속성을 포함하는 옵션
module.exports = {
  output: {
    filename: '[name].bundle.js'
  }
}
  1. 결과 파일 이름에 웹팩 내부적으로 사용하는 모듈 ID를 포함하는 옵션
module.exports = {
  output: {
    filename: '[id].bundle.js'
  }
}
  1. 매 빌드시 마다 고유 해시 값을 붙이는 옵션
module.exports = {
  output: {
    filename: '[name].[hash].bundle.js'
  }
}
  1. 웹팩의 각 모듈 내용을 기준으로 생성된 해시 값을 붙이는 옵션
module.exports = {
  output: {
    filename: '[chunkhash].bundle.js'
  }
}

이렇게 생성된 결과 파일의 이름에는 각각 엔트리 이름, 모듈 아이디, 해시 값 등이 포함된다.

Loader

로더(Loader)는 웹팩이 웹 애플리케이션을 해석할 때 자바스크립트 파일이 아닌 웹 자원(HTML, CSS, Images, 폰트 등)들을 변환할 수 있도록 도와주는 속성이다.

// webpack.config.js
module.exports = {
  module: {
    rules: []
  }
}

엔트리나 아웃풋 속성과는 다르게 module라는 이름을 사용한다.

Loader가 필요한 이유

웹팩으로 애플리케이션을 빌드할 때 만약 아래와 같은 코드가 있다고 가정해보자.

// app.js
import './common.css';

console.log('css loaded');
/* common.css */
p {
	color: blue;
}
// webpack.config.js
module.exports = {
  entry: './app.js',
  output: {
    filename: 'bundle.js'
  }
}

위 파일을 웹팩으로 빌드하게 되면 아래와 같은 에러가 발생한다.

위 에러 메세지의 의미는 app.js 파일에서 임포트한 common.css 파일을 해석하기 위해 적절한 로더를 추가해달라는 것이다.

CSS Loader 적용하기

이 때 해당 폴더에 아래와 NPM 명령어로 CSS 로더를 설치하고 웹팩 설정 파일 설정을 바꿔주면 에러를 해결할 수 있다.

npm i css-loader -D
// webpack.config.js
module.exports = {
  entry: './app.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\css$/,
        use: ['css-loader']
      }
    ]
  }
}

위의 module 쪽 코드를 보면 rules 배열에 객체 한 쌍을 추가했다.
그리고 그 객체에는 2개의 속성이 들어가 있는데 각각 아래와 같은 역할을 한다.

  • test: 로더를 적용할 파일 유형(일반적으로 정규 표현식 사용)
  • use: 해당 파일에 적용할 로더의 이름

정리하자면 위 코드는 해당 프로젝트의 모든 CSS 파일에 대해서 CSS 로더를 적용하겠다는 의미이다.
적용 후 빌드하면 정상적으로 실행되는 것을 알 수 있다.

자주 사용되는 로더 종류

앞에서 살펴본 CSS 로더 이외에도 실제 서비스를 만들 때 자주 사용되는 로더의 종류는 다음과 같다.

  • Babel Loader
  • Sass Loader
  • File Loader
  • Vue Loader
  • TS Loader

로더를 여러 개 사용하는 경우에는 다음과 같이 rules 배열에 로더 옵션을 추가해주면 된다.

module.export = {
  moudle: {
    rules: [
      { test: /\.css$/, use: 'css-loader' },
      { test: /\.ts$/, use: 'ts-loader' },
      // ...
    ]
  }
}

로더 적용 순서

특정 파일에 대해 여러 개의 로더를 사용하는 경우 로더가 적용되는 순서에 주의해야 한다.
로더는 기본적으로 오른쪽에서 왼쪽 순으로 적용된다.

CSS의 확장 문법인 SCSS 파일에 로더를 적용하는 예시를 보겠다.

module: {
  rules: [
    {
      test: /\.scss$/,
      use: ['css-loader', 'sass-loader']
    }
  ]
}

위 코드는 scss 파일에 대해 먼저 Sass 로더로 전처리 (scss 파일을 css 파일로 변환)를 한 다음 웹팩에서 CSS 파일을 인식할 수 있게 CSS 로더를 적용하는 코드이다.

만약 웹팩으로 빌드한 자원으로 실행했을 때 해당 CSS 파일이 웹 애플리케이션에 인라인 스타일 태그로 추가되는 것을 원한다면 아래와 같이 style 로더도 추가할 수 있다.

{
  test: /\.scss$/,
  use: ['style-loader', 'css-loader', 'sass-loader']
}

그리고, 위와 같이 배열로 입력하는 대신 아래와 같이 옵션을 포함한 형태로도 입력할 수 있다.

module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        { loader: 'style-loader' },
        {
          loader: 'css-loader',
          options: { modules: true }
        },
        { loader: 'sass-loader' }
      ]
    }
  ]
}

Plugin

플러그인(plugin)은 웹팩의 기본적인 동작에 추가적인 기능을 제공하는 속성이다.
로더랑 비교하면 로더는 파일을 해석하고 변환하는 과정에 관여하는 반면, 플러그인은 해당 결과물의 형태를 바꾸는 역할을 한다고 보면 된다.

플러그인은 아래와 같이 선언한다.

module.exports = {
  plugins: []
}

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

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

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

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

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

자주 사용하는 플러그인

  • split-chunks-plugin
  • clean-webpack-plugin
  • image-webpack-loader
  • webpack-bundle-analyzer-plguin

Concepts Review

여태까지 살펴본 웹팩 4가지 주요 속성을 도식으로 나타내보면 다음과 같다.

위 도식을 보면서 지금까지 배운 내용을 종합해보겠다.

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

위 속성 이외에도 resolve, devServer, devtool 속성에 대해 알고 있으면 좋다.

웹팩 맛보기

개발 환경 구성

먼저 아래 소프트웨어가 컴퓨터에 설치되어 있어야 한다.

웹 페이지 자원 구성

  1. 빈 폴더에서 아래 명령어로 package.json 파일을 생성
npm init -y
  1. 아래 명령어로 해당 폴더에 웹팩 관련 라이브러리와 lodash 라이브러리 설치
npm i webpack-cli -D
npm i lodash
  1. 폴더에 index.html 파일을 생성하고 아래 내용 추가
<html>
  <head>
    <title>Webpack Demo</title>
    <script src="https://unpkg.com/lodash@4.16.6"></script>
  </head>
  <body>
    <script src="src/index.js"></script>
  </body>
</html>
  1. 프로젝트 루트 레벨에 src 폴더를 생성하고 그 안에 index.js 파일 생성
function component() {
  var element = document.createElement('div');
  
  /* lodash is required for the next line to work */
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');
  
  return element;
}

document.body.appendChild(component());

웹팩 빌드를 위한 구성 및 빌드

  1. 웹팩 빌드 및 빌드 결과물로 실행하기 위해 각 파일에 아래 내용 반영
// index.js
import _ from 'lodash';

function component() {
  var element = document.createElement('div');

  /* lodash is required for the next line to work */
  element.innerHTML = _.join(['Hello','webpack'], ' ');

  return element;
}

document.body.appendChild(component());
<!-- index.html -->
<html>
  <head>
    <title>Webpack Demo</title>
    <!-- <script src="https://unpkg.com/lodash@4.16.6"></script> -->
  </head>
  <body>
    <!-- <script src="src/index.js"></script> -->
    <script src="dist/main.js"></script>
  </body>
</html>
  1. 웹팩 빌드 명령어를 실행하기 위해 package.json 파일에 아래 내용 추가
"scripts": {
  "build": "webpack --mode=none"
}
  1. npm run build 명령어 실행 후 index.html 파일을 라이브서버로 실행
  2. 프로젝트 폴더 루트 레벨에 webpack.config.js 파일 생성 후 아래 내용 추가
// webpack.config.js
// 'webpack' command will pick up this config setup by default
var path = require('path');

module.exports = {
  mode: 'none',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  }
};
  1. package.json 파일을 아래와 같이 수정
"scripts": {
  "build": "webpack"
}
  1. 다시 npm run build 명령어를 실행하여 빌드가 잘 되는지 확인
profile
Always happy coding 😊

0개의 댓글