티스토리 뷰

728x90

리액트 공부 중 웹팩 설정 부분을 자꾸 까먹어 내용을 따로 정리하게 되었습니다.
웹팩이 무엇이고 왜 사용하는지를 다루지 않습니다. 어떻게 웹팩을 설정하고 리액트와 함께 사용할 수 있는지에 대해 다룹니다.

초심자 입장에서 쓴 글이니 더 깊은 내용을 원하시는 분들은 다른 문서를 참조해주시면 감사하겠습니다.

 

해당 포스트는 조현영 님의 웹 게임을 만들며 배우는 리액트 강의와 webpack 공식 문서를 참고하여 작성했습니다.

1. npm 패키지 설치

우선 react, react-dom을 설치해 줍니다.

npm i react react-dom

webpack 관련 패키지를 개발용으로 설치해줍니다.

npm i -D webpack webpack-cli

ECMA2015 이후 문법과 jsx 문법을 사용하기 위해 babel 관련 패키지도 개발용으로 설치해줍니다.

npm i -D @babel/core @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties babel-loader

@babel/core : 이름 그대로 바벨 코어입니다. 필수
@babel/preset-xxx : preset은 plugin의 집합입니다.
@babel/preset-env: babel의 지원범위를 설정, 타깃 브라우저를 입력하면 사용자 환경에 맞춰 최신 ES를 사용할 수 있게 해줍니다.
@babel/preset-react: react 환경을 위한 프리셋입니다.
@babel/plugin-proposal-class-properties: class에서 state를 사용하려면 필요하다고 합니다
babel-loader: 바벨과 웹팩을 연결해줍니다.

 

 

2. 모듈 시스템과 웹팩 설정

index.html

<body></body> 사이에 다음 코드를 삽입합니다.

<body>
  <div id="root"></div>
  <script src="./dist/app.js"></script>
</body

client.jsx

여러 컴포넌트들을 각각 모듈화 하고, client.jsx에서 불러와 렌더링 해줍니다.

const React = require('react');
const ReactDom = require('react-dom');

const YourComponent = require('./YourComponent');

ReactDom.render(<YourComponent />, document.querySelector('#root'));

webpack.config.js

객체 하나를 exports 하도록 합니다. 모든 옵션을 하나의 코드로 보면 너무 헷갈리니까 부분 부분 쪼개어 설명합니다.

module.exports = {
  ...
};

- name, mode, devtool

name :  여러 개의 설정을 불러와야 할 때 사용한다고 합니다.

mode : webpack이 어떤 최적화를 해야 할지 알려줍니다. 'development', 'production' 두 인자를 줄 수 있고 각 모드에 맞춰 최적화합니다.

devtool : https://perfectacle.github.io/2016/11/14/Webpack-devtool-option-Performance/ 이 블로그에서 잘 설명해뒀습니다. 참고하시면 될듯해요.

name: 'number-baseball', // 필수는 아님
mode: 'development', // 실서비스시 'production'
devtool: 'eval'

- entry

entry, output 속성이 핵심입니다. entry는 입력, output은 출력이라고 생각하면 됩니다.
여러 파일들을 하나로 모아 index.html에서 부를 수 있는 "./dist/app.js"를 만들어야 합니다.

entry 속성에 빌드할 파일을 명시해줍니다.

entry: {
  // client.jsx에서 다른 jsx파일을 import하므로 그 파일들은 써줄 필요 없음
  app: ['./client.jsx'],
},

- resolve

entry에서 파일이 많아지면 확장자를 쓰기 귀찮습니다. resolve 속성에 관련된 확장자를 추가하여 다음처럼 쓰면 웹팩이 알아서 찾아줍니다.

resolve: {
  extensions: ['.js', '.jsx'],
},
entry: {
  // 확장자 쓸 필요 없음
  app: ['./client'],
},

- output

빌드 결과로 dist폴더 내에 app.js를 만들어야 합니다. path 모듈을 불러와 다음처럼 설정합니다.

output: {
  path: path.join(__dirname, 'dist'),
  filename: 'app.js',
},

- loader

loader는 모듈의 소스 코드에 적용되는 변환이라고 합니다. (무슨 말인지 이해 못했습니다..) entry 파일에 babel을 적용하기 위해 babel-loader를 설정해야 합니다.
module이라는 속성을 이용해 적용할 수 있습니다.

module: {
  rules: [
    {
      test: /\.jsx?/, // 정규표현식, .js .jsx 파일에 적용하겠다는 뜻
      loader: 'babel-loader',
      options: {
        presets: [
          ['@babel/preset-env',
            {
              targets: {
                browsers: ['> 5% in KR'],
              },
              debug: true,
            },],
          '@babel/preset-react',
        ],
        plugins: ['@babel/plugin-proposal-class-properties'],
      },
    },
  ],
},

