TIL - Webpack

김수지·2020년 3월 18일
0

TILs

목록 보기
31/39

Today What I Learned

Javascript를 배우고 있습니다. 매일 배운 것을 이해한만큼 정리해봅니다.
오늘은 Webpack에 대해 정리해봅니다.


얼마 전 어떤 CTO 분을 만나 개발자로서 앞으로 익혀야 할 것들을 자세히 들을 수 있는 시간이 있었다. 이 때 cra - eject 방식 말고 webpack 설정 경험에 대한 질문을 받았는데, 일전에 튜토리얼만 쓱쓱 따라해본 경험 뿐이라 자세히 이야기를 나눌 수 없었다. 이참에 한 번 더 webpack 기본 설정에 대해서 정리해보려고 한다.

1. What is Webpack?

  • 기본적으로 웹에서는 html dom을 이용하여 데이터를 띄운다. html에서 자바스크립트로 작성한 코드에 해당하는 부분은 <script> 태그를 이용해 불러오고 실행하는데, 렌더시켜야 하는 코드가 여러 개가 있을 경우 곧이 곧대로 script를 붙여서 렌더시킨다고 하면 로딩 과정에서 무리가 있고(병목현상), 또 어마어마한 양의 script를 복붙해야 한다.
    즉 불편하고, 오류 발생 가능성도 많은 데다가 사용자 친화적이지도 않다. 그래서 내부적으로 작성한 코드를 1개 파일로 모아서 dom으로 띄우는 과정(bundle)이 필요하다.
  • 바로 이 '하나의 js 파일로 모으는 역할'을 하는 것이 webpack이다.
  • Webpack : 서로 의존적인 관계에 있는 여러 개의 자바스크립트 파일을 한 번에 합쳐서 하나의 자바스크립트 파일로 만들어 주는 도구.
    webpack에서 babel도 적용할 수 있고, 빌드 시 콘솔 로그처럼 불필요한 것들을 제거하거나 css 파일을 번들링하는 등의 추가 작업도 함께 설정할 수 있다.
  • cf) Babel : a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.
    (급 공식페이지에서 퍼옴. 'es2015 이상의 문법을 구버전 브라우저나 환경에 맞춰 이전 버전의 문법체계로 바꿔주는 도구들'이라고 자체 해석하고 바벨도 나중에 til로 한 번 정리해야겠다)

2. How to build React with Webpack

  • react는 jsx라는 문법을 사용한다. 마치 js 코드에 html 태그를 섞어 쓴 듯한 모양을 하고 있기 때문에 이를 빌드할 때에는 바벨과 웹팩을 통해 jsx와 같은 실험적인 문법 구조를 js로 변환시키고 html dom에 띄우기 위해 번들링하는 작업이 필요하다. babel과 webpack이 모두 필요하다는 말.

  • 물론 이 과정은 create react app이라는 과정을 통해 자동으로 설정할 수 있다. 보통 react 코드들은 cra를 통해 빌드를 하고, eject한 후부터는 자체 설정에 의해 관리하는 경우가 많다고 한다. 이럴 때 cra 과정에서 어떤 작업을 대체하는지 알고 있어야 설정에 변화를 주거나 잘 운영할 수 있다.

  • 웹팩 공식문서ZeroCho님의 유튜브 강좌를 번갈아 가면서 확인하고 파일을 만들어봤다.

  • 예제 코드 전체 보기 : https://github.com/naseriansuzie/react-webpack-test

  • 과정은 크게 npm 설정 후 > 웹팩을 설정하고 > 마지막으로 변경 감지 시 자동 빌드 설정을 하는 것으로 나누어 보았다.

1. npm 설정과 component, html 파일 작성

  • 가장 먼저 폴더를 생성하고, 해당 폴더에서 npm init을 하고 package.json을 설정한다.

    mkdir react-webpack-test
    cd react-webpack-test
    npm init
  • 그런 다음 react와 react-dom을 dependency로 설치한다.

    npm i react react-dom
  • webpack과 webpack-cli를 devdependency로 설치한다.

    npm i -D webpack webpack-cli
  • Webpack으로 번들링하기 위해서는 터미널 창에 webpack을 쳐줘야 하는데 cli가 global로 되어 있지 않은 이상 command not found가 나올 것이다. 대신에 1) script를 직접 짜서 해당 script를 돌리거나 2) npx의 도움을 받아야 한다.

    • package.json에서 script를 추가 시,
    "script" : {
      "dev" : "webpack"
    }
    • 터미널 창에서 npx 이용 시,
    npx webpack
  • 이렇게 하면 기본적인 패키지는 설정한 셈이다.

  • 번들링 후 렌더시킬 html 파일을 하나 만들고 <div id="root></div>를 body 태그 안에 넣어둔다. 나중에 여기에 전체 번들 파일을 넣을 것이므로...

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Test</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="../dist/bundle.js"></script>
  </body>
</html>
  • 루트 컴포넌트 준비: 나는 app.jsx에 Hello라는 컴포넌트를 담는 초간단 구조를 준비했다.

    //Hello.jsx
    import React from "react";
    const Hello = () => <div>hello</div>;
    export default Hello;
    
    //app.jsx
    import React from "react";
    import { render } from "react-dom";
    import Hello from "./Hello";
    render(<Hello />, document.querySelector("#root"));

