[webpack] webpack으로 react + typescript + babel + husky 개발 환경 구축하기

Gyuhan Park·2024년 7월 9일
1

react

목록 보기
4/4

💭 TMI

CRA를 쓰다가 vite가 생긴 이후로 더더욱 빌드 환경을 직접 건드리는 경우가 없어졌는데, webpack을 사용해야하는 상황이 되었다. 사실 webpack이 근본(?)있는 모듈 번들러이기 때문에 공부할 필요성을 느꼈는데 동기부여가 좀 부족했기도 했고, webpack 쓸 줄 아냐고 물어보면 머뭇거리게 된다. 내 생각에 webpack을 제대로 이해해야 번들러를 이해했다고 할 수 있다. 이번 기회에 webpack 쓸 줄 아는 사람이 되어보자. 시간이 없다면 마지막 설정 부분만 추가하여도 된다.

🎀 webpack

[ webpack 핵심 5가지 ]

  • entry : webpack이 내부의 디펜던시 그래프 를 생성하기 위해 사용해야 하는 모듈 (진입점)
    • 엔트리 포인트가 (직간접적으로) 의존하는 다른 모듈과 라이브러리를 찾아냄
    • 기본값은 ./src/index.js
  • output : 번들을 내보낼 위치와 파일 이름을 지정하는 방법을 webpack에 알려주는 역할
    • 기본 출력 파일의 경우에는 ./dist/main.js로 , 생성된 기타 파일의 경우에는 ./dist 폴더로 설정
  • loader : webpack이 JS와 JSON 파일 외에 다른 유형의 파일을 처리할 때 사용
    • 다른 유형의 파일들을 유효한 모듈로 변환하여 사용하거나 디펜던시 그래프에 추가
    • 변환이 필요한 파일(들)을 식별하는 test 속성
    • 변환을 수행하는데 사용되는 로더를 가리키는 use 속성
  • plugin : 번들 최적화, 애셋 관리, 환경 변수 주입 등 광범위한 작업 수행
    • require ()를 통해 플러그인을 요청하고 plugins 배열에 추가
  • mode : development, production, none 중 설정하여 webpack에 내장된 환경별 최적화 활성화
    • 기본값은 production

📘 webpack 빌드 환경 구축하기

webpack으로 파일을 빌드할 수 있는 환경을 만들어보자.

webpack.config.js 파일을 루트 디렉토리에 생성하여 webpack 설정을 커스텀할 수 있다. 파일이 없어도 동작하지만 모두 기본값으로만 동작하기 때문에 추가적인 설정이 필요한 경우 파일을 생성한다. 또한 webpack을 cli 환경에서 실행하기 위해 webpackwebpack-cli 를 설치한다. webpack 4.0 이상부터 cli를 추가로 설치해야 하며, npm 스크립트를 통해 node_modules에서 webpack을 찾아 실행한다.

$ npm i -D webpack webpack-cli
// webpack.config.js
const path = require("path");

module.exports = {
  entry: "./src/test.js",
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname + "/dist"),
  },
  mode: "none"
};

package.json은 기본 설정값으로 생성하고, build 스크립트를 추가한 후 build를 실행하면 bundle.js 파일이 생긴 것을 확인할 수 있다.

$ npm init -y
// package.json
{
  "scripts": {
    "build": "webpack"
  },
}
$ npm run build
asset bundle.js 113 bytes [emitted] (name: main)
./src/test.js 29 bytes [built] [code generated]
webpack 5.92.1 compiled successfully in 88 ms

📘 webpack으로 HTML 빌드하기

위에서 빌드 환경을 구축하였다. 우리의 최종 목표는 React 개발 환경 구축이다. React 개발 환경을 생각해보면 아래와 같은 index.html을 불러오고, script 태그로 컴포넌트들을 불러왔다. 따라서, HTML을 불러올 수 있어야 한다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

하지만 webpack은 기본적으로 JavaScript와 JSON 파일만 이해할 수 있기 때문에, HTML을 문자열로 내보내는 html-loader 를 통해 HTML 파일을 webpack이 이해할 수 있다. options 으로는 minimize 라는 코드 최적화 옵션을 추가했는데, 추가하고 빌드 후 HTML 파일을 확인하면 줄바꿈이 없어져 한줄로 표현된 것을 볼 수 있다.

