1-10. 최적화 1 - useMemo()함수

밥이·2022년 2월 28일
0

React Project

목록 보기
10/14

Memoization 기법을 적용한 연산 최적화 배우기

Memoization은 그냥 메모를 해둔다. 라는 의미로 이미 계산해본 결과를 기억해두었다가 똑같은 계산을 시키면 다시 계산하지 않고, 그냥 답만 반환 하는 방법을 의미함.

마치 우리가 시험을 볼 때, 이미 풀어본 문제를 보기까지 똑같이 만난다면 다시 안풀어보고 답을 기억하고 있을 떄가 있는데 이거랑 유사함

위 사진 처럼 어제 풀었던 문제가 오늘 똑같이 나오면 굳이 다시 풀어볼 이유가 없음.. 어제 이미 문제를 풀었고 해결방법을 찾았기 때문에 기억한 답을 적기만 하면됨. 시간 아깝게 다시 계산하고 하면 낭비니까
이러한 상황을 Memoization을 이용하여 연산을 최적화 했다고 표현함

Memoization을 이용해 최적화 했다는 말은 그냥
우리가 다시 만난 문제를 풀기 위해서 또 다른 계산을 하지 않는다. 라는 의미이고,

Memoization을 이용했다는 것은, 이 연산을 최적화 하기 위해 이 문제에 대한 답을 이전에 기억해 두었다는 의미

즉, 이전과 똑같은 문제가 나오면 기억해둔 답을 계산하지 않고 바로 적는것

컴퓨터가 기억하는 용량의 한계는 있지만 인간보다 월등한 용량을 가지고 있음, 수천 수억개를 기억할 수 있고 까먹지도 않음
답을 기억하는 방법인 Memoization을 활용하여 프로그래밍하다 만난 문제를 해결하는 경우가 많음.

우리 프로젝트에 어떻게 적용해야 하는지 알아보기

  • 감정점수가 3이상이면 감정이 좋은거, 미만이면 나쁜걸로 하고 App컴포넌트에 현재 data State가 가지고 있는 일기들 중에
    (1). 기분이 좋은 일기가 몇개 있는지?? 카운팅 하기
    (2). 나쁜일기는 몇개 있는지?? 카운팅 하기
    (3). 기분이 좋은일기의 비율은 어떻게 되는지??

이 3가지 데이터를 구하는 함수를 만들어 보기
함수 이름은 getDiaryAnalysis로 적용
함수가 호출될때 console.log('일기 분석 시작');으로 확인하기

  1. 좋은일기는 data에 filter()적용해 data의 감정점수가 3이상 인것만 반환하고, 갯수 구하기
  2. 나쁜일기는 전체 일기데이터 갯수에서 좋은일기를 빼면됨
  3. 좋은일기 비율은 (좋은일기 / 총 일기데이터 갯수) * 100;
  4. 마지막으로 {}객체로 가공한 데이터 반환하기
  5. getDiaryAnalysis()를 호출하여 반환한 데이터 비구조 할당으로 받아 사용
  6. 화면에 렌더링 하기

화면에 렌더링 잘 되면 getDiaryAnalysis()함수가 몇번 호출되는지 콘솔확인 2번 동작한걸 볼 수 있음.
왜냐??

  • App컴포넌트가 Mount될때 data State의 값은 [ ]빈배열임.
  • 그 순간에 getDiaryAnalysis()함수는 값이 없는 채로 한번 실행되고
  • 그 다음 getData()의 API가 성공되고, setData가 이루어짐.
  • 그러면 일기 data가 한번 바뀌게 되고 App컴포넌트는 다시 리렌더가 일어남
  • 그러면서 App컴포넌트 안에있는 모든 함수들 (onCreate, onRemove, onEdit, getDiaryAnalysis)은 값이 바뀐채로 재생성이 되면서 getDiaryAnalysis() 코드가 다시 호출됨.

그렇기 때문에 getDiaryAnalysis()함수가 2번 호출된다는걸 알 수 있음.

여기서 일기 수정하기를 누르면 data State가 변경됐기 때문에, App컴포넌트가 리렌더링 되면서 getDiaryAnalysis()함수는 또 호출됨

그런데 일기 데이터를 수정하는 행위는 일기 데이터 분석하는 결과에 아무런 영향이 가지 않음.

왜냐면 수정할 수 있는 폭은 컨텐츠 뿐임. 감정점수가 바뀌는게 아니니까 (감정점수는 수정할 수 없음)

기분좋은일기, 나쁜일기의 갯수가 변할 수 없음에도 불구하고 다시 getDiaryAnalysis()함수가 수행됨
왜?? App컴포넌트가 리렌더링 되니까

이럴때 Memoization 기법을 활용함!!

useMemo()활용하기

  1. 우리가 최적화 하고 싶은 즉 Memoization하고 싶은 함수를 감싸주면됨
  2. useMemo()는 첫번째 인자로 콜백함수를 받아 콜백함수가 리턴 하는 값, 연산을 최적화 할 수 있도록 도와주는 기능
  3. 두번째로 deps Array [ ]를 전달해야하는데, useEffect에 있는 [ ]배열과 똑같음
  4. deps Array [data.length]에 값을 넣으면, 그 값이 변경 될 떄만! useMemo의 콜백함수가 실행됨
  5. 아무리 getDiaryAnalysis() 함수를 호출한다 하더라도, 일기데이터의 갯수가 변경되지 않으면, 그냥 계산하지 않고 똑같은 값을 리턴함

useMemo사용시 주의점!!

  • getDiaryAnalysis()함수를 useMemo()로 감싸 최적화를 하게되면 이 함수는 더이상 함수가 아님

  • useMemo()의 기능은 어떤 함수를 전달 받아서 뭘 리턴하냐면, 이 콜백함수가 리턴하는 "값"을 리턴함.
    그러니까 getDiaryAnalysis()는 "값"을 리턴 받게됨 useMemo()로 부터

  • 그래서 호출할때 getDiaryAnalysis() 이렇게 함수로 호출할게 아니라,
    getDiaryAnalysis 이런식으로 값으로 사용하여 호출해야함 (안그럼 에러남)

그러면 이제 일기를 수정하고 완료하면 getDiaryAnalysis는 실행되지 않고,
삭제할때 (일기 data갯수가 변경될때) 만 실행됨

정리
어떤 함수가 있고, 그 함수가 어떤값을 리턴하고 있는데 리턴 까지의 연산을 최적화 하고 싶다면 useMemo()를 사용하여, [ ] deps Array에 어떤 값이 변화할 때 마다
이 연산을 다시 수행 할 건지를 명시해주면 그 함수를 값처럼 사용해 연산 최적화를 할 수 있다.
주의 : 함수를 useMemo()로 감싸 최적화를 하게되면, 이 함수는 더 이상 함수가 아니고 "값"이므로 "값"으로 사용해야함

0개의 댓글