프론트엔드 스터디

웹팩(Webpack)이란?

옹재 2021. 7. 2. 11:07
728x90
반응형

웹팩이란?

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

웹팩 시작하기

  1. 빈 폴더에서 아래 명령어로 package.json 파일을 생성

    npm init -y
  2. 아래 명령어로 해당 폴더에 웹팩 관련 라이브러리와 lodash 라이브러리 설치

    npm i webpack webpack-cli -D
    npm i lodash
  3. 폴더에 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>
  4. 프로젝트 루트 레벨에 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());
  5. 웹팩 빌드 및 빌드 결과물로 실행하기 위해 각 파일에 아래 내용 반영

    // 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"
      }

      mode의 종류는 3가지

      • none
      • development
      • production

      기본적으로는 none으로 설정해서 진행되도 됨

    2. npm run build 명령어 실행 후 index.html 파일을 라이브서버로 실행

    3. 프로젝트 폴더 루트 레벨에 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')
        }
      };
    4. package.json 파일을 아래와 같이 수정

      "scripts": {
        "build": "webpack"
      }
    5. 다시 npm run build 명령어를 실행하여 빌드가 잘 되는지 확인

웹팩 설정 파일

var path = require('path');

module.exports = {
    mode:'none',
    entry : './src/index.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
    }
};

Entry

entry 속성은 웹팩에서 웹 자원을 변환하기 위해 필요한 최초 진입점이자 자바스크립트 파일 경로입니다. 위 코드를 보면 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'
  }
}

output 속성 옵션 형태

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

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

module.exports = {
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './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'
  }
}

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

CSS 로딩 에러

위 에러 메시지의 의미는 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.exports = {
  module: {
    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)은 웹팩의 기본적인 동작에 추가적인 기능을 제공하는 속성입니다. 로더랑 비교하면 로더는 파일을 해석하고 변환하는 과정에 관여하는 반면, 플러그인은 해당 결과물의 형태를 바꾸는 역할을 한다고 보면 됩니다.

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

// webpack.config.js
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 : 웹팩의 빌드 진행율을 표시해주는 플러그인

요약

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

웹팩 도식

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

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