React + webpack5 + TypeScript는 React 개발을 위한 강력한 조합입니다. webpack5는 React 애플리케이션을 빌드하고 배포하는 데 필요한 모든 도구를 제공하며, TypeScript를 사용하여 React 애플리케이션의 코드를 더 안전하고 유지 관리하기 쉽게 만들 수 있습니다.
이 글에서는 React + webpack5 + TypeScript를 빠르고 쉽게 세팅하는 방법을 소개합니다. CRA(Create React App)를 사용하지 않고, 직접 세팅을 진행하므로, React 개발에 대한 기본적인 이해가 있는 경우 누구나 따라 할 수 있습니다.
여러 블로그 글에서 세팅 방법을 찾아볼 수 있지만, 버전 차이 등 다양한 이유로 잘 안될 때가 있어서, 내가 직접 작성해 보려고 합니다...
결과물을 먼저 확인해 보시죠!
(자세한 스펙은 README에 작성되어 있습니다.)
React Repository: https://github.com/STHyeon/react-boilerplate
Boilderplate Repository: https://github.com/STHyeon/create-react-app-foundation
Installation
npx create-react-app-foundation my-app
Start
cd my-app
yarn install
yarn start
시작하기
개발 환경은 yarn과 node 20 버전을 사용합니다.
1. 개발 환경 준비
빈 폴더에 아래 명령어를 입력해 줍니다.
# 개발 환경 준비
yarn init -y
# 패키지 설치
yarn add react react-dom
yarn add -D typescript ts-node @types/react @types/react-dom @types/node
2. 타입스크립트 설정
yarn tsc --init
위 명령어를 입력하면 tsconfig.json 파일이 생성됩니다. 기존 내용이 있다면 모두 지우고, 아래와 같이 세팅해 주세요.
{
"compilerOptions": {
/* Language and Environment */
"target": "es2017", // Set the ECMAScript version to use
"lib": ["dom", "dom.iterable", "esnext"], // Specify a set of bundled library declaration files that describe the target runtime environment
"jsx": "react-jsx", // Set up the jsx
"experimentalDecorators": true, // Enable experimental features for ES Decorator
/* Modules */
"module": "esnext", // Set up the module
"moduleResolution": "node", // Set how to resolve modules (search)
"resolveJsonModule": true, // Enable importing .json files
"baseUrl": ".", // Specify the base directory to resolve non-relative module names
"typeRoots": ["node_modules/@types"], // Specify multiple folders that act like `./node_modules/@types`
/* JavaScript Support */
"allowJs": true, // Allow compilation of JavaScript files.
/* Emit */
"noEmit": true, // Do not emit output
"downlevelIteration": true, // Support for..of, spread, and destructuring syntax even when the target is ES3 and ES5
/* Interop Constraints */
"esModuleInterop": true, // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html
"allowSyntheticDefaultImports": true, // set export defaults to objects with exported values
"isolatedModules": true, // Ensure that each file can be safely transpiled without relying on other imports
"forceConsistentCasingInFileNames": true, // Enable case insensitivity for filenames (Enforce consistent casing for filenames)
/* Type Checking */
"strict": true, // Enable all strict type checking options
"noFallthroughCasesInSwitch": true, // Raises an error for a switch statement that we believe is incorrectly written
/* Completeness */
"skipLibCheck": true, // Whether to skip type checking of all declaration files (*.d.ts)
},
"include": ["src"]
}
옵션에 대한 간략한 설명을 달아두었습니다. 더 자세한 설명이 필요하시면 아래 링크를 참고해 주세요.
3. Babel 설정
TypeScript를 JavaScript로 변환하기 위해 Babel 세팅을 해줍니다.
# 패키지 설치
yarn add -D @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript babel-loader
babel.config.js 파일을 생성합니다.
/**
* Babel configuration.
*
* @type {import('@babel/core').ConfigFunction}
*/
module.exports = function (api) {
const isProdEnv = api.env('production');
api.cache(true);
/**
* Common babel config for all environments.
* @type {import('@babel/core').TransformOptions}
*/
const config = {
presets: [
'@babel/preset-react',
'@babel/preset-env',
'@babel/preset-typescript',
]
};
return config;
};
4. Webpack 설정
# 패키지 설치
yarn add -D webpack webpack-cli webpack-dev-server
yarn add -D ts-loader css-loader style-loader file-loader html-webpack-plugin
yarn add dotenv
webpack.config.ts 파일을 생성합니다.
/* eslint-disable @typescript-eslint/no-var-requires */
const dotenvConfig = require('dotenv');
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
dotenvConfig.config();
//
//
//
const isProd = process.env.NODE_ENV === 'production';
//
//
//
module.exports = {
entry: './src/index.tsx',
mode: isProd ? 'production' : 'development',
devtool: isProd ? 'hidden-source-map' : 'source-map',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'build'),
},
resolve: {
modules: ['node_modules'],
extensions: ['.ts', '.tsx', '.js', '.jsx'],
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.css?$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(webp|png|jpe?g|gif)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]',
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public', 'index.html'),
hash: true,
}),
],
};
5. package.json 설정
# 패키지 설치
yarn add cross-env
script 부분을 추가해 줍니다.
...
"scripts": {
"dev": "cross-env NODE_ENV=development webpack serve --config webpack.config.ts",
"build": "cross-env NODE_ENV=production webpack --progress",
},
...
package.json 전체 보기
{
"name": "react-boilerplate",
"version": "0.0.1",
"main": "index.js",
"license": "MIT",
"scripts": {
"dev": "cross-env NODE_ENV=development webpack serve --config webpack.config.ts",
"build": "cross-env NODE_ENV=production webpack --progress"
},
"dependencies": {
"cross-env": "^7.0.3",
"dotenv": "^16.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/preset-env": "^7.23.2",
"@babel/preset-react": "^7.22.15",
"@babel/preset-typescript": "^7.23.2",
"@types/node": "^20.8.6",
"@types/react": "^18.2.28",
"@types/react-dom": "^18.2.13",
"babel-loader": "^9.1.3",
"css-loader": "^6.8.1",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.5.3",
"style-loader": "^3.3.3",
"ts-loader": "^9.5.0",
"typescript": "^5.2.2",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
}
}
6. 기본 파일 추가
- public/index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<meta name="theme-color" content="#000000" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="cache-control" content="max-age=31536000, no-cache" />
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script src="index.js"></script>
</body>
</html>
- .gitignore
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
.nyc_output
/coverage
/cypress/screenshots
/cypress/videos
# production
/build
/dist
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
- src/index.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
//
//
//
const rootEl = document.getElementById('root') ?? document.body;
const root = createRoot(rootEl);
//
//
//
root.render(
<React.StrictMode>
<React.Suspense fallback={null}>
<App />
</React.Suspense>
</React.StrictMode>
);
- src/App.tsx
import React from "react";
const App: React.FC = () => {
return (
<div>
<h1>Hello World!</h1>
</div>
);
}
export default App;
폴더 구조
├── package.json
├── tsconfig.json
├── public
│ └── index.html
├── src
│ ├── App.tsx
│ └── index.tsx
├── .gitignore
├── babel.config.js
└── webpack.config.js
마무리
# 실행
yarn dev
웹 브라우저에서 localhost:3000에 접속하면 다음과 같은 화면이 나타납니다.
참고
- React-TS-boilerplate-제작기-환경-구성
- generate-your-web-app-boilerplate-like-create-react-app-does
이 글이 React + webpack5 + typescript에 대한 이해를 돕는 데 도움이 되었기를 바랍니다.
궁금한 점이 있으면 언제든지 질문해 주세요.
'Frontend > Development' 카테고리의 다른 글
왜 컴포넌트 안에서 new QueryClient 사용을 지양해야 할까? (0) | 2023.11.24 |
---|---|
React에서 한글 두 번 입력되는 오류, isComposing로 해결하기 (0) | 2023.10.29 |
MutationObserver로 클릭 이벤트 감지하기 (0) | 2023.09.25 |
MutationObserver란? DOM 변화 감지 방법 (0) | 2023.09.17 |
Storybook addon-controls 사용하기! (1) | 2020.11.07 |