React 18 alpha의 Automatic Batching 동작 확인

배경

React 18 alpha working group이 공개되면서 새로운 기능들을 미리 테스트해볼 수 있게 되었다. 그 중 Automatic Batching이 가장 체감이 클 것 같아 실험해봤다.

기존 React 17까지는 이벤트 핸들러 내부에서만 setState가 배치 처리되었다. Promise나 setTimeout 내부에서는 각 setState마다 리렌더링이 발생했다.

기존 동작 (React 17)

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

  function handleClick() {
    fetch('/api').then(() => {
      setCount(c => c + 1); // 리렌더링
      setFlag(f => !f);      // 리렌더링
    });
  }

  console.log('rendered');
  return <div>...</div>;
}

위 코드에서 handleClick 실행 시 'rendered'가 2번 찍혔다.

React 18에서의 변화

React 18부터는 Promise, setTimeout, native event handler 등 모든 곳에서 자동으로 배치 처리된다.

// React 18
fetch('/api').then(() => {
  setCount(c => c + 1);
  setFlag(f => !f);
  // 한 번만 리렌더링
});

실제로 alpha 버전으로 테스트해보니 'rendered'가 1번만 찍혔다.

flushSync로 강제 렌더링

배치를 원하지 않는 경우 flushSync를 사용할 수 있다.

import { flushSync } from 'react-dom';

flushSync(() => {
  setCount(c => c + 1);
});
// DOM 업데이트 완료
flushSync(() => {
  setFlag(f => !f);
});

소감

성능 최적화를 위해 신경 써야 했던 부분이 프레임워크 레벨에서 해결되는 건 좋은 방향이다. 다만 아직 alpha라 프로덕션 적용은 이르고, 라이브러리 호환성을 지켜봐야 할 것 같다.

React 18 alpha의 Automatic Batching 동작 확인