React 18 useTransition으로 검색 입력 최적화하기
문제 상황
5000개 이상의 상품 목록을 실시간 검색하는 기능을 구현했는데, 입력할 때마다 화면이 버벅이는 문제가 발생했다. debounce를 적용했지만 여전히 타이핑 지연이 느껴졌다.
useTransition 적용
React 18에서 새로 추가된 useTransition을 사용해 문제를 해결했다.
import { useState, useTransition } from 'react';
function ProductSearch({ products }) {
const [searchTerm, setSearchTerm] = useState('');
const [filteredProducts, setFilteredProducts] = useState(products);
const [isPending, startTransition] = useTransition();
const handleSearch = (e) => {
const value = e.target.value;
setSearchTerm(value); // 긴급 업데이트
startTransition(() => {
// 비긴급 업데이트
const filtered = products.filter(p =>
p.name.toLowerCase().includes(value.toLowerCase())
);
setFilteredProducts(filtered);
});
};
return (
<>
<input
value={searchTerm}
onChange={handleSearch}
placeholder="상품 검색..."
/>
{isPending && <span>검색 중...</span>}
<ProductList products={filteredProducts} />
</>
);
}
동작 원리
setSearchTerm은 즉시 실행되어 입력 필드가 즉각 반응한다startTransition내부의 필터링은 낮은 우선순위로 처리된다- React가 알아서 긴급한 업데이트를 먼저 처리하고 나머지는 나중에 렌더링한다
isPending으로 로딩 상태 표시 가능
결과
타이핑 지연이 거의 사라졌고, debounce보다 자연스러운 UX를 제공할 수 있었다. 특히 모바일에서 체감 성능이 크게 향상되었다.
Concurrent Rendering의 실용적인 활용 사례였고, 앞으로 무거운 연산이 필요한 곳에 적극 적용할 예정이다.