setState, useState๋ฅผ ๋๊ธฐ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
๋ฆฌ์กํธ(React)์ state ๋ ์ปดํฌ๋ํธ ๋ด๋ถ์ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๊ฐ์
๋๋ค.
ํด๋์คํ ์ปดํฌ๋ํธ๋ state ๋ฅผ ์ฌ์ฉํ๊ณ , ํจ์ํ ์ปดํฌ๋ํธ๋ useState ํ
(ํด๋์ค ๋ด๋ถ์์๋ ๋์ X )์ ์ฌ์ฉํฉ๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ ๋ณ์๋ฅผ ๋๊ณ ์ state๋ฅผ ์ฌ์ฉํด์ ๊ฐ์ ๊ด๋ฆฌํ ๊น์?
์ด๋ state ๊ฐ ๊ฐ๋ ํน์ฑ ๋๋ฌธ์ธ๋ฐ์. ๋ฐ๋ก ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ๋ฆฌ๋ ๋๋ง(Re-rendering)์ด ๋ฐ์ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
๋ฐ๋ผ์ ๊ฐ์ด ๋ณํํจ์ ๋ฐ๋ผ ์ค์๊ฐ(!!!)์ผ๋ก ํ๋ฉด์ด ๋ ๋๋ง๋๊ณ ๋ณํ๋ ๊ฐ์ด ํ๋ฉด์ ๋ฐ๋ก ๋ฐ์๋ฉ๋๋ค.
๊ฐ์ ๋ณํ๋ฅผ ๋ฆฌ์กํธ๋ ์์์ฐจ๋ฆด ์ ์๊ฒ ํด์ฃผ์ด์ผ ํ๋ฏ๋ก ๊ฐ์ ๋ณ๊ฒฝ์ ๋ฆฌ์กํธ๊ฐ ์ ๊ณตํ๋ ํจ์๋ฅผ ํตํด์๋ง ์ด๋ฃจ์ด์ ธ์ผ ํฉ๋๋ค.
//ํด๋์คํ ์ปดํฌ๋ํธ
class MyClass extends React.Component {
constructor(props) {
super(props);
//state
this.state = {
cnt: 0 //์ด๊ธฐํ 0
};
}
updateState = () => {
this.setState({ cnt: this.state.cnt + 1 });
}
render() {
return (
<div>
<p>๊ฐ:{this.state.cnt}</p>
<button onClick={this.updateState}>plus</button>
</div>
);
}
}
//ํจ์ํ ์ปดํฌ๋ํธ
import React, { useState } from 'react';
const MyFunc = () => {
//useState ํ
์ ํตํด state ์ฌ์ฉ
const [cnt, setCnt] = useState(0); //์ด๊ธฐํ 0
const plusNum = () => {
setCnt( cnt+1 );
}
return(
<div>
<p>๊ฐ:{cnt}</p>
{/* ํ
์ด ๋ฐํํ๋ ํจ์๋ฅผ ํตํด์๋ง ๊ฐ์ ๋ณ๊ฒฝํด์ผ ํจ */}
<button onClick={plusNum}>plus</button>
</div>
)
}
ํด๋์คํ ๋๋ ํจ์ํ์ ์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์น๊ตฌ๊ฐ ๋น๋๋ค.
plus๋ฅผ ๋๋ฅด๋ฉด ๊ฐ์ด 1์ฉ ํ๋ฌ์ค ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
ํ์ง๋ง ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ๋๋ ๊ฒฐ๊ณผ๊ฐ ์ด๋จ๊น์?
const plusNum = () => {
setCnt(cnt+1);
console.log('result:'+cnt);
}
์๋ํ ๊ฒ์ state ์ cnt+1์ ๊ฐ์ ์ค์ ํ๊ณ ์๋ก ์ค์ ๋ ๊ฐ์ ๋ฐ๋ก ์ฝ์์ฐฝ์ ์ถ๋ ฅํ๊ณ ์ถ์ ๊ฒ์ธ๋ฐ์. ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ฝ์์ฐฝ์ ๊ฒฐ๊ณผ๋ ํ ๊ฑธ์ ๋ฆ์ต๋๋ค.
์ ์ด๋ฐ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ผ๊น์?
๋ฐ๋ก ๋น๋๊ธฐ(Asynchronous)์ ํน์ฑ ๋๋ฌธ์ธ๋ฐ์.
1. ๋๊ธฐ์ ๋น๋๊ธฐ
๋๊ธฐ(Synchronous) – ์์๋๋ก ํ๋์ฉ ์ฒ๋ฆฌ.
๋น๋๊ธฐ(Asynchronous) – ์์๊ฐ ์๋ ์ด๋ฒคํธ์ ๋ฐ๋ผ ์ฒ๋ฆฌ.
์งฑ๊ตฌ์ ์ผ์์ ํตํด ๋๊ธฐ ์์
์ ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
์๋ง : “์งฑ๊ตฌ์ผ! ์ก์
๋ถ์ ๊ฐ์ ๋ก๋ณถ์ด 3์ธ๋ถ๋ง ํฌ์ฅํด ์ค๊ฒ ๋? ์ง์ ๊ฐ์ ธ์์ ๊ทธ๋ฆ์ ์ฎ๊ฒจ ๋ด๊ณ ์๋ง๋ฅผ ๋ถ๋ฌ!”
์งฑ๊ตฌ ํ๋ก์ธ์ค๋ 1.๋ก๋ณถ์ด๋ฅผ ์ฌ๋ฌ ๋๊ฐ์ 2.์ฃผ๋ฌธ์ ํ๊ณ 3.์ง์ ๋ค๊ณ ์์ 4.๋ค์ ๊ทธ๋ฆ์ ๋ด๊ณ 5.์๋ง๋ฅผ ๋ถ๋ฅด๋ ๊ณผ์ ์ด ๋ชจ๋ ์์๋๋ก ๋๊ธฐ๋ก ์งํ๋ฉ๋๋ค.
ํธ๊ธฐ์ฌ ๋ง์ ์งฑ๊ตฌ๋ ์๋ง ๋ง์ ์ ๋ค์๋ฆฌ๊ฐ ์๊ฒ ์ง๋ง์..
๊ทธ๋ ๋ค๋ฉด ๋น๋๊ธฐ ์์
์ ์ํค๋ ค๋ฉด ์ด๋ป๊ฒ ํ ๊น์?
๋น๋๊ธฐ ์๋ง : “์งฑ๊ตฌ์ผ! ์ก์
๋ถ์ ๋ก๋ณถ์ด 2์ธ๋ถ์ด๋ ์ตธ์ฝ๋น๋ฐ์ ์งฌ๋ฝ ๋๊ฐ๋ฅผ ๋ฐฐ๋ฌ ์์ผ์ ๋์ฐฉํ๋ฉด ๊ฐ์ ๊ทธ๋ฆ์ ์ฎ๊ฒจ ๋ด์์ค! ๋ฐฐ๋ฌ์ด ์ค๊ธฐ ์ ๊น์ง๋ ๋ฐฉ์ ์ฅ๋๊ฐ ์ข ์น์์ฃผ๋ฉด ์ด์ฝ๋น๋ฅผ ์ค์ง๋ ๋ชฐ๋ผ~!”
์์
์ ๊ฐ๊ฐ ์์ฒญํ๊ณ , ์์ฒญํ ์์
์ด ๊ฐ๊ฒ์์ ์งํ๋๋ ๋์ ์งฑ๊ตฌ๋ ๋ค๋ฅธ ์์
์ ํ ์ ์์ต๋๋ค.
์งฑ๊ตฌ๊ฐ ๋ฐฐ๋ฌ ์ฃผ๋ฌธ(์์
์์ฒญ )์ ํ๊ณ ๋์ฐฉํ๊ธฐ ์ ๊น์ง(์์ฒญ ์ฒ๋ฆฌ์ค )๋ ์ฅ๋๊ฐ ์น์ฐ๊ธฐ(๋ค๋ฅธ ์์
)๋ฅผ ์งํํ๋ค๊ฐ ๋ฐฐ๋ฌ์ด ์๋ฃ(์์ฒญ ์์
์๋ฃ )๋๋ฉด ๋ค์ ๊ทธ๋ฆ์ ์ฎ๊ฒจ ๋ด๋(์์ฒญ ๊ด๋ จ ์์
์งํ ) ์์
๋๋ค.
2. ๋๊ธฐ๋ก ์ฒ๋ฆฌํ๊ธฐ
๊ทธ๋ ๋ค๋ฉด ์ ์ํ์์ ์ฝ์ ์ถ๋ ฅ์ด ์
๋ฐ์ดํธ๋ ๊ฐ์ผ๋ก ๋ณ๊ฒฝ๋์ง ์๋ ์ด์ ๋ ๋ฌด์์ผ๊น์?
์ฌ๋ฌ ๊ธ๊ณผ ๋ฌธ๋ต์ ์ฐธ๊ณ ํ์ฌ ๋ด๋ฆฐ ๊ฒฐ๋ก ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋น๋๊ธฐ ํน์ฑ์ ๊ฐ๋ ์ด๋ฒคํธ ๋ฃจํ์ ์ํด setCnt ์์
์ ๋ค๋ก ๋ฐ๋ฆฌ๊ณ console.log์์
์ด ๋จผ์ ์คํ๋๊ธฐ ๋๋ฌธ์
๋๋ค.
๋ค์ ์ฝ๋์ ๊ฐ์ต๋๋ค.
const printSequence = () => {
console.log('first Call');
setTimeout(()=>{secondCall()},0)
console.log('third Call');
}
const secondCall = () => {
console.log('second Call');
}
์ฝ์์ฐฝ์ ๊ฒฐ๊ณผ๋์.
๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ๋ ํจ์๋ค์ด ์์ง๋ง ๊ธฐ๋ณธ์ ์ผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋จ์ผ ํ๋ก์ธ์ค์ด๋ฏ๋ก ๋๊ธฐ๋ก ์์
์ ํฉ๋๋ค.
ํ์ง๋ง ์์ ๊ฐ์ด ์์
์์๊ฐ ๋ค๋ฐ๋๋ ์ด์ ๋ ์ด๋ฒคํธ ๋ฃจํ๋ผ๋ ๋ณด์ด์ง ์๋ ์์ ์ํด ๋น๋๊ธฐ๋ก ์
๋ฌด๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์
๋๋ค.
๊ทธ๋ ๋ค๋ฉด setTimeout์ ํตํด console.log ์์
์๊ฐ์ ๋ค๋ก ์ฐ๊ธฐํ๋ฉด ์์
์ด ๋๋ ๋ค ๋ก๊ทธ๋ฅผ ์ฐ์ ํ
๋ ๊ฐ์ด ์ ๋๋ก ํ์๋์ง ์์๊น์?
const showAlert = () => {
setCnt(cnt+1);
setTimeout(()=>{
console.log('result(3sec):'+cnt)}
,3000);
}
plus๋ฅผ ๋ค์ฏ๋ฒ ๋๋ฅธ ๊ฐ๊ฐ์ ๊ฒฐ๊ณผ๋์.
๊ฐ์ 5๊น์ง ์ฐ์์ผ๋ ์ฝ์๋ 5๊น์ง ์ฐํ์ผ ํ์ง๋ง ์์ ๊ฐ์ด ์
๋ฐ์ดํธ ๋๊ธฐ ์ ์ ๊ฐ์ด ๋์ต๋๋ค.
์ด์ ๊ฐ ๋ฌด์์ผ๊น์?
๋ฐ๋ก setTimeout ํจ์์ ํน์ฑ ๋๋ฌธ์ธ๋ฐ์.
setTimeout ํจ์๋ ์คํํ ๋๋ง๋ค ์๋ก์ด ํจ์๊ฐ ๋ง๋ค์ด์ง๋ฉฐ ์ ๋ฌ๋๋ ํจ์ ๋ด๋ถ์ ๊ฐ์ ๋ณ์๊ฐ ์๋ ์ ๋ฌํ๋ ์์ ์ ๋ณ์์ ๊ฐ(์์)์ด ์ ๋ฌ๋๊ธฐ ๋๋ฌธ์ด๋ผ๊ณ ๋ณด๋ฉด ๋ฉ๋๋ค.
๋ฐ๋ผ์ 3์ด๊ฐ ์๋ 1000์ด ๋ค์ ์คํํ๋๋ผ๋ ์คํ๋๋ ๊ฐ์ ์ ๋ฌํ๋ ์์ ์ ๋ณ์์ ๊ฐ์
๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ ์ฝ๋๋ฅผ ๋๊ธฐ์ฒ๋ผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ผ๊น์?
state ์ค์ ์ ํด๋์คํ์ ํจ์๋ฅผ ์ ๋ฌ ํ๊ณ ํจ์ํ์ useEffect๋ฅผ ์ฌ์ฉ ํ๋ฉด ๋ฉ๋๋ค.
//ํด๋์คํ
updateState = () => {
this.setState(
{ cnt: this.state.cnt + 1 },
()=>{ console.log(this.state.cnt) }
)
}
//ํจ์ํ
const plusNum = () => {
setCnt(cnt+1);
}
useEffect(()=>{
console.log(cnt);
},[cnt])
์ด์ ์๋ํ ๋๋ก ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.
3. ๋น๋๊ธฐ๋ก ์๋ํ๋ ์ด์
๊ทธ๋ ๋ค๋ฉด state ์ค์ ์ ์ ๋น๋๊ธฐ๋ก ์๋ํ ๊น์?
์์์ ์ค๋ช
ํ๋๋ก state ๋ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํ๋๋ฐ์.
๋ณ๊ฒฝ์ด ํ๋๋ผ๋ฉด ๋ฆฌ๋ ๋๋ง์ด ํ๋ฒ๋ง ๋ฐ์ํ์ง๋ง ์์ญ ๊ฐ, ์๋ฐฑ ๊ฐ์ ๊ฐ์ด ๊ณ์ ๋ณ๊ฒฝ๋๋ค๋ฉด ๋ฆฌ์กํธ๋ ๋งค๋ฒ ๋ ๋๋ง๋ง ํ๋ค๊ฐ ์์ ๋ง๊ฐํ๊ณ ๋ง ๊ฒ์
๋๋ค. ์๋๋ ๋งํ ๊ฒ๋ ์๊ตฌ์.
๋ฐ๋ผ์ ๋ณ๊ฒฝ๋ ๊ฐ๋ค์ ๋ชจ์ ํ๋ฒ์ ์
๋ฐ์ดํธ๋ฅผ ์งํํ์ฌ ๋ ๋๋ง์ ์ค์ด๊ณ ์ ๋ฐฐ์น(Batch) ๊ธฐ๋ฅ์ ์ฌ์ฉํด ๋น๋๊ธฐ๋ก ์๋ํ๋ค๊ณ ๋ณผ ์ ์์ต๋๋ค.
์ฐธ๊ณ ๋ก ๋ฐฐ์น ์
๋ฐ์ดํธ๋ 16ms ์ฃผ๊ธฐ๋ผ๊ณ ํฉ๋๋ค!
18 ๋ฒ์ ์์ ์ถ๊ฐ๋ ์๋๋ฐฐ์น(Automatic Batching)๋ ๊ธฐ์กด์ ์ด๋ฒคํธ ํธ๋ค๋ฌ์์๋ง ์คํ๋๋ ๋ฐฐ์น๊ฐ ์ด์ ๋ setTimeout, Promise ๋ฑ์ ์ด๋ฒคํธ์์๋ ๋์๋ ์์ ์ด๋ฉฐ, flushSync() ๋ฑ์ ์ฌ์ฉํด ์์ธ๋ฅผ ๋ ์๋ ์๋ค๊ณ ํ์ฌ ๋ง์ ๊ธฐ๋๋ฅผ ๋ฐ๊ณ ์๋ ๊ฒ ๊ฐ์ ๋ฏธ๋ฆฌ ์์๋๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
์๋๋ฐฐ์น ๊ด๋ จํ ์์ธ ์ค๋ช
(์์ด)