React - 메모이제이션

김서영·2024년 5월 31일
0

CS 스터디 - React

목록 보기
20/28

메모이제이션


메모이제이션이란?

컴퓨터 프로그램 최적화 기술의 하나로, 함수의 계산결과를 저장해두고 동일한 입력으로 함수가 호출되면 다시 계산하지 않고 저장된 결과를 반환하는 최적화 기법

=>이를 통해 계산 시간을 줄이고 성능을 개선할 수 있다.

React에서는 메모이제이션을 주로 컴포넌트의 재렌더링을 방지하거나, 성능을 최적화하기 위해 사용한다.
React에서 메모이제이션을 구현하는 주요 방법은 React.memo, useMemo, 그리고 useCallback 훅 등이 있다.

React.memo

React.memo는 React 라이브러리에서 제공하는 고차 컴포넌트(HOC)로, 함수형 컴포넌트의 렌더링 결과를 메모이징해 성능을 최적화할 수 있다. (클래스형, 함수형 컴포넌트 모두 사용 가능)

작동 방법

props의 얕은 비교를 통해 이전과 현재의 props가 같은지 확인하고 props가 변경되지 않은 경우에는, 컴포넌트를 다시 렌더링하지 않고 재사용한다.
=> 부모 컴포넌트가 렌더링 되면 모든 자식 컴포넌트 또한 렌더링 되는데 props가 변경되지 않았다면 자식 컴포넌트는 렌더링 될 필요가 없다. 이때 React.memo 함수를 사용해 불필요한 렌더링을 방지해 준다.

  • React.memo는 props의 변화에만 영향을 준다.
  • props가 복잡한 객체인 경우 React.memo는 얕은 비교만 한다.
  • 다른 비교를 원하는 경우 React.memo의 두 번째 인자로 비교할 수 있는 함수를 넘겨주면 된다.

예시

React.memo를 사용하여 MyComponent를 메모이제이션한다.
App 컴포넌트에서 count 상태가 변경될 때 MemoizedComponent는 다시 렌더링되지 않는다.

import React from 'react';

// 일반 컴포넌트
const MyComponent = ({ value }) => {
  console.log('MyComponent rendered');
  return <div>{value}</div>;
}

// React.memo로 감싸서 메모이제이션
const MemoizedComponent = React.memo(MyComponent);

const App = () => {
  const [count, setCount] = React.useState(0);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <MemoizedComponent value="Hello, world!" />
    </div>
  );
}

export default App;

React.memo를 사용하면 좋은 경우

  • 함수형 컴포넌트인 경우
  • 컴포넌트가 같은 props로 자주 렌더링 되는 경우
  • 무겁고 복잡한 연산이 있는 경우

useMemo

useMemo 훅은 렌더링 최적화를 위한 React Hook으로 메모이즈 된 값을 return 한다. (함수형 컴포넌트에서만 활용 가능)
인자로 함수와 dependencies를 받고, dependencies 인자 중에 하나라도 변경이 되면 첫 번째 인자인 함수를 재실행한다.
dependencies 인자가 변경되지 않으면 이전 렌더링 값을 재활용한다.
dependencies 인자로 아무것도 전달하지 않으면 렌더링 할 때마다 새로운 값을 반환한다.

작동 방법

useMemo는 메모이제이션을 통해 연산의 결과값을 저장해 둔다. 특정 값이 변경될 때만 메모이제이션된 값을 재계산한다.

예시

useMemo 훅을 사용하여 calculate 함수의 결과를 메모이제이션한다.
num 값이 변경될 때만 계산을 수행한다.
이를 통해 불필요한 계산을 방지하고 성능을 최적화할 수 있다.

import React, { useState, useMemo } from 'react';

const ExpensiveCalculation = ({ num }) => {
  const calculate = (number) => {
    console.log('Calculating...');
    let result = 0;
    for (let i = 0; i < 1000000000; i++) {
      result += number;
    }
    return result;
  };

  const memoizedValue = useMemo(() => calculate(num), [num]);

  return <div>Calculated Value: {memoizedValue}</div>;
};

const App = () => {
  const [count, setCount] = useState(0);
  const [number, setNumber] = useState(5);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <button onClick={() => setNumber(number + 1)}>Increment Number</button>
      <ExpensiveCalculation num={number} />
      <div>Count: {count}</div>
    </div>
  );
}

export default App;

useCallback

useCallback 훅은 React에서 제공하는 훅 중 하나로, 함수를 메모이제이션하기 위해 사용된다.

작동 방법

useCallback 훅은 주어진 함수와 의존성 배열을 인자로 받아, 메모이징된 함수를 반환한다. 특정 값이 변경될 때만 메모이제이션된 함수를 재생성한다.

예시

useCallback 훅을 사용하여 handleIncrement와 handleTextChange 함수를 메모이제이션한다.
count나 text가 변경될 때만 함수를 재생성한다.
Button 컴포넌트는 프롭스가 변경되지 않는 한 다시 렌더링되지 않는다.

import React, { useState, useCallback } from 'react';

const Button = React.memo(({ onClick, children }) => {
  console.log('Button rendered: ', children);
  return <button onClick={onClick}>{children}</button>;
});

const App = () => {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');

  const handleIncrement = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  const handleTextChange = useCallback((event) => {
    setText(event.target.value);
  }, []);

  return (
    <div>
      <Button onClick={handleIncrement}>Increment</Button>
      <input type="text" value={text} onChange={handleTextChange} />
      <div>Count: {count}</div>
    </div>
  );
}

export default App;
profile
개발과 지식의 성장을 즐기는 개발자

0개의 댓글