즐코

webpack 기초, 기본적인 속성들 본문

Webpack

webpack 기초, 기본적인 속성들

YJLEE_KR 2023. 2. 3. 02:07

개요 

코드 재사용과 같은 유지보수 측면에서 파일을 여러 개로 분리해서 개발하기 시작했다.

이렇게 분리된 파일을 module이라고 하는데, module의 개념이 등장하면서 웹팩이 나오게 되었다.

 

즉, 모듈이 많아질수록 브라우저가 서버에 요청하는 수가 증가 => 네트워크 비용도 증가 => 페이지 로딩 시간이 up 되는 것이다.

따라서, 개발할땐 모듈로 나눠서 개발하지만 웹서버 배포할 때는 하나의 파일로 묶어서 배포하게 된다.

 

하나의 모듈을 묶는 작업을 bundling 이라고 하며 여러 개의 파일을 하나로 묶어주는 도구가 module bunlder이다.

모듈 번들러는 여러 종류가 있는데 그 중 인기 많은 모듈 번들러가 바로 webpack 이다!

 

보통 리액트, 넥스트, 뷰 등 라이브러리, 프레임워크를 설치하면 내부적으로 번들링 기능이 들어가 있어 config 파일만 만지면 되기에 webpack, webpack-cli를 따로 깔지 않아도 되지만 웹팩 기본을 익히기 위해 깔아서 공부해본다.

 

webpack 설치해서 실습해보기

npm init -y
npm i -D webpack webpack-cli

아래의 터미널 명령어로 빌드

npx webpack --entry ./src/index.js --output-path ./dist -mode production
  • --entry : webpack 의 진입점 (어떤 파일을 기준으로 번들링 할지 정해주는 옵션)
  • --output-path : 번들링한 결과물을 어디에 생성시킬지 정해주는 옵션
  • --mode : 번들링 모드 설정 (기본값 production || none || development) 

기본적으로 production을 적용하면 띄어쓰기 없이 완전히 압축, 최적화되서 main.js 빌드물이 탄생하지만, development 모드로 할 경우 압축없이 생성되서 번들링 파일의 사이즈는 크지만 보기는 편하다.

 

기본 모드인 production으로 번들링 한 결과물

위는 간단하게 터미널 명령어로 연습한거지만 실제 프로젝트나 현업에선 webpack.config.js 파일과 같은 웹팩 설정 파일을 통해 옵션을 정해준다. webpack.config.js 파일을 루트에 만들고 npx webpack 하면 빌드해준다.

 

webpack 주요 속성 (webpack.config.js)

entry

웹팩에서 웹 자원을 변환하기 위해 필요한 최초 진입점이자 js 파일 경로이다.

쉽게 말하면 어떤 파일을 기준으로 번들링 할지 정해준다.

// webpack.config.js
module.exports = {
  mode: 'development',
  resolve: {
    extensions: ['.js', '.jsx']
  },
  entry: {
    app: ['./src/index'] // resolve-extensions 를 쓰면 뒤의 확장자명을 빼도 된다.
  },
  • resolve : 웹팩이 알아서 경로나 확장자를 처리할 수 있게 도와주는 옵션

output

빌드한 결과물에 대한 속성

  • filename : 빌드한 파일명
  • path : 빌드 결과물이 저장될 경로 (path.resolve를 많이 써서 정해주는 편이다)
  • publicPath : 파일들이 위치할 서버 상의 경로
  • filename에 아래와 같이 여러가지 옵션을 넣을 수도 있으니 참고하자

1/ 결과 파일에 entry 속성을 포함하는 옵션

   : filename: '[name].bundle.js' => main.bundle.js 

2/ 결과 파일명에 웹팩 내부적으로 사용하는 모듈 id를 포함하는 옵션

  : filename: '[id].bundle.js' => 179.bundle.js 

3/ 매 빌드 시마다 고유 해시값을 붙이는 옵션

  : filename: '[name].[hash].bundle.js' ⇒ main.47c4694d241971f4759d.bundle.js

4/ 웹팩의 각 모듈 내용을 기준으로 생성된 해시 값을 붙이는 옵션

  : filename: ‘[chunkhash].bundle.js’ ⇒ df1cca0652b4071534a0.bundle.jsㅣ

 

// webpack.config.js
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/dist/',
  },

 

loader (module)

웹팩이 빌드 시 모듈, 파일 간의 관계를 파악하고 해석할 때, js 파일이 아닌 비자바스크립트 파일 즉, 웹소스들 (html, css, image, font 등)을 웹팩이 인식하여 변환할 수 있게 도와주는 속성이다.

쉽게 말하면, entry에서 output으로 변환할 때 개입하는 것이 loader 즉, module 속성이다

 

아래와 같이, app.js에서 css 파일을 import 해서 빌드하면 이 app.css 파일을 해석하기 위한 로더를 추가해줘야 한다. 그래서 필요한게 loader이다. 보통 css를 위해선 아래와 같은 로더와 플러그인을 설치한다. 플러그인에 대해선 아래에서 설명할 것이다.

