본문 바로가기

FrontEnd/React

React Hooks - useMemo(컴포넌트의 성능 최적화를 위해 사용되는 hook! useMemo와 useCallback)

출처: https://www.youtube.com/watch?v=e-CnI8Q5RY4

참고: https://velog.io/@eeeve/React-Hooks-useMemo (깔끔함)

(잠깐 복습. 컴포넌트 최적화를 위해 사용되는 대표적 2가지 Hooks ==>> useMemo, useCallback

 두번째 인자로 배열을 취하는 훅스 useEffect, useMemo, useCallback.

useEffect는 component life cycle과 밀접하게 연관됨. 2번째 인자로 아무것도 안주면 componentDidUpdate의 역할을, 빈배열을 주면 componentDidMount의 역할을 함.

useMemo 함수의 결과값을 반환함. useCallback 함수객체를 반환)

useMemo에서 Memo란 Memoization을 뜻함.

Memoization이란 기존에 함수를 호출하여 얻은 결과값을 어딘가에 저장해 두고 동일한 입력이 들어오면 또다시 함수를 호출하지 않고 그 저장된 결과값을 재활용하는 프로그래밍 기법을 말함. 즉, useMemo를 사용하면 memoization을 이용하여 calculate함수를 반복적으로 호출하지 않아도됨. 

"함수형 컴포넌트가 랜더링된다"라는 말뜻은 그 함수가 호출된다는 뜻이기도 함. 함수형 컴포넌트가  호출될 때마다 내부에 정의되어 있는 모든 변수들이 모두 초기화됨.

대부분의 리엑트 컴포넌트는 state, props의 변화로 수많은 랜더링을 거칩니다. 컴포넌트가 랜더링 될때 마다 value라는 변수가 초기화됨. 만약 calculate라는 함수가 무거운 함수면 굉장히 비효율적인 행위가 계속되는 것. 이러한 상황을 useMemo를 사용하여 memoization을 해주면 간편하게 해결가능함. useMemo는 처음 계산된 결과값을 메모리에 저장하여 component가 반복적으로 랜더링되더라도 계속해서 calcultate가 호출되지 않고 이전에 계산된 결과값을 메모리에서 꺼내와서 재사용하게 해줍니다.

useMemo는 두개의 인자를 받습니다. 첫번째로는 callback함수 둘째로는 배열을 받습니다.

 

첫번째 함수는 우리가 memoization해줄 값을 계산하여 return해주는 함수입니다. 이 callback함수가 return하는 값이 useMemo가 return하는 값이 됨. 두번째 인자인 배열은 의존성 배열이라고도 함. useMemo는 오직 배열안의 요소의 값이 업데이트될때만 콜백함수를 다시 호출하여 메모이제이션 된 값을 업데이트해서 다시 메모이제이션을 합니다. 만약 처음에 빈배열을 준다면 맨처음 컴포넌트가 마운드 되었을때만 값을 계산하고 이후에는 항상 메모이제이션된 값을 꺼내와서 사용합니다.

 


마운트? 컴포넌트가 처음 DOM트리가 붙어 랜더링되는 시기.

위와 같이 변수location은 원시타입의 값을 저장한다. 따라서 이와 같은 경우는 useEffect만으로도 해결이 가능하다. 하지만 아래와 같이 location이 객체를 저장할때는 얘기가 다르다.
이전코드에서 location변수가 취하는 값을 객체로만 바꾸어 주었다. 이렇게 객체를 변수로 취하면 비록 location과 관련없는 하루 몇끼먹냐는 input창에 숫자를 입력해도 관계없는 location  변수가 다시 초기화되면서 location은 새로운 객체로 초기화되고 이는 의존성 배열에 location을 가지고 있는 useEffect함수가 다시 호출되게 한다.

(****여기서 잠깐. 중요함. useEffect, useCallback, useMemo 모두 그 함수 이름이 첫번째로 오지만 의존성 배열을 먼저 확인하고 그 배열안에 있는 요소가 변경되었을시에만 callback함수가 호출된다****)

setNumber로 하루 끼니수가 수정되면서 component전체가 리랜더링되는 과정에서 변수 location의 값또한 새로운 객체로 초기화되면서 location변수는 새로운 객체를 갖게된다. 이에 따라 location변수가 변하였을때만 호출되는 useEffect함수가 재호출되는 현상이 발생한다.

 

이러한 문제상황(객체를 값으로 갖는 변수)을 효과적으로 해결할 수 있는 것이 useMemo이다. 

이와 같이 코드를 변경하면 location변수는 객체를 값으로 가지면서 기존의 변수의 객체값이 초기화되면서 쓸데없이 랜더링되던 문제점을 해결할 수 있다.

위 코드에서 모든 것을 그대로 두고 useMemo만 useEffect로 바꾸어 쓸 수 없나? 라고 의문을 가질수 있는데 useEffect는 반환값이 없어 반환값을갖는 useMemo를 사용해야 한다.

이 의문이 좀더 확장되어서는 useMemo와 useEffect의 차이점이 무엇이냐? 라고 물을 수 있겠는데 아직은 잘 모르겠으나 어떤이들은

 useEffect는 해당 컴포넌트의 렌더링이 완료된 후에 실행되지만, useMemo는 렌더링 중에 실행되어 집니다.

라고 말한다.