logo
github
Webpack Study
May 28, 2022

인프런 캡틴판교 - 프론트엔드 개발자를 위한 웹팩 강의를 듣고 정리한 내용입니다.


1주차

0. Webpack

웹팩이란?

프론트엔드 프레임워크에서 가장 많이 사용되는 모듈 번들러

모듈

프로그래밍 관점에서 특정 기능을 가지는 작은 코드 단위

웹팩에서의 모듈

웹팩에서의 모듈은 자바스크립트 모듈에만 국한되지 않고 웹 어플리케이션을 구성하는 모든 자월을 의미한다. 어플리케이션 제작에 필요한 모든 파일들이 각각 모듈에 해당한다.

모듈 번들링

웹 어플리케이션을 구성하는 여러 자원들을 하나의 파일로 병합 및 압축해 주는 동작 빌드, 번들링, 변환은 모두 같은 의미이다.

웹팩의 등장 배경

1) 파일 단위의 자바스크립트 모듈 관리의 필요성 변수를 중복 선언하거나 의도치 않은 값을 할당하는 문제가 발생할 수 있기 때문

2) 웹 개발 작업 자동화 도구 (Web Task Manager) 웹 서버에 배포할 때 <HTML, CSS, JS 압축 / 이미지 압축 / CSS 전처리기 변환> 등의 일을 자동화해 주는 도구의 필요성 증가 ➡️ Grunt, Gulp 등장

3) 웹 어플리케이션의 빠른 로딩 속도와 높은 성능 웹 사이트의 로딩 속도를 높이기 위해 처음에는 웹 태스크 매니저 또는 Lazy Loading을 활용했다. 웹팩은 필요할 때에 해당 자원을 요청하자는 철학을 가지고 있다.

웹팩으로 해결하려는 문제

1) 자바스크립트 변수 유효 범위 문제 ES6의 Modules 문법과 웹팩의 모듈 번들링으로 해결한다.

2) 브라우저별 HTTP 요청 숫자의 제약 브라우저에서 서버로 보낼 수 있는 HTTP 요청 수가 제한되어 있기 때문에 요청 숫자를 줄이는 것이 성능 향상 면에서나 사용자 측에서나 중요한 문제로 떠올랐다. ➡️ 웹팩을 이용하여 여러 개의 파일을 하나로 합치면 브라우저별 HTTP 요청 횟수 제약을 피할 수 있다.

3) 사용하지 않는 코드의 관리

4) Dynamic Loading & Lazy Loading 미지원 웹팩의 Code Splitting 기능을 이용해 원하는 모듈을 원하는 타이밍에 로딩할 수 있다.

1. Node.js와 NPM

Node.js와 npm 소개

Node.js: JavaScript 실행 환경 npm: 자바스크립트 라이브러리를 관리해 주는 도구

npm 초기화 명령어 - init

npm init -y

위 명령어를 실행하면 package.json 파일이 생성되고 기본값을 바로 넣어 줌

npm 설치 명령어 - install

npm install jquery

node_modules 폴더가 생성되고, 그 안에 jquery 폴더도 만들어짐

npm을 사용하는 이유와 장점1

라이브러리를 코드 중간에 삽입하는 경우, 어떤 라이브러리가 설치되어 있는지 알기 위해서는 모든 <script> 태그를 찾아봐야 한다는 불편함이 있다.

➡️ package.json을 사용하면 라이브러리와 버전을 관리하기 쉽다.

npm의 장점2

라이브러리 페이지를 찾아가서 cdn을 불러오는 것보다 npm install로 설치하는 게 훨씬 편리하다.

2. NPM(Node Package Manager)

npm 지역 설치 명령어와 제거 명령어 - uninstall

npm install gulp

위 명령어를 실행해 보면 node_modules 폴더에 수많은 폴더가 생기는데, 이는 gulp라는 라이브러리가 다른 많은 라이브러리들을 사용하여 함께 설치되었기 때문이다.

npm uninstall gulp

위 명령어를 실행하면 gulp와 함께 설치되었던 라이브러리들도 모두 제거된다.

npm 전역 설치 명령어 - install –global

npm install gulp --global

전역 설치하는 경우 node_modules 폴더에 추가되지 않는다.

전역으로 설치된 라이브러리 경로 확인

mac os 기준

/usr/local/lib/node_modules

지역 설치와 전역 설치 비교 정리

1) 지역 설치

npm install jquery
npm install jquery --save-prod

--save-prod는 기본값이기 때문에 위 두 명령어는 결과가 같다. 또한 install 대신i를 사용해도 된다.

2) 전역 설치 시스템 레벨에서 사용할 자바스크립트 라이브러리를 설치할 때 사용한다.

npm install gulp --global
npm install gulp -g

명령어 실행 창에 해당 라이브러리 이름을 입력하면 명령어를 인식한다.

