최적화 - useMemo

조뮁·2022년 11월 1일

React

목록 보기
16/34

Memoization

: 이미 계산해 본 연산 결과를 기억해 두었다가 동일한 계산 수행 시, 다시 연산하지 않고 기억해 주었던 데이터를 반환하는 방법

일기의 개수를 통계내는 함수 작성

// 감정점수로 계산하는 함수
  const getDiaryAnalysis = () => {
    console.log("일기 분석 시작");

    // 감정점수에 따른 일기 개수
    const goodCount = data.filter((it) => it.emotion >= 3).length;
    const badCount = data.length - goodCount;
    const goodRatio = (goodCount / data.length) * 100;
    return { goodCount, badCount, goodRatio };
  };

  // 컴포넌트 return 전에 감정점수 계산 함수 호출 -> 객체 비구조화 할당으로 받음
  const { goodCount, badCount, goodRatio } = getDiaryAnalysis();

return (
    <div className="App">
      {/* <Lifecycle /> */}
      <DiaryEditor onCreate={onCreate} />
      <div>전체 일기 : {data.length}</div>
      <div>기분 좋은 일기 개수 : {goodCount}</div>
      <div>기분 나쁜 일기 개수 : {badCount}</div>
      <div>기분 좋은 일기 비율 : {goodRatio}</div>
      {/* 삭제할 리스트의 id값을 onDelete에 전달하기 위해서는, DiaryItem에서 해당 정보를 전달해줘야함. 
      DiaryItem이 onDelete를 호출하게 하기 위해, DiaryItem의 부모인 DiaryList에 함수 전달 */}
      <DiaryList diaryList={data} onRemove={onRemove} onEdit={onEdit} />
    </div>
  );


함수 호출이 2번 된 이유

    1. 초기 data는 빈 배열이었음
    1. api로 데이터 받아오면서 App 컴포넌트 리랜더 -> 전체 함수 한번 더 호출

일기 수정시에도 컴포넌트가 리랜더링 되기 때문에 getDiaryAnalysis()는 또 호출됨

  • 일기 개수는 변화가 없기 때문에 getDiaryAnalysis() 자체가 다시 호출되는 것은 낭비!

useMemo()

: useMemo(callback(), [dependency array]); 형태로 사용

  • useMemo의 첫 번째 인자 : memoization 원하는 callback();
  • useMemo의 두 번째 인자 : [] -> 이 배열 안에 있는 데이터가 변화할때만 callback 함수 다시 수행됨
const getDiaryAnalysis = useMemo(
  () => {
    console.log("일기 분석 시작");

    // 감정점수에 따른 일기 개수
    const goodCount = data.filter((it) => it.emotion >= 3).length;
    const badCount = data.length - goodCount;
    const goodRatio = (goodCount / data.length) * 100;
    return { goodCount, badCount, goodRatio };
  }, [data.length]
);

// 컴포넌트 return 전에 감정점수 계산 함수 호출 -> 객체 비구조화 할당으로 받음
  const { goodCount, badCount, goodRatio } = getDiaryAnalysis();
  • memoization 하고 싶은 함수를 useMemo 함수로 감싸서 사용
  • getDiaryAnalysis() 는 useMemo()를 호출한 결과값처럼 됨
  • useMemo() 안에 callback함수로 memoization하길 원하는 함수를 전달한 형태가 됨

이대로 실행하면 Uncaught TypeError: getDiaryAnalysis is not a function error 발생

  • useMemo는 callback 함수가 return하는 값을 리턴함 -> getDiaryAnalysis()는 useMemo()의 결과값을 return 받음
  • getDiaryAnalysis는 함수가 아니라 값으로 사용하면 됨!
// getDiaryAnalysis가 return은 useMemo callback()의 결과값이기 때문에, 함수가 아니라 값으로 사용해야함
  const { goodCount, badCount, goodRatio } = getDiaryAnalysis;
  • 일기데이터를 수정해도 getDiaryAnalysis가 다시 호출되지 않음
  • 일기 삭제 시(data.length가 변경되었을 때) getDiaryAnalysis가 다시 호출됨

0개의 댓글