2. webpack config 설정

  • 이제 webpack의 설정을 해 줄 차례이다. 가장 중요+복잡+신기한 부분 :)

  • 폴더의 루트에서 webpack.config.js 파일을 만든다.

  • node의 common js 모듈에 따라서 module.exports를 설정하면서 객체 선언을 한다.

    const path = require('path');
    
    module.exports = {
     name: 'react with webpack setting',
     //어떤 것에 대한 웹팩 설정인지 제목 작성
     mode: 'development',
     // 개발모드 때는 development, 실제는 production
     devtool: 'eval',
     // production에서는 'hidden-source-map'을 많이 씀
     reslove: {
       extensions: ['.js', '.jsx'],
       // 번들링 할 파일들의 확장자 종류를 배열에 나열
     },
    
     entry : {
       app: ["./app", "./Hello"],
       // 번들링 할 파일들을 지정. 루트 파일 하나만 지정해도 문제 없음
     },
    
     output : {
       path: path.resolve(__dirname + 'dist'),
       //번들링 한 파일을 위치할 곳 명시
       publicPath: '/dist',
       //가상 주소처럼 지정, webpack-dev-server 사용 시 필요
       filename: "bundle.js",
       //번들한 파일 이름 지정
     }
    };
  • 기본적인 구조는 entry가 번들되어 output이 되는 구조인 것을 볼 수 있다. 여기에 일부 설정들을 추가해주는데 moduleplugins에 추가해주면 된다.

  • 이 때 사용할 babel을 먼저 설치해야 한다.

    • @babel/core : 기본적인 바벨 설정이 담김
    • @babel-preset-env : 브라우저 환경에 맞게 옛날 문법을 지원하는 역할
    • @babel-preset-react : jsx와 같이 react에서 사용하는 설정을 트랜스파일링 하는 역할
    • babel-loader : babel과 webpack을 연결하는 역할
      npm i -D @babel/core @babel-preset-env @babel-preset-react babel-loader
  • 다시 webpack.config.js로 가서 module 설정을 완료해준다.

      const path = require('path');
    
      module.exports = {
      name: 'react with webpack setting',
      //어떤 것에 대한 웹팩 설정인지 제목 작성
      mode: 'development',
      // 개발모드 때는 development, 실제는 production
      devtool: 'eval',
      // production에서는 'hidden-source-map'을 많이 씀
      reslove: {
        extensions: ['.js', '.jsx'],
        // 번들링 할 파일들의 확장자 종류를 배열에 나열
      },
    
      entry : {
        app: ["./app", "./Hello"],
        // 번들링 할 파일들을 지정. 루트 파일 하나만 지정해도 문제 없음
      },
    
      module : {
        rules : [{
          test: /\.jsx?/,
          // 규칙을 적용할 파일 종류를 설정
          loader: "babel-loader",
          options: {
            // babel 설정
            presets: [
              // preset(plugin들의 모임)을 나열
              ["@babel/preset-env", {
                // 특정 preset에 대해 설정을 지정할 수 있음
                targets : {
                  browsers: ["> 5% in KR"]
                  // 어떤 브라우저에 대응할지를 명시
                },
                debug: true
              }], "@babel/preset-react"
            ]
          }
        }]
      },
        
      output : {
        path: path.resolve(__dirname + 'dist'),
        //번들링 한 파일을 위치할 곳 명시
        publicPath: '/dist',
        //가상 주소처럼 지정, webpack-dev-server 사용 시 필요
        filename: "bundle.js",
        //번들한 파일 이름 지정
      }
    };
  • 이렇게 복잡하지만 babel과 webpack을 이용해 설정을 완료할 수 있다.

  • 그런 다음 초기에 설정해두었던 npx webpack이나 npm run dev script를 통해 리액트를 빌드할 수 있다.

  • 이렇게 cra 과정을 대신해서 webpack으로 react를 build해서 사용할 수 있다. 사용하다가 여러 수정사항이나 업데이트가 나올 때마다 해당하는 내용을 webpack.config.js에 반영하면 된다.

3. webpack dev server, react hot loader 설정

  • node에서 nodemon 없이 서버 수정 작업을 하다 보면 수시로 서버에 오류는 없는지, 변경 사항이 반영되었는지 확인을 하는 것이 어려운 것처럼 현재 빌드한 react에서도 변경사항이 있을 때마다 계속 webpack을 통해 번들링을하고 빌드를 해야 한다.

  • 무척 귀찮은 작업이므로 nodemon처럼 webpack-dev-server와 react-hot-loader를 설정하면 빌드한 내용을 개발 서버에서 수행하며 변경을 감지할 때마다 바로 view에서 확인할 수 있다.

  • 이를 위해서 2개 패키지를 설치해야 한다.

    npm i -D webpack-dev-server react-hot-loader
  • packagejson 파일에서 script를 수정한다. 나는 dev server & hot loader를 지정했을 때와 그렇지 않을 때 비교를 해보기 위해 다른 script를 추가했다.

    "script" : {
      "dev" : "webpack",
      "dev-hot" : "webpack-dev-server --hot"
    }
    
  • Reactdom에 렌더시킬 루트 컴포넌트 파일에서 react-hot-loader/root에서 hot을 꺼내 컴포넌트에 씌운다.

 import React from "react";
 import { render } from "react-dom";
 import { hot } from "react-hot-loader/root";
 import Hello from "./Hello";

 const Hot = hot(Hello);
 render(<Hot />, document.querySelector("#root"));
  • 터미널에서 npm run dev-hot를 치면 https://localhost:8080에서 빌드된 리액트 뷰를 볼 수 있고, 변경사항이 발생할 때마다 계속 터미널 창에서 감지하는 것을 볼 수 있다. 나는 html을 public 폴더 아래에 위치해서 https://localhost:8080/public에서 아래와 같은 화면을 볼 수 있었다.

  • 이렇게 webpack 기본 설정을 마쳐본다. 복잡했지만 논리를 깨치게 되어 만족스럽다 :)
profile
선한 변화와 사회적 가치를 만들고 싶은 체인지 메이커+개발자입니다.

0개의 댓글