지역 설치 명령어 옵션 - –save-dev(-D)

npm 지역 설치에 자주 사용되는 옵션 두 가지

npm install jquery --save-prod
npm install jquery --save-dev

npm i jquery
npm i jquery -D

dependencies와 devDependencies의 차이점

dependencies는 npm i jquery jquery-ui와 같이 실행되었을 때, devDependencies는 npm i vue -D와 같이 실행했을 때 추가된다.

구분해서 설치하는 이유는, dependency는 어플리케이션의 로직과 연관 있는 라이브러리들이 추가되고, devDependency는 webpack, js-compression, sass 등과 같은 개발 보조 라이브러리들이 설치된다.

개발용 라이브러리와 배포용 라이브러리 구분하기

npm 지역 설치 시 해당 라이브러리가 배포용인지, 개발용인지 구분해야 한다. 배포용 라이브러리는 npm run build 실행 시 최종 어플리케이션 코드 안에 포함이 되지만, -D로 옵션을 주어 설치한 라이브러리는 빌드 후 배포할 때 어플리케이션 코드에서 빠지게 된다.

개발할 때에만 사용하고 배포할 때에는 빠져도 좋은 라이브러리들

  • webpack 빌드 도구
  • eslint 코드 문법 검사 도구
  • imagemin 이미지 압축 도구

2주차

1. 개발 환경 구성과 빌드 과정

웹 페이지 자원 구성

아래 명령어로 package.json 파일 생성 후 웹팩과 lodash 라이브러리 설치

npm init -y

npm i webpack webpack-cli -D
npm i lodash

index.html 파일과 src 폴더 아래에 index.js 생성

<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>
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>
  </head>
  <body>
    <script src="dist/main.js"></script>
  </body>
</html>

package.json에 웹팩 빌드 명령어 추가

"scripts": {
  "build": "webpack --mode=none"
}

npm run build 명령어 실행 후 라이브 서버로 실행 프로젝트 루트 레벨에 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'),
  },
};

package.json 수정

"scripts": {
  "build": "webpack"

npm run build 실행하여 빌드 확인!

2. 웹팩의 4가지 속성

웹팩의 빌드(파일 변환) 과정을 이해하기 위해서는 아래 4가지 주요 속성에 대해 알아야 한다. 일단 이전에 작성했던 webpack.config.js 파일은 다음과 같다.

var path = require('path');

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

1) Entry

말 그대로 웹 자원을 변환하기 위해 필요한 “최초 진입점”이자 자바스크립트 파일 경로

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

위와 같이 되어 있으면 웹팩 실행 시 index.js를 대상으로 빌드를 수행한다는 뜻이다.
따라서 entry로 지정한 파일에는 웹 어플리케이션의 전반적인 구조와 내용을 담고 있어야 한다.

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

위와 같이 엔트리 포인트를 2개 이상 사용하는 방식은 멀티 페이지 어플리케이션에 적합하다.

2) Output

웹팩 사용 후 결과물의 파일 경로를 의미한다.
옵션은 객체 형태로 추가해야 하며, 일반적으로 filenamepath 속성을 함께 정의한다.

var path = require('path');

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

위 코드에서 path.resolve()는 인자로 넘어온 경로를 조합하여 유효한 파일 경로를 만들어 주는 Node.js의 API이다. 즉, ./dist/bundle.js에 결과물을 저장한다는 뜻이다!

filename 속성에는 여러 옵션을 넣을 수 있다.

output: {
  filename: '[name].bundle.js';
  filename: '[id].bundle.js';
  filename: '[name].[hash].bundle.js';
  filename: '[chunkhash].bundle.js';
}
  • 결과 파일 이름에 entry 속성을 포함
  • 결과 파일 이름에 웹팩 내부 모듈 ID를 포함
  • 빌드할 때마다 고유한 해시값을 붙임
  • 웹팩 모듈 내용을 기준으로 생성된 해시값 붙임

3) Loader

웹팩이 웹 어플리케이션을 해석할 때 JS 파일이 아닌 웹 자원(HTML, CSS, Images, Fonts)들을 변환할 수 있도록 도와주는 속성 - module 이라는 이름 사용

module.exports = {
  module: {
    rules: [],
  },
};

🏷 CSS Loader 적용하기 css-loader 설치 후 webpack.config.js 파일을 다음과같이 변경한다.

npm i css-loader -D
module.exports = {
  entry: './app.js',
  output: {
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['css-loader'],
      },
    ],
  },
};
  • test: 로더를 적용할 파일 유형 (보통 정규식 사용)
  • user: 해당 파일에 적용할 로더의 이름

🏷 자주 사용되는 로더 종류

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

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

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

위 코드는 scss 파일을 sass로더로 전처리 한 다음, 웹팩에서 css 파일을 인식할 수 있도록 css 로더를 적용한다.

