티스토리 뷰

위 영상에서 리랜더링이 발생하는 컴포넌트에 표시되도록 설정을 해놓았습니다.

input창에 onChange이벤트가 발생하면 useState훅을 이용해서 state가 변경됩니다.

 

React에서 컴포넌트가 렌더링하는 규칙에는 크게 세 가지가 존재합니다.

  1. state나 props가 변경되었을 때
  2. forceUpdate()를 실행했을 때
  3. 부모 컴포넌트가 렌더링 되었을 때

위의 영상에서는 state가 변화함에 따라 전체 컴포넌트가 전부 리랜더링이 발생하고 있는 상황입니다.

지금은 컴포넌트의 크기가 작아서 큰 영향은 없지만 컴포넌트가 커지거나 로직이 매우 큰 함수가 있다면 버벅거리고 느려지는 현상이 발생할겁니다. 단지 input에 제목을 입력했을 뿐인데, 무거운 함수를 계속해서 새로 만들 필요가 없겠죠.

 

메모이제이션이란 컴퓨터가 동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술입니다.

메모이제이션 기능을 적절히 사용하면 컴포넌트의 불필요한 재렌더링을 줄여서 빠른 렌더링을 가능하게 합니다.

 

리액트에서 훅으로 메모이제이션을 하는 방법은 useCallback, useMemo, React.memo가 있습니다.

React.memo

React.memo는 컴포넌트를 메모이제이션 합니다.

memo로 감싸진 컴포넌트는 props로 받는 name과 class가 같다면

새로 렌더링되는 결과가 저장된 결과와 같기 때문에 해당 컴포넌트를 재렌더링 하지 않습니다.

function Students({ name, class }) {
	return(
		<div>
			<p> 학생 명단표 </p>
			<div> 이름 : {name} </div>
			<div> 반 : {class} </div>
		</div>
	)
}

export default React.memo(Students)

* 임동현님(https://velog.io/@s2s2hyun/React%EB%A9%94%EB%AA%A8%EC%9D%B4%EC%A0%9C%EC%9D%B4%EC%85%98Memoization)의 예제를 그대로 사용했습니다.

 

만약 Students컴포넌트의 부모 컴포넌트가 재렌더링 된다고 하더라도

props로 넘어오는 값이 동일하다면 이 컴포넌트는 재렌더링되지 않습니다. 

 

useCallback

useCallback은 어떤 경우에 사용할까요?

함수형 컴포넌트의 경우 상태값이 변경되면 리렌더링이 일어난 후 함수들도 다시 생성됩니다.

이것이 잘 와닿지는 않습니다.

근데 리랜더링이 일어날 때마다 함수 객체가 계속 생기고 그것이 메모리에 계속 쌓여가고 있다고 생각됩니다.

아래 코드를 보면서 더 정리해보겠습니다.

// Text.jsx
const Text = ({title, value}) => <div>{title}:{value}</div>;
// Button.jsx
const Button = ({ handleClick, children }) => <button onClick={handleClick}>{children}</button>;
// Name.jsx
const Name = () => <div>홍길동</div>;

// BodyProfile.jsx
const BodyProfile = () => {
  const [weight, setWeight] = useState(0);
  const incrementWeight = () => setWeight(weight + 1);

  const [height, setHeight] = useState(0);
  const incrementHeight = () => setHeight(height + 1);

  return(
    <>
      <Name/>
      <Text title="weight" value={weight}/>
      <Button handleClick={incrementWeight}>몸무게 증가</Button>
      <Text title="height" value={height}/>
      <Button handleClick={incrementHeight}>키 증가</Button>
    </>
  );
}

* (https://thisblogfor.me/react/hooks_memoization/)의 예제를 그대로 사용했습니다.

 

위 컴포넌트가 리렌더링 되면 incrementWeight, incrementHeight가 계속 새로 만들어집니다.

그 말은 계속 새로운 메모리 주소를 차지하는 객체가 생깁니다.

리액트는 얕은 비교를 하기 때문에 메모리 주소로 props의 변화를 감지하게 되는데

계속 새로운 함수의 메모리 주소가 전달되니,

incrementWeight, incrementHeight를 props로 받는 Button컴포넌트는

계속 props가 바뀌는 줄 알고 React.Memo를 적용해도 리렌더링이 발생하게 되는 겁니다.

useCallback으로 함수를 감싸주면 원할 때만 새 함수를 만들 수 있습니다.

const incrementHeight = useCallback(() => {
  setHeight(height + 1);
}, [height]);

const incrementWeight = useCallback(() => {
  setWeight(weight + 1);
}, [weight]);

이렇게 해주면 훅에 전달된 콜백함수를 메모이제이션하고

의존성 배열에 전달한 값이 변할 때만 새로 생성하게 합니다.

useMemo

function MyComponent({ x, y }) {
  const z = compute(x, y);
  return <div>{z}</div>;
}

* (https://www.daleseo.com/react-hooks-use-memo/)의 예제를 그대로 사용했습니다.

이런 컴포넌트의 경우, compute라는 함수가 연산이 오래 걸리는 함수라면

매번 리렌더링이 발생할 때마다 오래 걸리는 함수를 계속 호출하게 되고 사용자 경험에 안 좋은 영향을 미칩니다.

x, y값이 자주 바뀌는 게 아니라면 메모이제이션을 사용해서 z값을 그대로 사용할 수 있습니다.

function MyComponent({ x, y }) {
  const z = useMemo(() => compute(x, y), [x, y]);
  return <div>{z}</div>;
}

 

React.Memo, useCallback, useMemo의 경우 정말 사용해야 할 경우인지 확실히 생각해봐야 할 것 같습니다.

예를 들어 Memo의 경우, props가 자주 바뀌는 컴포넌트에 무분별하게 적용하게 되면 오히려 추가 연산이 들어가게 됩니다.

useMemo의 경우에는 적용된 레퍼런스가 재활용을 위해서 가비지 컬렉션에서 제외된다고 합니다.

그래서 메모리를 더 쓰게 되니 정말 useMemo를 쓰는 게 더 최적화에 좋은 건지

확실하게 생각해보고 사용해야겠습니다.

 

 

300

참고:

https://velog.io/@s2s2hyun/React%EB%A9%94%EB%AA%A8%EC%9D%B4%EC%A0%9C%EC%9D%B4%EC%85%98Memoization

 

[React]메모이제이션(Memoization)

setState 함수를 사용하게 되면, 화면 전체가 다시 렌더가 되면서 state 와 여러개의 함수들을 다시 그려내게 됩니다. 그런데, 단순하게 이메일 주소를 받아오는 과정이라고 했을 때 Input 태그에 onCha

velog.io

https://react.vlpt.us/basic/18-useCallback.html

 

18. useCallback 를 사용하여 함수 재사용하기 · GitBook

18. useCallback 을 사용하여 함수 재사용하기 useCallback 은 우리가 지난 시간에 배웠던 useMemo 와 비슷한 Hook 입니다. useMemo 는 특정 결과값을 재사용 할 때 사용하는 반면, useCallback 은 특정 함수를 새

react.vlpt.us

https://www.daleseo.com/react-hooks-use-memo/

 

React Hooks: useMemo 사용법

Engineering Blog by Dale Seo

www.daleseo.com

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함