"์ปดํฌ๋ํธ"๋ผ๊ณ ๋ถ๋ฅด๋ ๋์จํ๊ฒ ์ฐ๊ฒฐ๋ ์ ๋์ผ๋ก ๊ด์ฌ์ฌ๋ฅผ ๋ถ๋ฆฌํฉ๋๋ค.
const element = <h1>Hello, world!</h1>;
"์์ ํฌํํ ํ๊ทธ ๋ฌธ๋ฒ์ ๋ฌธ์์ด๋, HTML๋ ์๋๋๋ค."
React๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ง๋ง, ํ๋ ์์ํฌ์ ์ ์ฌํ๊ฒ ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค. ๊ทธ ์ค์์๋ JSX ๋ฌธ๋ฒ, ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ, Virtual DOM(VDOM), ๋ ๋ ์ฌ์ดํด์ด React์ ์ฃผ์ ํน์ง์ด๋ค.
JSX ๋ฌธ๋ฒ
JSX๋ JavaScript XML ๋๋ JavaScript Syntax Extension์ผ๋ก ๋ถ๋ฆฐ๋ค. JSX๋ JavaScript์ XML(๋๋ HTML)์์๋ฅผ ๊ฒฐํฉํ ๋ฌธ๋ฒ์ผ๋ก, React์์ ์ปดํฌ๋ํธ๋ฅผ ์ ์ํ๋ ๋ฐฉ๋ฒ์ด๋ค. ์ผ๋ฐ์ ์ผ๋ก JavaScript ์ฝ๋ ๋ด์์ HTML ์์๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ด๊ธฐ ๋๋ฌธ์ ๋งํฌ์ ๊ณผ ๋ก์ง์ ํ ๊ณณ์์ ๋ค๋ฃฐ ์ ์๋ ์ฅ์ ์ด ์๋ค.
JSX ๋ฌธ๋ฒ์ ํน์ง
- JSX๋ JavaScript ๋ด์์ HTML ์์๋ฅผ ์ ์ํ ์ ์๋ ๋ฌธ๋ฒ์ด๋ค.
- React์์ ์ฌ์ฉ๋๋ ๋ชจ๋ ์ปดํฌ๋ํธ๋ JSX๋ฅผ ํตํด ํ๋ฉด์ ๋ ๋๋ง๋๋ค.
์์ ๋น๊ต:
1. Angular์ฒ๋ผ ๋งํฌ์ ๊ณผ ๋ก์ง์ ๋ถ๋ฆฌํ๋ ๋ฐฉ์
- HTML(๋งํฌ์ ) ํ์ผ์ UI๋ฅผ ์ ์ํ๊ณ , JavaScript(๋ก์ง) ํ์ผ์ ๊ธฐ๋ฅ์ ์ ์ํ๋ค. ์ด ๋ฐฉ์์ ๋ช ์์ ์ผ๋ก ํ์ผ์ ๋๋์ด ์์ฑํด์ผ ํ๋ค.
<!-- HTML -->
<h2>Product Details</h2>
<div *ngIf="product">
<h3>{{ product.name }}</h3>
<h4>{{ product.price | currency }}</h4>
<p>{{ product.description }}</p>
<button type="button" (click)="addToCart(product)">Buy</button>
</div>
// JavaScript
@Component({
selector: 'app-product-details',
templateUrl: './product-details.component.html',
styleUrls: ['./product-details.component.css']
})
export class ProductDetailsComponent {
product: Product | undefined;
addToCart(product: Product) {
this.cartService.addToCart(product);
}
}
2. React์ Vue์ฒ๋ผ ์ปดํฌ๋ํธ๋ฅผ ํ๋์ ํ์ผ์์ ์์ฑํ๋ ๋ฐฉ์
- React๋ HTML๊ณผ JavaScript๋ฅผ ํ๋์ ์ปดํฌ๋ํธ ํ์ผ ๋ด์์ ์ ์ํ๋ค. ์ด๋ก ์ธํด ํ ๊ณณ์์ UI์ ๋ก์ง์ ๊ด๋ฆฌํ ์ ์๋ค.
function ProductDetails({ product }) {
return (
<div>
<h3>{product.name}</h3>
<h4>{product.price}</h4>
<p>{product.description}</p>
<button onClick={() => addToCart(product)}>Buy</button>
</div>
);
}
JSX ๋ฌธ๋ฒ์ ์ฅ์
1. JS์ HTML์ ํํ์ผ์์ ๊ด๋ฆฌ
- React ์ปดํฌ๋ํธ๋ UI์ ๋ก์ง์ ํ๋์ ํ์ผ๋ก ์์ฑํ์ฌ ๊ฐ๋ฐ ํจ์จ์ฑ์ ๋์ธ๋ค. ์ด๋ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋ฆฝ์ ์ด๊ณ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋จ์๋ก ๋ง๋ค์ด์ค๋ค.
import { useState } from 'react'
import './App.css'
function App() {
const [count, setCount] = useState(0)
return (
<>
<h1>Vite + React</h1>
<div className='card'>
<button onClick={() => setCount((count) => count + 1)}>count is {count}</button>
<p>
Edit <code>src/App.jsx</code> and save to test HMR
</p>
</div>
<p className='read-the-docs'>Click on the Vite and React logos to learn more</p>
</>
)
}
export default App
React ์ปดํฌ๋ํธ ์: HTML or XML + JS + CSS ๋ชจ๋ ํ๋์ `.jsx` ํ์ผ ๋ด ์กด์ฌ
2. JSX๋ ๊ฒฐ๊ตญ JS๋ก ์ปดํ์ผ๋จ
- JSX๋ ๋ธ๋ผ์ฐ์ ์์ ์ง์ ์คํ๋ ์ ์๊ธฐ ๋๋ฌธ์, Bable์ ์ํด JSX๋ฅผ JavaScript๋ก ์ปดํ์ผํ๋ค.
const element = <h1 className="greeting">Hello, World!"</h1> // This is JSX
์ด ์ฝ๋๋ ์ปดํ์ผ ์ ์๋์ ๊ฐ์ด ๋ณํ๋๋ค.
const element = React.createElement('h1', { className: 'greeting' }, 'Hello, World!');
JSX ์ ์ฝ์ฌํญ
1. JSX๋ ๋ฌด์กฐ๊ฑด ํ๋์ ์์๋ก ๋ฐํ๋์ด์ผํ๊ธฐ์, ์ฌ๋ฌ ์์๋ฅผ ์์ฑํ๋ ค๋ฉด ํ๋์ ํ๊ทธ๋ก ๊ฐ์ธ์ผํ๋ค.
<div>
<h1>์ค๋์ ํ ์ผ</h1>
<ul>
<li>๋นจ๋ํ๊ธฐ</li>
<li>์์ ํ๊ธฐ</li>
<li>1์ ์ฝ์</li>
</ul>
</div>
// ๊ฐ์ธ์ฃผ๋ ๋
ธ๋๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ง ์์ ๊ฒฝ์ฐ Fragment๋ฅผ ์ฌ์ฉ
<React.Fragment>
</React.Fragment>
// or
<>
</>
2. `class`๊ฐ ES6(JS)์ ํด๋์ค ๋ฌธ๋ฒ์ ์์ฝ์ด์ด๊ธฐ์ ๋์ ํ์ฌ `className` ์ฌ์ฉ
<div className="container">
</div>
3. JS ๋ก์ง(๋ณ์๋ ํจ์)์ ๋ฃ๊ธฐ ์ํด์๋ ์ค๊ดํธ๋ฅผ ์ด์ด์ ๊ทธ ์์ JS๋ก์ง์ ๋ฃ์ด์ผ ํจ `{}`
function Container({ children }) {
const title = '์ค๋์ ํ ์ผ';
return (
<div>
<h1>{title}</h1>
{children}
</div>
)
}
๊ธฐํ ๋ฌธ๋ฒ
- ์ฃผ์: HTML, XML ์ฃผ์ ํํ ๋ฒ `<!-- ์ฃผ์ -->` ์ด ์๋ `{/* ์ฃผ์ */}` ์ฌ์ฉ
- React Component(Element)๊ฐ JSX๋ก ์์ฑ๋๋ฉด ๋๋ฌธ์๋ก ์์ํด์ผํจ.
- ์๋ฌธ์๋ก ์์ํ๋ Element๋ HTML Element๋ก ์ธ์
function TodoList() {
return (
<Container>
<div>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
</Continer>
)
}
- ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ if๋ฌธ์ด ์๋ ์ผํญ์ฐ์ฐ์ ์ฌ์ฉ
function TodoList() {
const todoList = []
return (
<Container>
<div>
{todoList.length > 0 ?
todoList.map(todo => <div key={todo.id}>{todo.value}</div>)
: "์๋ก์ด ํ ์ผ์ ์
๋ ฅํด๋ณด์ธ์."}
</div>
</Continer>
)
}
- ์ฌ๋ฌ HTML ์๋ฆฌ๋จผํธ๋ฅผ ํ์ํ ๋๋ `map` ํจ์ ์ฌ์ฉ
- `map`ํจ์๋ฅผ ์ฌ์ฉ ์ ๋ฐ๋์ `key` ์์ฑ ํ์ ํ์, ๊ทธ๋ ์ง ์์ผ๋ฉด ๊ฒฝ๊ณ ํ๊ธฐ
๋จ๋ฐฉํฅ ๋ฐ์ธ๋ฉ: ํจ์ํ ์ปดํฌ๋ํธ์ Hook
React์์ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ๋ฐ์ดํฐ๋ฅผ Model(์ํ)์์ View(UI)๋ก ํ๋ฅด๊ฒ ํ๋ ๋ฐฉ์์ผ๋ก, ๋ฐ์ดํฐ๊ฐ ํ ๋ฐฉํฅ์ผ๋ก๋ง ํ๋ฅธ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค. ์ด๋ ์ํ๊ฐ ๋ณ๊ฒฌ๋๋ฉด ํ๋ฉด์ด ์๋์ผ๋ก ์ ๋ฐ์ดํธ๋๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๋ฉฐ, React๋ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ปดํฌ๋ํธ ๊ธฐ๋ฐ UI๋ฅผ ๋ ๋๋งํ๋ค.
MVC๋ฅผ ์์๋ก ์ค๋ช
- View(HTML): "ํ๋ฉด์ ๋ณด์ด๋ ๊ฒ, ํ๋ฉด" ← Rendering
- Model(JS): "๋ธ๋ผ์ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ์๋ ๋ฐ์ดํฐ" ← Data
- Controller(JS):"Model(๊ฐ)์ ๋ณ๊ฒฝํ๋ ํจ์" ← "Event" Handling โ "Data" Handling
1. ๋ฐ์ธ๋ฉ์ ๊ฐ๋
๋ฐ์ธ๋ฉ์ View(ํ๋ฉด)์ Model(๋ธ๋ผ์ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ดํฐ)๋ฅผ ์ผ์น์ํค๋ ์์ ์ด๋ค. ์ฆ, ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ํ๋ฉด์ ๊ทธ ๋ฐ์ดํฐ๊ฐ ๋ฐ์๋๋๋ก ํ๊ณ , ํ๋ฉด์ด ์ ๋ฐ์ดํธ๋ ๋๋ง๋ค ์ํ๊ฐ ๋ณ๊ฒฝ๋๋๋ก ๋๊ธฐํํ๋ ๊ณผ์ ์ ์๋ฏธํ๋ค.
2. ๊ณผ๊ฑฐ์ ํด๋์ค ์ปดํฌ๋ํธ vs ํ์ฌ์ ํจ์ํ ์ปดํฌ๋ํธ
- React๋ ๊ณผ๊ฑฐ์ ํด๋์ค ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ง๋ง, ํจ์ํ ์ปดํฌ๋ํธ์ Hooks๊ฐ ๋์
๋ ์ดํ๋ก ํจ์ํ ์ปดํฌ๋ํธ๊ฐ ์ฃผ๋ก ์ฌ์ฉ๋๊ณ ์๋ค.
- ํด๋์ค ์ปดํฌ๋ํธ์์๋ ๋ณต์กํ ๋ฉ์๋์ ์๋ช ์ฃผ๊ธฐ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ํ ๊ด๋ฆฌ์ UI ์ ๋ฐ์ดํธ๋ฅผ ์ฒ๋ฆฌํ๋ค.
- ๋ฐ๋ฉด, ํจ์ํ ์ปดํฌ๋ํธ๋ ์ง๊ด์ ์ธ ํจ์ ๊ธฐ๋ฐ ๋ก์ง์ผ๋ก ๋์ํ๋ฉฐ, React์ ์ํ ๊ด๋ฆฌ์ ์ฌ์ด๋ ์ดํํธ ์ฒ๋ฆฌ๋ ๋ ๋ช ํํ๊ฒ ๊ตฌ๋ถ๋์ด ์๋ค.
3. ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ๊ณผ ํจ์ํ ์ปดํฌ๋ํธ
- React์ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ์ํ ๋ณํ๊ฐ ์๊ธฐ๋ฉด ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก UI๋ฅผ ๋ค์ ๋ ๋๋งํ๋ค.
- Model(์ํ) → View(UI)์ ํ๋ฆ์ ์ ์งํ๋ฉฐ, ์ํ๋ณ๊ฒฝ ํธ๋ค๋ฌ(`setState`)๋ฅผ ํตํด ์ํ๋ฅผ ์ ๋ฐ์ดํธํ๋ค.
- ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์ปดํฌ๋ํธ๋ ๋ค์ ๋ ๋๋ง๋์ด UI๊ฐ ์ต์ ์ํ๋ก ์ ๋ฐ์ดํธ๋๋ค.
4. React Hooks: ํจ์ํ ์ปดํฌ๋ํธ์์ ์ํ์ ํจ๊ณผ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ
- Hooks๋ ํจ์ํ ์ปดํฌ๋ํธ์์ ์ํ ๊ด๋ฆฌ์ ์ฌ์ด๋ ์ดํํธ ์ฒ๋ฆฌ๋ฅผ ์ฝ๊ฒ ํด์ฃผ๋ API์ด๋ค.
- `useState`: ์ํ ๊ด๋ฆฌ๋ฅผ ์ํ Hook์ผ๋ก, ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ํ๋ฅผ ๊ด๋ฆฌํ ์ ์๋ค.
- `useEffect`: ์ฌ์ด๋ ์ดํํธ(์: API ํธ์ถ, ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ๋ฐ๋ฅธ ๋ฆฌ๋ ๋๋ง)๋ฅผ ์ฒ๋ฆฌํ๋ Hook.
import { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
- `useState`๋ฅผ ์ฌ์ฉํ์ฌ `count` ์ํ๋ฅผ ๊ด๋ฆฌํ๊ณ , `useEffect`๋ก ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ๋ธ๋ผ์ฐ์ ํ์ดํ์ ์ ๋ฐ์ดํธํ๋ค. ์ด์ฒ๋ผ ํจ์ํ ์ปดํฌ๋ํธ์์ ์ํ์ ์ฌ์ด๋ ์ดํํธ๋ฅผ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค.
5. Hooks ์ฌ์ฉ ๊ท์น
- Hooks๋ ๋ฐ๋์ ํจ์์ ์ต์์์์ ํธ์ถ๋์ด์ผ ํ๋ค. ์ด๋ React๊ฐ ์ปดํฌ๋ํธ์ ๋ ๋๋ง ์์์ ๋ง์ถฐ ์ํ์ ํจ๊ณผ๋ฅผ ๊ด๋ฆฌํ ์ ์๋๋ก ํ๊ธฐ์ํ ๊ท์น์ด๋ค.
- ๋ฐ๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ, ์ค์ฒฉ๋ ํจ์ ์์์ Hooks๋ฅผ ํธ์ถํ๋ฉด ์๋๋ค. ์ด๋ ๊ฒ ๋๋ฉด ๋ ๋๋ง ์์๊ฐ ๊นจ์ง๋ฉด์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
const Example = () => {
// โ
- ์ฌ๋ฐ๋ฅธ ์ฌ์ฉ
const [count, setCount] = useState(0);
// โ - ์กฐ๊ฑด๋ฌธ ์์์ ์ฌ์ฉ ๋ถ๊ฐ
if (count > 0) {
const [otherState, setOtherState] = useState(false); // ์ด๋ ๊ฒ ์ฌ์ฉํ๋ฉด ์ ๋จ
}
return <div>{count}</div>;
};
โน๏ธ์ฐธ๊ณ
[ASAC 6๊ธฐ ๊ฐ์์๋ฃ]
https://hackernoon.com/react-functional-components-are-the-future
'๐ปDEV-STUDY > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[React] React์ State, Props, Ref์ ์ญํ (1) | 2024.09.18 |
---|---|
[React] Vite๋ก React ์ด๊ธฐ ์ฑ ์ค์ (2) | 2024.09.18 |
[React] ๋ ๋๋ง๋ฐฉ์(CSR)๊ณผ ์น ์ดํ๋ฆฌ์ผ์ด์ ๊ตฌ์กฐ(SPA) (1) | 2024.09.17 |
[React] React์ ๋ฑ์ฅ๊ณผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ vs ํ๋ ์์ํฌ (1) | 2024.09.17 |