npm i css-loader style-loader mini-css-extract-plugin -D
  • rules : 하나의 loader 속성에 대한 규칙을 정해주는 속성이다. rules 배열에 객체 한 쌍씩을 추가한다.
    • test : 로더를 적용할 파일 유형 (정규식 사용)
    • use : 해당 파일에 적용할 로더명
  • 로더는 적용 순서에 주의해야 한다. 무조건 오른쪽 -> 왼쪽 순으로 적용된다.
    • css-loader : css 파일을 빌드 결과물에 포함하게 해주는 역할
    • style-loader : css-loader로 생성된 string들을 <style> 태그에 css 를 넣어주는 역할
    • sass-loader : .scss 파일을 css로 변환해주는 역할
    • style-loader는 css-loader가 .css 확장자 파일들이 번들링에 포함된 이후에 <style> 태그를 이용해 html 파일에 적용시킬 수 있으므로, use: ['style-loader', 'css-loader'] 이 순서를 꼭 지켜줘야한다!

plugins

웹팩의 기본적인 동작에 추가적인 기능을 제공하는 속성이다. 웹팩으로 변환한 파일에 추가적인 기능을 더하고 싶을 때 사용한다.

loader vs. plugin
로더 : 파일을 해석하고 변환하는 과정에 관여
플러그인 : 해당 결과 빌드물의 형태를 바꾸는 역할

기가 막히게 이해가 잘되게 해주는 도식이다

  • 플러그인의 배열에는 생성자 함수로 생성한 객체 인스턴스만 추가할 수 있다.
  • 아래와 같이 plugins상에 MiniCssExtractPlugin 를 추가하고 빌드할 경우, bundle.js 뿐만 아니라 main.css도 번들 파일에 생성이 되었다! 대신, 실행해보면 css가 적용이 되지않았다. 이때, index.html 상에 <link rel=”stylesheet” href=”./dist/main.css”> 를 추가하니 적용되었다!
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'none',
  entry: './index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          mode === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader'
        ]
      }
    ]
    plugins: [
      new MiniCssExtractPlugin(),
      new HtmlWebpackPlugin({
        template: 'index.html', // index.html 템플릿을 기반으로 빌드 결과물을 추가해줌
      })
    ]
  }
}

위에서 module-rules-use에 대해 설명하자면, 개발 모드일 경우 style-loader로 style tag에 넣어주고, 배포 모드엔 css파일을 별도로 만들도록 설정한 것이다. 

- style-loader : <style> tag 에 모든 css 값이 들어감
- MiniCssExtractPlugin : 별도의 css 파일을 생성함

 

  • 웹팩 설정 시 필요한 플러그인 자료 : https://webpack.js.org/plugins/
  • 자주 쓰는 플러그인
    • mini-css-extract-plugin : CSS를 포함하는 JS 파일 당 CSS 파일을 별도로 추출해준다.
    • html-webpack-plugin : 따로 분리해서 번들한 css, js파일들을 각각 html 파일 상에 link, script 태그로 추가해줘야하는데, 그걸 자동화해서 html 상에 추가해서 생성해주는 플러그인 (template 속성이 없다면 자동으로 index.html 파일을 생성해준다)
    • clean-webpack-plugin : 빌드 이전 결과물을 제거하는 플러그인
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
   plugins: [
        new MiniCssExtractPlugin({filename: 'style.css'}),
        new HtmlWebpackPlugin({template: './src/index.html'}),
        new CleanWebpackPlugin(),
    ]
}

devtool 옵션

  • source-map 
    • 보통 production 모드로 빌드를 할 경우 번들 파일이 난독화되서 나오는데, 이 때 실제 번들 전의 오리지날 파일 상의 코드와 번들링된 파일을 맵핑해주는 도구를 설정해준다.
    • 하지만 이 옵션이 켜져있을 경우 빌드 후 에러가 났을 때 프로젝트 전체 소스를 다 확인할 수 있기 때문에 정보 유출의 위험 방지를 위해 실서버에 올리기 위해 빌드하는 경우엔 해당 source-map 설정을 꺼준다.

개발자도구-Sources 탭에서 실제 js파일과 번들 파일을 맵핑해준다.

 

webpack Dev Server

웹팩의 빌드 대상 파일이 변경되었을 때 매번 웹팩 명령어로 빌드 실행을 하지 않아도 코드만 변경하고 저장하면 웹팩으로 빌드한 후 브라우저를 자동으로 새로고침해준다. 

신기한건, 웹팩 데브 서버를 실행해서 웹팩 빌드를 하는 경우엔 빌드한 결과물이 파일 탐색기나 프로젝트 폴더 상에 보이지 않는다.

=> 웹팩 데브 서버로 빌드한 결과물은 메모리에 저장되고 파일로 생성되지 않기 때문이다

 

webpack-dev-server를 설치해보자!

npm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin

package.json - scripts 에 명령어 추가

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

아래와 같이 webpack.config.js 파일 상에 devServer 옵션을 추가해주고 npm run dev 실행 시 localhost:9000 상으로 dev server가 실행된다!

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'none',
  entry: './index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devServer: {
    port: 9000,
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'index.html',
    }),
  ],
};

 

이제 기본적인 웹팩 속성에 대해선 파악했다. 예전에 웹팩을 처음 배웠을 땐 뭔소리며 먼 미래의 일이라 생각해서 크게 신경쓰지 않았는데, 실제로 써먹어야할때가 오니 꽤 재밌게 느껴진다. 회사에서 번들링 시 필요한 로더나 플러그인들을 이것저것 찾아보면서 유용하게 쓴 것들만 정리해둘 예정이다!

 

'Webpack' 카테고리의 다른 글

webpack-bundle-analyzer / 번들링 파일 분석!  (0) 2023.01.31
Comments