[React] 복잡한 연산이 있을 때 memoization

🍉effy·2022년 10월 11일
0

React 는 Virtual DOM 을 사용해서 어플리케이션의 성능을 향상시킨다.
렌더링이 된 후, 이전 렌더된 결과와 비교해서 DOM 을 업데이트 시킬지 결정하고, 가상돔인 virtual dom 이 변화 되었을 때, 즉 이전과 비교하여 변경이 있을 때만 실제 돔을 변경하도록 한다.

리렌더링이 필요하지 않은 경우, 불필요한 리렌더링을 제어하고 복잡한 연산이 있을 때 재사용하기 위해 고민을 해볼 필요가 있다.


연산이 많이 필요한 경우에 대해

나같은 경우에는 map 으로 돌린 input의 value 들을 재가공 했어야 했다.
각 항목의 체크 여부에 따라 각 항목의 작은 field 가 열리는데, 백에 보내주기 위해 체크한 항목을 key 값으로, 그 항목의 field 값을 value 값으로 객체를 만들어야 했다.

다른 체크 항목은 선택한 항목의 value 를 배열 안에 넣어주기만 하면 됐지만 선택한 항목의 열린 필드의 값을 연결시켜줘야 했다.


const handleDiseasesField = (e: React.ChangeEvent<HTMLInputElement>) => {
    setDiseasesObj([
      ...diseasesObj,
      {
        [e.target?.name]: e.target?.value,
      },
    ]);
  };

리팩토링 이전의 코드.
이렇게 하면

[
	{03 Diseases of the blood or blood-forming organs: '34'},
	{06 Mental, behavioural or neurodevelopmental disorders: '23'},
]

와 같이 원하는 구성으로 잘 들어가지만 input 에 퍼포먼스가 생길 때마다 중복되어 값이 들어가게 된다.

[
	{03 Diseases of the blood or blood-forming organs: '34'},
	{06 Mental, behavioural or neurodevelopmental disorders: '23'},
    {06 Mental, behavioural or neurodevelopmental disorders: '235'},
]

퍼포먼스를 줄이기 위해 debounce 를 사용해도 그거랑은 상관이 없다.
왜냐면 그대로 그저 onChange 가 일어날 때마다 복사하기 때문 ,,,


const handleDiseasesField = useCallback(
    (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
      const name = e.target?.name;
      setDiseasesObj((prev: any) => ({ ...prev, [name]: e.target.value }));
    },
    [],
  );

빈 배열에 굳이 배열을 더 넣을 필요가 없었는데,, 배열을 지우고 재구성.
배열 안에 항목마다 객체가 생겨나지 않게 하면서, 한 객체 안에 key, value 의 쌍으로 항목들을 모두 담는다.
그리고 해당 field에 퍼포먼스가 일어날 때마다 객체가 생겨나지 않는다.
하지만 해당 field 에 입력한 값을 지우면,

이렇게 입력 값을 지워도 빈 스트링으로 변경되어 담기게 된다.
선택한 항목들만 보내주어야 하기 때문에 정제를 해야 했는데,

  const requestData = useMemo(
    () =>
      Object.entries(diseasesObj)
        .map((ele: [string, unknown]) => {
          return { [ele[0]]: ele[1] };
        })
        .filter((ele) => Object.values(ele).join('').length > 0),
    [diseasesObj],
  );

Object.entries 로 한 객체 내에 있는 key, value 쌍을 배열 내에 각 객체로 만들어 담는다.
map 을 ele[0] 를 key 형식으로, ele[1] 을 value 형식으로 재가공.
위의 경우처럼 입력값을 지웠을 때 해당 객체를 없애주기 위해
value 를 배열에 담고 string 으로 변환시켜, 길이가 0보다 큰 것 즉, 빈 값이 아닌 것들만 필터링 한다.


[
	{03 Diseases of the blood or blood-forming organs: '34'},
	{06 Mental, behavioural or neurodevelopmental disorders: '23'},
]

복잡한 연산을 통해 원하던 구성으로 재가공 완료.

많은 연산이 들어가기 때문에, 필드의 state 가 변할 때만 활용하도록 useMemo hook 을 사용한다.

이전 값을 기억해두었다가 조건 즉 state 가 변할 때만 재활용 하여 사용한다.

profile
Je vais l'essayer

0개의 댓글