본문 바로가기
Web Study

React.memo()에 대해

by 쿠리의일상 2023. 4. 3.

React.memo( )

컴포넌트의 props 가 바뀌지 않았다면, 리렌더링을 방지하여 컴포넌트의 리렌더링 성능 최적화를 해주는 함수

- 즉, useState, useReducer, useContext 와 같이 상태와 관련된 리렌더링과는 무관함!

HOC (Higher Order Component) 이며, 렌더링 결과를 메모이징하여 불필요한 리렌더링을 건너 뛰어, UI 성능을 증가시킬 수 있다. 

React.memo(컴포넌트)

위처럼 컴포넌트를 감싸주면 된다.

컴포넌트가 React.memo() 로 래핑 될 때 리액트는 컴포넌트를 렌더링 하고 결과를 메모이징한다.

그리고 다음 렌더링이 일어날 때 props 가 동일하다면 리액트는 메모이징된 내용을 재사용해준다. (리렌더링X)

 

props 동등 비교

React.memo() 는 props 혹은 props 의 객체를 비교할 때 얕은 비교를 한다.

비교 방식을 수정하고 싶다면 React.memo()의 두번째 매개변수로 비교함수를 만들어 넘겨주면 된다.

React.memo(컴포넌트, [equalFunc(prevProps, nextProps)]);

equalFunc(prevProps, nextProps) 함수prevProps 와 nextProps 가 같다면 true를 반환해준다.

 

React.memo() 를 써줘야 할 때

✨ 같은 props 로 렌더링이 자주 일어나거나 무겁고 비용이 큰 연산이 있는 컴포넌트

 

반대로 React.memo() 를 사용하지 말아야 할 때는 위의 경우가 아닌 경우이다.

성능 관련 변경이 잘못 적용된다면 오히려 악화될 수 있다.

 

1. 기술적으로 가능하나 클래스 컴포넌트는 React.memo 로 래핑하는 것은 적절하지 않다고 한다.

2. 렌더링될 때 props 가 자주 변하여 동등 비교를 위해 비교 함수를 자주 수행하는 컴포넌트

 

 

함수형 업데이트?

상태 변화 함수에 등록하는 콜백함수의 파라미터에서 최신 상태 변수를 참조할 수 있기에 deps에 상태 변수를 넣지 않아도 되므로 최적화가 가능해진다.

 

React.memo() 와 콜백함수, useCallback

함수 객체는 일반 객체와 동일한 비교 원칙을 따르므로 함수 객체는 자신에게만 동일하다 (즉 비원시 타입..이란거다)

function sumFactory() {
  return (a, b) => a + b;
}
const sum1 = sumFactory();
const sum2 = sumFactory();

console.log(sum1 === sum2); // => false
console.log(sum1 === sum1); // => true
console.log(sum2 === sum2); // => true

 

부모 컴포넌트가 자식 컴포넌트의 콜백함수를 정의하면 새 함수가 암시적으로 생성될 수 있다.

함수의 동등성 때문에 메모이제이션을 적용할 때는 콜백을 받는 컴포넌트 관리에 주의해야 한다.

리렌더링할 때마다 부모 함수가 다른 콜백 함수의 인스턴스를 넘길 가능성이 있다.

 

이 문제를 해결하려면 props의 콜백함수를 매번 동일한 콜백 인스턴스로 설정해야하는데, useCallback() 을 사용하여 콜백 인스턴스를 보존시켜준다.

 

 

useMemo 와 함께 쓰기

props 가 배열이나 객체 등의 비원시 타입이라면, 부모 컴포넌트가 리렌더링 될 때,

해당 비원시 타입 또한 재정의(선언) 되므로 새로운 메모리 주소를 할당 받고, 결과적으로 값은 변하지 않았지만

메모리 주소를 새로 받았기에 리렌더링이 되어버린다.

이 경우 useMemo 와 함께 사용하면 메모이제이션이 되어 리렌더링을 막을 수 있다.