대량 데이터 렌더링 문제 (리액트)

now·2025년 4월 1일

react

목록 보기
3/3

대량 데이터 렌더링 문제 최적화 방안

Scatter 차트를 react-chartjs-2 를 사용해 구현하는 과정에서 데이터 포인트가 10,000개 이상으로 증가할 경우 브라우저의 렌더링 성능이 한계를 초과하여 렌더링 시간이 과도하게 길어지거나 화면이 멈추고 오류가 발생하는 문제가 확인됨.

해결방안

  1. 많은 데이터를 나타낼 때 유용한 다른 라이브러리를 사용

    • 대부분의 고성는 차트 라이브러리는 유료이고 아직 현재 구현된 기능을 사용하는 사용자의 수가 많지 않아 고려하지 않음
  2. 렌더링 최적화 적용

    • 데이터 분할 렌더링: 한 번에 모든 데이터를 렌더링하지 않고 10,000개 단위로 배치 렌더링해 성능 부담을 줄임
    • 기존 포인트 재 렌더링 방지: 이미 렌더링된 데이터는 리렌더링 되지 않도록 불필요한 리렌더링 방지
    • 포인트 크기 최적화: 포인트의 크기를 지정하여 렌더링 시간을 낮춤
const CHUNK_SIZE = 10000;
const [data, setData] = useState<ChartData<'scatter'>>({
    datasets: [
        {
            label: '',
            data: [],
            backgroundColor: [] as string[],
            ///=========> 포인트 크기 설정
            pointRadius: 3,
            pointHoverRadius: 4,
        },
    ],
});
const dataChunks = useMemo(() => chunkData(eda || [], CHUNK_SIZE), [eda]);
const loadNextChunk = () => {
    if (chunkIndex < dataChunks.length) {
        const newChunk: any = dataChunks[chunkIndex];
        const newPoints = newChunk?.map((item) => ({
            x: item.reduced_emb[0],
            y: item.reduced_emb[1],
            edaItem: item,
        }));
        const newColors = newChunk.map((item) => colorMap[item.label]);

        setData((prevData) => ({
            datasets: [
                {
                    ...prevData.datasets[0],
                    data: [...prevData.datasets[0].data, ...newPoints],
                    backgroundColor: [...(prevData.datasets[0].backgroundColor as string[]), ...newColors],
                },
            ],
        }));

        setChunkIndex((prevIndex) => prevIndex + 1);
    }
};
    
useEffect(() => {
    if (getEda.status.isSuccess && eda) {
        loadNextChunk();
    }
}, [getEda.status.isSuccess]);

return (
	<div className='chart-area'>
	///////==========> 버튼을 추가해 데이터가 필요한 경우 만개씩 추가
	    {eda?.length > data?.datasets[0]?.data?.length && (
	        <BoButton onClick={loadNextChunk}>
	            {`more: ${data?.datasets[0]?.data?.length || 0} / ${eda?.length || 0}`}
	        </BoButton>
	    )}
	    <Scatter options={options} data={data} />
	</div>
)

0개의 댓글