ย TLDR;
react๋ ํน๋ณํ ์ค์ ์ด ์๋ ์ด์ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ๋ชจ๋ ํจ์๋ฅผ ์คํํ๊ณ ๋ ํ ํ๋ฒ์ state update๋ฅผ ์ํํ๋ค.
Batching
state ์ผ๊ด์ฒ๋ฆฌ
์ฌ์ ์ ์๋ฏธ
โข
์ง๋จ, ํจ๊ป ๋ฌถ๋ค
๋ฆฌ์กํธ์์์ ์๋ฏธ
โข
ํผํฌ๋จผ์ค ๊ฐ์ ์ ์ํด ๋ค์์ state ์
๋ฐ์ดํธ๋ฅผ ํ๋์ ๋ฆฌ๋ ๋์ ๊ทธ๋ฃนํ(์ผ๊ด์ฒ๋ฆฌ) ํ๋ ๊ฒ
์ค์ํ ์์
์ํฉ
โข
์์์ ์์ ์๋์ด ์ข
์
์์๊ฒ ์ฃผ๋ฌธํ๋ ์ํฉ
โข
์๋์ ์ด 4๊ฐ์ ๋ฉ๋ด๋ฅผ ์ฃผ๋ฌธํ๋ ์ํฉ
batching
1.
์ข
์
์์ด ์๋์ ํ
์ด๋ธ์ ๋์ฐฉํด ์ฃผ๋ฌธ์ ๋ฐ์
2.
์๋์ด ๋ฉ๋ด๋ฅผ ๋ณด๋ฉฐ 4๊ฐ์ ๋ฉ๋ด๋ฅผ ์ฃผ๋ฌธํจ
3.
์ด ๋ ์ข
์
์์ 4๊ฐ์ ๋ฉ๋ด์ ๋ํ ์ฃผ๋ฌธ์ ๋ค ๋ฐ๊ณ ์นด์ดํฐ๋ก ๊ฐ์ 4๊ฐ์ ๋ฉ๋ด๋ฅผ ์ฃผ๋ฐฉ์ ์ ๋ฌ
streaming
โข
์ผ๊ด์ฒ๋ฆฌ batching๊ณผ ๋ฐ๋๋๋ ๊ฐ๋
1.
์ข
์
์์ด ์๋์ ํ
์ด๋ธ์ ๋์ฐฉํด ์ฃผ๋ฌธ์ ๋ฐ์
2.
์๋์ด ๋ฉ๋ด๋ฅผ ๋ณด๋ฉฐ 4๊ฐ์ค ์ฒซ๋ฒ์งธ ๋ฉ๋ด๋ฅผ ์ฃผ๋ฌธํจ
a.
์ข
์
์์ ๋ฉ๋ด๋ฅผ ๋ฃ์๋ง์ ์นด์ดํฐ๋ก ๊ฐ์ ์ฒซ๋ฒ์งธ ๋ฉ๋ด๋ฅผ ์ฃผ๋ฐฉ์ ์ ๋ฌ
b.
์ข
์
์์ ๋ค์ ์๋์ ํ
์ด๋ธ์ ๋์ฐฉํด ์ฃผ๋ฌธ์ ๋ฐ์
c.
์๋์ด ๋ฉ๋ด๋ฅผ ๋ณด๋ฉฐ 4๊ฐ์ค 2๋ฒ์งธ ๋ฉ๋ด๋ฅผ ์ฃผ๋ฌธํจ
d.
์ข
์
์์ ๋ฉ๋ด๋ฅผ ๋ฃ์๋ง์ ์นด์ดํฐ๋ก ๊ฐ์ ๋๋ฒ์งธ ๋ฉ๋ด๋ฅผ ์ฃผ๋ฐฉ์ ์ ๋ฌ
e.
4๊ฐ์ ๋ฉ๋ด๊น์ง ๋ฐ๋ณตโฆ
๋ฆฌ์กํธ ์์
๊ธฐ๋ณธ batching ์์
function App() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
function handleClick() {
setCount(c => c + 1); // ๋ฆฌ๋ ๋๋์ง ์์
setFlag(f => !f); // ๋ฆฌ๋ ๋๋์ง ์์
// Batching -> ๋ฆฌ์กํธ๊ฐ ์๋์ผ๋ก ๋ง์ง๋ง์ ํ๋ฒ์ ๋ฆฌ๋ ๋๋ง ํจ
}
return (
<div>
<button onClick={handleClick}>Next</button>
<h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
</div>
);
}
TypeScript
๋ณต์ฌ
โข
๋ถํ์ํ ๋ฆฌ๋ ๋๊ฐ ์ฌ๋ผ์ง๋ฏ๋ก ํผํฌ๋จผ์ค๊ฐ ๊ฐ์ ๋จ
โข
๋ฆฌ์กํธ 17๊น์ง ์์ ๊ฐ์ด ์ด๋ฒคํธํธ๋ค๋ฌ ๋ด๋ถ์์๋ง batching์ด ์ํ๋ฌ์์
๋ฆฌ์กํธ 18 batching ์์
function App() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
function handleClick() {
fetchSomething().then(() => {
// React 18 and later DOES batch these:
setCount(c => c + 1);
setFlag(f => !f);
// React will only re-render once at the end (that's batching!)
});
}
return (
<div>
<button onClick={handleClick}>Next</button>
<h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
</div>
);
}
TypeScript
๋ณต์ฌ
โข
๋ฆฌ์กํธ 18์ createRoot๋ก ์์๋ ํ๋ก์ ํธ๋ state update๋ ์์น์ ์๊ด์์ด ๋ชจ๋ batching ์
๋ฐ์ดํธ
โฆ
์ด๋ฒคํธ ํธ๋ค๋ฌ์์๋
function handleClick() {
setCount(c => c + 1);
setFlag(f => !f);
// ๋ง์ง๋ง์ ํ๋ฒ๋ง ๋ฆฌ๋ ๋๋ง
}
TypeScript
๋ณต์ฌ
โฆ
setTimeout ์ฝ๋ฐฑํจ์ ์์๋
setTimeout(() => {
setCount(c => c + 1);
setFlag(f => !f);
// ๋ง์ง๋ง์ ํ๋ฒ๋ง ๋ฆฌ๋ ๋๋ง
}, 1000);
TypeScript
๋ณต์ฌ
โฆ
fetch resolve ์์๋
fetch(/*...*/).then(() => {
setCount(c => c + 1);
setFlag(f => !f);
// ๋ง์ง๋ง์ ํ๋ฒ๋ง ๋ฆฌ๋ ๋๋ง
})
TypeScript
๋ณต์ฌ
โฆ
addEventListener ์์๋
elm.addEventListener('click', () => {
setCount(c => c + 1);
setFlag(f => !f);
// ๋ง์ง๋ง์ ํ๋ฒ๋ง ๋ฆฌ๋ ๋๋ง
});
TypeScript
๋ณต์ฌ
batching์ด ์ซ์ผ๋ฉด
import { flushSync } from 'react-dom'; // Note: react-dom, not react
function handleClick() {
flushSync(() => {
setCounter(c => c + 1);
});
// DOM ๋ฐ๋ก ์
๋ฐ์ดํธ
flushSync(() => {
setFlag(f => !f);
});
// DOM ๋ฐ๋ก ์
๋ฐ์ดํธ
}
TypeScript
๋ณต์ฌ
โข
๋ฌผ๋ก ํํ ์ผ์ด์ค๊ฐ ์๋๋ฏ๋ก ์ฃผ์ ํด์ ์ฌ์ฉ โ ๊ผญ ํ์ด์ผ ํ ๊น?๋ผ๋ ์์ธ๋ก ์ฌ์ฉํ์. ์๊ฐ๋ณด๋ค ์ธ์ผ ์๋ค.