React 18 베타에서 Concurrent Rendering 테스트해보기
배경
관리자 페이지에서 5000개 이상의 상품 리스트를 렌더링할 때 검색 입력이 버벅이는 문제가 있었다. 디바운싱을 적용했지만 입력 자체가 느린 느낌은 여전했다.
React 18 베타에서 Concurrent Rendering 기능이 공개되어 테스트 환경에 적용해봤다.
기존 코드
function ProductList() {
const [keyword, setKeyword] = useState('');
const filtered = products.filter(p =>
p.name.toLowerCase().includes(keyword.toLowerCase())
);
return (
<>
<input
value={keyword}
onChange={e => setKeyword(e.target.value)}
/>
<ul>
{filtered.map(product => (
<ProductItem key={product.id} product={product} />
))}
</ul>
</>
);
}
입력과 렌더링이 동기적으로 처리되어 입력이 블로킹됐다.
useTransition 적용
import { useState, useTransition } from 'react';
function ProductList() {
const [keyword, setKeyword] = useState('');
const [deferredKeyword, setDeferredKeyword] = useState('');
const [isPending, startTransition] = useTransition();
const handleChange = (e) => {
setKeyword(e.target.value);
startTransition(() => {
setDeferredKeyword(e.target.value);
});
};
const filtered = products.filter(p =>
p.name.toLowerCase().includes(deferredKeyword.toLowerCase())
);
return (
<>
<input value={keyword} onChange={handleChange} />
{isPending && <span>검색 중...</span>}
<ul style={{ opacity: isPending ? 0.6 : 1 }}>
{filtered.map(product => (
<ProductItem key={product.id} product={product} />
))}
</ul>
</>
);
}
입력은 즉시 반영되고, 리스트 렌더링은 낮은 우선순위로 처리되어 타이핑이 부드러워졌다.
결과
- 입력 응답성이 체감상 확실히 개선됐다
- isPending을 활용해 로딩 상태를 자연스럽게 표현할 수 있었다
- 아직 베타라 프로덕션 적용은 보류했지만, 정식 출시되면 도입할 예정이다
React 18의 Concurrent 기능들이 기존 성능 문제를 더 선언적으로 해결할 수 있게 해줄 것 같다.