React 18 beta의 Automatic Batching, 실제로 얼마나 달라지나
배경
React 18 beta가 지난 6월 공개된 후 팀 내에서 도입 검토를 시작했다. concurrent rendering보다 먼저 눈에 들어온 건 automatic batching이었다.
기존에는 React 이벤트 핸들러 내부에서만 batching이 동작했다. setTimeout이나 Promise 내부의 setState는 각각 리렌더를 발생시켰다.
기존 동작 (React 17)
function handleClick() {
fetch('/api/data').then(data => {
setLoading(false); // 리렌더 1
setData(data); // 리렌더 2
});
}
위 코드는 2번의 리렌더가 발생했다. React DevTools Profiler로 확인하면 두 개의 commit이 기록된다.
React 18에서의 변화
function handleClick() {
fetch('/api/data').then(data => {
setLoading(false);
setData(data);
// 자동으로 batching됨, 리렌더 1회만 발생
});
}
실제 프로젝트의 데이터 페칭 로직에 적용해봤다. 평균적으로 Promise 콜백 내 3~4개의 setState가 있었는데, 각각이 모두 batching 처리됐다.
성능 측정
대시보드 페이지의 초기 로딩 시나리오를 비교했다.
- React 17: 12회 렌더
- React 18: 5회 렌더
체감 성능 차이는 크지 않았지만, Profiler 상으로는 명확한 개선이 보였다.
flushSync로 opt-out
특정 상황에서 즉시 렌더링이 필요하면 flushSync를 사용할 수 있다.
import { flushSync } from 'react-dom';
flushSync(() => {
setCount(count + 1);
});
// DOM이 즉시 업데이트됨
setFlag(true);
아직 실무에서 필요한 케이스는 없었다.
결론
코드 변경 없이 얻는 최적화라 마이그레이션 부담이 적다. concurrent features는 아직 학습 중이지만, automatic batching만으로도 18 도입을 검토할 가치가 있어 보인다.