리액트의 렌더링 성능 향상을 위해 어떻게 해야 하나요? (feat. useCallback, React.memo, useMemo)

mimmi·2024년 12월 1일
0

React

목록 보기
6/9

브라우저 렌더링

리액트에서 렌더링 === 함수를 호출하는 것

예시코드: 불필요한 렌더링을 막아보자!

  • FirstChild: state
  • SecondChild: props

리렌더링 조건

  • state가 바뀌었을 때
  • props가 바뀌었을 때

💡 참조값이 달라졌다?

  • Parent 컴포넌트가 리렌더링될 때마다 handleClick 함수가 매번 재생성이 됨
  • 함수가 ‘참조’ 타입의 데이터이기 때문!

🤔 그렇다면 참조값이 바뀌지 않도록 해주면, secondChild의 불필요한 리렌더링을 방지해줄 수 있지 않을까?

시도 1️⃣ 함수를 메모이제이션?

  • useCallback : 함수를 메모이제이션
    • 메모이제이션?
      • 기존에 수행한 연산의 결괏값을 어딘가에 저장해두고 필요할 때 재사용하는 기법
    • 의존성 배열이 바뀌지 않는 이상, 컴포넌트가 리렌더링 될 때마다 변수에 같은 함수가 할당됨

  • React.createElement

    계층으로 구성된 React.createElement 를 순차적으로 호출

    어차피 내부 로직이 실행되면서 SecondChild의 createElement도 실행이 되어버림… ㅠ

✅ 리액트에서의 렌더링 - Render Phase → Commit Phase

  • 재조정!

🤔 useCallback으로 불필요한 렌더링을 막을 수는 없었지만?
그래도 렌더링 최적화 효과는 있음!

시도 2️⃣ render phase까지 막아볼 순 없을까? (React.memo)

React.memo

  • 전달받은 props가 이전 props와 비교했을 때 같으면, 컴포넌트의 리렌더링을 막아줌
  • 마지막으로 렌더링된 결과를 재사용하는 고차 컴포넌트
  • props 비교 시, 기본적으로 얕은 비교를 통해서 진행!
    • 원시 타입의 데이터인 경우, 값이 다른지 비교!

    • 참조 타입의 데이터인 경우, 참조값이 같은지를 비교!


    • 비교 함수를 넣어서 비교 가능

props인 onClick을 비교!

시도 3️⃣ 객체를 props로 넘겨주게 된다면? (useMemo)

  • 아쉽게도 리렌더링이 발생

  • 결국 매번 다른 참조값을 가짐

🤔 useMemo

  • 함수에 대한 메모이제이션을 제공하는 useCallback과는 다르게,
    값에 대한 메모이제이션을 제공!
  • 의존성 배열에 들어있는 값이 변경되지 않는 이상, 매번 리렌더링 될 때마다 같은 값을 반환


결론

1. useCallback, React.memo, useMemo를 이용해 리액트 렌더링 성능 향상 가능

🤔 무작정 사용해도 좋을까?
  • 결국은 모두 비용..
  • 어떤 곳에 적용해야 최적화할 수 있는건지 고민해볼 필요가 있음

2. 최적화 도구를 사용하기 전에, 불필요한 렌더링이 발생하지 않도록 근본적으로 설계하자

3. 어떻게 코드를 개선할까?

  • 기존에는 위 코드처럼 부모 컴포넌트 내부에서 Consoler 컴포넌트를 사용함

  • children을 사용해서 Consoler 컴포넌트를 주입
  • 오른쪽 코드는 바벨로 컴파일된 코드
    • Consoler 컴포넌트의 React.createElement가 존재하지 않기 때문에 부모 컴포넌트가 호출되더라도 Consoler 컴포넌트는 호출되지 않음

4. 성급한 최적화는 금물!


출처
https://www.youtube.com/watch?v=1YAWshEGU6g

0개의 댓글