개발 일기

memoization을 이용한 useMemo, React.memo 본문

React

memoization을 이용한 useMemo, React.memo

ji_su_04 2024. 7. 10. 16:10

memoization

반복되는 결과 값을 메모리에 저장하고 특정 결과가 나올 때 다시 연산하지 않고 데이터를 반환시키는 방법.

비유하자면 캐싱과 같은 기능이라고 한다.

 

useMemo

특정 값이 변화될 때 리턴 연산을 수행할 것임을 명시

 

ex) const cacheValue = useMemo(calculateValue, dependencies)

 

여기서 calculateValue는 캐시(저장)하려는 값.

dependencies는 의존 인자이며 이 값이 변경 됐을때 값을 재계산한다.

 

이때 dependencies에 빈 배열을 넣는다면 useEffect와 같이 마운트시에만 값을 계산한다.

 

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

 

간단한 예시로 a, b 값이 변경 될 때  useMemo의 첫번째 인자인 함수가 실행되어 값이 재계산되고, 그렇지 않은 경우 메모이즈된 값을 리턴한다.

 

React.memo

컴포넌트에 동일한 props 값이 들어온다면 React.memo는 컴포넌트 랜더링 과정을 스킵 후 마지막에 랜더링 했던 결과를 재사용한다.

 

간단한 예를 들어 부모 컴포넌트에서 1번 컴포넌트와 2번 컴포넌트에 각각 다른 props를 넘겨준다고 했을때 

1번 컴퍼넌트에 넘긴 props 값을 부모에서 변경한다면 1번 2번 컴포넌트 둘다 리랜더링을 하게 된다.

이 경우 2번 컴포넌트는 불필요한 랜더링을 하게 되는데 이 문제를 해결하기 위해 React.memo를 활용한다.

 

const TextComponent = React.memo(({text}) => {
	return <div>{text}</div>
});

const NumberComponent = React.memo(({number})=>{
	return <div>{number}</div>
});

const TestComponent = () => {
	const [count, setCount] = useState(1);
    const [text, setText] = usetState("");
    
    return (
    	<div>
        	<div>
        		<button onClick={() => setCount(count + 1)}>{count}</button>
        	</div>
        	<div>
            	<input type="text" value={text} onChange={(e) => setText(e.target.vlaue)}/>
            </div>
        </div>
    )
};

 

위에 예시 코드를 보면 버튼을 클릭하여 카운트가 증가할 경우 NumberCompoent만 리랜더링 되고 인풋에 값을 입력할 경우 TextComponent만 리랜더링 된다.

 

이때 얕은 비교와 깊은 비교가 있는데 우선 얕은 비교에 대해 알아볼 필요가 있다.

얕은 비교는 값에 의한 비교가 아니라 주소에 의한 비교이다.

자바스크립트에서는 객체, 함수, 배열 같은 비원시 타입의 자료형의 비교는 값에 의한 비교가 아닌 주소에 의한 비교를 한다.

이때 a=b를 비교한다면 각각 객체를 할당한 고유한 메모리 주소를 가지고 비교를 하게 된다.

그래서 만약 위의 예시 코드에서 버튼을 클릭시 특정 object.count의 값을 업데이트 시켜준다면 이때 값은 변경되지 않는다.

 

const CounterB = ({ obj }) => {
	useEffect(() => {
		console.log(`CounterB Update = count : ${obj.count}`);
	});

	return <div>{obj.count}</div>;
}

const areEqual = (prevProps, nextProps) => {
  	// 이전 props와 현재 props가 같다면 리렌더링을 일으켜라는 의미
	return prevProps.obj.count === nextProps.obj.count;
}

const MemoizedCounterB = React.memo(CounterB, areEqual);

return ( 
  <MemoizedCounterB obj={obj} /> 
);

 

깊은 비교를 위해선 위의 예시 코드와 같이 두개의 인자를 넘겨줘서 값을 비교하면 된다.

 

React.memo 와 useMemo의 차이

간단히 정리하자면 React.memo는 전달받은 props의 값이 변할 때, useMemo는 두번째 인자인 dependency가 변할 때 인자로 넘긴 함수가 실행되며, 그렇지 않으면 함수는 실행되지 않고 이전의 메모이즈된 결과를 반환한다.

반응형

'React' 카테고리의 다른 글

useRef vs useState  (0) 2024.07.11
React.StrictMode 호출 문제  (0) 2024.04.26
React Redux 개념정리  (0) 2023.02.02
React 개념정리  (0) 2023.02.02
4. Diary 만들기 (Redux-Toolkit, axios.fatch, 수정)  (0) 2023.02.02