메모이제이션(Memoization)이란?
JS 메모이제이션에서도 공부했지만 리마인드 차원에서 다시 살펴 보자면, 프로그래밍에서 반복되는 결과를 메모리에 저장 해놓고 다음에 같은 결과가 나올 때 다시 계산할 필요없이 빨리 실행 하는 코딩 기법을 말하는 것이다.
1. React에서 Memoization
먼저 React에서 컴포넌트가 렌더링하는 규칙에는 대표적으로 크게 3가지가 존재한다.
- State가 업데이트된 컴포넌트
- Props가 변경된 컴포넌트
- Re-Rendering 된 부모컴포넌트의 모든 자식컴포넌트
이 중 세번째 Re-Rendering 된 부모컴포넌트의 모든 자식컴포넌트들은 불필요한 렌더링이 일어난다.
이러한 불필요한 렌더링은 애플리케이션의 규모가 커질수록 더욱 성능저하가 올 수 있다.
따라서 성능최적화를 위해 메모이제이션을 하는데 대표적으로 React.memo, useMemo, useCallback가 있다.
2. React.memo
공식문서를 확인해보면 첫 문장에 다음과 같이 적혀있다.
"memo lets you skip re-rendering a component when its props are unchanged."
props가 변하지 않을 경우 re-rendering을 건너 뛴다.
또한 공식문서에 따르면 React.memo는 고차 컴포넌트(Higher Order Component, HOC)이며, React.memo를 이용해서 감싸는 방식으로 자식 컴포넌트가 받는** props에 변화가 있다면 리렌더링을 하고 변화가 없다면 기존에 저장되어 있던 내용을 재사용한다.
고차 컴포넌트 공식문서 (HOC, Higher Order Component)란?
고차 컴포넌트는 컴포넌트 로직을 재사용하기 위해 사용되고 컴포넌트를 매개변수로 받아 새로운 컴포넌트르 반환하는 함수를 의미합니다.
2-1. React.memo 활용예시
테스트 환경 - codepen
import React from 'https://esm.sh/react@18.2.0'
import ReactDOM from 'https://esm.sh/react-dom@18.2.0'
// 기본 컴포넌트
const MyComponent = ({ name }) => {
console.log('MyComponent 리렌더리이이잉'); // 렌더링 로그 출력
return <div>Hello, {name}!</div>;
};
// React.memo로 래핑된 컴포넌트
const MemoizedComponent = React.memo(MyComponent);
// 사용 예시
const App = () => {
const [count, setCount] = React.useState(0);
console.log('리렌더리이이잉');
// count 상태가 변경될 때마다 App 컴포넌트가 재렌더링됨
// 그러나 MemoizedComponent는 동일한 name prop으로 재렌더링되어도 이전에 계산한 결과를 재사용함
return (
<div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<MyComponent name="SeungWon" />
</div>
);
};
ReactDOM.render(<App/>,document.getElementById("root"));
출처: https://openai.com/blog/chatgpt
위 예시 코드에서는
- MyComponent라는 기본 컴포넌트를 정의
- React.memo() 함수를 사용하여 MemoizedComponent라는 래핑된(감싸준) 컴포넌트를 생성.
- App에서 버튼을 클릭하여 count를 setCount로 상태를 업데이트 App은 리렌더링.
- App은 리렌더링이 되지만 React.memo() 래핑된 MyComponent는 props.name이 "SeungWon"으로 하드코딩 되어있기 때문에 App에서 아무리 상태변화를 주어도 불필요한 렌더링이 일어나지 않는다.
2-2. React.memo 언제 사용해야 될까?
- 함수형 컴포넌트에서만 적용 가능 (클래스형에서는 PureComponent으로 사용한다.)
- 같은 props로 리렌더링 자주 일어나는 컴포넌트에 유용하다. React.memo()는 props를 비교하여 메모이제이션을 하는 함수기 때문에 props가 계속해서 바뀌는 컴포넌트에서는 성능최적화를 기대하기 어렵다.
- 컴포넌트의 렌더링 비용(무겁고, 복잡한 연산이 있는)큰 경우
3. React.memo 주의사항
React.memo()는 얕은 비교만 수행한다. 컴포넌트의 props를 얕은 비교(Shallow comparison)로 변경되었을 때에만 리렌더링을 방지한다. 즉, 객체나 함수를 props로 받을 때 값이 같더라도 이전 참조값과 다르기 때문에 리렌더링이 발생 합니다. 해당 부분을 방지하려면 useMemo, useCallback 등의 hook이 있고, React.memo(Component, areEqual)에 두번째 인자값으로 이전 props와 새로운 props를 비교하여 true/false를 반환하고 리렌더링을 결정하는 함수이다.
React.memo(Component, areEqual) 예시
const customEqual = (prevProps, nextProps) => {
// props.name 이 같을 경우 저장된 값을 사용.
// 리턴에 있는 조건이 만족하면 리렌더링을 하지 않는다.
return prevProps.name === nextProps.name;
};
const MyComponent = React.memo(Component, customEqual);
'React > [React] 메모이제이션' 카테고리의 다른 글
[React] useMemo, useCallback 사용법 (0) | 2024.01.01 |
---|