React 18+ ์๋ ๋ฐฐ์นญ(Batching)
๐ฆ Cukehater
ยท1๋ ์
2022๋ 3์ ๋ฆฌ์กํธ 18๋ฒ์ ์ด ์ถ์๋์๋๋ฐ, ์ด์ ๋ฒ์ ์ธ ๋ฆฌ์กํธ 17์ด 16์ ๋นํด ํฌ๊ฒ ๋ฌ๋ผ์ง์ง ์์ ์ ๊ณผ ๋ฌ๋ฆฌ 18๋ฒ์ ์์๋ ์ฌ๋ฌ ์๋ก์ด ๊ธฐ๋ฅ์ด ์๊ฐ๋์๋ค.
ํนํ ์๋ ๋ฐฐ์นญ์ 2๋ ์ด ์ง๋ ์ง๊ธ๊น์ง ๋ฆฌ์กํธ ์ํ๊ณ์ ๋ํ ๊น์ ์ดํด ์์ด๋ ์ฑ๋ฅ์ ์ต์ ํํ ์ ์๋ค๋ ์ ์์ ๊ฐ๋ฐ์๋ค์ด ์ฝ๊ฒ ์ ๊ทผํ๊ณ ์ดํดํ ์ ์๋ ๊ธฐ๋ฅ์ผ๋ก ํ๊ฐ๋ฐ๊ณ ์๋ค.
์ด๋ฒ ๊ธ์์๋ ๋ฆฌ์กํธ ๋ ๋๋ง ๊ณผ์ ์์ ๋ฐฐ์นญ์ ๋ํ ๊ฐ๋ ์ ์์๋ณธ๋ค.
TL;DR
๋ฆฌ์กํธ๋ ์ํ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ํด๋น ๊ฐ์ ๋ค๋ฃจ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ํธ์ถํ์ฌ ๋ ๋๋ง์ ์ํํ๊ณ , ์ปดํฌ๋ํธ๊ฐ JSX ์๋ฆฌ๋จผํธ๋ฅผ ๋ฐํํ๋ฉด ์๋ก์ด ๊ฐ์ DOM์ ์์ฑํ๋ค. ์ดํ ์์ฑ๋ ๊ฐ์ DOM์ ์ด์ ๋ฒ์ ์ ๊ฐ์ DOM๊ณผ ๋น๊ต๋์ด ์ ๋ฐ์ดํธ๊ฐ ํ์ํ ๋ถ๋ถ์ ์๋ณํ๋๋ฐ, ์ด๋ฅผ ์กฐ์ ์ด๋ผ๊ณ ํ๋ค.
์ต์ข ์ ์ผ๋ก ์ ์ฉํ ๊ฐ์ DOM์ด ๊ฒฐ์ ๋๋ฉด, ์ ์ฉ ๋จ๊ณ๋ก ๋์ด๊ฐ๊ณ ์ฌ์ฉ์๋ UI์ ๋ณ๊ฒฝ์ ๋๋ ์ ์๋ค. ๋ฆฌ์กํธ๋ ์ด๋ฌํ ๊ณผ์ ์์ ์ฌ๋ฌ ์ํ ๊ฐ์ด ๋์์ ๋ณ๊ฒฝ๋๋๋ผ๋ ํ ๋ฒ์ ์ ๋ฐ์ดํธํ์ฌ ์ฑ๋ฅ์ ํฅ์์ํค๋ ๊ธฐ๋ฅ์ ๊ฐ๊ณ ์๋๋ฐ, ์ด๋ฅผ ๋ฐฐ์นญ์ด๋ผ๊ณ ํ๋ค.
๊ธฐ์กด ๋ฐฐ์นญ์ ๋จ์ ์ Promise
, ํ์ด๋จธ ํจ์, Native Event๋ก ๋ฐ์ํ๋ ์ํ ๊ฐ ๋ณํ๋ฅผ ๊ฐ์งํ์ง ๋ชปํ์ผ๋, 18๋ฒ์ ๋ถํฐ๋ createRoot
ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ฆฌ์กํธ๊ฐ ์ด๋ฅผ ๊ฐ์งํ ์ ์๊ฒ ๋์๋ค. ์ด๊ฒ์ด ์๋ ๋ฐฐ์นญ์ด๋ค.
๋ฆฌ์กํธ์ ๋ ๋๋ง ๊ณผ์
๋ฐฐ์นญ์ ์ค๋ช ํ๊ธฐ์ ์ฐ์ ๋ฆฌ์กํธ์์ ์ํ ๊ฐ์ด ๋ณํ๋ฉด ์ด๋ค ๊ณผ์ ์ ๊ฑฐ์น๋์ง ์ดํดํ ํ์๊ฐ ์๋ค.
๋ฆฌ์กํธ ๋ ๋๋ง
์ํ ๊ฐ์ ๋ณ๊ฒฝํ๋ฉด ๋ฆฌ์กํธ๋ UI๋ฅผ ๋ณ๊ฒฝํ ์ค๋น์ ๋ค์ด๊ฐ๋๋ฐ, ๊ทธ ์ฒซ ๋ฒ์งธ ๋จ๊ณ๊ฐ ๋ ๋๋ง์ด๋ค. ์ด ๋จ๊ณ์์ ๋ฆฌ์กํธ๋ ๋ณ๊ฒฝ๋ ์ํ ๊ฐ์ ์ค์ฌ์ผ๋ก ์๋ก์ด ๊ฐ์(Virtual) DOM์ ์์ฑํ๋ค.
์ํ ๊ฐ์ด ๋ณํ๋ฉด ๋ฆฌ์กํธ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ํธ์ถ(๋ฆฌ๋ ๋๋ง)ํ์ง๋ง ์ํ ๊ฐ์ด ๋ณํ๋ ์ฆ์ ์ปดํฌ๋ํธ๊ฐ ํธ์ถ๋๋ ๊ฒ์ ์๋๋ค. ๋ฆฌ์กํธ๋ ์ปดํฌ๋ํธ๋ฅผ ์ธ์ ํธ์ถํด์ผํ ์ง ์ต์ ์ ์๊ฐ์ ๊ณ์ฐํ์ฌ ์ ์ ํ ํ์ด๋ฐ์ ์ํ ๊ฐ์ด ๋ณ๊ฒฝ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ํธ์ถํ๋๋ฐ, ์ด๋ ๋ฆฌ์กํธ๋ง์ด ๊ทธ ๊ถํ์ ๊ฐ์ง๋ฉฐ ์ธ์ ์ปดํฌ๋ํธ๋ฅผ ํธ์ถํ ์ง๋ ์ฐ๋ฆฌ๊ฐ ์ ์ ์๋ค.
์กฐ์ (Reconciliation)
์ปดํฌ๋ํธ๊ฐ ๋ค์ ํธ์ถ๋๋ฉด ๋ณ๊ฒฝ๋ ์ํ ๊ฐ์ ๋ฐํ์ผ๋ก ๊ฐ์ DOM์ ๋ค์ ๊ทธ๋ฆฐ๋ค. ์กฐ์ ๋จ๊ณ์์ ์๋ก ๊ทธ๋ ค์ง ๊ฐ์ DOM ๊ณผ ์ด์ ๊ฐ์ DOM์ ๋น๊ตํ์ฌ ์ ๋ฐ์ดํธ๊ฐ ํ์ํ ๋ถ๋ถ์ ์๋ณํ๋ค. ๋ณ๊ฒฝ ์ฌํญ์ด ์๋ณ๋๋ฉด, ์ค์ DOM์ ๋ํ ์ ๋ฐ์ดํธ๋ฅผ ์ต์ํํ๊ธฐ ์ํด ์ ๋ฐ์ดํธ๊ฐ ํ์ํ ์ปดํฌ๋ํธ๋ง ๋ค์ ๋ ๋๋งํ๋ค.
์ ์ฉ(Commit)
์ต์ข ์ ์ผ๋ก ์ด์ ๋จ๊ณ์์ ์๋ณ๋ ์ ๋ฐ์ดํธ๊ฐ ์ค์ (Actual) DOM์ ๋ฐ์๋๋ค. ์ ์ฉ ๋จ๊ณ๊น์ง ์๋ฃ๋๋ฉด ์ฌ์ฉ์๋ ๋น๋ก์ ํ๋ฉด ์์์ ๋ณํ๋ UI๋ฅผ ํ์ธํ ์ ์๋ค.
๋ฆฌ์กํธ ๋ฐฐ์นญ
๋ฆฌ์กํธ์์ ๋ฐฐ์นญ์ ์ํ ๊ฐ์ ๋ณํ๋ก ์ธํด ๋ฐ์ํ๋ ์ฌ๋ฌ ์ ๋ฐ์ดํธ๋ฅผ ํ๋์ ๊ทธ๋ฃน์ผ๋ก ๋ฌถ์ด์ ์ฒ๋ฆฌํ๋ ๋ฉ์ปค๋์ฆ์ ๋งํ๋ค.
์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ ์์ ์ ์ฌ๋ฌ ์ํ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ ์ฝ๋๊ฐ ์๋ค๋ฉด, ๋ฆฌ์กํธ๋ ์ด๋ฅผ ๋ชจ๋ ๊ธฐ๋ค๋ฆฐ๋ค. ๋จ ํ๋์ ์ํ ๊ฐ์ด ๋ณ๊ฒฝ๋์๋ค๊ณ ํด์ ๋ฐ๋ก ๋ ๋๋ง ๋จ๊ณ๋ก ๋์ด๊ฐ๋ ๊ฒ์ด ์๋๋ผ ๊ฐ์ ์ด๋ฒคํธ ์ฃผ๊ธฐ์์ ์ฒ๋ฆฌํ ์ ์๋ ๋ณ๊ฒฝ์ ์ ํ๋์ ๊ทธ๋ฃน์ผ๋ก ์ฒ๋ฆฌํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํ๋ค.
์ฆ, ๋ฆฌ์กํธ ๋ฐฐ์นญ์ ๋ฆฌ์กํธ์ ์ํ ๊ฐ์ ์ผ์ ํ ์ฃผ๊ธฐ๋ก ์ฒ๋ฆฌํ๋ ์์ ์ ๋งํ๋ค.
์์๋ฅผ ํตํด ๋ฐฐ์นญ์ ์ดํด๋ณด์.
์๋ ์ฝ๋๋ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ํ A
, B
, C
์ ์์์ ์ซ์๋ฅผ ํ ๋นํ๊ณ useEffect
์์ ๊ฐ์งํ์ฌ ๋ก๊ทธ๋ฅผ ์ถ๋ ฅํ๋ค.
javascript
import { useEffect, useState } from 'react'
const setRandomNumber = () => {
return Math.floor(Math.random() * 100) + 1
}
export default function App() {
const [A, setA] = useState(0)
const [B, setB] = useState(0)
const [C, setC] = useState(0)
const handleClick = () => {
setA(setRandomNumber)
setB(setRandomNumber)
setC(setRandomNumber)
}
useEffect(() => {
console.log(`A: ${A}, B: ${B}, C: ${C}, Total: ${A + B + C}`)
}, [A, B, C])
return (
<>
<button onClick={handleClick}>์ฌํ ๋น</button>
<h4>A: {A}</h4>
<h4>B: {B}</h4>
<h4>C: {C}</h4>
</>
)
}

