React 18 Beta의 Automatic Batching 동작 분석

배경

프로젝트에 React 18 Beta를 적용하기 전에 주요 변경사항을 검토하던 중 Automatic Batching에 대해 테스트해봤다. 기존 React 17에서는 이벤트 핸들러 내부에서만 배칭이 동작했는데, 18에서는 범위가 확장된다고 한다.

기존 동작 (React 17)

function handleClick() {
  setCount(c => c + 1); // 배칭 O
  setFlag(f => !f);     // 배칭 O (1번 렌더링)
}

function fetchData() {
  fetch('/api/data').then(() => {
    setCount(c => c + 1); // 배칭 X
    setFlag(f => !f);     // 배칭 X (2번 렌더링)
  });
}

이벤트 핸들러 밖의 비동기 콜백에서는 각 setState마다 렌더링이 발생했다.

React 18 변경사항

function fetchData() {
  fetch('/api/data').then(() => {
    setCount(c => c + 1); // 자동 배칭
    setFlag(f => !f);     // 자동 배칭 (1번 렌더링)
  });
}

setTimeout(() => {
  setCount(c => c + 1);
  setFlag(f => !f); // 이것도 배칭됨
}, 1000);

모든 상황에서 자동으로 배칭된다. 실제로 렌더 카운터를 달아서 측정해보니 Promise, setTimeout 모두 1번만 렌더링됐다.

배칭 해제가 필요한 경우

간혹 즉시 DOM 업데이트가 필요한 경우 flushSync를 사용할 수 있다.

import { flushSync } from 'react-dom';

function handleClick() {
  flushSync(() => {
    setCount(c => c + 1);
  });
  // 여기서 DOM이 업데이트된 상태
  flushSync(() => {
    setFlag(f => !f);
  });
}

결론

대부분의 경우 성능 향상으로 이어질 것으로 보인다. 특히 비동기 데이터 페칭 후 여러 상태를 업데이트하는 패턴에서 효과가 클 것 같다. 다만 정식 릴리즈 전까지는 프로덕션 적용은 보류할 예정이다.

React 18 Beta의 Automatic Batching 동작 분석