[리액트 성능개선] useMemo, React.memo

박영태·2023년 2월 18일
1
post-thumbnail

Memoization?

함수가 실행될 때마다 매번 동일한 계산이 많이 필요한 경우, 다시 계산하지 않고 이전에 계산된 결과를 기억해 두었다가 데이터를 반환 이렇게 함으로써, 렌더링하는 동안 불필요한 계산을 줄일 수 있어서 컴포넌트의 성능을 개선할 수 있다.

useMemo,React.memo

  • useMemo : 리액트 hook (값을 return), 함수형 컴포넌트에서만 사용 가능
  • React.memo : 고차 컴포넌트(Higher Order Component) (컴포넌트를 return), 함수형, 클래스형 모두 사용 가능

*꼭 필요할 때만 사용

캐시된 값이 커지면 메모리 사용량이 증가할 수 있으며, 오히려 렌더링 성능을 저하시키는 원인이 될 수 있다. 따라서, 적절한 상황에서 사용하는 것이 좋다.

useMemo 사용법

const memoizedValue = useMemo(() => computeExpensiveValue(a,b),[a,b])

useMemo는 두 가지 매개변수를 받는다. 첫 번째 매개변수는 이전에 계산한 값을 반환하는 함수다.

두 번째 매개변수는 함수에서 사용하는 의존성 배열이다. 의존성 배열의 값이 변경될 때마다 useMemo는 함수를 다시 실행하여 새 결과를 생성한다. 의존성 배열의 값이 변경되지 않으면, useMemo는 이전에 캐시된 값을 사용한다.

React.Memo

  • props가 이전과 동일한 값이면 재렌더링하지 않고, 다른 값이면 재렌더링하여 컴포넌트를 다시 만들어 반환한다.
  • React.memo에 쓰인 컴포넌트 안에서 구현한 state가 변경되면 컴포넌트는 재렌더링이 된다.

[사용방법]

export default React.memo(componenet);

export MyComponenet = React.memo((props) = > {
  return()

[예제]

TextView 컴포넌트와 CountView 컴포넌트 안에useEffect()가 있는데 2번째 인자에 값이 없으므로 그 컴포넌트가 업데이트가 될때마다 실행이된다.

즉, 컴포넌트가 재렌더링될때마다 콘솔창에 출력을 하게 된다.


count 증가 버튼과 text에 글을 쓰면 전부 리렌더링 되어 콘솔창에 출력이 된다.

count가 증가하는데 text 부분이 재렌더링 될 필요가 없다. 불필요한 재렌더링을 막기 위해서 React.memo를 이용해보자.

count 증가 버튼만 눌렀는데 CountView 컴포넌트만 재렌더링이 되었다.

props로 들어오는 값(text)이 동일하여 TextView는 이전 렌더링 결과값을 그대로 반환하였고,

props로 들어오는 값(count)이 이전과 동일하지 않아 CountView는 재렌더링하여 결과값을 반환하였다.

props가 object인 경우 얕은 비교를 하기 때문에, 같은 객체가 들어가더라도 리렌더링이 발생하게 된다.
(자바스크립트가 객체나 함수 또는 배열같은 비원시 타입 자료형을 비교할때 값을 비교할때 값에의한 비교가 아닌 주소에 의한 비교인 얕은 비교를 하게 된다.)
이를 위해서는 React.memo의 두번째 인자에 areEqual이라는 비교함수를 넣어서, 기존의 props와 새로운 props의 값을 비교해주는 방법을 사용하면 된다.

const MyComponent  = (props) => {
  return ()
}
const areEqual = (prevProps, nextProps) {
 if (prevProps.id === nextProps.id) {
   return true //이전 프롭스 = 현재 프롭스 => 리렌더링을 일으키지 않게 된다
 }
  return false // 이전 과 현재가 다르다  => 리렌더링을 일으켜라
}
export default React.memo(MyComponent, areEqual);

[예제]



Counter B가 업데이트 되었다고 출력된 이유는 prop인 obj가 객체이기 때문이다. 자바스크립트에서는 기본적으로 객체를 비교할때 얕은 비교를 하기 때문에 문제가 생긴다.

areEqual 사용하여 Counter B 컴포넌트에서 obj prop을 얕은 비교하지 않도록 렌더링 최적화

profile
안녕하세요

1개의 댓글

comment-user-thumbnail
2023년 2월 19일

잘읽고갑니다

답글 달기