본문 바로가기
배움 기록/React

[React] useMemo와 useCallback 개념 정리 (+ 리렌더링, 메모이제이션, useEffect ...)

by dygreen 2023. 3. 5.

 

useMemo와 useCallback의 개념에 대해 정리해보겠습니다

 

기본적으로 useMemo와 useCallback은 리렌더링을 최적화하는데 도움이 되도록 만들어진 Hook이다.

 

 

📌 리렌더링 (re-rendering) ?

React는 Virtual DOM을 사용하고 있다.

따라서 리렌더링이 되는 조건에 충족되는 상황이라면,

이전의 Virtual DOM과 현재의 Virtual DOM을 비교하여 변경된 값에 대해 DOM 트리를 업데이트 해준다.

 

리렌더링 시각화 이미지

 

위에서 언급한 리렌더링이 되는 조건은 다음과 같다.

  • 자신의 state가 변경될 때
  • 부모 컴포넌트로부터 새로운 props가 들어올 때 / 변경될 때
  • 부모 컴포넌트가 리렌더링될 때

 

📌 메모이제이션 (memoization) ?

과도한 리렌더링은 성능 저하의 원인이 된다.

따라서 필요할 때만 리렌더링될 수 있도록 하는 방법으로 useMemouseCallback을 사용할 수 있다.

해당 Hook을 이해하기 위해서는 '메모이제이션'이라는 개념을 먼저 이해해야 한다.

 

메모이제이션은 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술이다.

 

이것을 적절하게 사용하면 중복 연산을 피할 수 있기 때문에 메모리를 조금 더 쓰더라도 애플리케이션의 성능을 최적화할 수 있다.

 

📌 useMemo

useMemo는 메모이제이션된 값을 반환하는 함수이다.

const [ex, setEx] = useState(0)

const 복잡한계산함수 = useMemo(() => {
  return 계산결과
},[ex])

 

  •  계산이 복잡한 함수를 useMemo로 감싸주고, 결과 값을 return 해준다.
  •  useMemo 함수가 그 값을 저장해두고 있다가 ex가 변경될 때만 복잡한계산함수를 실행시켜 메모이제이션된 값을 업데이트 해준다.

 

[번외] useMemo와 useEffect의 차이 ?

언뜻 보면 useMemouseEffect는 동일한 기능을 하는 것처럼 보인다. (dependency에 따라 코드를 실행하는 점에서)

둘의 차이를 알아보자면,,,

 

| useMemo

처리 시간이 오래 걸리는 함수일 경우 렌더링마다 계산하기에 비효율적이기 때문에

값을 기억해놓고 dependency가 변경되었을 경우에만 다시 계산해주는 기능이다.

 

| useEffect

api 호출, 타이머 등 렌더링 과정에서 한 번만 호출해도 될 기능들이 렌더링되어 실행되거나

호출과정에서 렌더링에 영향을 끼칠 수 있는 것들을 모아서 따로 처리하기 위한 기능이다.

 

| 결론 |

useEffect렌더링 후에 실행되지만, useMemo렌더링 중에 실행된다.

 

📌 useCallback 

useCallback은 메모이제이션된 함수를 반환하는 함수이다.

const ParentComp() => {
  const [ex, setEx] = useState(0)

  // useCallback 사용: ex가 변경될 때만 <ChildComp/>가 리렌더링된다
  const fnOnclick = useCallback(() => {
    setEx(ex + 1)
  },[ex])
  
  return (
    <>
      <h1>Parent Component</h1>
      <p>Ex: {ex}</p>
      <ChildComp fnOnclick={fnOnclick} />
    </>
  )
}

 

  • useCallback을 사용하면 fnOnclick 함수가 계속 새로 만들어지는 것을 방지할 수 있다.
  • ex가 변경될 때만 새로운 함수를 만들고, 그렇지 않을 경우엔 (메모이제이션된) 동일한 함수를 불러온다.
  • 자식 컴포넌트에 함수를 props로 넘겨줄 때, (자식 컴포넌트의) 불필요한 렌더링을 방지할 수 있다.

 


위의 내용들로 볼 때, useMemo와 useCallback은 성능 최적화를 위해 필수로 사용해야 한다고 생각할 수 있지만

헛된 리렌더링을 방지하기 위해 기존 데이터와 바뀐 데이터를 비교하는 연산이 추가되므로

작은 프로젝트일 경우 오히려 성능에 부담이 될 수 있다.

따라서 꼭 필요한 무거운 연산/컴포넌트가 있을 경우 사용하는 것이 좋다!

 


참고 : 
https://ko.reactjs.org/docs/hooks-reference.html#usememo
https://narup.tistory.com/273
https://surviveasdev.tistory.com/entry/%EC%9D%B8%ED%84%B0%EB%B7%B0-%EC%A7%88%EB%AC%B8-useCallback%EA%B3%BC-useMemo%EC%97%90-%EC%B0%A8%EC%9D%B4%EC%A0%90
https://whales.tistory.com/87

 

728x90

댓글