React 18 Concurrent Rendering 적용 후기
배경
회사 대시보드 프로젝트에서 데이터 테이블 렌더링 성능 이슈가 있었다. 수천 개 행을 렌더링할 때 입력 필드가 버벅이는 문제였다. React 18의 startTransition으로 해결할 수 있을 것 같아 마이그레이션을 진행했다.
마이그레이션
기본 업그레이드는 간단했다.
npm install react@18 react-dom@18
ReactDOM.render 를 createRoot로 변경했다.
// Before
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, document.getElementById('root'));
// After
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
startTransition 적용
검색 필터와 테이블 렌더링을 분리했다.
import { startTransition } from 'react';
const handleSearch = (value) => {
setSearchTerm(value); // 즉시 반영
startTransition(() => {
setFilteredData(filterData(value)); // 낮은 우선순위
});
};
입력 필드는 즉시 반응하고, 무거운 테이블 렌더링은 나중에 처리된다. 체감 성능이 확실히 개선됐다.
Automatic Batching
React 18부터 setTimeout, Promise 내부에서도 자동으로 배칭된다. 불필요한 리렌더링이 줄어들어 네트워크 요청 후 여러 state 업데이트를 해도 한 번만 렌더링됐다.
주의사항
서드파티 라이브러리 중 일부가 Concurrent Rendering과 호환되지 않았다. react-beautiful-dnd가 StrictMode에서 경고를 발생시켰고, 이슈를 찾아보니 업데이트 대기 중이었다. 당장은 StrictMode를 일부 컴포넌트에서 해제했다.
결론
React 18의 Concurrent 기능은 UX 개선에 효과적이었다. 마이그레이션 비용도 크지 않았다. 다만 라이브러리 호환성은 미리 확인이 필요하다.