React
[React] typescript 시작하기 - 떽떽대는 개발공부
떽이
2021. 3. 15. 15:06
지금까지 포스팅은 javascript 로 react 프로젝트를 구성하는 것이었다.
오늘은 typescrypt 를 이용하여 react 프로젝트를 시작하는 법을 포스팅 해보겠다.
먼저 디렉토리를 하나 생성한다.
<!-- study_typescript 디렉토리 생성 -->
mkdir study_typescript
<!-- 디렉토리로 이동 -->
cd study_typescript
<!-- package.json 파일 생성 -->
npm init -y
<!-- webpack 설치 -->
npm install --save-dev webpack webpack-dev-server webpack-cli@3
<!-- babel 설치 -->
npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/preset-react babel-preset-es2015 @babel/preset-typescript
<!-- react 설치 -->
npm install --save react react-dom
<!-- typescript 설치 -->
npm install --save @types/react @types/react-dom
<!-- 기타 모듈 설치 -->
npm install --save-dev html-webpack-plugin mini-css-extract-plugin html-loader
최상위 디렉토리에 webpack.config.js, tsconfig.json, .babelrc 을 생성하고 아래와 같이 작성한다.
webpack.config.js
const path = require("path");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "bundle.js",
path: path.resolve(__dirname + "/dist"),
publicPath: '/'
},
devServer: {
contentBase: path.resolve("./dist"),
index: "index.html",
port: 3000,
},
mode: "development",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: "/node_modules",
use: ['babel-loader'],
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
{
test: /\.(png|jpg|gif)$/i,
use: [
'file-loader'
]
},
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './src/index.html',
filename: 'index.html'
}),
new MiniCssExtractPlugin({})
],
resolve: {
extensions: ['*', '.js', '.jsx', '.json', 'css', '.ts', '.tsx'],
}
};
tsconfig.json
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es5",
"jsx": "react"
},
"include": [ "./src/*" ]
}
.babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript"
]
}
package.json
{
"name": "study_typeScript",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --config ./webpack.config.js --mode development"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.13.10",
"@babel/preset-env": "^7.13.10",
"@babel/preset-react": "^7.12.13",
"@babel/preset-typescript": "^7.13.0",
"babel-loader": "^8.2.2",
"babel-preset-es2015": "^6.24.1",
"html-loader": "^2.1.2",
"html-webpack-plugin": "^5.3.1",
"mini-css-extract-plugin": "^1.3.9",
"webpack": "^5.24.4",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.2"
},
"dependencies": {
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.2",
"react": "^17.0.1",
"react-dom": "^17.0.1"
}
}
이제 src 디렉토리를 생성하고 index.html 파일을 작성한다.
src/index.html
<!DOCTYPE html>
<html lang="kr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>study</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
드디어 typescript 를 사용할 index.tsx를 작성한다.
src/index.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
// 함수형 컴포넌트
const Component: React.FunctionComponent<{ title: string }> = ({ children, title }) =>
<div title={title}>
{children}<br />
{title}
</div>;
// 클래스형 컴포넌트
class Root extends React.Component {
render() {
return (
<div>
<Component title={'Hello'}>
Hello
</Component>
</div>
)
}
}
ReactDOM.render(<Root/>, document.getElementById('app'));
위와 같이 작성하하면 폴더 구조는 아래와 같다.
결과는 아래와 같다.
만약 index.tsx 의 구조들을 모두 나누게 되면 아래와 같다.
src/index.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import { Root } from "@components/Root";
ReactDOM.render(
<Root/>
, document.getElementById('app')
);
index 안의 컴포넌트들은 src 디렉토리 아래 components 디렉토리를 생성하여 관리한다.
src/components/Root.tsx
import * as React from "react";
import { Contents } from "@components/Contents";
export class Root extends React.Component {
render() {
return (
<div>
<Contents title={'Hello'}>
Hello
</Contents>
</div>
)
}
}
src/components/Contents.tsx
import * as React from "react";
export const Contents: React.FunctionComponent<{ title: string }> = (
{ children, title }
) => {
return (
<div title={title}>
{children}<br />
{title}
</div>
)
}