[React] state์ ๋ฆฌ๋ ๋๋ง
โ ์ state๊ฐ ํ์ํ๊ฐ?
HTML์ด๋ React์์ UI๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ ์ธ ๊ตฌ์กฐ์ด๋ค.
๊ทธ๋ฐ๋ฐ UI๋ ์ฌ์ฉ์ ์ ๋ ฅ, ๋คํธ์ํฌ ์๋ต, ํ์ด๋จธ ๋ฑ ์ธ๋ถ ์๊ทน์ ๋ฐ๋ผ ๋ฐ๋์ด์ผ ํ๋ค.
- ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ซ์๊ฐ ์ฆ๊ฐํด์ผ ํจ
- ๋ก๊ทธ์ธํ๋ฉด ์ฌ์ฉ์ ์ด๋ฆ์ด ๋ณด์ฌ์ผ ํจ
- ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ฉด ๋ฆฌ์คํธ๊ฐ ๋ฐ๋์ด์ผ ํจ
์๋ ๋ ๋ ๋ฐฉ์
์ํ๊ฐ ๋ฐ๋ ๋๋ง๋ค ์ง์ ํจ์๋ฅผ ํธ์ถํ์ฌ ์๋์ผ๋ก ๋ ๋๋ง์ ํ ์๋ ์๋ค.
let count = 0;
function handleClick() {
count++;
document.getElementById("value").textContent = count;
}
์ด ๋ฐฉ์์ ์ด์ฉํ๋ฉด ๋ ๋ ํ์ด๋ฐ์ ํ๋จํ๊ณ ๊ฐ์ ์ถ์ ํด์ผํ๋ค. ๋ํ DOM์ ์๋์ผ๋ก ์กฐ์ํ๋ค.
๋ง์ฝ count
์ ์์กดํ๋ ๋ค๋ฅธ UI ์์๋ ๋ก์ง์ด ์์ผ๋ฉด, ๋๊ธฐํ๊ฐ ๋๋ฝ๋์ด ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ ์๋ค.
React์ state
๋ฅผ ์ด์ฉํ๋ฉด count
๋ผ๋ ์ํ ํ๋๋ง ๊ด๋ฆฌํ๋ฉด React๊ฐ UI๋ฅผ ์๋์ผ๋ก ์
๋ฐ์ดํธํด์ฃผ๊ธฐ ๋๋ฌธ์ ์์ ํ๊ณ ํจ์จ์ ์ด๋ค.
โ Vanilla JS์ DOM ์์ ๊ณผ React์ ๊ฐ์ DOM ๋น๊ต
๋ธ๋ผ์ฐ์ ๊ฐ DOM์ ๋ ๋๋งํ๋ 5๋จ๊ณ
์ผ๋ฐ์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ๋ HTML/CSS/JS๋ฅผ ๋ฐ์ ์๋ ์์๋๋ก ํ๋ฉด์ ๊ตฌ์ฑํ๋ค.
- HTML ํ์ฑ → DOM ํธ๋ฆฌ ์์ฑ
- CSS ํ์ฑ → CSSOM ํธ๋ฆฌ ์์ฑ
- DOM + CSSOM → ๋ ๋ ํธ๋ฆฌ(Render Tree) ์์ฑ
- Layout (Reflow) → ๊ฐ ์์์ ์์น, ํฌ๊ธฐ ๊ณ์ฐ
- Paint (Repaint) → ์ค์ ํฝ์ ์ ํ๋ฉด์ ์น ํจ
์ด๊ฑธ ํฉ์ณ์ ๋ ๋๋ง ํ์ดํ๋ผ์ธ ๋๋ ๋ ๋ ํธ๋ฆฌ ์์ฑ ๋ฐ ํ๋ฉด ์ถ๋ ฅ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์ผ๋ฐ JavaScript (Vanilla JS)์ ๋ฌธ์ ์
- DOM์ ์ง์ ์์ ํ ๋๋ง๋ค ์ด ํ์ดํ๋ผ์ธ์ด ์ ์ฒด ํน์ ์ผ๋ถ ์ฌ์คํ๋๋ค.
- ํนํ Layout & Paint ๋จ๊ณ๊ฐ ๋น๋ฒํ๊ฒ ๋ฐ์ํ๋ฉด ์ฑ๋ฅ ์ ํ๊ฐ ์๊ธฐ๊ณ , ์ ๋๋ฉ์ด์ , ํด๋ฆญ ๋ฐ์์ด ๋๋ ค์ง๋ ๋ ๋๋ง ๋ณ๋ชฉ(bottleneck)์ด ์๊ธด๋ค.
document.getElementById("item").style.width = "200px";
document.getElementById("item").style.height = "300px";
๋ ๋ฒ ๋ชจ๋ layout & paint๊ฐ ๋ฐ์ํ๋ค.
React๋ ์ด๋ป๊ฒ ์ต์ ํํ ๊น?
React๋ Virtual DOM(๊ฐ์ DOM)์ด๋ผ๋ ๊ตฌ์กฐ๋ฅผ ๋์ ํด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค.
๊ฐ์ DOM
- ์ค์ DOM์ ๋ฉ๋ชจ๋ฆฌ์์ ๋ณต์ ํด ๋ง๋ ๊ฐ๋ฒผ์ด ํธ๋ฆฌ ๊ตฌ์กฐ
- ์ํ(state)๊ฐ ๋ฐ๋๋ฉด, React๋ ๊ฐ์ DOM์ ๋จผ์ ์ ๋ฐ์ดํธํจ
- ์ด์ ๊ฐ์ DOM๊ณผ ๋ณ๊ฒฝ๋ ๊ฐ์ DOM์ ๋น๊ตํด์ ์ฐจ์ด์ ๋ง ๊ณ์ฐ(diffing)
๋ณ๊ฒฝ์ ๋ง ์ค์ DOM์ ๋ฐ์
- ๊ณ์ฐ์ด ๋๋๋ฉด ๊ฐ์ฅ ์ต์ํ์ DOM ์์ ๋ง ์ ์ฉ(batch update / ์ผ๊ด ์ฒ๋ฆฌ)
- ๋ ๋๋ง ํ์ ์ต์ํ → ์ฑ๋ฅ ์ต์ ํ ํจ๊ณผ
โ state
state
๋ ์ปดํฌ๋ํธ ์์์ ๋์ ์ผ๋ก ๋ณํ๋ ๊ฐ์ ์ ์ฅํ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค.
์ปดํฌ๋ํธ๋ state
๊ฐ ๋ฐ๋๋ฉด ์๋์ผ๋ก ๋ค์ ๋ ๋๋ง๋๋ฉฐ, ์ฌ์ฉ์ ์ํธ์์ฉ, ๋น๋๊ธฐ ์๋ต ๋ฑ ๋ค์ํ ์ด์ ๋ก state
๊ฐ ๋ณ๊ฒฝ๋ ์ ์๋ค.
useState
ํ
ํจ์ํ ์ปดํฌ๋ํธ์์ state
๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด React๊ฐ ์ ๊ณตํ๋ ํ
์ด๋ค.
const [state, setState] = useState(initialValue);
initialValue
:state
์ ์ด๊ธฐ๊ฐ. ์ซ์, ๋ฌธ์์ด, ๊ฐ์ฒด, ๋ฐฐ์ด, ํจ์ ๋ฑ ์ด๋ค ์๋ฃํ๋ ๊ฐ๋ฅํจ.state
: ํ์ฌ ์ํ ๊ฐsetState
: ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ํจ์ (modifier)
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // ์ด๊ธฐ๊ฐ 0
return (
<div>
<span>ํ์ฌ ๊ฐ: {count}</span>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
state๋ฅผ ๋ณ๊ฒฝํ๋ 2๊ฐ์ง ๋ฐฉ์
์ง์ ํ ๋น ๋ฐฉ์
setCount(count + 1);
- count๊ฐ ํ์ฌ ํด๋ก์ ์์ ์๋ ๊ฐ์ด๋ผ๋ฉด, ์ด๊ฑธ ๊ธฐ๋ฐ์ผ๋ก ์ ๊ฐ์ ์ง์ ๊ณ์ฐํด์ ๋ฃ๋ ๋ฐฉ์
- ์ํ ์ ๋ฐ์ดํธ๊ฐ ๋น๋๊ธฐ์ ์ด๊ธฐ ๋๋ฌธ์, ์ฌ๋ฌ ๋ฒ ์ฐ์ ํธ์ถ ์ ๊ฐ ๊ผฌ์ผ ์ ์์
- ์๋ก์ด ๊ฐ์ด ๊ธฐ์กด ์ํ์ ๋ฌด๊ดํ ๋ ์ฌ์ฉ
ํจ์ํ ์ ๋ฐ์ดํธ ๋ฐฉ์
setCount(prev => prev + 1);
- ํจ์์ ์ฒซ ๋ฒ์งธ ์ธ์ prev๋ ํ์ฌ ์ํ ๊ฐ์ ๋ปํจ
- ์ด ๋ฐฉ์์ React๊ฐ ์ต์ ์ํ ๊ฐ์ ์๋์ผ๋ก ๋ฃ์ด์ฃผ๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ ๋ฒ ์ฐ์ ํธ์ถํ๊ฑฐ๋ ๋น๋๊ธฐ ์ํฉ์์๋ ์์ ์ ์
- ๊ธฐ์กด ์ํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ณ์ฐ/๋ณํํ ๋ ์ฌ์ฉ
const [count, setCount] = useState(0);
<button onClick={() => setCount(count + 1)}>+1</button>
const [count, setCount] = useState(0);
<button onClick={() => setCount(prev => prev + 1)}>+1</button>