리액트 렌더링 최적화

Yun·2024년 3월 27일
0

개인공부

목록 보기
11/28

React.memo, useMemo, useCallback
리액트 렌더링 최적화를 위한 기법

  • 컴포넌트가 리렌더링되는 조건

    • 부모에서 전달받은 props가 변경될 때
    • 부모 컴포넌트가 리렌더링될 때
    • 자신의 state가 변경될 때

Memoization : 메모이제이션이란, 비용이 많이 드는 함수 호출의 결과를 저장하고 동일한 입력이 다시 발생할 때 캐시된 결과를 반환하여 컴퓨터 프로그램의 속도를 높이는데 주로 사용되는 최적화 기술이다.


React.memo

  • 컴포넌트의 렌더링 결과를 메모하여 성능 최적화에 사용하는 고차 컴포넌트(HOC)이다.

    HOC(Higher Order Component)는 공통된 로직을 수행하여 필요힌 결과물을 표현할 수 있도록 한다.

  • React 컴포넌트의 메모화된 버전을 만들 수 있다.
  • 컴포넌트의 props가 변경된 경우에만 다시 렌더링된다.

Example

  • react는 부모 컴포넌트가 리렌더링되면 자식 컴포넌트도 리렌더링된다.

  • 부모 컴포넌트 A에 자식 컴포넌트 B, C, D가 있다고 가정하자.

    • DCARD들이 무수히 많다면 그 CARD들 또한 전부 리렌더링된다.
  • D 컴포넌트를 React.memo로 묶으면 A가 리렌더링되어도 DCARD들은 불필요한 리렌더링을 하지 않는다.

  • A에서 Dprops를 전달한다면, props가 다른 경우에만 D를 리렌더링한다.

    • React.memoprops를 얕은 비교(객체의 주소값을 비교)하여 다른 경우에만 리렌더링한다.
    • 만약 A 컴포넌트에서 함수나 객체를 props로 전달한다면 D 컴포넌트는 리렌더링 된다. A 컴포넌트의 함수와 객체는 리렌더링되면 새로운 주소값을 가지게 되기 때문.
  • 따라서 props 보단 string으로 값을 전달하는 것이 좋다.

import React from 'react';

const MyComponent = React.memo(({ prop1, prop2 }) => {
  // render component based on prop1 and prop2
});

export default MyComponent;

useMemo

  • 동일한 값을 반환하는 함수를 반복적으로 호출해야한다면 처음 값을 계산할 때 해당 값을 메모리에 저장해 필요할 때마다 다시 계산하지 않고 메모리에서 꺼내서 재사용하는 것이다.

  • useMemo()를 사용하면 연산된 결과 값을 캐싱해주기 때문에, 매렌더링마다 고비용 연산이 일어나는 것을 방지할 수 있습니다.

  • useMemo()는 연산된 결과값이 바뀌지 않는다면 재연산이 일어나지 않는다.

  • 고비용 연산을 방지하기 위해 사용하지만, 메모할 만큼 어려운 연산이 나리 때는 제거해야 공간을 절약할 수 있다.

import React, { useMemo } from 'react';

const MyComponent = ({ data }) => {

  const result = useMemo(() => {
    // ...
    return computedResult;
  }, [data]); // data가 바뀔 때만 함수가 실행된다.
  
  return (
  // ...

useCallback

  • useCallback은 함수를 메모화하는 데 사용한다.

  • useMemo()와 메커니즘은 같지만, 값이 아닌 함수 자체를 캐싱한다는 차이가 있다.

  • useCallback을 사용하지 않는 경우

const PageMemoized = React.memo(Page);

const App = () => {
  const [state, setState] = useState(1);
  const onClick = () => {
    console.log('Do something on click');
  };
  return (
    // ...
    // onClick이 계속 새로 만들어지기 때문에 memo를 사용해도 계속 리렌더링된다.
    <PageMemoized onClick={onClick} />);
};
  • useCallback을 사용하는 경우
const PageMemoized = React.memo(Page);

const App = () => {
  const [state, setState] = useState(1);
  const onClick = useCallback(() => {
    console.log('Do something on click');
  }, []);

  return (
    // onClick을 memoization 해서 Page 리렌더링을 막는다.
    <PageMemoized onClick={onClick} />
  );
};

참고

  • 대부분의 경우엔 useMemouseCallback을 사용하지 않는다.

  • 첫 렌더링 때 값을 캐시해야 하므로, 상당한 지연시간이 생길 수 있다. 컴퓨터 자원이 낭비되고 애플리케이션이 느려질 가능성이 있다.

  • 단순히 값이나 함수를 메모이제이션하는 것은 성능이 미미한 영향을 끼치거나 오히려 악영향이다.

  • 따라서 위 기능들은 하위 컴포넌트가 리렌더링되는 것을 막기 위해서만 사용하는 것이 옳다.


출처

0개의 댓글