html-webpack-plugin은 생성된 모든 번들을 자동으로 삽입하여 HTML 파일을 생성한다. plugin 만 적용하면 HTML 파일이 그대로 output으로 나오는데, 그 파일에서 오류가 발생해도 빌드 오류가 나지 않는다. 반대로 loader만 적용하면 해석할 수 있도록 처리했는데 해석할 파일을 주지 않는 셈이므로 빌드 결과로 HTML 파일이 나오지 않는다.

따라서 html-loader라는 loader와 html-webpack-plugin 이라는 plugin을 적용하여 HTML 파일을 읽을 수 있게 되었다.

npm i -D html-webpack-plugin html-loader
// webpack.config.js
const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  ...,
  module: {
    rules: [
      {
        test: /\.html$/,
        use: [
          {
            loader: "html-loader",
            options: { minimize: true }
          }
        ]
      }
    ]
  },
  plugins: [
    new HTMLWebpackPlugin({
      template: "./index.html", // 읽을 파일명
      filename: "./index.html", // output으로 출력할 파일명
    }),
  ],
};

📘 webpack으로 React 빌드하기

위에서 작업한 내용으로 HTML 파일을 읽을 수 있으며, script 태그로 불러오는 JS 파일을 불러올 수 있다. 하지만 React 컴포넌트를 사용하기 위해선 js 문법 그대로가 아닌 React의 규칙대로 코드가 변경되어야 한다. React 에서 사용하는 JSX 문법을 JS로 트랜스파일하기 위해 babel 을 사용해야 한다. @babel/preset-react 를 사용하지 않고 render()를 실행하려고 하면 오류가 발생하는데, JSX 문법 을 해석할 수 없어서 발생하는 오류임을 알 수 있다.

$ npm i -D @types/react @types/react-dom @babel/preset-env @babel/preset-react babel-loader
$ npm i react react-dom
// src/index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
// .babelrc
{
  "presets": [
    "@babel/preset-env",
    ["@babel/preset-react", { "runtime": "automatic" }]
  ]
}
// webpack.config.js
const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  ...,
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ["babel-loader"],
      }
    ],
  },
};

🚨 JSX 파일 빌드하기

babel로 jsx 문법을 js로 변환하는 것과는 별개로, jsx 확장자를 사용한다면 resolve 할 수 없다는 오류가 발생한다. webpack은 앞에서 말했듯이 JavaScript와 JSON 파일만 이해할 수 있기 때문이다. 그래서 설정을 통해 resolve할 때 확인하는 확장자를 추가로 설정할 수 있다.

module.exports = {
  resolve: {
    extensions: [".js", ".jsx"],
  },
  ...
};

📘 webpack으로 css 빌드하기

위에 설정만으로도 React 개발을 진행할 수 있다. 하지만 reset.css 같은 css 파일을 추가할 경우도 존재하는데, 현재는 webpack이 css 파일을 이해하지 못한다. css-loader 를 활용하여 css 파일을 webpack이 읽을 수 있도록 한다.

$ npm i -D css-loader
// webpack.config.js
module.exports = {
  module: {
    rules: [
      ...
      {
        test: /\.css$/,
        use: ["css-loader"],
      },
    ],
  },
};

하지만, build가 완료된 index.html 파일을 열어보면 css 적용 ❌
css 파일을 읽은 후 어딘가에 저장해야 적용할 수 있음

🚨 css를 index.html에 합치기 vs 별도의 css파일로 추출

  • style-loader : development 환경에서 사용 권장
    • injects CSS into the DOM using multiple하기에 css파일을 추출하는 것보다 더 빠르다.
  • MiniCssExtractPlugin : production 환경에서 사용 권장
    • css파일을 추출하게 되면 css파일과 js파일을 parallel load할 수 있어 사용자가 페이지를 빠르게 load할 수 있다.

use에 있는 loader 순서는 오른쪽에서 왼쪽 순서로 실행 된다.
css-loader로 css 파일을 읽고, style-loader로 DOM에 css를 주입한다.

