Babel, Webpack 이제는 공부할 때다

진실·2022년 6월 14일
post-thumbnail

React, 너 어떻게 브라우저에서 동작하는데?

지금까지 리액트를 개발할 때는 CRA로 프로젝트를 생성하고, 거기서 react 코드만 작성하였다.

그런데 생각을 해보자. html + css + js 로만 개발할 때는 html 파일을 만들고 거기에 style tag로(혹은 link) css를, script tag로 javascript 파일을 인클루드 하였다. react의 index.html 그 어디를 봐도 내가 작성한 jsx 코드를 인클루드 하는 코드가 보이지 않는다. 개발자 도구를 띄워봐도, 내가 작성한 파일들이 로드 된 흔적은 어디에도 없다. 그러나 화면에서는 잘 동작한다. 뿐만 아니라 react hooks, jsx는 vanilla js가 아닌데 도대체 어떻게 작동을 하고 있는 것인가.

이게 무슨 일인가??????

...!!!!!! 그렇다. babel과 webpack이 알아서 잘 html 파일 하나로 바꿔줬기 때문이다.

얘네가 뭔데 그렇게 잘 바꿔주는가?

알아보자. 렛츠고 !!!@!

Babel

이를 이해하기 위해선 먼저 바벨을 알아야 한다.

왜 바벨이 필요한데?

여러분이 리액트로 개발을 했다. 리액트는 vannilla js가 아니다. react hook도 있고 jsx도 사용한다. 하지만 결국에 얘도 브라우저에서 렌더링이 돼야 한다. 즉, vanilla js로 바뀌어야 한다는 것이다.

IE에서는 es6 문법인 화살표 함수가 해석되지 못한다. 즉, ES5 문법으로 변환이 필요하다.

뿐만 아니라 필자가 사랑하는 typescript도 있다. typescript 문법 이거 누가 해석해주는데????

즉, 다양한 프레임워크에서 작성된 코드를 다양한 브라우저에서 렌더링 해야한다.
-> 이를 해주는 것이 바벨이다. 바벨 너 정말 멋지다!

transpile

a 파일에서 b 파일로 변환하는 것을 transpile이라고 한다. babel이 하는 짓이 transpile이다. compile과의 차이점은, compile은 high level에서 low level로 변환한다는 것이다. transpile은 변환 전 후의 파일의 레벨이 같다.
예를 들면 compile은 .c => .o이고, transpile은 .js => .js이다.

transpile의 세 단계

transpile은 세 단계로 나뉜다 : parsing, transforming, printing

parsing

Abstract Symentic Tree를 만들어서 코드를 파싱하는 과정이다.

transforming

진짜 변환이 이루어지는 곳이다.

printing

변환된 코드를 출력하는 단계다.

babel, 함 써보자!

npm i @babel/core를 하면 parsing, printing은 해준다.
유감이게도 transforming은 해주지 않는다. 그럼 이걸 누가 해주는데???

plugin을 설치합니다.(스스로 만들어도 됨.) 그리고 babel.config.js에서 plugin을 연결해주면 된다. 여기서는 자세한 usage까지는 설명하지 않겠다.

자주 사용되는 플러그인의 목록은 다음과 같다.

  • babel-plugin-block-scoping (let => var)
  • plugin-transform-arrow-function (화살표 함수 => 그냥 함수)

다만, 리액트 프로젝트 하나 만들면 연결해야 할 플러그인이 너어어어무 많다!!

"그래서 우리는 플러그인을 묶어 preset이라는 걸 만들어 사용합니다."

예를 들어 react를 trnaspile하는 플러그인에 대한 preset은 preset-react라고 이미 있다. 자주 사용되는 preset의 목록은 다음과 같다.

  • preset-env : ESMA Script 2015+ 변환
  • preset-flow : flow 변환
  • preset-react : react 변환
  • preset-typescript : ts 변환

다만, babel은 지가 바꿀 수 있는 것만 바꾼다. es6의 promise라는 개념은 es5에 아예 존재하지도 않았으므로 어떻게 바꿀 수가 없다. 따라서 이럴 때는 polyfill까지 사용해야 한다. polyfill에 대해서는 자세히 다루지는 않겟다.

webpack

후... 이렇게 숨차게 babel이 뭔지 알아봤다. babel로 브라우저가 인식할 수 있는 js로 어케 잘 바꾼다는 것 같다. 하지만 아직도 우리의 의문은 해결되지 않았다. 내가 열심히 작성한 코드가 왜 네트워크 탭에서 안 보이는 것인가??

but. 네트워크 탭을 다시 한번 봐보자. bundle 어쩌구 js 파일이 보일 것이다. 그렇다...!!! 내가 작성한 모든 js(혹은 ts) 코드는 이 bundle 파일에 들어간 것이다.

왜 bundle.js에 합치는데?

님들이 작성한 코드를 생각해보시라. 일단 파일의 개수가 적지 않을 것이다. 그리고 수많은 복잡한 의존관계를 포함한다. 이 많은 파일들을 전부 가져와서 브라우저에서 의존 관계를 resolve 할 수 없다. 애초에 import, require 등의 문법은 브라우저가 모른다. 노드 기반 프레임워크에서만 동작할 수 있다. 그렇기에 우리는 작성한 코드를 하나의 파일에 합치고 (bundling) 이걸 해 주는 게 webpack이다.

webpack의 구성 요소

const port = process.env.PORT || 3000
const HtmlWebpackPlugin = require("html-webpack-plugin")

module.exports = {
  mode: "development",
  entry: "./src/index.tsx", // 번들링을 시작할 js 파일의 위치
  output: {
    filename: "bundle.[hash].js", // 번들링 결과 생성된 js 파일이 저장될 경로
  },
  module: {
    rules: [
      // babel loader
      {
        test: /\.(js|jsx)$/, // .js, .jsx 파일에 대해
        exclude: /node_modules/, // node_modules는 transpile하지 않음.
        use: {
          loader: "babel-loader",
        },
      },
      // html loader
      {
        test: /\.html$/, // .html파일에 대해
        use: [
          {
            loader: "html-loader",
            options: {
              minimize: true,
            },
          },
        ],
      },
      {
        test: /\.tsx?$/, // .tsx 파일에 대해
        use: "ts-loader",
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "public/index.html", // public/index.html를 template으로 지정
    }),
  ],
  devServer: {
    host: "localhost",
    port: port,
    open: true,
  },
  resolve: {
    extensions: [".tsx", ".ts", ".js"],
  },
}

webpack을 사용하기 위해선 entry, output, loader, plugin 이렇게 네 가지를 정의해줘야 한다.

  • entry : c에서 main함수처럼, 코드의 시작점이 되는 파일의 경로
  • output : bundling 결과 생성된 파일을 저장할 경로
  • loader : 기본적으로 webpack은 js, json만 번들링 가능하므로 기타 이미지, css loader에 대한 정의
  • plugin : 기타 툴들

얘네를 webpack.config.js에 정의해주면 이제 webpack을 사용할 수 있게 된다.

정리

한 마디로 요악하자면, babel이 브라우저가 알아들을 수 있게 코드를 transpile하고, 이 transpile된 파일들을 webpack이 합친다.

이상으로 babel과 webpack의 기본 개념을 알아보았다.

그럼 안녕~

profile
반갑습니다.

0개의 댓글