본문 바로가기
프로젝트/무붕 예약 사이트 프로젝트

[프로젝트] 랜더링 최적화: 전역 상태의 문제?

by 꽁이꽁설꽁돌 2024. 10. 5.
728x90
반응형

프로젝트를 하던 도중 랜더링 부분에서 최적화의 필요성이 느껴져서 프로파일러를 켜본 순간

헉.... 최악의 랜더링이 펼쳐졌다. 그래서 내가 해결한 것을 정리해보고자 한다.

분명히 하나의 배열을 바꾸었는데 모든 것이 리랜더링 되는 모습...

 

무엇이 문제일까 계속해서 찾아보았다.

 

하면서 쿼리가 문제일까 하며 쿼리 데브툴도 쓰고 다 시도해 본 것 같다 ㅜㅜ

쿼리 캐싱 데이터를 보고 관리하기 편해서 알면 좋을 것 같다

 

 

그래서 리액트 프로파일러를 통해 원인을 찾아보았다 

hook이 원인임을 볼 수 있다.

 

그렇다면 아무리 생각해도 기존 hook에서는 문제가 될 것이 없었다.. 그렇다면 zustand로 쓴 전역상태가 문제가 있다는 것이었다. 그래서 찾아보니 프로파일러에서는 zustand도 hook으로 인식된다는 것을 알게 되었다.

 

 

아래 드래그를 전역상태로 관리한 것이 문제였다

 

전역상태의 코드

import { dragWeekendInterface } from '@/types/reservationItemTypes';
import { create } from 'zustand';



interface DragState {
  dragStartIndex: dragWeekendInterface;
  dragEndIndex: number | null;
  isDoing: string;
  setDragStartIndex: (
    index: number | null,
    weekend?: number | undefined,
  ) => void;
  setDragEndIndex: (index: number | null) => void;
  setIsDoing: (isDo: string) => void;
}

export const useDragStore = create<DragState>((set) => ({
  dragStartIndex: { index: null },
  dragEndIndex: null,
  isDoing: '',
  setDragStartIndex: (index, weekend) =>
    set((state) => ({
      dragStartIndex: weekend
        ? { index, weekend }
        : { ...state.dragStartIndex, index },
    })),
  setDragEndIndex: (index) => set({ dragEndIndex: index }),
  setIsDoing: (isDo) => set({ isDoing: isDo }),
}));

 

 

그래서 전역상태를 단일 state hook으로 바꾸었다. 또한 callback을 써주어 함수의 재호출을 막고자 하였다.

 

단일 useHook으로 만든 코드

import { useState, useCallback } from 'react';
import { reservationInterface } from '@/types/reservationItemTypes';

export const useBackDrag = () => {
  const [selectedCells, setSelectedCells] = useState<string[]>([]);

  const draggingClear = useCallback(() => {
    setSelectedCells([]);
  }, []);

  const rangeDragging = useCallback(
    (
      start: number,
      end: number,
      items: reservationInterface[],
      reservationWeekend: number,
    ) => {
      const strIdx = Math.min(start, end);
      const endIdx = Math.max(start, end);

      const selected: string[] = [];
      for (let i = strIdx; i <= endIdx; i++) {
        selected.push(`${items[i].start}-${reservationWeekend}`);
      }

      setSelectedCells(selected);
    },
    [],
  );

  return {
    selectedCells,
    setSelectedCells,
    draggingClear,
    rangeDragging,
  };
};

export default useBackDrag;

 

이와 같이 바뀐 줄만 랜더링 된다 ><

 

전역 상태를 남용하면 랜더링이 문제가 될 수 있으니 주의 하자..

그렇다고 아예 안쓰는 건 프롭스 드릴링으로 인해 랜더링 효율이 떨어지니 필요에 따라 적절히 써주자

반응형