// webpack.config.js
module.exports = {
  module: {
    rules: [
      ...
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

📘 webpack으로 ts 빌드하기

마지막으로 타입스크립트까지 적용해보려고 한다. 앞에서 설명한 것처럼 .ts, .tsx 확장자를 resolve 하기 위해 설정에 추가해줘야 한다. 그리고 타입스크립트를 webpack이 이해하기 위해 ts-loader 를 사용해야 하며, ts-loader가 typescript를 load하기 위해 typescript를 설치해야 한다.

$ npm i -D ts-loader typescript
// webpack.config.js
module.exports = {
  module: {
	  resolve: {
			extensions: [".js", ".jsx", ".ts", ".tsx"],
	  },
    rules: [
      ...
      {
        test: /\.(ts|tsx)$/,
        use: "ts-loader",
        exclude: /node_modules/,
      },
    ],
  },
};

typescript를 트랜스파일하기 위해 tsconfig.json 파일이 필요하다. 새로운 JSX 변환 방식(React 17+)으로 jsx를 사용하기 위해"jsx": "react-jsx" 를 추가하였고, default export하는 라이브러리를 가져오기 위해 "allowSyntheticDefaultImports": true 를 추가하였다.

{
  "compilerOptions": {
    "target": "ESNext", // 코드의 변환 대상 ECMAScript 버전을 최신 버전으로 지정
    "module": "ESNext", // 최신 ECMAScript 버전 모듈 시스템을 타겟으로 컴파일
    "moduleResolution": "node", // TypeScript가 모듈을 해석하고 처리하는 방식 지정
    "outDir": "./dist", // 컴파일된 파일이 저장될 출력 디렉토리 지정
    "noImplicitAny": true, // 암시적 any를 허용하지 않음
    "strict": true, // 엄격한 타입 검사
    "jsx": "react-jsx", // 새로운 JSX 변환 방식(React 17+)을 사용하기 위해 필요
    "jsxImportSource": "@emotion/react", // React의 jsx()함수가 아니라 Emotion의 jsx()함수를 대신 사용
    "allowSyntheticDefaultImports": true, // default export 가 없어도 import 허용
    "sourceMap": true, // 디버깅 시 어떤 파일에서 에러났는지 추적 용이
  },
}

tsconfig.json 에서 "jsx": "react-jsx" 를 추가하면 babel을 설정하지 않아도 jsx를 해석할 수 있다. 처음에는 ts-loader 의 부가 기능인줄 알았는데, 생각해보니 타입스크립트는 원래 자바스크립트로 트랜스파일하여 실행한다.

그럼 언제 트랜스파일이 될까?

ts-loader는 tsc를 사용해 트랜스파일을 진행하고, tsconfig.json 설정을 따른다고 한다.

✅ ts-loader vs babel-loader

webpack으로 TypeSciprt를 다루는 방법은 2가지가 있다.

  1. ts-loader : TS → JS 트랜스파일 + 타입 체크. But, 타입 체크로 인해 빌드 속도 느림
  2. babel-loader + @babel/preset-typescript : TS → JS 트랜스파일 + 타입 체크 ❌. But, 빌드 속도 빠름

개발 환경에서는 빌드 단계에서 오류를 미리 방지하기 위해 타입 체크가 필요하기 때문에 ts-loader를 사용하고, 프로덕션 환경에서는 이미 타입 체크가 되어 있으며, ci 환경에서 빠르게 빌드하고 babel-loader로 polyfill을 제공할 수 있기 때문에 프로덕션 환경에서 사용하는 것이 적절하다고 판단할 수 있다.

근데, 타입 체크를 한다고 그렇게 빌드 속도가 차이날까?

🚨 속도 비교

그래서 파일은 거의 없지만 속도를 테스트해보기로 했다. 크게 차이 안나면 타입 체크를 해주는 ts-loader를 사용할 생각으로 테스트를 진행하였다.

babel-loader + @babel/preset-typescript

babel-loader + @babel/preset-typescript + @babel/preset-react 로 빌드했을 때 1초 내외로 빌드되는 것을 확인할 수 있다.

코드빌드 결과

ts-loader

ts-loader로만 빌드할 경우 약 2초정도 걸리는 것을 확인할 수 있다.

코드빌드 결과

ts-loader + ForkTsCheckerWebpackPlugin

ForkTsCheckerWebpackPlugin 를 사용하면 ts-loader options에 transpile:true가 자동으로 들어가 컴파일과 번들링만 빨리 실행하고, 타입 체크는 따로 실행할 수 있다. 플러그인을 적용하면 타입체크도 하고, 1.6초가 걸리는 것을 확인할 수 있다.

코드빌드 결과

속도를 비교해본 결과, 플러그인을 사용해도 1.6배 정도 차이나는 것을 확인할 수 있다. 따라서, ts-loader + ForkTsCheckerWebpackPlugin 는 개발 환경, babel-loader는 프로덕션 환경에 분리해서 적용하는 게 효율적이라고 판단하였다.

📘 webpack으로 image 빌드하기

일단 image를 빌드하기 전에 tsx로 설정하였다면 모듈 또는 해당 형식 선언을 찾을 수 없습니다. 라는 오류가 발생한다. 이것은 타입스크립트가 이미지 확장자를 읽지 못해서인데, custom.d.ts 파일을 만들고 타입을 declare해주면 된다. 만들어도 인식이 안된다면 tsconfig.json의 include 범위를 확인해보자.

// custom.d.ts
declare module "*.jpg";
declare module "*.png";
declare module "*.jpeg";
declare module "*.gif";
declare module "*.svg";
// src/App.tsx
import TEST from "./assets/images/test.jpg";

const App = () => {

  return (
			...
      <img src={TEST} width={100} />
  );
};

타입 에러는 사라졌지만 build 시 오류가 발생하는데, 이미지를 빌드하기 위해선 file-loader 를 사용해야 webpack이 이해할 수 있다.

module.exports = {
  ...
  module: {
    rules: [
	  ...,
      {
        test: /\.(png|jpe?g|gif)$/i,
        use: [
          {
            loader: "file-loader",
            options: {
              name: "[path][name].[ext]",
            },
          },
        ],
      },
    ],
  },
};

📘 webpack-dev-server 적용하기

개발환경은 모두 구축했는데 소스코드를 수정할 때마다 웹팩으로 직접 빌드해야 확인할 수 있는 게 너무 불편하다.
webpack-dev-server : 소스코드를 수정할때마다 알아서 webpack이 빌드해주는 도구
소스코드 수정 후 저장하면 webpack이 자동으로 빌드하고, 브라우저 화면도 수정된 코드가 적용된다. (HMR)
static을 설정하지 않으면 output 을 기준으로 경로가 설정된다.
소스코드를 수정 후 새로고침을 하지 않더라도 webpack-dev-server 에서 HMR을 기본으로 지원해주기 때문에 브라우저에 바로 반영된다.

webpack-dev-server v4.0.0부터 Hot Module Replacement가 기본적으로 활성화되어 있습니다.
https://webpack.kr/configuration/dev-server/#devserverhot

$ npm i -D webpack-dev-server
// webpack.config.js
module.exports = {
  devServer: {
    port: 3000
  },
  ...
}
// package.json
{
  "scripts": {
    "start": "webpack serve --config webpack.config.js"
  },

📘 babel

@babel/core

  • 바벨이 작동하기 위한 핵심 기능 존재
    • 입력 소스 코드를 가져와 파싱하여 AST(Abstract Syntax Tree) 생성
    • 생성한 AST를 필요한 형태의 AST로 변환
    • 변환한 AST로 출력 소스 코드 생성

@babel/cli

  • 터미널의 명령어 인터페이스를 통해 컴파일 가능
  • 공식 문서에서는 관리의 용이성을 이유로 프로젝트별로 로컬에 설치하는 것을 권장

@babel/preset-env

  • 환경에 대한 구문 변환 설정을 쉽게 설정하고 관리 가능
  • 바벨을 설정할 때 플러그인이 없으면 ES6문법을 ES5로 바꿔주는 것과 같은 변환 작업 ❌
  • preset-env 없이 필요한 플러그인만 설치도 가능
    • ES6의 화살표 함수를 ES5 구문으로 변환 : @babel/plugin-transform-arrow-functions 플러그인

polyfill

polyfill : 브라우저에서 지원하지 않는 코드를 사용 가능한 코드 조각이나 플러그인으로 변환한 코드

최신 문법은 구형 브라우저에서 동작하지 않을 수 있다. 이때는 최신 문법을 구형 브라우저에서도 동작하는 코드로 변환한 polyfill 을 제공해야 한다.

여러가지 방법으로 제공할 수 있는데, 해당 블로그에 따라 전역 스페이스 오염 문제와, 바벨 런타임 플러그인의 인스턴스 메소드 문제를 모두 해결한 core-js 를 사용하였다.
target을 ie 8로 하고 빌드하면 빌드 파일의 라인 수가 증가하는 것으로 적용된지를 확인할 수 있다.

$ npm i -D core-js

.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": "> 2%, not dead",
        "useBuiltIns": "usage",
        "corejs": "3.37",
        "shippedProposals": true
      }
    ],
    "@babel/preset-typescript",
    ["@babel/preset-react", { "runtime": "automatic" }]
  ]
}

