서녕이네 개발단지

[React] automatic batching (자동 배칭) 본문

프론트엔드/React

[React] automatic batching (자동 배칭)

zero2-pooh 2023. 6. 12. 18:48

Automatic batching

❗️automatic batching에 들어가기 앞서 batching이 무엇인지 알아야 한다.

 

batching

- 리액트는 기본적으로 batching을 활용한다. 

 

batching (배칭)이란❓

 -이벤트 핸들러나 hooks안에서 상태 업데이트를 묶어서 동작하도록 만들어준다. 즉, 렌더링이 한 번만 일어나게 해 준다.

 

배칭(batching)은 리액트가 더 나은 성능을 위해 여러 개의 state(상태) 업데이트를  하나의 re-render가 발생하도록 그룹화하는 것을 의미한다.

function App() {
  const [count, setCount] = useState(0);
  const [flag, setFlag] = useState(false);

  function handleClick() {
    setCount(c => c + 1); // 아직 리렌더링 X
    setFlag(f => !f); // 아직 리렌더링 X
    // React는 함수가 끝나면 리렌더링 할 것이다 (-> 이것이 배칭)
  }

  return (
    <div>
      <button onClick={handleClick}>Next</button>
      <h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
    </div>
  );
}

예를 들어~ 위 예시를 보면, 

하나의 클릭 이벤트 안에 두 개의 state 업데이트를 가지는 경우, React는 항상 이러한 작업을 하나의 렌더링으로 일괄 처리하였다.

다음 코드를 실행할 경우, state를 두 번 변경하지만, React는 한 번의 렌더링만 수행한 것을 확인할 수 있다.

 


react 17에서의 batching

리액트 17에서도 batching은 존재하였지만 지원되는 범위가 리액트 18가 달랐다.

  • 오직 리액트 이벤트 핸들러 내부에서만 배칭이 적용되었다 (camel case인 onClick, onMouseMove, onLoad 등등..)
  • promises, setTimeout, native event handlers들 안에서는 배칭이 되지 않았다.❌

 


react 18에서의 batching (automatic batching)

새롭게 버전업이 된 react 18에서는 automatic batching으로 인해 react 17에서 보던 배칭과는 다른 점을 볼 수 있다.

 

 

automatic batching

- automatic batching, 자동 배칭이란❓

 

말 그대로 모든 업데이트가 자동으로 배칭 됨을 의미.

리액트 이벤트 핸들러 내부뿐만 아니라 promises, setTimeout, native event handlers들 안에서도 배칭이 적용된다.

 

 

하지만❗️  여기에는 조건이 존재한다.

  • createRoot를 사용했을 때만 automatic batching이 적용된다. ⭕️
  • 이전 legacy인 render를 사용하게 되면 리액트 18 버전이어도 automatic batching이 적용되지 않는다.❌

 

const root = ReactDOM.createRoot(document. getElementByld('root'));
 root.render(
	<React.StrictMode>
	  <App />
	</React.StrictMode>
);

👉🏻 createRoot라서 자동 배칭 적용 가능!!

 

ReactDOM.render(
  <React. StrictMode>
    <App /> 
  </React.StrictMode>,
document. getElementByld("root")
);

👉🏻 이전 legacy인 render를 사용하여 자동 배칭 적용 불가!!

 

 


batching을 원하지 않을 경우엔? (flushSync)

flushSync

배칭을 강제적으로 하지 않게 만드는 것은 흔하게 발생해서는 안 되는 일이고 일반적인 과정은 아닐 것이다.

 

하지만 일부 코드는 상태 변경 직후에 DOM에서 무언가를 읽어야 할 수도 있을 것이다.

이러한 경우에는 ReactDOM.flushSync()를 사용하여 배칭을 선택적으로 하지 않을 수도 있다.

import { flushSync } from "react-dom";

function handleClick() {
  flushSync(() => {
    setCounter((a) => a + 1);
  });
  // 이 과정이 끝났을 때 React는 DOM을 업데이트한 상태
  flushSync(() => {
    setNumber((b) => !b);
  });
  // 이 과정이 끝났을 때 React는 DOM을 업데이트한 상태
}

 

💡 flushSync안의 setState 개수가 아닌  flushSync가 하나의 렌더링으로 처리된다.

 

 

 

 

참고

https://velog.io/@dbwjd5864/React-18-automatic-batching에-대해-알아보자

https://nyol.tistory.com/146