Front-end/Typescript

[TypeScript] TSX: TypeScript์™€ React์˜ ๋งŒ๋‚จ ๐ŸŒ€

xeunnie 2024. 12. 20. 01:00
728x90
๋ฐ˜์‘ํ˜•

TSX ํ†บ์•„๋ณด๊ธฐ! ๐ŸŒ€

TSX(TypeScript + JSX)๋Š” TypeScript์™€ JSX(JavaScript XML)๋ฅผ ๊ฒฐํ•ฉํ•œ ํ˜•ํƒœ๋กœ, TypeScript์˜ ์ •์  ํƒ€์ž… ๊ฒ€์‚ฌ์™€ React์˜ ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ ๊ฐœ๋ฐœ์„ ๋™์‹œ์— ์ฆ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ๋ฒ•์ž…๋‹ˆ๋‹ค. React ํ”„๋กœ์ ํŠธ์—์„œ TSX๋ฅผ ํ™œ์šฉํ•˜๋ฉด, ๊ฐ•๋ ฅํ•œ ํƒ€์ž… ์•ˆ์ •์„ฑ๊ณผ ์ฝ”๋“œ ํ’ˆ์งˆ์„ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” TSX์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๋ถ€ํ„ฐ ์„ค์ •, ์ฃผ์˜์‚ฌํ•ญ, ๊ทธ๋ฆฌ๊ณ  ์‹ค๋ฌด์—์„œ ๋งˆ์ฃผ์น  ์ˆ˜ ์žˆ๋Š” ์—๋Ÿฌ์™€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•๊นŒ์ง€ ํ•œ ๋ฒˆ์— ์•Œ์•„๋ด…์‹œ๋‹ค! ๐Ÿ› ๏ธ


TSX๋ž€? ๐Ÿค”

TSX๋Š” React ์ปดํฌ๋„ŒํŠธ์—์„œ TypeScript์˜ ํƒ€์ž… ๊ฒ€์‚ฌ์™€ JSX ๋ฌธ๋ฒ•์„ ๋™์‹œ์— ์‚ฌ์šฉํ•˜๋Š” ํŒŒ์ผ ํ˜•์‹์ž…๋‹ˆ๋‹ค.

.tsx ํ™•์žฅ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, React ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋ฐœ์— ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.

  • JSX๊ฐ€ HTML๊ณผ ๋น„์Šทํ•œ ๋ฌธ๋ฒ•์œผ๋กœ UI๋ฅผ ํ‘œํ˜„ํ•œ๋‹ค๋ฉด, TSX๋Š” ์—ฌ๊ธฐ์— ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ๋”ํ•ฉ๋‹ˆ๋‹ค.
  • TypeScript์˜ ์ •์  ํƒ€์ž… ๊ฒ€์‚ฌ๋กœ ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ์˜ค๋ฅ˜๋ฅผ ์žก์•„๋‚ผ ์ˆ˜ ์žˆ์–ด, ์•ˆ์ •์ ์ธ React ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

TSX ์„ค์ •ํ•˜๊ธฐ ๐Ÿ› ๏ธ

TSX๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด TypeScript์™€ React ํ”„๋กœ์ ํŠธ๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1. ํ”„๋กœ์ ํŠธ ์ดˆ๊ธฐํ™”

(1) ์ƒˆ React ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ:

# npm
npx create-react-app my-app --template typescript

#yarn
yarn create react-app todo-app --template typescript

 

์ด ๋ช…๋ น์€ TypeScript ์„ค์ •์ด ํฌํ•จ๋œ React ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

 

(2) ์ˆ˜๋™ ์„ค์ •ํ•˜๊ธฐ: ๊ธฐ์กด React ํ”„๋กœ์ ํŠธ์— TypeScript ์ถ”๊ฐ€

# npm
npm install typescript @types/react @types/react-dom

# yarn
yarn add typescript @types/react @types/react-dom

# yarn devDependencies๋กœ ์„ค์น˜ ์‹œ
yarn add typescript @types/react @types/react-dom -D

 

์ด์ œ .ts์™€ .tsx ํŒŒ์ผ์„ ์‚ฌ์šฉํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

2. TypeScript ์„ค์ • (tsconfig.json)

TypeScript ์„ค์ • ํŒŒ์ผ์ธ tsconfig.json์—์„œ TSX๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค:

