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์ ์ฅ์ ๐ก
- ์ ์ ํ์
๊ฒ์ฌ
- ์ปดํ์ผ ๋จ๊ณ์์ ์ค๋ฅ๋ฅผ ๋ฏธ๋ฆฌ ์ก์๋ด์ด ์์ ์ ์ธ ์ฝ๋๋ฅผ ๋ณด์ฅํฉ๋๋ค.
- IDE ์ง์
- ์๋ ์์ฑ, ์ฝ๋ ๋ค๋น๊ฒ์ด์ , ์ค์๊ฐ ์ค๋ฅ ๊ฐ์ง๋ฅผ ํตํด ๊ฐ๋ฐ ์์ฐ์ฑ์ ๋์ ๋๋ค.
- ๋ช
ํํ ์ธํฐํ์ด์ค
- 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์ ๊ฐ๋ ฅํ ์กฐํฉ์ผ๋ก, ์ ์ค์ ์ธ ๊ฐ๋ฐ์์ ๊ธธ์ ๊ฑธ์ด ๋ณด์ธ์!
๐ท์ ์ค์ ๊ฐ๋ฐ์๊ฐ ๋์ด๋ด ์๋น! ๐ท