home

batching

๊ธ€ ๋ถ„๋ฅ˜
small
ํ‚ค์›Œ๋“œ
react
์ƒ์„ฑ์ผ
2023/02/26 12:42
์ตœ๊ทผ ์ˆ˜์ •์ผ
2023/10/15 23:02
์ž‘์„ฑ์ค‘

ย 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
๋ณต์‚ฌ
โ€ข
๋ฌผ๋ก  ํ”ํ•œ ์ผ€์ด์Šค๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์ฃผ์˜ ํ•ด์„œ ์‚ฌ์šฉ โ†’ ๊ผญ ํ–ˆ์–ด์•ผ ํ• ๊นŒ?๋ผ๋Š” ์ž์„ธ๋กœ ์‚ฌ์šฉํ•˜์ž. ์ƒ๊ฐ๋ณด๋‹ค ์“ธ์ผ ์—†๋‹ค.

์ฐธ์กฐ