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>
    )
}