최적화 1 - 연산 결과 재사용
✔ 이미 계산 해본 연산결과를 기억해 두었다가 동일한 계산을 시키면 다시 연산하지 않고 기억해 두었던 데이터를 반환 시키게 하는 방법
✔ 연산 과정을 최적화한다
먼저 Memoization을 사용하지 않은 상황에서 일기의 감정점수의 통계치를 구하는 함수를 만들어 준다.
지금 현재 data state가 가지고 있는 일기들 중에서
1. 기분이 좋은 일기(3,4,5)는 몇개 있는지
2. 기분이 안 좋은 일기(1,2)는 몇개 있는지
3. 기분이 좋은 일기의 비율은 어떻게 되는지
위의 세가지를 구하는 함수
//App컴포넌트
const getDiaryAnalysis = () => {
console.log("일기 분석 시작");
//1. 기분이 좋은 일기는 몇개 있는지를 구하는 함수
//현재 일기 데이터 중에서 filter메서드를 이용하여 일기의 감정이 3이상인
//것들을 새로운 배열에 넣어 그 배열의 길이를 goodCount상수에 넣어준다.
const goodCount = data.filter((it)=> it.emotion >=3).length;
// 2. 기분이 나쁜 일기의 개수를 구하는 함수
// 현재 전체 일기의 개수에서 기분이 좋은 일기의 갯수를 빼주면 된다.
const badCount = data.length - goodCount;
//3. 좋은 일기의 비율을 구하는 함수
const goodRatio = (goodCount/ data.length) *100;
//위의 세개의 데이터를 객체로 리턴해줌
return{goodCount, badCount, goodRatio};
}
//비구조화 할당으로 getDiaryAnalysis함수를 호출
const {goodCount, badCount, goodRatio} = getDiaryAnalysis();
return (
<div className="App">
<DiaryEditor onCreate = {onCreate}/>
<div>전체일기 : {data.length}</div>
<div>기분 좋은 일기 개수 : {goodCount}</div>
<div>기분 나쁜 일기 개수 : {badCount}</div>
<div>기분 좋은 일기 비율 : {goodRatio}</div>
<DiaryList onEdit={onEdit} onRemove={onRemove} diaryList ={data}/>
</div>
);
}
결과값
✔ 위의 결과값을 보면 Memoization을 사용하지 않은 상황은 App.js가 리렌더링 될때마다, getDiaryAnalysis()함수가 변화하지 않았음에도 리렌더링 된다.
✔ 굉장히 비효율적이다.
✔ 위와 같은 비효율성 막기위해 최적화를 위해 Memoization을 사용한다.
✔ Memoization를 적용하려면 useMemo함수를 사용해야 한다.
- 최적화를 위해 useMemo를 사용하면 된다.
- react에서 useMemo를 import해온다.
import { useEffect, useMemo, useRef, useState} from 'react';
- useMemo는 최적화하고 싶은 함수를 감싸준다.
- useMemo함수는 첫번째 인자로 콜백함수를 받아서 콜백함수가 리턴하는 값(연산)을 최적화할 수 있게 도와준다.
- useMemo의 두번째 인자로 배열을 전달해야 한다.
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 ])
// const {goodCount, badCount, goodRatio} = getDiaryAnalysis();
const {goodCount, badCount, goodRatio} = getDiaryAnalysis;
//✔ 이전에는 함수로서 호출하여 객체를 반환하는 형태였다면,
//useMemo()을 이용하게 되면 useMemo()의 콜백함수의 return값을 변수
//(getDiaryAnalysis)에 할당하는 형태가 된다.
//✔ 그래서 useMemo를 사용하게 되면 getDiaryAnalysis는
//더이상 함수가 아닌 값이 되게 된다.
return (
<div className="App">
<DiaryEditor onCreate = {onCreate}/>
<div>전체일기 : {data.length}</div>
<div>기분 좋은 일기 개수 : {goodCount}</div>
<div>기분 나쁜 일기 개수 : {badCount}</div>
<div>기분 좋은 일기 비율 : {goodRatio}</div>
<DiaryList onEdit={onEdit} onRemove={onRemove} diaryList ={data}/>
</div>
);
}
✔ []안에 있는 값이 변화를 하게 된다는 순간에만 getDiaryAnalysis의 값을 변경하고, 그 이외의 상황에서는 반환한 값을 기억해, App.js가 리렌더링 되어도, 리렌더링을 하지 않는다.
✔ data.length가 변화하지 않는 상황에서 App.js가 리렌더링 될때에는 getDiaryAnalysis의 useMemo의 콜백함수가 실행되지 않으며, data.length가 변화할때만, getDiaryAnalysis의 useMemo의 콜백함수가 호출된다.