React 18 Concurrent Rendering으로 대용량 리스트 성능 개선

문제 상황

관리자 페이지에서 5000개 이상의 주문 데이터를 테이블로 보여주는 기능이 있었다. 검색어를 입력할 때마다 전체 리스트를 필터링하면서 UI가 멈추는 현상이 발생했다. 사용자 입력이 끊기는 수준이라 개선이 필요했다.

React 18 useTransition 도입

React 18의 Concurrent Rendering 기능 중 useTransition을 사용해 긴급하지 않은 업데이트를 지연시키기로 했다.

import { useState, useTransition } from 'react';

function OrderList({ orders }) {
  const [searchTerm, setSearchTerm] = useState('');
  const [filteredOrders, setFilteredOrders] = useState(orders);
  const [isPending, startTransition] = useTransition();

  const handleSearch = (e) => {
    const value = e.target.value;
    setSearchTerm(value); // 즉시 업데이트
    
    startTransition(() => {
      // 무거운 필터링 작업은 transition으로
      const filtered = orders.filter(order => 
        order.customerName.includes(value) ||
        order.orderNumber.includes(value)
      );
      setFilteredOrders(filtered);
    });
  };

  return (
    <div>
      <input 
        value={searchTerm} 
        onChange={handleSearch}
        placeholder="주문번호 또는 고객명 검색"
      />
      {isPending && <LoadingSpinner />}
      <OrderTable data={filteredOrders} />
    </div>
  );
}

결과

  • 입력 필드는 즉시 반응하고, 리스트 필터링은 백그라운드에서 처리됨
  • isPending 상태로 로딩 인디케이터를 자연스럽게 표시 가능
  • 사용자 경험이 크게 개선되었다는 피드백을 받음

추가 고려사항

가상화 라이브러리(react-window 등)를 함께 사용하면 더 좋겠지만, 일단 간단한 API 변경만으로도 체감 성능이 향상되어 만족스러웠다. React 18의 Concurrent 기능들이 점진적으로 도입하기 좋은 구조라는 점이 인상적이었다.