4) Plugin

웹팩의 기본적인 동작에 추가적인 기능을 제공하는 속성이다.
플러그인의 배열에는 생성자 함수로 생성한 객체 인스턴스만 추가될 수 있다.

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  plugins: [new HtmlWebpackPlugin(), new webpack.ProgressPlugin()],
};
  • HtmlWebpackPlugin: 웹팩으로 빌드한 결과물로 HTML 파일 생성
  • ProgressPlugin: 웹팩의 빌드 진행률을 표시

3. Tutorials

mode 속성은 웹팩으로 빌드할 때 development, production, none 모드를 설정할 수 있다.

module.exports = {
  mode: 'none',
};

3주차

Webpack Dev Server

코드 변경 후 저장하면 웹팩 빌드 후 브라우저를 자동으로 새로고침 해 준다.

특징

"scripts": {
  "dev": "webpack serve",
  "build": "webpack"
}

웹팩 데브 서버를 실행하여 빌드한 결과물은 메모리에 저장되고 따로 파일로 생성되지는 않는다. 따라서 개발 완료 후 명령어를 이용해 파일로 생성해야 한다.

Proxy 설정

실무에서 가장 흔히 사용되는 속성! CORS 에러를 해결할 수 있다.
실제 브라우저에서는 localhost:8080/api/login 으로 요청했지만, 서버에서는 domain.com 에서의 요청으로 받아들이기 때문에 CORS 에러가 발생하지 않는다!

// webpack.config.js
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'domain.com',
        changeOrigin: true,
      },
    },
  },
};

HMR (Hot Module Replacement)

브라우저를 새로고침 하지 않아도 웹팩으로 빌드한 결과물이 웹 어플리케이션에 반영되도록 도와주는 설정이다.

module.exports = {
  devServer: {
    hot: true,
  },
};

Source Map

배포용으로 빌드한 파일과 원본 파일을 서로 연결시켜 주는 기능이다.
서버에 배포 시 웹 자원을 압축하는데, 이 파일에서 에러가 난다면 소스맵을 이용하여 원본 소스 파일을 확인할 수 있다.

// webpack.config.js
module.exports = {
  devtool: 'cheap-eval-source-map',
};

Advanced

Mode Config

웹핵 실행 모드 - mode

module.exports = {
  mode: 'none',
  entry: '',
  // ...
};
  • none: 설정 안 함
  • development: 개발 모드
  • production: 배포 모드 (default)

실행 모드에 따라 웹팩 설정 달리 하기

웹팩으로 개발 시 보통 2가지 경우로 나누어 작업한다.

  • 개발할 때 사용할 웹팩 설정
  • 배포할 때 사용할 웹팩 설정
// webpack.config.js
module.exports = (env) => {
  let entryPath =
    env.mode === 'production' ? './public/index.js' : './src/index.js';

  return {
    entry: entryPath,
    output: {},
    // ...
  };
};
// package.json
{
  "build": "webpack",
  "development": "npm run build -- --env.mode=development",
  "production": "npm run build -- --env.mode=production"
}

함수에 있는 env 인자는 환경변수를 의미하고, 웹팩을 실행할 때 옵션으로 넘겨 줄 수 있다. 혹은 두 번째 방법 처럼 npm 커스텀 명령어로도 사용할 수 있다.

webpack --env.a=10
{
  "build": "webpack --env.a=10"
}

Webpack Merge

여러 개의 웹팩 설정 파일을 하나로 병합해 준다. (보통 개발용과 배포용으로 나누어 설정하기 때문)
앞서 있던 예시처럼 실행 모드에 따라 조건문으로 작성할 수도 있지만, 파일을 분리하는 방식을 권장한다.

웹팩 설정 파일 구분 전략

파일 분리 전, 개발용과 배포용 설정 파일에서 공통으로 쓰이는 부분을 먼저 분리한다. 보통 아래와 같은 방식으로 구분한다!

  • webpack.common.js
  • webpack.dev.js
  • webpack.prod.js

webpack.common.js 공통 설정 파일에는 entry, output, plugins 같이 실행 모드에 관계 없이 항상 들어가는 코드를 추가한다.

// webpack.common.js
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
  },
  plugins: [new CleanWebpackPlugin(), new HtmlWebpackPlugin()],
};

webpack.dev.js
개발용 설정 파일에는 개발자 도구나 웹팩 데브 서버 설정을 추가한다. 또한 webpack-merge 라이브러리 설치 후 webpack.common.js 파일을 로딩하여 병합한다.

// webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: { contentBase: './dist' },
});

webpack.prod.js
배포 전 웹 리소스 최적화를 위한 설정을 추가한다.

// webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'production',
});
corinthionia
🍀 Winning Mentality💭 능동적인 사고를 통한 성장을 위해 노력합니다
© Joohyun Kim (김주현) Corinthionia