https://github.com/ssi02014/create-compare-react
๐ vanilla js ์ ๋น๊ตํ๋ฉฐ ํ์ตํ๋ react
https://github.com/ssi02014/create-compare-react
javascript react vanilla-javascript
Last synced: 8 months ago
JSON representation
๐ vanilla js ์ ๋น๊ตํ๋ฉฐ ํ์ตํ๋ react
- Host: GitHub
- URL: https://github.com/ssi02014/create-compare-react
- Owner: ssi02014
- Created: 2022-01-26T13:42:19.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2022-03-14T15:40:13.000Z (over 3 years ago)
- Last Synced: 2024-12-30T06:45:29.215Z (9 months ago)
- Topics: javascript, react, vanilla-javascript
- Language: JavaScript
- Homepage:
- Size: 163 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# ๐ป ๋ง๋ค๊ณ ๋น๊ตํ๋ฉฐ ํ์ตํ๋ ๋ฆฌ์กํธ
## ๐ ch-1 Vanilla Javascript
- MVC ํจํด์ผ๋ก ๊ฒ์ํผ ๊ตฌํํ๊ธฐ
### ๐ lite-server ์คํ ๋ช ๋ น์ด
```
npx lite-server --baseDir vanilla
npx lite-server --baseDir react
```
### ๐ MVC๋?
```
Model, View, Controller์ ์ฝ์. ์ํํธ์จ์ด ๋์์ธ ํจํด์ ํ๋๋ก, ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ธฐ๋ฅ์ ๊ตฌ๋ถํจ์ผ๋ก, ์ ๋๋ ๊ฐ๋ฐ์ ๊ฐ๋ฅํ๊ฒ ํ๋ค
```1. Model
- `๋ฐ์ดํฐ` ๋ฐ `๋น์ฆ๋์ค ๋ก์ง`์ ๋ด๋นํ๋ค.
- ๋ชจ๋ธ์ `๋ฐ์ดํฐ๋ง ๊ด๋ฆฌ`ํ๋ค. ์ดํ๋ฆฌ์ผ์ด์ ๋ฐ์ดํฐ์ ํ๋ฉด ์ถ๋ ฅ์ ์ํ ์ํ๋ฅผ ๋ค๋ฃฌ๋ค.
- ex) DB์ ํต์ ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๋ค, ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํ์ฌ ์ฒ๋ฆฌํ๋ค ๋ฑ
2. View
- `ํ๋ฉด`์ ๋ด๋นํ๋ค. (์ฌ์ฉ์์๊ฒ ์ด๋ค ํ๋ฉด์ ๋ณด์ฌ์ฃผ๋ฉด ๋๋์ง)
- ๋ทฐ๋ ์ธ๋ถ์์ ๋ฐ์ดํฐ๊ฐ ๋ค์ด์จ๋ค๊ณ ๊ฐ์ ํ๊ณ ํ๋ฉด์ ๊ทธ๋ฆฐ๋ค. ๊ทธ๋ฆฌ๊ณ ์์ ์ ์ญํ ์ด ์๋๋ผ๊ณ ํ๋จ๋๋ฉด `์ปค์คํ ์ด๋ฒคํธ`๋ก ์ธ๋ถ์ ์ด๋ฅผ ์๋ฆฐ๋ค.
3. Controller
- ์์ฒญ์ ๋ฐ์ Model๊ณผ View ์ฌ์ด์ `๋ค๋ฆฌ ์ญํ `์ ํ๋ค.
- ๋ชจ๋ธ๊ณผ ๋ทฐ๋ฅผ ์ฌ์ฉํด ์ดํ๋ฆฌ์ผ์ด์ ์ด ๋์๊ฐ๊ฒ๋ ํ๋ ๊ฒ์ด ์ปจํธ๋กค๋ฌ์ ์ญํ ์ด๋ค.
- `๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝ`ํ๊ณ ์ด๋ฅผ `๋ทฐ์ ๋ฐ์`ํด ํ๋ฉด์ ๋ ๋๋งํ๋ค.
- ๋ฐ๋๋ก ๋ทฐ์์ ์ฌ์ฉ์ ์ ๋ ฅ์ด ๋ฐ์ํ๋ฉด ์ด๋ฅผ ๋ชจ๋ธ์ ์ ์ฅํด์ ์ดํ๋ฆฌ์ผ์ด์ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ค.- ๊ตฌ๋ถ๋ ์ญํ ๋ก ์ธํด ์ญํ (์ฑ ์)์ด ๋ช ํํด์ง๊ณ ์ ์ง ๋ณด์์ ์ด์ ์ด ์๋ค.
- ์ ์ฐํ๊ณ ํ์ฅ์ฑ์ด ์ข๋ค.
- ๋จ์ ์ผ๋ก๋ ์ค๊ณ ์ ๋ง์ ์๊ฐ ๋ฐ ๋น์ฉ์ด ์๋น๋ ์ ์๋ค.
### ๐ Javascript CustomEvent(), dispatchEvent()
- CustomEvent: ์์ฑ์๋ ์๋ก์ด `CustomEvent`๋ฅผ ์์ฑํฉ๋๋ค.
- dispatchEvent: ์ด๋ฒคํธ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ค์ `dispatchEvent(event)`๋ฅผ ํธ์ถํด ์์์ ์๋ ์ด๋ฒคํธ๋ฅผ ์คํ์ํจ๋ค.```js
// CustomEvent ๊ธฐ๋ณธ ๊ตฌ๋ฌธ
CustomEvent(typeArg);
CustomEvent(typeArg, options);
```- ๋งค๊ฐ๋ณ์
- typeArg: ์ด๋ฒคํธ์ ์ด๋ฆ์ ๋ํ๋ด๋ ๋ฌธ์์ด
- options(Optional): ๋ค์ ์์ฑ์ ํฌํจํ๋ ๊ฐ์ฒด- ์์
```js
// CustomEvent ์์ฑ
const catFound = new CustomEvent("animalfound", {
detail: {
name: "cat",
},
});
const dogFound = new CustomEvent("animalfound", {
detail: {
name: "dog",
},
});obj.addEventListener("animalfound", (e) => console.log(e.detail.name));
// ์ด๋ฒคํธ ๋ฐ์ก
obj.dispatchEvent(catFound);
obj.dispatchEvent(dogFound);// ์ฝ์์ "cat"๊ณผ "dog"๊ฐ ๊ธฐ๋ก๋จ
```
## ๐ ch-2 React ์๊ฐ
### ๐ React
- DOM์ ์๋ฆฌ๋จผํธ๊ฐ ์๋ฏ์ด ๋ฆฌ์กํธ ์ฑ์๋ `์๋ฆฌ๋จผํธ(Element)`๋ผ๋ ๊ฐ๋ ์ด ์๊ณ ์ด๊ฒ์ ๋ฆฌ์กํธ ์ฑ์ ๊ตฌ์ฑํ๋ ์ต์ ๋จ์๋ค.
- ์์๊ฐ ๋ชจ์ฌ ๋ฌผ์ง์ ์ด๋ฃจ๋ฏ ๋ฆฌ์กํธ ์๋ฆฌ๋จผํธ ์ฌ๋ฌ๊ฐ๋ฅผ ๋ชจ์ ๋ฆฌ์กํธ ์ฑ์ ๋ง๋ ๋ค. ๋ฆฌ์กํธ ์๋ฆฌ๋จผํธ๋ ๋ฌธ์๋ฅผ ํํํ๋ ๋ฐฉ์์ด๋ผ๋ ์ ์์ ๋ ์๋ฆฌ๋จผํธ์ ์ ์ฌํ๋ค.```
"์๋ฆฌ๋จผํธ(Element)"๋ ๋ฆฌ์กํธ ์ฑ์ ๊ตฌ์ฑํ๋ ์ต์ ๋จ์๋ค.
```- React ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ๊ณตํ๋ API ์ค ์๋ฆฌ๋จผํธ๋ฅผ ๋ง๋ค ์ ์๋ ๊ฒ์ด ๋ฐ๋ก `createElement()` ํจ์๋ค. ์๋ ์์ ์์ "Hello world" ๋ฌธ์์ด์ ๋ด์ h1 ์๋ฆฌ๋จผํธ๋ฅผ ๋ง๋ค ๋ ์ฌ์ฉํ๋ค.
```js
React.createElement("h1", null, "Hello World"); // 6
```- ์ฝ์ ๋ก๊ทธ๋ก ๋ฐํ๋ ๊ฐ์ ์ฐ์ด๋ณด๋ฉด ๋ ์๋ฆฌ๋จผํธ์ ๋ฌ๋ฆฌ `์ผ๋ฐ ๊ฐ์ฒด`๋ค.
```
{
type: "h1",
props: {
children: "Hello World"
}
}
```- `๊ฐ์๋(Virtual Dom)`์ ๋ฆฌ์กํธ ์ดํ๋ฆฌ์ผ์ด์ ๊ณผ ๋ ์ฌ์ด์ ์์นํ๋ ๊ณ์ธต์ผ๋ก์จ ์ต์ํ์ ์ฐ์ฐ์ผ๋ก ํ๋ฉด์ ๊ทธ๋ฆฐ๋ค.
### ๐ ReactDOM
- ๋ฆฌ์กํธ๊ฐ ๋ง๋ ๊ฐ์๋์ `์ผ๋ฐ ๊ฐ์ฒด`์ด๋ค. ๋ฆฌ์กํธ๊ฐ ๊ฐ์๋์ ์ฌ์ฉํ์ง ์๊ณ ๋์ ์ง์ ์ฌ์ฉํ๋ค๋ฉด ๋ธ๋ผ์ฐ์ ์์๋ง ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ ํ๋์์์ง ๋ชจ๋ฅธ๋ค. ํ์ง๋ง ์ผ๋ฐ ๊ฐ์ฒด ๋ชจ์์ ๊ฐ๋ ๊ฐ์๋์ ์ด๊ฑธ ๋ ๋๋งํ๋ ํ๊ฒฝ์ ๋ฐ๋ผ ์ฌ๋ฌ ๊ณณ์์ ์ฌ์ฉํ ์ ์๋ค.
- ๋ฆฌ์กํธ๋ฅผ ์น ๋ธ๋ผ์ฐ์ ์์ ๋์ํ๊ฒ ํ๋ ค๋ฉด `๊ฐ์๋`์ด ๋ API ํธ์ถํ๋๋ก ํ๋ฉด ๋ ๊ฒ์ด๋ค. ์ด๋ฌํ ์ญํ ์ ํ๋ ๊ฒ์ด `ReactDOM` ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค. ๋ณดํต์ ์น ๊ฐ๋ฐ์์ ๋ฆฌ์กํธ๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํ๋ฉด `react + reactDOM`์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.```html
```
- ์ ์์ ๊ฐ ๋ฆฌ์กํธ ๋ค์์ผ๋ก ๊ฐ์ ธ์จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ฐ๋ก ReactDOM์ด๋ค.
```js
ReactDOM.render(element, document.querySelector("#app")); // 7
```- ์ดํ๋ฆฌ์ผ์ด์ ์์๋ ๋ฆฌ์กํธ ์๋ฆฌ๋จผํธ๋ฅผ ReactDOM.render() ํจ์์ ์ธ์๋ก ์ ๋ฌํ๋ค.
- `ReactDOM.render()` ํจ์๋ `๋ฆฌ์กํธ ์จ๋ฆฌ๋จผํธ`๋ฅผ ๋ฐ์์ ๊ฐ์๋์ ๋ง๋ค๊ธฐ ์์ํ๋ค.
- ์ด๋ ๊ฒ ๋ง๋ค์ด์ง ๊ฐ์๋์ ์ง์ง ๋์ ๋ฐ์๋๊ณ ๊ทธ ์์น๋ ๋ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ ์์ด๋ `app`์ ์จ๋ฆฌ๋จผํธ์ ์์์ด๋ค. ์ด๋ฐ ๊ณผ์ ์ ํตํด ๋ฆฌ์กํธ ์ดํ๋ฆฌ์ผ์ด์ ์ด ๋์ ๋ฐ์๋๋ค.
### ๐ Babel
```html
```
- ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ์ ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉํ๊ธฐ ์ํ ๋๊ตฌ๋ก ๋๋ถ๋ถ์ ๋ธ๋ผ์ฐ์ ธ๋ฅผ ์ง์ํ ์ ์๋ ์ฝ๋๋ก ๋ณํํ๋ค.
- ๋ฆฌ์กํธ ๊ณต์๋ฌธ์์๋ ๋ฐ๋ฒจ ๋ฐ์์ ํธ๋์คํ์ผ๋ฌ ์์ด๋ ๊ฐ๋ฐํ ์ ์๋ ๋ฐฉ๋ฒ์ ์๋ดํ๋ค.```
https://ko.reactjs.org/docs/react-without-es6.html
```- ํ์ง๋ง ์ค์ ๊ฐ๋ฐ ํ๋ก์ ํธ๋ฅผ ์งํ ํด๋ณด๋ฉด ์ด๊ฒ๋ง์ผ๋ก๋ ๊ธ๋ฐฉ ํ๊ณ๋ฅผ ๋๋๋ค. ์์ผ๋ก ๋ค๋ฃฐ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ ํด๋์ค ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ณด๋ค ํธํ๋ค.
- ํด๋์ค ๋ฌธ๋ฒ์ ํฌํจํ ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ ๋ ๋ฐ๋ฒจ์ด ํ์ํ๋ค. ๋ฟ๋ง ์๋๋ผ ์์ผ๋ก ์๊ฐํ JSX ๋ฌธ๋ฒ์ ์ฌ์ฉํ ๋์๋ ๋ฐ๋ฒจ์ด ํ์ํ๋ค.
- ๋ณดํต์ ํฐ๋ฏธ๋ ๋ช ๋ น์ด๋ฅผ ์คํํ๊ฑฐ๋ ์นํฉ๊ฐ์ ๋ฒ๋ค๋ฌ๋ก ํตํฉํด์ ์ฌ์ฉํ๋ค.
### ๐ ํ ํ๋ฆฟ ์ธ์ด
- ์๋ฆฌ๋จผํธ๋ฅผ ์์ฑํ ๋ `document.createElement()` ํจ์๋ฅผ ์ฌ์ฉํ๋ค.
- ํธ๋ฆฌ ํํ์ ๋์ ๋ง๊ฒ ์๋ฆฌ๋จผํธ๋ฅผ ๊ตฌ์ฑํ๋ ค๋ฉด ์๋ฆฌ๋จผํธ ๊ฐ์ `๋ถ๋ชจ-์์` ๊ด๊ณ๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค.```js
const h1 = document.createElement("h1"); // 1
const header = document.createElement("header"); // 2
header.appendChild(h1); // 3
```- ์๋ฆฌ๋จผํธ h1์ ๋ง๋ค๊ณ `(1)` ์ด๊ฑธ ์์์ผ๋ก ๊ฐ์ header ์๋ฆฌ๋จผํธ๋ ๋ง๋ ๋ค`(2)`. ๊ทธ๋ฆฌ๊ณ ๋์ appendChild() ํจ์๋ฅผ ์ด์ฉํด h1์ header์ ์์ ์๋ฆฌ๋จผํธ๋ก ๋ง๋ค์๋ค`(3)`.
- ํธ๋ฆฌ ํํ์ ์น ๋ฌธ์ ๊ตฌ์กฐ์ ์ด๋ฐ ์ฝ๋๋ ๋์ด๋๊ธฐ ๋ง๋ จ์ด๋ค. ๋ฌธ์ ๋ UI๋ฅผ ๋ํ๋ด๋ ์ฝ๋๊ฐ ์ฝ๊ธฐ ์ด๋ ต๋ค๋ ๊ฒ์ด๋ค. ์ฝ๋๋ฅผ ์ ์ฌํ ๋ค์ฌ๋ค ๋ด์ผ๋ง UI๋ฅผ ๊ฐ๋ ํ ์ ์๋ค.
- ๊ทธ๋์ ๋์์ผ๋ก ๋์ค๋ ๊ฒ์ด `ํ ํ๋ฆฟ ์ธ์ด`๋ค. ํธ๋ค๋ฐ, Pug๊ฐ ๋ํ์ ์ด๊ณ ์ต๊ทค๋ฌ์ Vue.js๋ ๋๋ฆ์ ํ ํ๋ฆฟ ๊ธฐ๋ฅ์ ์ง์ํ๋ค.
- ๋ฆฌ์กํธ ์์ฒด๋ ํ ํ๋ฆฟ ์ธ์ด๋ฅผ ์ง์ํ์ง ์๋๋ค. ๊ทธ์ผ๋ง๋ก UI๋ง ๋ด๋นํ๋ ์์ฃผ ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
- ๋ฆฌ์กํธ ์๋ฆฌ๋จผํธ๋ฅผ ์์ฑํ๋ ํจ์์ธ `createElement()`๋ก ์์ ์์๋ฅผ ์ถ๊ฐํ ์๋ ์์ง๋ง ์ฉ ์ฌ์ด ํธ์ ์๋๋ค.```js
const h1 = React.createElement("h1", null, "Hello world");
const header = React.createElement("header", null, h1);
```- ๊ฐ๋ฐ์ ํ ์๋ ์์ง๋ง ๊ฐ๋ฐํด์ผ UI๊ฐ ๋์ด๋ ์๋ก ๋ถํธํ ๊ฒ์ด ์ฌ์ค์ด๋ค. ์ฝ๊ธฐ ์ด๋ ค์ด ์ฝ๋๊ฐ ๋๊ธฐ ๋๋ฌธ์ด๋ค.
- ๋ฆฌ์กํธ์์๋ `JSX`๋ผ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ฅ ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ค.
### ๐ JSX(JavaScript XML)
- `JSX(JavaScript XML)`๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ํ์ฅ ๋ฌธ๋ฒ์ด๋ค. UI ๋ค๋ฃจ๋ ์ฝ๋์ ๊ฐ๋ ์ฑ์ ๋์ด๊ธฐ ์ํด ๊ณ ์๋ ๋ฌธ๋ฒ์ด๋ค. createElement() ํจ์๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๋ฐฉ์์ ์ฝ๊ธฐ ์ด๋ ค์ด UI ์ฝ๋๋ฅผ ๋ง๋ค ์ ๋ฐ์ ์๋ค.
- JSX๋ ๋ง์น ๋งํฌ์ ๋ฌธ๋ฒ ๊ฐ๋ค.```js
Hello world
// React.createElement('h1', null, 'Hello world')
```- JSX๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฆฌ์กํธ UI ์ฝ๋์ ๋ชจ์ต์ด HTML๊ณผ ๋ฎ๋๋ค. ๋ ๊ตฌ์กฐ์ ์ ์ฌํ๊ธฐ ๋๋ฌธ์ ์ฝ๋๋ก๋ถํฐ UI์ ์ฝ๊ฒ ์ถ์ธกํ ์ ์๋ค.
- JSX๋ก ๋ง๋ ์ฝ๋๋ `๋ฐ๋ฒจ`์ ์ํด ๋ณํ๋๋๋ฐ `React.crateElement()` ํจ์ ํธ์ถ๋ก ๋์ฒด ๋๋ค. `๋ฐ๋ฒจ REPL`์์ ์ง์ JSX ์ฝ๋๊ฐ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๋ณํ๋๋ ๋ชจ์ต์ ํ์ธํด ๋ณด์.
- ๋ถ๋ชจ/์์ ๊ด๊ณ๋ HTML๊ณผ ๊ฐ๋ค.```jsx
Hello world
```
- ํ์คํ UI ์ฝ๋์ ๊ฐ๋ ์ฑ์ด ๊ฐ์ ๋์๋ค. ์ด๊ฒ๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฐ๋ฒจ์ ์ํด `React.createElement()` ํจ์ ํธ์ถ๋ก ๋ณํ๋๋ค.
- ๋ฆฌ์กํธ ์๋ฆฌ๋จผํธ๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์ ๋๋ฌธ์ `ReactDOM.render()`์ ์ธ์๋ก ์ ๋ฌ๋ ์ ์๋ค.```jsx
// 1
const element = (
Hello world
);// 2
ReactDOM.render(element, document.querySelector("#app"));
```- JSX๋ ์๋ฐ์คํฌ๋ฆฝํธ ํํ์์ด๊ธฐ ๋๋ฌธ์ `๊ฐ`์ผ๋ก `ํ๊ฐ`๋๊ณ ๋ฐํ๋ ๋ฆฌ์กํธ ์จ๋ฆฌ๋จผํธ๋ฅผ element ์์์ ํ ๋นํ๋ค`(1)`.
- ์ด ์๋ฆฌ๋จผํธ๋ฅผ `ReactDOM.render()`์ ์ ๋ฌํ๋ฉด `๊ฐ์๋(Virtual Dom)`์ ๋ง๋ค๊ณ ์ด๊ฑธ `#app` ์๋ฆฌ๋จผํธ์ ๋ถ์ฌ ๋ ๋๋ง๋๊ณ ์ฐ๋ฆฌ๋์ hello world๋ ํ ์คํธ๋ฅผ ๋ณผ ์ ์๋ ๊ฒ์ด๋ค.
### ๐ค ์ค๊ฐ ์ ๊ฒ
- ๋ฆฌ์กํธ ์ฑ์ ์ด๋ฃจ๋ ์ต์๋จ์๊ฐ `๋ฆฌ์กํธ ์๋ฆฌ๋จผํธ`์ธ๋ฐ ์ด๊ฑธ ๋ฆฌ์กํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ `React.createElement()` ํจ์๋ก ๋ง๋ค์ ์๋ค.
- ๋ฆฌ์กํธ ์๋ฆฌ๋จผํธ๋ฅผ `๊ฐ์ ๋`์ผ๋ก ๋ง๋ค์ด ์ค์ ๋์ ๋ฐ์ํด ์ฃผ๋ ๊ฒ์ด ๋ฐ๋ก `ReactDOM`์ ์ญํ ์ด๋ค. ๋ฆฌ์กํธ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋ฐ๋์ ์ด ๋ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
- ๋ฆฌ์กํธ ์ฝ๋ฉ์ ํธํ๊ฒ ํ๋ ค๋ฉด `๋ฐ๋ฒจ`๊ฐ์ ํธ๋์คํ์ผ๋ฌ์ ๋์์ ๋ฐ๋ ๊ฒ์ด ์ข๋ค. ํด๋์ค, JSX ๋ฌธ๋ฒ์ ์ฌ์ฉํ ์ ์๊ฒ๋ ํด์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.
- JSX๋ `UI ์ฝ๋์ ๊ฐ๋ ์ฑ`์ ๋์ฌ์ค๋ค. ํจ์ ํธ์ถ๋ง์ผ๋ก๋ ๋ฆฌ์กํธ ์ดํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์ด ๊ฐ๋ฅํ์ง๋ง ์ฝ๊ฐ์ ๋ฌธ๋ฒ์ ๊ฐ๋ฏธํ๋ฉด ์๊ฐ๋ณด๋ค UI ๊ฐ๋ฐ ํ๊ฒฝ์ด ํธํด์ง๋ค.
## ๐ ch-3 React ์ฌ์ฉํธ
### ๐ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ
- ์๋ฆฌ๋จผํธ๊ฐ ๋ฆฌ์กํธ ์ฑ์ ๊ตฌ์ฑํ๋ ์ต์๋จ์๋ผ๋ฉด, ์ปดํฌ๋ํธ๋ UI๋ฅผ ๋ํ๋ด๋ ์๋ฆฌ๋จผํธ์ ์ดํ๋ฆฌ์ผ์ด์ ๋ก์ง์ ํฌํจํ `์์ ๊ฐ๋ `์ด๋ค.
- ๋ก์ง์ ์ปดํฌ๋ํธ์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ฉด์ UI ์๋ฆฌ๋จผํธ๋ฅผ ์ ์ดํ๋ค. ์ฐ๋ฆฌ๊ฐ ํ๋ ค๋ ๊ฒ์ ์ ๋ ฅ ๊ฐ์ด๋ผ๋ ์ํ๋ฅผ ๊ธฐ์ตํ๋ ค๋ ๊ฒ์ด๋ค. ์ปดํฌ๋ํธ๊ฐ ์ ํฉํ๋ค.```jsx
// 1
class App extends React.Component {
render() {
// 2
return (
<>
๊ฒ์
>
);
}
}ReactDOM.render(, document.querySelector("#app")); // 3
```- ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ React ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ๊ณตํ `Component ํด๋์ค`๋ฅผ `์์`ํด์ ๋ง๋๋๋ฐ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ํ๋ด๋ App ์ปดํฌ๋ํธ๋ก ์ด๋ฆ ์ง์๋ค(1).
- ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ๊ตฌ์ฑ ์์ ์ค `render()` ๋ฉ์๋๋ ๋ฆฌ์กํธ ์ฑ์ ๊ธฐ๋ณธ ๊ตฌ์ฑ ์์์ธ ๋ฆฌ์กํธ ์๋ฆฌ๋จผํธ๋ฅผ ๋ฐํํด์ ๋์ ๋ง๋๋ ์ญํ ์ ํ๋ค(2).
### ๐ State
- ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ๊ตฌ์ฑ์์ ์ค state๋ `์ปดํฌ๋ํธ์ ์ํ๋ฅผ ์ ์ฅํ๊ธฐ ์ํ ์ฉ๋`์ด๋ค. ์ด๊ฒ์ ์ปดํฌ๋ํธ๊ฐ ์ ์งํด์ผ ํ ๊ฐ์ผ๋ก์ `์ปดํฌ๋ํธ ๋ด๋ถ์์๋ง ์ ๊ทผ`ํ ์ ์๋ ์์ฑ์ ๊ฐ์ง๋ค.
- ํด๋์ค์์ state๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด `์์ฑ์ ํจ์`์์ `๋ฉค๋ฒ ๋ณ์`๋ก ๋ฑ๋กํด ์ด๊ธฐ๊ฐ์ ์ค์ ํ๋ค.```jsx
constructor() {
super() // 1
this.state = { searchKeyword: "" } // 2
}
```- App ํด๋์ค๋ React.Component ํด๋์ค๋ฅผ ์์ํ๊ธฐ ๋๋ฌธ์ ์์ฑ ์์ ์ `๋ถ๋ชจ์ ์์ฑ์ ํจ์๋ฅผ ํธ์ถ`ํด์ผ ํ๋ค(1). ๊ทธ๋ฆฌ๊ณ ๋์ ์์ฑ๋ `this`์ `state`๋ ๊ฐ์ฒด๋ฅผ ๋ฑ๋กํด ์ํ๋ฅผ ๋ง๋ค ์ ์๋ค(2).
### ๐ ์ด๋ฒคํธ ์ฒ๋ฆฌ
- ์ธํ ์์์ ๋ฌธ์๋ฅผ ์ ๋ ฅํ๋ฉด `change` ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ค. ์ด ์ด๋ฒคํธ๋ฅผ ์์ ํ๋ฉด ์ ๋ ฅํ ๊ฐ์ ์ ์ ์๋๋ฐ ์ด๊ฑธ๋ก ์ํ๋ฅผ ๊ฐฑ์ ํ๋ฉด ๋์ง ์์๊น?
- ์ปดํฌ๋ํธ์ state๋ input ์๋ฆฌ๋จผํธ์ value์ ์ฐ๊ฒฐ๋์ด ์๊ธฐ ๋๋ฌธ์ ์ ๋ ฅํ ๊ฐ์ด ๊ณง์ฅ ์ธํ ์๋ฆฌ๋จผํธ์ ํ์๋ ๊ฒ์ด๋ค.
- ๋ฆฌ์กํธ์์ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ ์ผ๋ฐ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ์ ์ฌํ๋ค. ๋ค๋ง ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ด๋ฆ์ด ์กฐ๊ธ ๋ค๋ฅด๋ค. ์์ JSX์์๋ ์๊ฐ ํ๋ฏ์ด HTML์์ change ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋ ค๋ฉด `onchange` ๋ผ๋ ์ด๋ฆ์ ์์ฑ์ ์ฌ์ฉํ์ง๋ง ๋ฆฌ์กํธ์๋ onChange๋ก `์นด๋ฉ์ผ์ด์ค`๋ฅผ ์ฌ์ฉํ๋ค.```jsx
this.handleChangeInput(e)} // 1
/>
```- change ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ํด๋์ค์ handleChange ๋ฉ์๋๊ฐ ์ฒ๋ฆฌํ๋๋ก ์ฐ๊ฒฐํ๋ค.
- value ์์ฑ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก onChange๋ ์๋ฐ์คํฌ๋ฆฝํธ ํํ์์ ์ฌ์ฉํ๋ ค๋ฉด ์ค๊ดํธ๋ฅผ ์ฌ์ฉํ๋ค. ์ต๋ช ํจ์๋ฅผ ์ฌ์ฉํ๋๋ฐ ๊ฐ์ฒด๋ก ๋ฐ์ `์ด๋ฒคํธ ๊ฐ์ฒด`๋ฅผ ๊ณง์ฅ `handleChangeInput() ๋ฉ์๋์ ์ ๋ฌํ๋ค.````jsx
handleChangeInput(event) {
const searchKeyword = event.target.value
this.searchKeyword = searchKeyword
this.forceUpdate() // 1
}
```- handleChangeInput() ์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ํธ๋ค๋ฌ ์ด๋ฆ์ ์ ํ๋ค(1). `handle*`๋ก ์์ํ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ด๋ฆ์ ๋ฆฌ์กํธ ๊ด๋ก๋ฅผ ๋ฐ๋๋ค.
- ์ธํ ์๋ฆฌ๋จผํธ์ ์ฐ๊ฒฐ๋์ด ์๋ ์ํ๋ฅผ ์ด ๊ฐ์ผ๋ก ๊ฐฑ์ ํ๋ฉด ํ๋ฉด์ด ๋ฐ์ํ ๊ฒ์ด๋ค. ํ์ง๋ง ์ ์ฝ๋์ฒ๋ผ ์ง์ state ๊ฐ์ฒด๋ฅผ ์ง์ ์์ ํ๋ฉด ๋ฆฌ์กํธ ์จ๋ฆฌ๋จผํธ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
- ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ ์ค์ค๋ก ๊ทธ๋ ค์ ธ์ผ ํ ๋๋ฅผ ์๊ณ ์๊ณ ํ์ํ ๋๋ง `render()` ํจ์๋ฅผ ํธ์ถํด์ ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ๊ทธ๋ฆฐ๋ค. ๋ง์ฝ `๊ฐ์ ๋ก ์ปดํฌ๋ํธ์ render() ํจ์๋ฅผ ํธ์ถ`ํ๋ ค๋ฉด ํด๋์ค์ `forceUpdate()` ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.```jsx
handleChangeInput(event) {
const searchKeyword = event.target.value
this.setState({ searchKeyword }) // 1
}
```- ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๊ฐ `์ค์ค๋ก ์ํ์ ๋ณํ๋ฅผ ์ธ์ง`ํ๊ณ `render()๋ฅผ ํธ์ถ`ํ๋๋ก ํ๋ ๋ฐฉ๋ฒ์ด ํ์ํ๋ค. ๊ธฐ์ตํ์!! ํญ์ ์ปดํฌ๋ํธ์ ์ํ๋ฅผ ๊ฐฑ์ ํ๋ ค๋ฉด `setState()` ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์!
- ํด๋์ค๊ฐ ์ ๊ณตํ๋ setState() ๋ฉ์๋๋ก ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ค. ์ด ๋ฉ์๋๋ ์ปดํฌ๋ํธ์ ์ํ๋ฅผ ๋ณํ์ํค๊ฒ ๋ค๋ ์ปดํฌ๋ํธ์์ ์ง์ ์ ์ธ ์ฝ์์ด๋ค.
- ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๋น๋ก์ ์ปดํฌ๋ํธ๋ ์ํ ๋ณํ๋ฅผ ์ ์ ์๊ณ ๋ค์ ๊ทธ๋ ค์ผํ ์ง ์ฌ๋ถ๋ ํ๋จํ ์๋ ์๋ ๊ฒ์ด๋ค.
### ๐ ํผ ์ ์ถ(submit)๊ณผ ์ด๊ธฐํ(reset)
- ํผ์์ ์ํฐ๋ฅผ ์ ๋ ฅํ๋ฉด `submit` ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋๋ฐ ์ด๋ฅผ ์ก์์ ์ฒ๋ฆฌํ๋ ค๋ฉด, ๋ณ๊ฒฝ ์ด๋ฒคํธ๋ฅผ onChange ์์ฑ์ผ๋ก ๋ฐ๋ฏ์ด onSubmit ์์ฑ์ผ๋ก ํผ ์ ์ถ(submit)์ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค.
- form ๋ด๋ถ์์ button์ ๊ธฐ๋ณธ์ ์ผ๋ก submit ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ค.```js
this.handleSubmit(event)}>
```- button์ type="reset" ์์ฑ์ ์ํด ํผ์ reset ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํฌ ์ ์๋ค.
```js
this.handleReset()}>
```
### ๐ ๋ฆฌ์คํธ์ ํค
- ๋ฆฌ์กํธ ๊ณต์ ๋ฌธ์๋ฅผ ์ดํด๋ณด๋ฉด, `Key๋ ์๋ฆฌ๋จผํธ์ ์์ ์ ์ธ ๊ณ ์ ์ฑ์ ๋ถ์ฌํ๊ธฐ ์ํด ๋ฐฐ์ด ๋ด๋ถ์ ์๋ฆฌ๋จผํธ์ ์ง์ ํด์ผ ํฉ๋๋ค.` ๋ผ๊ณ ์ค๋ช ์ด ๋์ ์๋ค.
- ์ฌ๊ธฐ์ ๋ค์ `๊ฐ์๋(virtual dom)`์ด ๋์จ๋ค. ๋ฆฌ์กํธ ์จ๋ฆฌ๋จผํธ๋ฅผ ๊ฐ์๋์ผ๋ก ๋ง๋ค๊ณ ์ด์ ๊ฐ์๋๊ณผ ์ฐจ์ด๊ฐ ์๋ ๋ถ๋ถ๋ง ๊ณ์ฐํด ์ค์ ๋์ ๋ฐ์ํ๋ฉด์ ๋ ๋๋ง ์ฑ๋ฅ์ ์ฌ๋ฆฐ๋ค๊ณ ํ๋ค.
- ์ด๋, `ํธ๋ฆฌ ๋น๊ต`๋ฅผ ์งํํ๋๋ฐ `O(n^3)`๋งํผ์ ๊ณ์ฐ ๋ณต์ก๋๋ฅผ ๊ฐ์ง๋ค. ํ๋ฉด์ ๊ทธ๋ฆด ๋๋ง๋ค ์ด๋ฌํ ๊ณ์ฐ์ ๋นํจ์จ์ ์ด๊ณ ํ๋ฉด ๋ ๋๋ง์ ์คํ๋ ค ๋๋ฆฌ๊ฒ ๋ง๋ค ์๋ ์๋ค.
- ๊ทธ๋์ ๋ ๊ฐ์ง ๊ฐ์ ํ์ `์ฌ์กฐ์ (Reconciliation) ์๊ณ ๋ฆฌ์ฆ`์ ์ฌ์ฉํ๋ค. (1) ์จ๋ฆฌ๋จผํธ ํ์ ์ด ๋ค๋ฅผ ๊ฒฝ์ฐ์ (2) Key ๊ฐ์ด ๋ค๋ฅผ ๊ฒฝ์ฐ, ๊ฐ ๊ฐ ํ๋ฉด์ ์กฐ์ ํ๋๋ก ํ๋๋ฐ `O(n)`์ผ๋ก ๊ณ์ฐ ๋ณต์ก๋๊ฐ ํ์ฐํ๊ฒ ์ค์ด๋ ๋ค๊ณ ํ๋ค.
- ๋ฆฌ์คํธ ์จ๋ฆฌ๋จผํธ๋ li๋ฅผ ์ฌ๋ฌ ๊ฐ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์จ๋ฆฌ๋จผํธ ํ์ ์ผ๋ก ์ฐจ์ด๋ฅผ ํ๋จํ ์๋ ์๊ณ ์ด ๊ฒฝ์ฐ `์ ์ผํ ๊ฐ์ key ์์ฑ์ ์ฌ์ฉ`ํจ์ผ๋ก์จ ๋ฆฌ์กํธ๊ฐ ์ด์ ๊ฐ์๋๊ณผ ์ฐจ์ด๋ฅผ ๊ณ์ฐํ๋๋ก ์๋ ค์ผ ํ๋ค. ๋ณดํต ๋ฐ์ดํฐ์ `์์ด๋ ๊ฐ`์ ์ฌ์ฉํ๊ธฐ๋ฅผ ๊ถ์ฅํ๋ค.```jsx
```
- ๋ฐฐ์ด ๋ฉ์๋์ธ `map()`์ ์ฌ์ฉํด์์ธ์ง ๋ฉ์๋์ ๋๋ฒ ์งธ ์ธ์์ธ `index`๋ฅผ ์ฌ์ฉํ๊ธฐ๋ ํ๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ ๊ณ ์ ํ ๊ฐ์ด ์์ ๊ฒฝ์ฐ `์ตํ์ ์๋จ`์ผ๋ก ๊ณ ๋ คํ๊ณ `์ง์`ํ๋ ๊ฒ์ด ์ณ๋ค. ์ฑ๋ฅ ์ ํ๋ ํ๋ฉด์ด ๊ฐฑ์ ๋์ง ์๋ ๋ฌธ์ ๋ฅผ ๋ดํฌํ๊ธฐ ๋๋ฌธ์ด๋ค.
### ๐ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ์ ์๋ช ์ฃผ๊ธฐ
- ์ปดํฌ๋ํธ ์ํ ๋ฑ ์ด๊ธฐํ ์์
์ ์๋ฃํ๋ฉด ์ปดํฌ๋ํธ ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ค`(constructor)`
- ๊ทธ๋ฆฌ๊ณ ๋ฆฌ์กํธ ์จ๋ฆฌ๋จผํธ๋ฅผ ์ด์ฉํด ๊ฐ์๋์ ๊ทธ๋ฆฌ๊ณ ์ด๊ฑธ ์ค์ ๋์ ๋ฐ์ํ๋ค`(render)`
- ๋์ ๋ฐ์๋๋ ๊ฒ์ ๋ง์ดํธ๋๋ค๋ผ๊ณ ํํํ๋๋ฐ ๋ง์ดํธ๊ฐ ์๋ฃ๋๋ฉด`(componentDidMount)` ์ด๋ฒคํธ๋ฅผ ๋ฐ์ธ๋ฉํ๊ฑฐ๋ ์ธ๋ถ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฑ์ ์์
์ ์ํํ๋ค
- ์ปดํฌ๋ํธ๊ฐ ์ฌ๋ผ์ง๊ธฐ ์ ์ ์ฆ ๋ง์ดํธ ์ง์ ์๋`(compoentWillUnmount)` ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ ๊ฑฐํ๋ ๋ฑ ๋ฆฌ์์ค ์ ๋ฆฌ ์์
์ ํ๋ค
- ๋ง์ง๋ง์ผ๋ก ์ปดํฌ๋ํธ๋ ๋ณธ์ธ์ ์ถ์ ๋ง๊ฐํ๋ ์์๋ฅผ ๋ฐ๋ฅธ๋ค
### ๐ ์ด๋ฒคํธ ์ ํ๋ฅผ ๋ง๋ stopPropagation()
- `stopPropagation()`์ ๋ฒ๋ธ๋ง๊ณผ ์บก์ณ๋ง ๊ฐ์ ์ ํ๋ฐฉ์์ ์ฌ์ฉํ์ง ์๊ณ ๊ทธ๋ฅ ์ํ๋ ํ๊ทธ์์์ ์ด๋ฒคํธ๋ง ์ ๊ฒฝ์ฐ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ ๋ฉ์๋์ด๋ค.
```js
const keywordList = (
- this.search(item.keyword)}>
{idx + 1}
{item.keyword}
{this.state.keywordList.map((item, idx) => (
))}
);
```
- button์ ํด๋ฆญํ๋ฉด ์๋จ์ ์๋ li์ click์ด๋ฒคํธ๊ฐ ๋ฒ๋ธ๋ง์ ํตํด์ ๊ฐ์ด ์คํ๋๋ ์์ ์ด๋ค. ์ด๊ฒ์ ์๋์น ์์ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์ํ๋ค.
```js
handleRemoveHistory(e, keyword) {
e.stopPropagation();
store.removeHistory(keyword);
const historyList = store.getHistoryList();
this.setState({ historyList });
}
```
- ์ด๋ฐ ์ํฉ์ ๋ฐฉ์งํ๊ธฐ ์ํด์ `stopPropagation()`์ ์ฌ์ฉํ๋ค. `stopPropagation()`์ ์ถ๊ฐํจ์ผ๋ก์จ ์ด๋ฒคํธ ์ ํ๋ ๋์ํ์ง ์๊ณ button ํ๊ทธ ๋ด์์๋ง ํด๋ฆญ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
## ๐ ch-4 ์ปดํฌ๋ํธ
### ๐ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ์ด์
- ๊ด๋ จ๋ ์ฝ๋ ๋ฉ์ด๋ฆฌ๋ฅผ ๋ชจ์ ํ๋์ ๋
๋ฆฝ๋ ๊ฐ๋
์ผ๋ก `์ถ์ํ`ํ๋ ๊ธฐ๋ฒ์ ํ๋ก๊ทธ๋๋ฐ์์ ๊ฐ๋ฐ์์ ์ฌ๊ณ ๋ ฅ์ ๋น์ฝ์ ์ผ๋ก ๋์ฌ์ค๋ค.
- ์ํ์ UI ์ฝ๋๋ก ์ด๋ฃจ์ด์ง ํ๋ฉด ๊ฐ๋ฐ์์๋ `์ปดํฌ๋ํธ`๋ผ๋ ๊ฐ๋
์ ์ฌ์ฉํด `์ถ์ํ` ํ ์ ์๋ค.
### ๐ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ๋ก ๊ฐ์
- ๋ฆฌ์กํธ ์ปดํฌ๋ํธ์์ UI ์ํ๋ก ์ฌ์ฉํ ์ ์๋ ๊ฒ์ state ๋ง๊ณ ๋ `props`๊ฐ ์๋ค.
- State๊ฐ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ๊ด๋ฆฌ๋ ์ํ๋ผ๋ฉด props๋ ์ปดํฌ๋ํธ ์ธ๋ถ์์ ๋ค์ด์ ๋ด๋ถ UI์ ์ํฅ์ ์ค ์ ์๋ ๋
์์ด๋ค.
- ์ด ๊ฐ์ ์์กดํ ๋ฆฌ์กํธ ์จ๋ฆฌ๋จผํธ๋ฅผ ๋ง๋ค๋ฉด props ๋ณํ์ ๋ฐ๋ผ UI๊ฐ ๋ฆฌ์กํฐ๋ธํ๊ฒ ๋ฐ์ํ๋ค.
```jsx
// App.js
class App extends React.Component {
render() {
return ; // 3
}
}
// Header.js
const Header = ({ title }) => {
return (
{title}
);
};
```
- Props๋ `๊ฐ์ฒด ๋ชจ์`์ผ๋ก ์ปดํฌ๋ํธ๋ก ์ ๋ฌ๋๋ค. ์ด ๊ฐ์ผ๋ก ๋ฆฌ์กํธ ์จ๋ฆฌ๋จผํธ๋ฅผ ๋ง๋ ๋ค. ์ปดํฌ๋ํธ์ props๋ ์์ฑ ์ด๋ฆ์ผ๋ก ์ ๋ฌํ๋ค. Hello ์ปดํฌ๋ํธ๋ ์ ๋ฌ๋ `name ๊ฐ`์ ๋ฐ๋ผ UI๊ฐ ๋ณ๊ฒฝ๋ ๊ฒ์ด๋ค.
### ๐ ์กฐํฉ: ์ปดํฌ๋ํธ ๋ด๊ธฐ
- ๋ฆฌ์กํธ ํด๋์คํ ์ปดํฌ๋ํธ๋ ํด๋์ค ์์์ผ๋ก ์ปดํฌ๋ํธ ์ฌํ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์๋๋ค.
```
Facebook์์๋ ์์ฒ ๊ฐ์ React ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ง๋ง,
์ปดํฌ๋ํธ๋ฅผ ์์ ๊ณ์ธต ๊ตฌ์กฐ๋ก ์์ฑ์ ๊ถ์ฅํ ๋งํ ์ฌ๋ก๋ฅผ ์์ง ์ฐพ์ง ๋ชปํ์ต๋๋ค.
- ์ถ์ฒ: ๋ฆฌ์กํธ ๋ฌธ์
```
- ๋์ , props๋ฅผ ํตํด ์ปดํฌ๋ํธ๋ฅผ ํฉ์ฑํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค.
```jsx
const List = ({ data, onClick, renderItem }) => {
return (
- onClick(item.keyword)}>
{renderItem(item, idx)}
{data.map((item, idx) => (
))}
);
};
```
- ํด๋์ค๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ํจ์ ์ปดํฌ๋ํธ๋ก ๋ง๋ List์ปดํฌ๋ํธ์ด๋ค. ์ธ๋ถ์์ ๋ ๋๋ง์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ฃผ์
๋ฐ๊ฒ ๋ค๋ ์๋์ด๋ค.
- ํค์๋ ๋ชฉ๋ก ๋ฐ์ดํฐ๋ฅผ props.data๋ก ๋ฐ์๋ค.
- ๋ฆฌ์คํธ ์ถ๋ ฅ๊น์ง๋ง ๋ด๋นํ๊ณ ๋ฆฌ์คํธ๋ฅผ ๊ตฌ์ฑํ๋ ๊ฐ ํญ๋ชฉ์ ์ถ๋ ฅํ๋ ํจ์๋ props.renderItem์ด๋ ์ด๋ฆ์ผ๋ก ์ ๋ฌํ๋๋ก ํ๋ค.
- ์ฐธ๊ณ ๋ก, props์ ํจ์๋ฅผ ์ ๋ฌํ ์ ์๋ค. ์ด๋ฌํ ํจ์ ์ค ๋ฆฌ์กํธ ์๋ฆฌ๋จผํธ๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ `render props`๋ผ๊ณ ํ๋ค.
```jsx
const KeywordList = ({ onClick }) => {
const [data, setData] = useState([]);
const renderItem = useCallback((item, idx) => {
return (
<>
{idx + 1}
{item.keyword}
>
);
});
useEffect(() => {
setData(store.getKeywordList());
}, []);
return ;
};
```
- ์ List ์ปดํฌ๋ํธ๋ฅผ ์ด์ฉํ KeywordList ํจ์ํ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์๋ค.
- List ์ปดํฌ๋ํธ๊ฐ `๊ณตํต ๋ก์ง`๊ณผ `UI`๋ฅผ ๋ด๋ ์ปดํฌ๋ํธ์ด๊ณ , ์ด๋ฅผ ์ด์ฉํด์ KeywordList๋ฅผ ๋ง๋ค์๋ค.
- ํด๋์ค ์์๊ณผ ๋ฌ๋ฆฌ List์์ renderItem์ด๋ render props๋ฅผ ์ ๋ฌํด์ List๊ฐ ์ปดํฌ๋ํธ๋ฅผ ๊ทธ๋ฆฌ๋๋ก ํ๋ค. ๋ฟ๋ง์๋๋ผ ์ปดํฌ๋ํธ ์์ฒด๋ก props๋ฅผ ์ ๋ฌํ ์ ์๋ค.
- ์ด๋ ๊ฒ props๋ก `์ปดํฌ๋ํธ๋ฅผ ์ ๋ฌ`ํ๊ฑฐ๋ `๋ ๋ํ๋ ๋ฐฉ๋ฒ์ ์ ๋ฌ`ํ๋ ๋ฐฉ์์ `์ปดํฌ๋ํธ ๋ด๊ธฐ`๋ผ๊ณ ๋ถ๋ฅธ๋ค.
### ๐ ์กฐํฉ: ํน์ํ
- ์ปดํฌ๋ํธ ๋ด๊ธฐ ๋ง๊ณ ์ปดํฌ๋ํธ๋ฅผ ์กฐํฉํ๋ ๋ฐฉ์์ผ๋ก ํน์ํ๊ฐ ์๋ค.
```jsx
onst List = ({ data, onClick, hasIndex, hasDate, onRemove }) => {
const handleClickRemove = useCallback((e, keyword) => {
e.stopPropagation();
onRemove(keyword);
}, []);
return (
- onClick(item.keyword)}>
{hasIndex && {idx + 1}}
{item.keyword}
{hasDate && (
{formatRelativeDate(item.date)}
)}
{!!onRemove && (
handleClickRemove(e, item.keyword)}
>
)}
{data.map((item, idx) => (
))}
);
};
```
- ๊ธฐ์กด์ ์ปดํฌ๋ํธ ๋ด๊ธฐ๋ณด๋ค ์ธ๋ถ์์ ๋ฐ๋ props๊ฐ ์ฆ๊ฐ ํ๋ค. props๋ฅผ ์ด๋ป๊ฒ ์ค์ ํ๋๋์ ๋ฐ๋ผ ์กฐ๊ธ์ฉ ๋ค๋ฅธ ๋ชจ์๊ณผ ํ์๋ฅผ ํ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋๋๋ฐ ์ฌ์ฉํ๋ค.
- ์ ์์ ์์๋ hasIndex๋ฅผ ์ค์ ํ๋ฉด ์ข์ธก์ ์์๋ฅผ ํ์ํ๋๋ก ํ๊ณ , hasDate์ onRemove ํจ์์ ๋ฐ๋ผ ๋ ์ง์ ์ญ์ ๋ฒํผ์ ๋ณด์ด๋๋ก ํ๋ค.
```jsx
const KeywordList = ({ onClick }) => {
const [data, setData] = useState([]);
useEffect(() => {
setData(store.getKeywordList());
}, []);
return ;
};
export default KeywordList;
```
- ์ KeywordList ๋ฆฌ์คํธ์์๋ ์์์ ํค์๋๋ฅผ ํ์ํ๊ธฐ์ํด hasIndex๋ฅผ props๋ก ์ ๋ฌํ๋ค.
- KeywordList๋ ์์๊ฐ ์๋ List์ ํน์ํ ๊ฒฝ์ฐ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
### ๐ ์ปดํฌ๋ํธ ์ฌ์ฌ์ฉ ๋ฐฉ๋ฒ ์ ๋ฆฌ
- ์์. ๊ณตํต ๋ก์ง์ ๋ถ๋ชจ ํด๋์ค๊ฐ ๊ฐ๋๋ก ํ๋ค. ๋ฆฌ์คํธ ์ํ๋ฅผ ๊ฐ์ง๊ณ ์ด๋ฅผ ๋ฆฌ์คํธ ๋ ๋๋งํ๋ค. ์ ํต์ ์ธ OOP ์คํ์ผ์ ์์ ๊ตฌ์กฐ๋ฅผ ํ์ฉํ ์ ์๋ค๋ ์ ์์๋ ์ต์ํ ๋ฐฉ์์ด๋ค. ํ์ง๋ง ์์ ๋จ๊ณ๊ฐ ๋ง์์ง๋ฉด ์ฝ๋๋ฅผ ํ์ ํ๋๋ฐ ๋ค์ ์ด๋ ค์ธ ์๋ ์๋ค๋ ๋จ์ ์ด ์๋ค. ํนํ state์ ๋ฐ์ํ๋ UI ์ฝ๋๊ฐ ์์ ๊ตฌ์กฐ์ ๊ฐ๋ ค ์ ๋ณด์ด์ง ์์ ์๋ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์คํ๋ ค ๋ฆฌ์กํธ ์ปค๋ฎค๋ํฐ์์๋ ์ง์ํ๋ ๋ถ์๊ธฐ์ธ ๊ฒ ๊ฐ๋ค.
```
React๋ ๊ฐ๋ ฅํ ํฉ์ฑ ๋ชจ๋ธ์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ์์ ๋์ ํฉ์ฑ์ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ ๊ฐ์ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค. - ์ถ์ฒ: ๋ฆฌ์กํธ ๋ฌธ์ > ํฉ์ฑ vs ์์
```
- ์กฐํฉ(์ปดํฌ๋ํธ ๋ด๊ธฐ): ํจ์๋ฅผ ์กฐํฉํ๋ฏ ์ปดํฌ๋ํธ๋ฅผ ์กฐํฉํ๋ ๋ฐฉ์์ผ๋ก ์ฝ๋ ์ฌํ์ฉ์ ๊ถ์ฅํ๋ค. ๋ฆฌ์กํธ์ props ์๋ ์ด๋ ํ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ ์ ๋ฌํ ์ ์๋๋ฐ props๋ฅผ ํ์ฉํด์ ์ปดํฌ๋ํธ๋ฅผ ์กฐํฉํ๋ค. ์ฌ๊ธฐ์๋ ๋ ๋๋ง ์ฉ๋์ render props๋ฅผ ์ ๋ฌํ๋ค. ์ด ์ธ์๋ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ์์ฒด๋ฅผ ์ ๋ฌํด ์กฐํฉํ ์๋ ์๋ค.
- ์กฐํฉ(ํน์ํ): ์ด๊ฒ๋ props๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ด๋ผ๋ ์ ์์๋ ๊ฐ์ง๋ง ์ ๊ทผ์ ์ฐจ์ด๋ผ๊ณ ์๊ฐํ๋ค. KeywordList๋ List ์ปดํฌ๋ํธ์ ํน์ํ ๊ฒฝ์ฐ์ด๋ค. List ์ปดํฌ๋ํธ์ ์ข์ธก ์์๊ฐ ์๋ ํน์ํ ๊ฒฝ์ฐ์ธ ์ ์ด๋ค. HistoryList๋ ๊ทธ๋ฌํ๋ฐ ์ฐ์ธก์ ๋ ์ง์ ๋ฒํผ์ด ์์นํ List์ ํน์ํ ๊ฒฝ์ฐ์ธ ๊ฒ์ด๋ค.