{
  "compilerOptions": {
    "jsx": "react", // JSX ๋ฌธ๋ฒ• ์‚ฌ์šฉ
    "strict": true, // ์—„๊ฒฉํ•œ ํƒ€์ž… ๊ฒ€์‚ฌ
    "esModuleInterop": true, // ES ๋ชจ๋“ˆ ํ˜ธํ™˜์„ฑ
    "moduleResolution": "node", // ๋ชจ๋“ˆ ํ•ด์„
    "target": "ES6", // ์ปดํŒŒ์ผ ๋Œ€์ƒ
    "module": "ES6", // ๋ชจ๋“ˆ ํ˜•์‹
    "skipLibCheck": true // ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํƒ€์ž… ๊ฒ€์‚ฌ ๊ฑด๋„ˆ๋›ฐ๊ธฐ
  }
}

TSX ๊ธฐ๋ณธ ๋ฌธ๋ฒ• ๐ŸŒŸ

1. ๊ธฐ๋ณธ React ์ปดํฌ๋„ŒํŠธ ์ž‘์„ฑ

type Props = {
  name: string;
};

const Welcome: React.FC<Props> = ({ name }) => {
  return <h1>Hello, {name}!</h1>;
};

export default Welcome;

 

2. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋ง

const Button: React.FC = () => {
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    console.log("Button clicked!", event);
  };
  return <button onClick={handleClick}>Click Me</button>;
};

 

3. ์ปดํฌ๋„ŒํŠธ ์ƒํƒœ ๊ด€๋ฆฌ

React์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉด์„œ ํƒ€์ž…์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

import { useState } from "react";

const Counter: React.FC = () => {
  const [count, setCount] = useState<number>(0);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
};

TSX์˜ ์žฅ์  ๐Ÿ’ก

  1. ์ •์  ํƒ€์ž… ๊ฒ€์‚ฌ
    • ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ์˜ค๋ฅ˜๋ฅผ ๋ฏธ๋ฆฌ ์žก์•„๋‚ด์–ด ์•ˆ์ •์ ์ธ ์ฝ”๋“œ๋ฅผ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
  2. IDE ์ง€์›
    • ์ž๋™ ์™„์„ฑ, ์ฝ”๋“œ ๋„ค๋น„๊ฒŒ์ด์…˜, ์‹ค์‹œ๊ฐ„ ์˜ค๋ฅ˜ ๊ฐ์ง€๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค.
  3. ๋ช…ํ™•ํ•œ ์ธํ„ฐํŽ˜์ด์Šค
    • Props์™€ State์— ํƒ€์ž…์„ ์ง€์ •ํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ ๊ฐ„ ๋ฐ์ดํ„ฐ ํ๋ฆ„์ด ๋ช…ํ™•ํ•ด์ง‘๋‹ˆ๋‹ค.

TSX ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์‚ฌํ•ญ โš ๏ธ

1. Props์™€ State์— ๋ช…ํ™•ํ•œ ํƒ€์ž… ์ง€์ •

Props์™€ State์˜ ํƒ€์ž…์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ํƒ€์ž… ์•ˆ์ •์„ฑ์ด ๊นจ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•ญ์ƒ ๋ช…์‹œ์ ์œผ๋กœ ํƒ€์ž…์„ ์ง€์ •ํ•˜์„ธ์š”.

type Props = {
  name: string;
};

 

2. ์ด๋ฒคํŠธ ํƒ€์ž… ์ฒ˜๋ฆฌ

React์˜ ์ด๋ฒคํŠธ ํƒ€์ž…์€ DOM ์ด๋ฒคํŠธ์™€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ด๋ฒคํŠธ ํƒ€์ž…์ž…๋‹ˆ๋‹ค:

  • React.ChangeEvent<HTMLInputElement>: ์ž…๋ ฅ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ
  • React.MouseEvent<HTMLButtonElement>: ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
  • React.FormEvent<HTMLFormElement>: ํผ ์ œ์ถœ ์ด๋ฒคํŠธ

3. ๊ธฐ๋ณธ HTML ์†์„ฑ ํƒ€์ž…

React๋Š” ๋ชจ๋“  HTML ์†์„ฑ์— ๋Œ€ํ•œ ํƒ€์ž…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

const Link: React.FC = () => {
  return <a href="https://example.com" target="_blank" rel="noopener noreferrer">Visit</a>;
};

 