์ํ A
, B
, C
๊ฐ ๋์์ ๋ณ๊ฒฝ๋์ด๋ ๋ฐฐ์นญ ๋๋ถ์ ์ํ ๊ฐ์ ํ๋์ ๊ทธ๋ฃน์ผ๋ก ๋ณ๊ฒฝ๋์ด ํ ๋ฒ์ ๋ ๋๋ง๋ง ๋ฐ์ํ๋ค.
๋ฆฌ์กํธ 17๋ฒ์ ์์ ๋ฐฐ์นญ
๋ฆฌ์กํธ 17๋ฒ์ ๊น์ง๋ ์ ์ ์ด๋ฒคํธ์ ์ฐ๊ฒฐ๋ ํจ์ ๋ด์์ ๋ณ๊ฒฝ๋ ์ํ ๊ฐ๋ง ๋ฐฐ์นญ์ ๋ฒ์ ์์ ๋ค์ด์๋ค๋ ๋ฌธ์ ์ ์ด ์์๋ค. ๋ฐ๋ผ์ setTimeOut
๊ณผ ๊ฐ์ ํ์ด๋จธ ํจ์์ Promise
, Native Event๋ฑ์ ๋ฐฐ์นญ์ ํจ๊ณผ๋ฅผ ๋๋ฆด ์ ์์๊ณ ์ด๋ฌํ ์ ์ ์ฑ๋ฅ ์ต์ ํ์๋ ๊ฑฐ๋ฆฌ๊ฐ ๋ฉ์ด์ก๋ค.
์ ์์ ์ฝ๋์์ ๋น๋๊ธฐ๋ก ์คํ๋๋ ์ฝ๋๋ฅผ ์ถ๊ฐํด ๋ณด์.
javascript
const timer = (t) => {
return new Promise(res => setTimeout(res, t));
}
๊ทธ๋ฆฌ๊ณ ๋ฆฌ์กํธ์ ์ด๋ฒคํธ ํจ์๋ฅผ ๋ณ๊ฒฝํ๋ค.
javascript
const handleClick = async () => {
await timer(0);
setA(setRandomNumber)
setB(setRandomNumber)
setC(setRandomNumber)
};
๋ฆฌ์กํธ 17๋ฒ์ ์์ ํด๋น ์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์๋ค.

