React 렌더링 최적화

메모이제이션

메모이제이션(memoization)은 컴퓨터 프로그램이 동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술이다. 동적 계획법의 핵심이 되는 기술이다.

리액트의 메모이제이션은 바로 이전의 값만 메모이제이션한다.

const Memoized = React.memo(Component)
<!-- 새롭게 렌더링 -->
<Memoized num="{1}" />
<!-- 직전 elements를 사용 -->
<Memoized num="{1}" />
<!-- 새롭게 렌더링 -->
<Memoized num="{2}" />
<!-- 새롭게 렌더링 -->
<Memoized num="{1}" />

메모이제이션의 이유는 2가지다.
1. 비싼 연산을 반복하는 것을 피하여 성능 향상
2. 안정된 값 제공

리액트는 메모이제이션을 위해 3개의 API를 제공한다.
1. React.memo 2. useMemo 3. useCallback

React.memo를 사용하면 컴포넌트에서 리렌더링이 필요한 상황에서만 리렌더링이 되도록 설정할 수 있다.
useMemo는 메모이제이션된 값(함수가 실행되고 반환된 결과)을 반환한다.
useCallback은 메모이제이션된 콜백을 반환한다.

컴포넌트가 리렌더링 되는 상황

  1. state, props가 업데이트 될 때
  2. 부모 컴포넌트가 렌더링 될 때
  3. shouldComponentUpdate에서 true가 반환될 때
  4. forceUpdate가 실행될 때

useMemo

React Hook중 하나로 React에서 CPU소모가 심한 함수들을 캐싱하기 위해 사용된다.
컴포넌트 내에서 어떤 함수가 값을 리턴하는데 하나의 변화에도 값을 리턴하는데 많은 시간을 소요한다면 이 컴포넌트가 리렌더링 될 때마다 함수가 호출되면서 많은 시간을 소요하게 될 것이다.

useCallback

function App() {
  const [body, setBody] = useState()
  const fetchOptions = {
    method: 'POST',
    body,
    headers: { 'content-type': 'application/json' },
  }

  const callApi = () => (body ? fetch('/url', fetchOptions) : null)

  useEffect(() => {
    const result = callApi()
    if (!result) return
  }, [callApi])

  return <>...</>
}

callApi는 컴포넌트에서 매번 새롭게 렌더링이 될 때마다 계속해서 만들어질 것이다.
이 값을 안정시키기 위해서 useCallback을 사용해야한다.

그 외

useRef

리액트에서 특정 요소의 크기를 가져오거나 focus를 설정하는 등 특정 DOM을 선택해야할 상황이 있다.
컴포넌트 안에서 조회 및 수정가능한 변수를 관리하는 용도도 있다.
useRef로 변수를 관리하게되면 그 변수가 업데이트 된다고 해서 컴포넌트가 리렌더링되지 않는다.

  1. 컴포넌트에 focus를 위치시킬 필요가 있는 경우
  2. 속성 값을 초기화(clear)할 필요가 있는 경우
    ex. setInterval이나 setTimeout같은 함수는 clear시켜주지 않으면 메모리를 많이 소모한다
  3. 컴초넌트의 속성 정보를 리렌더링하지 않으면서 조회, 수정할때
    ex. setInterval, setTimeout을 통해 만들어진 id, scroll 위치

좋은 웹페이지 즐겨찾기