[React] 컴포넌트 최적화를 위한 useMemo Hook

YJ·2023년 7월 25일
0

useMemo 정의

useMemo에서 'Memo'란, Memoization을 뜻한다.

동일한 값을 return하는 함수를 반복적으로 호출해야 한다면 맨 처음 값을 계산할 때 해당 값을 메모리에 저장해서 필요할 때마다 다시 계산하지 않고 메모리에서 꺼내 재사용하는 기법이다.

들어가기 전에 한 가지 알아둬야 할 것이 있다.

함수형 컴포넌트란?

함수형 컴포넌트는 말 그대로 함수이다.
함수형 컴포넌트가 렌더링 된다는 것은 그 함수가 호출된다는 것이고, 함수는 호출될 때마다 내부의 모든 변수들이 초기화 된다.

function Component () {
  const value = calculate();
  return <div>{value}</div>;
}

function calculate () {
  return 10;
}

컴포넌트가 렌더링 될 때마다 value 변수가 초기화 되기 때문에 calculate 함수는 반복적으로 호출된다.
그런데 만약 calculate 함수가 무거운 일을 하는 함수라면 아주 비효율적일 것이다.

이때 useMemo를 사용해 memoization 해주면, 간단히 해결할 수 있다.
useMemo는 처음 계산된 결과값을 메모리에 저장해서 컴포넌트가 반복적으로 렌더링 되어도 calculate를 다시 호출하지 않고, 이전에 이미 계산된 결과값을 메모리에서 꺼내와 재사용할 수 있게 해준다.

useMemo 구조

const value = useMemo(() => {
  return calculate();
}, [item])

useMemo는 두 개의 인자를 받는데, 첫 번째 인자는 콜백 함수, 두 번째 인자로는 배열을 받는다.

1. 콜백 함수

  • memoization할 값을 계산해서 return해주는 함수
  • 콜백 함수가 return하는 값이 바로 useMemo가 return하는 값이다.
  • 콜백 함수는 렌더링 중에 실행된다. 그러므로 렌더링 중에 수행되지 않을 작업을 콜백 함수 내에 작성하지 않는 것이 좋다.

2. 의존성 배열

  • 배열 안의 요소 값이 업데이트 될 때만 콜백 함수를 다시 호출한다. 그러면 memoization된 값을 업데이트해서 다시 memoization 해준다.
  • 빈 배열을 넣어주면 처음 컴포넌트가 마운트 되었을 때만 값을 계산하고 이후에는 항상 memoization된 값을 꺼내와 사용한다.

어떤 경우에 useMemo가 빛을 발할까?

임의의 컴포넌트 내부 코드 중 일부를 가져왔다고 생각해보자.

// 예제 1

const [isKorea, setIsKorea] = useState(true);

const location = isKorea ? '한국' : '외국';

useEffect(() => {
  console.log('useEffect 호출');
}, [location])
// 예제 2

const [isKorea, setIsKorea] = useState(true);

const location = {
  country: isKorea ? '한국' : '외국',
};

useEffect(() => {
  console.log('useEffect 호출');
}, [location])

예제 1예제 2는 location의 값이 변할 때마다 컴포넌트의 렌더링이 발생한다는 점에서는 동일하다.

그러나 예제 1은 location이 아닌 다른 값 변화에 의한 렌더링 시 useEffect가 실행되지 않는 반면, 예제 2는 location이 아닌 다른 값 변화에 의한 렌더링에도 useEffect가 실행된다.

이 차이는 location 변수에 할당된 값의 타입이 다르다는 점에서 발생한다.

객체 타입의 변수는 리렌더링 시 객체 자체를 재할당 받으므로 변수가 가리키는 주소값이 변하기 때문에 location이 바뀐다고 인식되므로 useEffect가 계속 실행되는 것이다.

이럴 경우 useMemo를 사용해 컴포넌트 최적화를 해주면 좋겠지!

// 예제 2에 useMemo 적용

const location = useMemo(() => {
  return {
     country: isKorea ? '한국' : '외국',
  }
}, [isKorea])

그러나 useMemo 역시 무분별한 사용은 지양해야 한다.

useMemo를 사용한다는 것은 값을 재활용하기 위해 따로 메모리를 소비해서 저장한다는 것이므로 불필요한 값까지 모두 memoization 해버리면 오히려 성능이 악화될 수 있으므로 필요할 때만 적절히 사용해야 한다!


※ 참고 자료
React 공식 문서
React Hooks에 취한다 - useMemo 제대로 사용하기

profile
Hello

0개의 댓글