๋ฆฌ์กํธ 17๋ฒ์ ๊น์ง๋ ํ๋ก๋ฏธ์ค๊ฐ ์ฌ์ฉ๋๋ฉด ํด๋น ์ฝ๋๋ ๋ฐฐ์นญ ๊ทธ๋ฃน์ ํฌํจ์ํค์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ๋ก๊ทธ๊ฐ ์ธ ๋ฒ์ฉ ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋ฆฌ์กํธ 18๋ฒ์ ์์ ๋ฐฐ์นญ
๋ฆฌ์กํธ 18๋ฒ์ ์์๋ Root ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ด createRoot
ํจ์๋ก ๋ณ๊ฒฝ๋์๊ณ ,Promise
์ ํ์ด๋จธ ํจ์, Native Event ๋ชจ๋ ์ด์ ๋ ๋ฆฌ์กํธ๊ฐ ์์์ ๊ฐ์ ์ฃผ๊ธฐ์์ ์ฒ๋ฆฌํ๊ณ ์ด๋ฒคํธ๋ฅผ ๋ถ๋ฅํ ์ ์๊ฒ ๋์๋ค.
์ด ๊ธฐ๋ฅ์ ์๋ ๋ฐฐ์นญ์ด๋ผ๊ณ ํ๋ค.
javascript
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
)


๐ฆ Cukehater
๊ฐ๋ฐ ๊ฒฝํ๊ณผ ๊ธฐ์ ์ ์ธ์ฌ์ดํธ๋ฅผ ๊ณต์ ํฉ๋๋ค ๐ปโจ