Knowledge/React.js

[React.js] React Web Games - Multiplication Game (Webpack)

winCow 2021. 7. 19. 23:45

 

1. Webpack

웹팩은 여러 개의 .js, .jsx 파일을 하나의 .js 파일로 만들어 주는 역할을 한다. 웹팩의 설치 방법은 다음과 같다.

 

npm init

해당 폴더에서 npm을 실행시킨다. name, author, license 등을 적당히 입력하면 package.json 파일이 생성된다. 다시 npm을 통해 필요한 패키지를 설치하면 package.json이 업데이트된다.

 

npm i react react-dom

react와 react-dom을 설치한다.

 

npm i -D webpack-cli

webpack-cli를 설치하되, D 옵션(devDependencies)을 통해 개발 시에만 이를 사용하고, 실제 배포 시에는 사용하지 않는다는 옵션을 추가한다.

이렇게 react, react-dom, webpack-cli를 설치하면, 이것들이 기존의 Gugudan.html에서 작성했던 script 태그 안의 src 속성과 crossorigin 속성을 대체해 준다.

 

npm i -D @babel/core @babel/preset-env @babel/preset-react babel-loader

바벨 코어는 최신 문법으로 바꾸어 주는 기본적인 바벨 기능, preset-env는 사용자의 환경에 맞춰 주는 기능, preset-react는 JSX를 읽는 기능을 하며, 바벨 로더는 바벨과 웹팩을 연결해 주는 기능을 가지고 있다.

 

 

2. 파일 쪼개기: HTML

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>구구단</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="./app.js"></script>
  </body>
</html>

따라서 Gugudan.html에 작성했던 대부분의 코드는 다른 파일로 옮기고, index.html로 파일명을 변경한 뒤, 최소한의 코드만을 작성한다.

 

 

3. 파일 쪼개기: client.jsx

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

const GugudanWebpack = require("./GugudanWebpack");

ReactDom.render(<GugudanWebpack />, document.querySelector("#root"));

root 문서를 선택해 구구단 웹팩 컴포넌트를 렌더링할 cliend.jsx 파일을 위와 같이 만든다.

 

 

4. 파일 쪼개기: GugudanWebpack.jsx

const React = require("react");

const GugudanWebpack = () => {
  const [first, setFirst] = React.useState(Math.ceil(Math.random() * 9));
  const [second, setSecond] = React.useState(Math.ceil(Math.random() * 9));
  const [value, setValue] = React.useState("");
  const [result, setResult] = React.useState("");
  const inputRef = React.useRef(null);

  const onChangeInput = (e) => {
    setValue(e.target.value);
  };

  const onSubmitForm = (e) => {
    e.preventDefault();
    if (parseInt(value) === first * second) {
      setResult("정답: " + value);
      setFirst(Math.ceil(Math.random() * 9));
      setSecond(Math.ceil(Math.random() * 9));
      setValue("");
      inputRef.current.focus();
    } else {
      setResult("땡");
      setValue("");
      inputRef.current.focus();
    }
  };
  return (
    <>
      <div>
        {first} x {second} = ?
      </div>
      <form onSubmit={onSubmitForm}>
        <input ref={inputRef} onChange={onChangeInput} value={value} />
        <button>입력!</button>
      </form>
      <div id="result">{result}</div>
    </>
  );
};

module.exports = GugudanWebpack;

함수형 컴포넌트로 만들어 두었던, 기존 Gugudan.html에 작성되어 있던 script 부분을 따로 GugudanWebpack.jsx 파일로 만든다. 이 때, 필요한 패키지와 라이브러리는 컴포넌트 위에서 선언하고, 마지막에 해당 컴포넌트를 export하는 과정이 반드시 필요하다. 이러한 과정은 Node.js에서 사용하는 모듈 시스템인데, 이렇게 파일을 쪼개고 export, import를 하면, 필요한 부분에서 필요한 컴포넌트만을 사용할 수 있게 된다.

 

 

5. webpack.config.js

const path = require("path");
module.exports = {
  name: "Gugudan-setting",
  mode: "development",
  devtool: "eval",
  resolve: {
    extensions: [".js", ".jsx"],
  },

  entry: {
    app: ["./client"],
  },

  module: {
    rules: [
      {
        test: /\.jsx?/,
        loader: "babel-loader",
        options: {
          presets: [
            [
              "@babel/preset-env",
              {
                targets: {
                  browsers: ["last 2 chrome versions"],
                },
              },
            ],
            "@babel/preset-react",
          ],
          plugins: [],
        },
      },
    ],
  },

  output: {
    path: path.join(__dirname),
    filename: "app.js",
  },
};

webpack.config.js 파일은 webpack으로 합칠 파일들을 설정한다. 

먼저, path는 Node.js에서 경로를 쉽게 조작할 수 있도록 만든 설정이다. module.exports에 실제로 input과 output 될 파일들을 설정한다. name에는 해당 설정의 이름을 적고, mode에 development를 입력하면 개발자 모드가 된다. production을 입력하면 배포 모드가 된다. 또, devtool에는 eval을 입력하고, resolve의 extensions로 .js, .jsx를 전달하면, 엔트리 되는 파일들 중 해당 확장자가 포함된 파일이 있는지를 체크해 준다.

entry에는 출력을 위해 입력되어야 할 것들이 들어간다. app 배열에 들어있는 파일들이 합쳐져 새로운 파일을 만들어 낸다. 여기서는 client.jsx와 GugudanWebpack.jsx가 합쳐지는데, GugudanWebpack.jsx는 이미 client.jsx에서 import 되었으므로 생략했다.

module에는 적용할 모듈을 작성해 주는데, test에 전달한 정규표현식을 따라 .js, .jsx 파일에 바벨 로더에 따른 룰이 적용된다. 추가적인 옵션으로 미리 설치한 presets를 전달하면 된다. 특히, preset-env의 target으로 브라우저를 최적화할 수 있는데, 이를 통해 브라우저를 제한함으로써 불필요한 바벨의 설정을 방지하고 속도를 올릴 수 있다. 상세한 옵션은 https://github.com/browserslist/browserslist 페이지에서 확인할 수 있다.

presets 이외의 옵션으로, plugins를 전달할 수도 있는데, 이는 확장 프로그램과 같은 것으로, 웹팩의 공식 문서(

https://webpack.js.org/)에서 옵션의 종류를 확인할 수 있다.

output에는 path.join(__dirname)을 전달하는데, 이는 경로를 통합해 주는 역할을 한다. __dirname은 현재 폴더를 의미하고, 현재 폴더의 하위 폴더를 경로로 설정하려면 join의 두 번째 매개변수로 해당 폴더 명을 전달하면 된다. filename으로는 생성될 파일의 이름을 전달한다.

 

 

6. webpack 실행

위와 같이 모든 설정을 끝낸 후, 웹팩을 실행하면 filename에서 설정한 이름대로 파일이 생성된다.

npx webpack

npm run dev

웹팩을 실행할 때는 위와 같이 npx webpack을 실행하거나, npm run dev을 실행할 수 있다. 단, npm run dev을 실행하기 위해서는 미리 package.json의 scripts에 "dev": "webpack"를 전달해 주어야 한다.

 

 

7. require & import

Node.js의 모듈 시스템이다. export default Component를 통해 해당 컴포넌트를 다른 파일에서 사용할 수 있으며 이 때 import 'Component' from 'path'를 사용한다. 라이브러리를 사용할 때도 이를 이용한다. require도 마찬가지로 다른 파일을 불러올 때 사용한다.