📘 husky

husky 는 .git 디렉토리와 같은 디렉토리에 있어야 한다. .git 에서 git 관련 데이터를 모두 관리하고 있고, 커밋이나 푸시 모두 .git 디렉토리 정보를 바탕으로 처리되기 때문이다. 하지만 현재 디렉토리 구조상 루트 디렉토리에서 .git 이 관리되며, 하위 디렉토리인 frontend 에 package.json이 존재하므로 추가 처리가 필요하다. husky가 최근에 9버전으로 버전업되면서 래퍼런스가 별로 없었지만 릴리즈 노트를 통해 바뀐 부분만 수정하여 처리하였다.

commit-msg

팀에서 정한 git convention 에 따라 허용하는 prefix를 지정 → ALLOWED_PREFIXES
브랜치명을 {prefix}/#{issue_number} 로 설정하므로 브랜치명에서 이슈 번호 추출 → ISSUE_NUMBER
prefix와 postfix 를 체크하여 팀에서 정한 컨벤션을 지켰는지 확인하고, 지켜지지 않을 경우 커밋을 취소한다.

COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat $1)

# 허용하는 commit prefix
ALLOWED_PREFIXES="^(feat|fix|refactor|build|docs|chore|test|style|design|init): "

# 현재 브랜치명
CURRENT_BRANCH=$(git branch --show-current)

