๐ ํต์ฌ ๊ฐ๋ ์ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
์นดํ์์ ์ฃผ๋ฌธ์ ๋ฐ๋ ์ง์์ด ์๋ค๊ณ ์์ํด๋ณด์ธ์.
์ผ๋ฐ ์๋ (๋๊ธฐ, sync): ์ฃผ๋ฌธ → ์ปคํผ ๋ง๋ค๊ธฐ → ๋ค์ ์๋ ๋ฐ๊ธฐ. ๋ฌด์กฐ๊ฑด ํ ๋ฒ์ ํ ๋ช ์ฉ ์์๋๋ก ์ฒ๋ฆฌํฉ๋๋ค.
์นดํ ์ง์ (๋น๋๊ธฐ, async): ์ฃผ๋ฌธ์ ๋ฐ์ ๋ค ์ปคํผ ๊ธฐ๊ณ์ ๋ฒํผ ๋๋ฌ๋๊ณ → ์ปคํผ๊ฐ ๋์ค๋ ๋์ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ → ๋ค์ ์๋ ์ฃผ๋ฌธ์ ๋จผ์ ๋ฐ์ต๋๋ค. ์ปคํผ๋ ๋์ค์ ์์ฑ๋๋ฉด ๊ฐ์ ธ๋ค์ค๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์ ๋ฆฌ์กํธ๊ฐ ๋ฑ ์ด ์นดํ ์ง์์ฒ๋ผ ๋์ํฉ๋๋ค.
๐ 1๋จ๊ณ — ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ธฐ๋ณธ: ์ฝ๋๋ ์์์ ์๋๋ก ์คํ๋๋ค (๋๊ธฐ)
๋ณดํต ์ฝ๋๋ ๊ทธ๋ฅ ์์์ ์๋๋ก ์์๋๋ก ์คํ๋ฉ๋๋ค.
console.log(1 + 1) // 2 ์ถ๋ ฅ
console.log(2 + 1) // 3 ์ถ๋ ฅ
console.log(3 + 1) // 4 ์ถ๋ ฅ
์ฝ์์ 2, 3, 4 ์์๋๋ก ์ถ๋ ฅ๋ฉ๋๋ค. ๋น์ฐํ ์๊ธฐ์ฒ๋ผ ๋ค๋ฆฌ์ฃ ?
๐ 2๋จ๊ณ — ๊ทธ๋ฐ๋ฐ ํน๋ณํ ํจ์๋ค์ ๋ค๋ฅด๊ฒ ๋์ํ๋ค (๋น๋๊ธฐ)
ajax, ์ด๋ฒคํธ๋ฆฌ์ค๋, setTimeout ๊ฐ์ ํจ์๋ค์ ์ฒ๋ฆฌํ๋ ๋ฐ ์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค. ์๋ฅผ ๋ค์ด ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ajax๋ ์ธํฐ๋ท ์ํฉ์ ๋ฐ๋ผ 1์ด, 10์ด๋ ๊ฑธ๋ฆด ์ ์์ต๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ์ด๋ฐ ์ฝ๋๋ฅผ ๋ง๋๋ฉด "์ด๊ฑฐ ์ค๋ ๊ฑธ๋ฆฌ๋๊น ์ผ๋จ ์ ์ณ๋๊ณ ์๋ ์ฝ๋ ๋จผ์ ์คํํ ๊ฒ!" ํฉ๋๋ค.
console.log(2) // โ ๋จผ์ ์คํ → 2 ์ถ๋ ฅ
axios.get('/data').then(() => {
console.log(3) // โข ajax ์๋ฃ๋๊ณ ๋์ → 3 ์ถ๋ ฅ
})
console.log(4) // โก ajax ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋จผ์ ์คํ → 4 ์ถ๋ ฅ
๊ฒฐ๊ณผ: 2 → 4 → 3 ์์ผ๋ก ์ถ๋ ฅ๋ฉ๋๋ค.
์ฌ์ง์ด ajax๊ฐ 0.001์ด๋ฐ์ ์ ๊ฑธ๋ ค๋ 2 → 4 → 3 ์ ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์ ํน์ฑ์ด ๊ทธ๋ ์ต๋๋ค.
๐ 3๋จ๊ณ — ๋ฆฌ์กํธ์ setState๋ ๋น๋๊ธฐ์ ๋๋ค!
์ฌ๊ธฐ์๋ถํฐ๊ฐ ์ง์ง ์ค์ํฉ๋๋ค.
๋ฆฌ์กํธ์์ state๋ฅผ ๋ฐ๊ฟ ๋ ์ฐ๋ setState ํจ์ (setCount, setName ๋ฑ)๋ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค. ์ฆ, ์คํ์ ์์ฒญํด๋๊ณ ์๋ฃ๋๊ธฐ ์ ์ ๋ค์ ์ค ์ฝ๋๊ฐ ๋จผ์ ์คํ๋ ์ ์์ต๋๋ค.
๐ ์ค์ ๋ฒ๊ทธ ์์ — "์ ํ ๋ฒ ๋ ์คํ๋์ง?"
์๋ ๊ฐ์ ๊ธฐ๋ฅ์ ๋ง๋ค๊ณ ์ถ๋ค๊ณ ํด๋ด ์๋ค.
๋ฒํผ์ ๋๋ฅผ ๋๋ง๋ค ๋์ด๊ฐ 1์ฉ ๋์ด๋๋๋ฐ, 3๋ฒ ์ด์ ๋๋ฅด๋ฉด ๋์ด๊ฐ ๋ ์ด์ ๋์ง ์์์ผ ํ๋ค.
(20์ด์์ ์์ํด์ 22์ด์์ ๋ฉ์ถฐ์ผ ํจ)
function App() {
let [count, setCount] = useState(0) // ๋ฒํผ ๋๋ฅธ ํ์
let [age, setAge] = useState(20) // ๋์ด
return (
<div>
<p>๋์ด: {age}์ด</p>
<button onClick={() => {
setCount(count + 1) // โ count๋ฅผ +1
if (count < 3) { // โก count๊ฐ 3 ๋ฏธ๋ง์ด๋ฉด
setAge(age + 1) // โข ๋์ด๋ +1
}
}}>
๋๋ฅด๋ฉด ํ ์ด ๋จน๊ธฐ
</button>
</div>
)
}
์ธ๋ป ๋ณด๋ฉด ๋ง๋ ์ฝ๋ ๊ฐ์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ์ค์ ๋ก ๋๋ ค๋ณด๋ฉด 23์ด๊น์ง ์ฆ๊ฐํฉ๋๋ค. 22์ด์์ ๋ฉ์ถฐ์ผ ํ๋๋ฐ ์ ๊ทธ๋ด๊น์?
๐ ๋ฒ๊ทธ์ ์์ธ
๋ฒํผ์ ์ธ ๋ฒ์งธ ๋๋ ์ ๋๋ฅผ ๋ถ์ํด๋ณด๋ฉด:
โ setCount(count + 1) ์คํ → count๋ฅผ 3์ผ๋ก ๋ฐ๊ฟ๋ฌ๋ผ๊ณ ์์ฒญ
↓ ๊ทธ๋ฐ๋ฐ ์ด ์์
์ด ๋น๋๊ธฐ๋ผ์ ์์ง ์๋ฃ๊ฐ ์ ๋จ!
↓ count๋ ์์ง 2์ธ ์ํ
โก if (count < 3) ์ ์ฒดํฌ → count๊ฐ ์์ง 2๋๊น ์กฐ๊ฑด์ด ์ฐธ!
↓ setAge(age + 1) ์คํ๋จ → ๋์ด๊ฐ ๋ +1
โข ๋์ค์ setCount๊ฐ ์๋ฃ๋์ด count๊ฐ 3์ด ๋จ
์ฆ, "count๋ฅผ 3์ผ๋ก ๋ฐ๊ฟ๋ผ" ๋ ์์ฒญ์ ํด๋จ์ง๋ง ์์ง ์๋ฃ๋๊ธฐ ์ ์ if (count < 3) ์ ์ฒดํฌํด๋ฒ๋ฆฌ๋๊น, count๊ฐ ์ฌ์ ํ 2๋ก ๋ณด์ฌ์ ๋์ด๊ฐ ํ ๋ฒ ๋ ์ฆ๊ฐํ๋ ๊ฒ๋๋ค.
โ ํด๊ฒฐ์ฑ — useEffect ํ์ฉ
ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ด๋ ์ต๋๋ค. "count๊ฐ ์์ ํ ๋ฐ๋๊ณ ๋ ๋ค์์ age๋ฅผ ๋ฐ๊พธ๋ ์ฝ๋๋ฅผ ์คํํด๋ผ" ๊ณ ์์๋ฅผ ๋ณด์ฅํด์ฃผ๋ฉด ๋ฉ๋๋ค. ์ด๋ useEffect๋ฅผ ์๋๋ค.
function App() {
let [count, setCount] = useState(0)
let [age, setAge] = useState(20)
// count๊ฐ ๋ณ๊ฒฝ๋ ์ดํ์ ์คํ๋จ
useEffect(() => {
if (count !== 0 && count < 3) { // count๊ฐ 0(์ด๊ธฐ๊ฐ)์ผ ๋๋ ์ ์ธ
setAge(age + 1)
}
}, [count]) // count๊ฐ ๋ฐ๋ ๋๋ง ์ด ์ฝ๋ ์คํ
return (
<div>
<p>๋์ด: {age}์ด</p>
<button onClick={() => {
setCount(count + 1) // ๋ฒํผ ๋๋ฅด๋ฉด count๋ง ๋ฐ๊ฟ
}}>
๋๋ฅด๋ฉด ํ ์ด ๋จน๊ธฐ
</button>
</div>
)
}
๋์ ์์
โ ๋ฒํผ ํด๋ฆญ → setCount(count + 1) ์คํ
โก count๊ฐ ์์ ํ ๋ณ๊ฒฝ๋จ
โข useEffect ๋ฐ๋ → ์ด ์์ ์ count๋ ์ง์ง ์ ๊ฐ
โฃ if (count !== 0 && count < 3) ์ฒดํฌ → ์ ํํ ๊ฐ์ผ๋ก ํ๋จ
โค ์กฐ๊ฑด์ ๋ง์ผ๋ฉด setAge(age + 1) ์คํ
์ด๋ ๊ฒ ํ๋ฉด count๊ฐ 3์ด ๋ ์๊ฐ๋ถํฐ count < 3 ์กฐ๊ฑด์ด ๊ฑฐ์ง์ด ๋์ด ๋์ด๊ฐ ๋ ๋์ง ์์ต๋๋ค. 22์ด์์ ์ ํํ ๋ฉ์ถฅ๋๋ค!
๐ก count !== 0 ์กฐ๊ฑด์ ์ถ๊ฐํ ์ด์ : useEffect๋ ํ์ด์ง๊ฐ ์ฒ์ ๋ก๋๋ ๋๋ ํ ๋ฒ ์คํ๋ฉ๋๋ค. ๊ทธ๋ count๋ 0์ธ๋ฐ, ์ด ์์ ์ ๋์ด๊ฐ ๋์ด๋ฒ๋ฆฌ๋ฉด ์ ๋๋๊น count๊ฐ 0์ผ ๋๋ ๊ฑด๋๋ฐ๊ฒ ํ ๊ฒ๋๋ค.
๐ ํ ์ค ์ ๋ฆฌ
| ๋๊ธฐ (sync) | ์ฝ๋๊ฐ ์์์ ์๋๋ก ์์๋๋ก ์คํ๋จ |
| ๋น๋๊ธฐ (async) | ์ค๋ ๊ฑธ๋ฆฌ๋ ์์ ์ ์ ์ณ๋๊ณ ๋ค์ ์ฝ๋ ๋จผ์ ์คํ |
| setState๋ ๋น๋๊ธฐ | state ๋ณ๊ฒฝ ์์ฒญ ํ ์๋ฃ ์ ์ ๋ค์ ์ค์ด ์คํ๋ ์ ์์ |
| ํด๊ฒฐ์ฑ | useEffect๋ก "์ด state๊ฐ ๋ฐ๋ ๋ค์์ ์คํํด์ค" ์์ ๋ณด์ฅ |
setState ์ฐ๋ค๊ฐ ๊ฐ์ด ์ด์ํ๊ฒ ๋์ํ๋ค๋ฉด, "๋น๋๊ธฐ๋ผ์ ์์ง ๊ฐ์ด ์ ๋ฐ๋ ์ํ์ผ ์ ์๋ค" ๋ ๊ฑธ ๋จผ์ ๋ ์ฌ๋ ค๋ณด์ธ์!