rules: 여러 종류의 로더를 설정할 수 있습니다. 따라서 배열을 사용합니다.
├─ test: loader를 적용할 파일 확장자를 뜻합니다. 위 설정에선 정규 표현식을 사용해 .js, .jsx를 나타내었습니다.
├─ loader: 적용할 loader의 종류입니다. babel-loader를 적용해 웹팩이 바벨을 해석할 수 있게 해 줍니다.
└─ options: 바벨의 옵션을 넣어줍니다. 아마 웹팩과 무관한 설정으로, 이 경우엔 바벨 자체의 옵션을 뜻하는 것 같습니다. 따라서 웹팩을 이해하기 위해 필수적인 요소는 아닙니다. 위 옵션들은 나중에 바벨 관련된 포스팅을 따로 파서 설명하겠습니다.

- plugins

webpack에서 부가적으로 설정할 수 있는 플러그인들입니다. 여러 종류가 있습니다.

plugins: [new webpack.LoaderOptionsPlugin({ debug: true })],

- 완성된 설정 파일

결과적으로 다음과 같은 webpack.config.js 파일을 작성했습니다.
한꺼번에 보면 정말 복잡해 보이지만 속성 하나하나를 쪼개어 보면 전혀 어렵지 않다는 걸 알 수 있습니다.

const path = require('path');
const webpack = require('webpack');

module.exports = {
  name: 'number-baseball',
  mode: 'development',
  devtool: 'eval',

  resolve: {
    extensions: ['.js', '.jsx'],
  },
  entry: {
    app: ['./client'],
  },
  module: {
    rules: [
      {
        test: /\.jsx?/,
        loader: 'babel-loader',
        // babel 옵션
        options: {
          presets: [
            [
              '@babel/preset-env',
              {
                targets: {
                  browsers: ['> 5% in KR'],
                },
                debug: true,
              },
            ],
            '@babel/preset-react',
          ],
          plugins: ['@babel/plugin-proposal-class-properties'],
        },
      },
    ],
  },
  plugins: [new webpack.LoaderOptionsPlugin({ debug: true })],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'app.js',
  },
};

 

3. 웹팩으로 빌드하기

웹팩 실행

두 가지 방법으로 웹팩을 실행할 수 있습니다.

1) package.json의 script 추가

package.json 에 다음 코드를 삽입합니다.

{
  ...
  "scripts": {
    "dev": "webpack"
  },
  ...
}

그 후 다음처럼 실행합니다.

npm run dev

2) npx

혹은 다음 명령어로 바로 실행합니다.

npx webpack

 

이후 웹팩을 실행하면 dist 폴더 내에 하나의 통합 파일인 app.js가 생성됩니다.
이제 index.html에서 app.js를 불러와 실행할 수 있습니다!

 

4. webpack-dev-server, react-hot-loader

파일을 수정할 때마다 웹팩을 실행하기가 여간 귀찮은 게 아닙니다.
다음 두 패키지를 이용하면 편하게 로컬 서버를 제공해주고, 내 코드의 변경점을 감지하여 자동으로 업데이트해줍니다.

webpack-dev-server

webpack.config.js를 읽어 빌드하고, 로컬 서버를 제공합니다.

react-hot-loader

.jsx 파일이 수정될 때 자동으로 업데이트해주는 거 같은데 정확히는 모르겠습니다. 어느 정도 숙달이 됐을 때 자세히 알아보도록 하겠습니다.

npm 패키지 설치

다음 두 패키지를 개발용으로 설치해줍니다.

npm i -D react-hot-loader webpack-dev-server

기존 설정에서 변경점

package.json

scripts - dev를 다음과 같이 수정합니다.

"scripts": {
  "dev": "webpack-dev-server --hot"
},

client.jsx

3, 6, 8번째 줄이 변경되었습니다.

const React = require('react');
const ReactDom = require('react-dom');
const { hot } = require('react-hot-loader/root');

const YourComponent = require('./YourComponent');
const Hot = hot(YourComponent);

ReactDom.render(<Hot />, document.querySelector('#root'));

webpack.config.js

babel-loader 옵션의 plugin을 추가합니다. 21번째 줄을 확인해주세요.

module: {
    rules: [
      {
        test: /\.jsx?/,
        loader: 'babel-loader',
        options: {
          presets: [
            [
              '@babel/preset-env',
              {
                targets: {
                  browsers: ['> 5% in KR'],
                },
                debug: true,
              },
            ],
            '@babel/preset-react',
          ],
          plugins: [
            '@babel/plugin-proposal-class-properties',
            'react-hot-loader/babel',
          ],
        },
      },
    ],
  },

또한 output 속성에서 publicPath를 지정해주어야 웹팩 데브 서버가 해당 폴더에 app.js를 생성합니다.
이와 관련해서는 나중에 이해도가 높아지면 좀 더 공부해보도록 하고 일단은 하라는 대로 해보겠습니다.

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

 

 

모든 설정을 끝내고 로컬 서버로 접속하면 코드를 수정하고 저장할 때마다 브라우저 화면이 변경되는 것을 볼 수 있습니다.

 

728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함