# 브랜치명에서 이슈 번호 추출. 브랜치명 : {prefix}/#{issue_number}
ISSUE_NUMBER=$(echo $CURRENT_BRANCH | sed -n 's/.*#\([0-9]*\).*/\1/p')

if ! echo "$COMMIT_MSG" | grep -Eq "$ALLOWED_PREFIXES"; then
  echo "Error: Commit message does not follow the convention."
  echo "Allowed prefixes: feat:, fix:, refactor:, build:, docs:, chore:, test:, style:, design:, init:"
  exit 1
fi

if ! echo "$COMMIT_MSG" | grep -q "#$ISSUE_NUMBER"; then
  echo "Error: Commit message does not contain the issue number #$ISSUE_NUMBER."
  exit 1
fi

pre-commit

lint-staged : staged된 파일에 대해서만 lint를 실행하는 도구
현재 변경된 파일(staged)만 lint를 실행하기 위해 해당 도구를 사용한다.

cd frontend && npx lint-staged

pre-push

eslint와 prettier를 commit할 때 잡더라도 타입 에러나 빌드 에러는 잡아주지 않는다. 따라서 원격 저장소에 push하기 전에 빌드하여 에러를 미리 확인할 수 있도록 처리한다.

cd frontend && npm run build-dev

package.json

prepare 는 npm 에서 자체적으로 제공하는 스크립트 명령어 중 하나다.
처음 프로젝트를 로컬에 클론받고 npm install 을 실행할 때 자동으로 함께 호출된다.
해당 명령어로 husky 가 동작하기 위해 필요한 초기 설정 파일들을 설치한다.

{
	...
  "scripts": {
    "prepare": "cd .. && husky frontend/.husky",
  },
  "devDependencies": {
    "husky": "^9.0.11",
    "lint-staged": "^15.2.7",
 
  },
  "lint-staged": {
    "**/*.{ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ]
  },
}

📘 결론

webpack으로 React 개발환경을 구축해보았다. 확실히 직접 구축해보니 webpack 핵심 기능들이 각각 어떤 기능들을 하는지 이해할 수 있었고, 이해를 바탕으로 추후에 커스텀할 수 있을 것 같다. 해당 개발환경으로 js, jsx, ts, tsx, css, html, 이미지 파일까지 빌드가 가능하다.

✅ 패키지 설치

npm i react react-dom
npm i -D @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript @types/react babel-loader css-loader html-loader html-webpack-plugin style-loader ts-loader typescript webpack webpack-cli webpack-dev-server core-js husky lint-staged

