CRA 없이 웹팩을 사용하여 React+TypeScript 개발 환경 세팅하기(2)

지누·2023년 8월 3일
1
post-thumbnail

하나의 게시글에 작성하고 싶었으나, 내용이 너무 길어져 1편에 이어서 작성한다.

1.타입스크립트 관련 라이브러리 설치

1-1. 타입스크립트 패키지

npm i -D typescript @types/react @types/react-dom

  • typescript : 타입스크립트
  • @types/react : React 라이브러리에 대한 타입 선언 파일
  • @types/react-dom : React DOM 라이브러리에 대한 타입 선언 파일

타입 선언 파일(d.ts)

타입스크립트 코드에서 타입 추론을 도와주는 파일이다.
존재하는 대부분의 라이브러리는 자바스크립트로 작성되었고, 타입스크립트는 해당 코드에서 변수, 함수의 타입을 알 수 없다. 그래서 d.ts 확장자를 가지는 선언 파일을 통해 알려주어야 한다.

1-2. 바벨

npm i -D @babel/preset-typescript

  • @babel/preset-typescript : 타입스크립트를 사용할 때 필요한 플러그인들의 집합이다.

1-3. 웹팩

1편에서 웹팩 설정을 할 때webpack.config.js 파일 하나만 사용했다. mode:development를 사용했던 것을 기억할 것이다. 이번에는 webpack에서 production모드와 development모드를 분리하여 각각 세팅한 뒤, webpack.common.js파일로 합칠 것이다.

npm i -D webpack-merge

  • webpack-merge : 웹팩 설정 파일을 병합해주는 라이브러리이다.

1-4. 로더

npm i -D ts-loader

  • ts-loader : 웹팩에서 타입스크립트 코드를 처리하기 위한 로더이다.

1편에 이어 여기까지 진행했다면 package.json이 다음과 같을 것이다.

{
  "name": "frontend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack serve --mode development --open --hot",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.14.2"
  },
  "devDependencies": {
    "@babel/core": "^7.22.9",
    "@babel/preset-env": "^7.22.9",
    "@babel/preset-react": "^7.22.5",
    "@babel/preset-typescript": "^7.22.5",
    "@types/react": "^18.2.18",
    "@types/react-dom": "^18.2.7",
    "babel-loader": "^9.1.3",
    "clean-webpack-plugin": "^4.0.0",
    "css-loader": "^6.8.1",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^5.5.3",
    "style-loader": "^3.3.3",
    "ts-loader": "^9.4.4",
    "typescript": "^5.1.6",
    "webpack": "^5.88.2",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^4.15.1",
    "webpack-merge": "^5.9.0"
  }
}

2. TypeScript 설정 - tsconfig.json

tsc --init 명령어를 통해 타입스크립트 설정 파일인 tsconfig.json을 초기화 하자.

tsc

tsc는 타입스크립트 컴파일러의 명령어이다. tsc 명령어를 통해 프로젝트 내의 내의 타입스크립트 파일들은 tsconfig.json에 설정된 대로 자바스크립트 파일로 변환된다.

명령어를 입력했다면, 수많은 주석으로 이루어진 tsconfig.json이 프로젝트 최상위 디렉터리에 생성되었을 것이다.
tsconfig.json은 자신이 원하는 스타일로 컴파일러의 옵션을 설정 할 수 있다.
각각의 옵션에 관한 내용은 아직 잘 모르니까, 여기를 참고해서 공부해야겠다.

기본 코드는 지우고 다음 코드를 tsconfig.json에 붙여넣자

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "lib": ["dom", "ES2015", "ES2016", "ES2017", "ES2018", "ES2019", "ES2020"],
    "allowJs": true,
    "jsx": "react-jsx", //중요
    "sourceMap": true,
    "outDir": "./dist", //중요
    "isolatedModules": true,
    "strict": true,
    "moduleResolution": "node",
    "baseUrl": "./",
    "paths": {
      "@components/*": ["components/*"],
      "@pages/*": ["pages/*"]
    },
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true
  }
}
  • jsx : 타입스크립트가 jsx문법인 React 컴포넌트를 어떻게 처리할 지 결정한다.
    • jsx : "preserve" 옵션은 컴파일러에게 jsx문법을 변환하지 말라는 옵션이다. 이 옵션때문에 30분동안 문제점을 찾았다..
  • outDir : 컴파일된 자바스크립트 파일이 출력되는 디렉터리

3. Babel 설정 - babel.config.js

@babel/preset-typescript 라이브러리를 추가로 설치했기 때문에 babel.config.js를 다음 코드로 변경해준다.

module.exports = {
  presets: [
    "@babel/preset-react",
    "@babel/preset-env",
    "@babel/preset-typescript",
  ],
};

4. Webpack 설정

4-1. webpack.common.js

const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const path = require("path");

module.exports = {
  entry: "./src/index.tsx", //변경되었음을 눈치 챌 것
  resolve: {
    extensions: [".js", ".jsx", ".ts", ".tsx"],
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: ["babel-loader", "ts-loader"],
      },
      {
        test: /\.(png|jpe?g|gif)$/,
        use: [
          {
            loader: "file-loader",
          },
        ],
      },
    ],
  },
  output: {
    path: path.join(__dirname, "/dist"),
    filename: "bundle.js",
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./public/index.html",
    }),
    new CleanWebpackPlugin(),
  ],
};

4-2. webpack.dev.js

const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");

module.exports = merge(common, {
  mode: "development",
  devtool: "eval",
  devServer: {
    historyApiFallback: true,
    port: 3000,
    hot: true,
  },
});

4-3.webpack.prod.js

const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");

module.exports = merge(common, {
  mode: "production",
  devtool: "hidden-source-map",
});

추가된 옵션은 다음과 같다.

  • resolve : 웹팩에서 모듈을 해석하는 규칙으로, 어떤 확장자를 처리할 지 지정한다.
  • devtool : 웹팩이 생성하는 소스맵을 제어하는 옵션이다. 소스맵이란 웹팩 번들링 결과물과 원본 소스간의 매핑 정보를 제공한다.
    • eval 옵션은 소스맵을 빠르게 생성하지만 용량이 크다.
    • hidden-source-map 옵션은 가장 느리지만 외부에서 리액트 구조를 확인할 수 없으므로 배포 단계에서 사용된다.

4-4. 스크립트 설정

package.json의 스크립트를 다음과 같이 설정한다.

...
  "scripts": {
    "dev": "webpack-dev-server --config webpack.dev.js --open --hot",
    "build": "webpack --config webpack.prod.js",
    "start": "webpack --config webpack.dev.js"
  },
...

npm run dev 명령어를 통해 웹팩 개발 서버를 실행 가능하다.

5. 리액트 애플리케이션 생성

src폴더 내부의 App.jsx -> App.tsx , index.jsx->index.tsx로 변경해준다.
그리고 타입스크립트가 동작하는지 궁금하므로, App.tsx를 다음처럼 변경했다.

import React from "react";

const add = (a: number, b: number): number => a + b;
const App = () => {
  return <div className="container">React!</div>;
};

export default App;

npm run dev 명령어를 실행하면 정상적으로 동작한다!


Create-React-App의 소중함을 깨달았다. 웹팩을 이용하여 직접 개발 환경을 설정하고, 글을 쓰면서 좀 더 이해하는 계기가 되었지만 여전히 완벽히 이해할려면 멀었다고 생각한다. 이것저것 도전해보자~

profile
열심히 좀 살자😱

0개의 댓글