4. ForwardRef ์‚ฌ์šฉ

์ปดํฌ๋„ŒํŠธ์—์„œ Ref๋ฅผ ์ „๋‹ฌํ•˜๋ ค๋ฉด React.forwardRef๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

import React, { forwardRef } from "react";

type InputProps = {
  placeholder: string;
};

const Input = forwardRef<HTMLInputElement, InputProps>((props, ref) => (
  <input ref={ref} placeholder={props.placeholder} />
));

export default Input;

์‹ค๋ฌด์—์„œ ์ž์ฃผ ๋งˆ์ฃผ์น˜๋Š” ์—๋Ÿฌ์™€ ํ•ด๊ฒฐ๋ฒ• ๐Ÿ› ๏ธ

1. Property 'x' is missing in type ์—๋Ÿฌ

  • ์›์ธ: Props ํƒ€์ž…์„ ์ง€์ •ํ–ˆ์œผ๋‚˜, ํ•„์š”ํ•œ ์†์„ฑ์„ ์ „๋‹ฌํ•˜์ง€ ์•Š์•˜์„ ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ: ๋ˆ„๋ฝ๋œ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜, ์˜ต์…”๋„ ์†์„ฑ(?)์œผ๋กœ ์ง€์ •ํ•˜์„ธ์š”.
type Props = {
  name?: string; // Optional
};

 

2. Cannot find name 'React'

  • ์›์ธ: TypeScript ์„ค์ •์—์„œ JSX๋ฅผ ์‚ฌ์šฉํ•  ์ค€๋น„๊ฐ€ ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ: tsconfig.json์—์„œ jsx ์˜ต์…˜์„ ํ™•์ธํ•˜์„ธ์š”.
"jsx": "react-jsx"

 

3. Type 'undefined' is not assignable

  • ์›์ธ: State ๋˜๋Š” Props์— ํƒ€์ž…์„ ์ง€์ •ํ•˜์ง€ ์•Š์•„, undefined ํƒ€์ž…์ด ํฌํ•จ๋œ ๊ฒฝ์šฐ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ: ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ํƒ€์ž…์„ ๋ช…ํ™•ํžˆ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
const [value, setValue] = useState<string>(""); // ๊ธฐ๋ณธ๊ฐ’ ์„ค์ •

TSX๋กœ ์ƒ์‚ฐ์„ฑ ๋†’์ด๊ธฐ ๐Ÿ’ป

1. ์ œ๋„ค๋ฆญ ํ™œ์šฉ

  • ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ์ž‘์„ฑ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
type ListProps<T> = {
  items: T[];
  render: (item: T) => JSX.Element;
};

const List = <T,>({ items, render }: ListProps<T>) => (
  <ul>{items.map(render)}</ul>
);

 

2. ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž… ํ™œ์šฉ

  • TypeScript์˜ ๋‚ด์žฅ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด ํƒ€์ž…์„ ๊ฐ„์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค.
type User = {
  id: number;
  name: string;
};

type UserPreview = Pick<User, "name">; // 'id' ์ œ์™ธ

๋งˆ๋ฌด๋ฆฌ: TSX๋กœ ๋” ์•ˆ์ „ํ•˜๊ณ  ์ƒ์‚ฐ์ ์œผ๋กœ! ๐Ÿ›ก๏ธ

TSX๋Š” React ํ”„๋กœ์ ํŠธ์—์„œ ํƒ€์ž… ์•ˆ์ „์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ด๋Š” ๋ฐ ํ•„์ˆ˜์ ์ธ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ ์ ˆํ•œ ์„ค์ •๊ณผ ํƒ€์ž… ์ง€์ •์œผ๋กœ ์‹ค์ˆ˜๋ฅผ ์ค„์ด๊ณ , ํšจ์œจ์ ์ธ ํ˜‘์—…์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. React์™€ TypeScript์˜ ๊ฐ•๋ ฅํ•œ ์กฐํ•ฉ์œผ๋กœ, ์ „์„ค์ ์ธ ๊ฐœ๋ฐœ์ž์˜ ๊ธธ์„ ๊ฑธ์–ด ๋ณด์„ธ์š”!

 

๐ŸŒท์ „์„ค์˜ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด๋ด…์‹œ๋‹น! ๐ŸŒท

728x90
๋ฐ˜์‘ํ˜•