✅ 디렉토리 구조

📦Project
 ┣ 📂dist
 ┣ 📂src
 ┃ ┣ 📜App.tsx
 ┃ ┗ 📜index.js
 ┣ 📜.babelrc
 ┣ 📜.gitignore
 ┣ 📜index.html
 ┣ 📜package-lock.json
 ┣ 📜package.json
 ┣ 📜style.css
 ┣ 📜tsconfig.json
 ┗ 📜webpack.config.js 

✅ webpack.config.js

const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/index.tsx",
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname + "/dist"),
  },
  devServer: {
    port: 3000,
  },
  mode: "development",
  resolve: {
	extensions: ['.js', '.jsx', '.ts', '.tsx'],
	alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  module: {
    rules: [
      {
        test: /\.html$/,
        use: [
          {
            loader: "html-loader",
            options: { minimize: true },
          },
        ],
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(ts|tsx)$/,
        use: "ts-loader",
        exclude: /node_modules/,
      },
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        use: [
          {
            loader: "file-loader",
            options: {
              name: "[path][name].[ext]",
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new HTMLWebpackPlugin({
      template: "./index.html", // 읽을 파일명
      filename: "./index.html", // output으로 출력할 파일명
    }),
  ],
};

✅ tsconfig.json

{
  "compilerOptions": {
    "target": "ESNext", // 코드의 변환 대상 ECMAScript 버전을 최신 버전으로 지정
    "module": "ESNext", // 최신 ECMAScript 버전 모듈 시스템을 타겟으로 컴파일
    "moduleResolution": "node", // TypeScript가 모듈을 해석하고 처리하는 방식 지정
    "outDir": "./dist", // 컴파일된 파일이 저장될 출력 디렉토리 지정
    "noImplicitAny": true, // 암시적 any를 허용하지 않음
    "strict": true, // 엄격한 타입 검사
    "jsx": "react-jsx", // 새로운 JSX 변환 방식(React 17+)을 사용하기 위해 필요
    "jsxImportSource": "@emotion/react", // React의 jsx()함수가 아니라 Emotion의 jsx()함수를 대신 사용
    "allowSyntheticDefaultImports": true, // default export 가 없어도 import 허용
    "sourceMap": true, // 디버깅 시 어떤 파일에서 에러났는지 추적 용이
    "baseUrl": ".", // 모듈 해석 기본 경로
    "paths": {
      // 경로 별칭 설정
      "@/*": ["src/*"]
    }
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

✅ .babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": "> 2%, not dead",
        "useBuiltIns": "usage",
        "corejs": "3.37",
        "shippedProposals": true
      }
    ],
    "@babel/preset-typescript",
    ["@babel/preset-react", { "runtime": "automatic" }]
  ]
}

✅ package.json

{
  "scripts": {
    "build": "webpack",
    "start": "webpack serve --config webpack.config.js"
  },
	"dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
  "devDependencies": {
    "@babel/cli": "^7.24.8",
    "@babel/core": "^7.24.8",
    "@babel/preset-env": "^7.24.8",
    "@babel/preset-react": "^7.24.7",
    "@babel/preset-typescript": "^7.24.7",
    "@types/react": "^18.3.3",
    "babel-loader": "^9.1.3",
    "css-loader": "^7.1.2",
    "file-loader": "^6.2.0",
    "html-loader": "^5.0.0",
    "html-webpack-plugin": "^5.6.0",
    "style-loader": "^4.0.0",
    "ts-loader": "^9.5.1",
    "typescript": "^5.5.3",
    "webpack": "^5.92.1",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^5.0.4"
  }
}

https://webpack.kr/
https://webpack.kr/guides/typescript/#loader
https://joshua1988.github.io/webpack-guide/webpack/what-is-webpack.html
https://velog.io/@pop8682/번역-왜-babel-preset이-필요하고-왜-필요한가-yhk03drm7q
https://ui.toast.com/fe-guide/ko_BUNDLER
https://techblog.woowahan.com/6465/
https://onlydev.tistory.com/163#:~:text=%40babel%2Fcore 패키지에는 바벨,코드를 생성해 나타낸다.

profile
단단한 프론트엔드 개발자가 되고 싶은

0개의 댓글