본문 바로가기
React

[React] 성능 개선 1. 재렌더링 막는 memo(), useMemo

by dong_su 2023. 12. 22.

설명

  • 컴포넌트가 재렌더링되면 거기 안에 있는 자식 컴포넌트는 항상 함께 재렌더링 된다.
  • 평소엔 문제가 없지만 만약 자식 컴포넌트 렌더링 시간이 1초같이 큰 시간이라면,
  • 부모컴포넌트가 재렌더링 될때마다 1초나 느린 문제가 생긴다. 그럴 땐 memo를 이용하면 된다.

예시

function Child(){
  console.log('재렌더링됨')
  return <div>자식임</div>
}

function Cart(){ 

  let [count, setCount] = useState(0)

  return (
    <Child />
    <button onClick={()=>{ setCount(count+1) }}> + </button>
  )
}
  • Cart 컴포넌트 안에 Child 컴포넌트를 만들고 버튼 클릭 시 Cart 컴포넌트가 재렌더링 되게 했는데
  • 이 경우 Child 컴포넌트도 재렌더링 된다. 

memo() 사용

import {memo, useState} from 'react'

let Child = memo( function(){
  console.log('재렌더링됨')
  return <div>자식임</div>
})

function Cart(){ 

  let [count, setCount] = useState(0)

  return (
    <Child />
    <button onClick={()=>{ setCount(count+1) }}> + </button>
  )
}

 

  • 위 코드와 같이 memo를 import 후 Child 컴포넌트의 구현부분을 memo()로 감싸면
  • Cart 컴포넌트가 재렌더링 될 때 자식인 Child 컴포넌트는 재렌더링이 되지 않는다.
  • 정확히는 Cart 컴포넌트가 재렌더링 될 때, Child 컴포넌트로 보낸 props 값이
  • 변하면 재렌더링되고 변하지 않으면 재렌더링이 되지 않는다.
  • 자식 컴포넌트가 함수 표현식으로 만들어질 때만 가능하다.

그럼 memo는 불필요한 재렌더링을 막아주니 자주 써도 되는건가?

  • memo로 감싼 컴포넌트는 불필요한 재렌더링을 막기 위해,
  • 기존 props와 바뀐 props를 비교하는 연산이 추가되기 때문에 오히려 부담이 될 수도 있다고 한다.
  • 그러니 필요한 경우에만 사용하자.

비슷한 개념인 useMemo

useMemo는 useEffect와 비슷한 용도이다.

import {useMemo, useState} from 'react'

function 함수(){
  return 반복문10억번돌린결과
}

function Cart(){ 

  let result = useMemo(()=>{ return 함수() }, [])

  return (
    <button onClick={()=>{ setCount(count+1) }}> + </button>
  )
}

 

  • 예를 들어 반복문을 과도하게 돌려야 하는 경우
  • Cart 컴포넌트가 랜더링될 때 마다 실행될텐데 useMemo의 콜백함수 return 부분에 실행할 코드를 넣어두면
  • useEffect처럼 dependency 부분을 이용해서 필요 할 때만 실행할 수 있다.
  • useEffect와는 실행되는 순서만 다르고 똑같다고 한다.