개발자 Saaad

[React] React.memo, useCallback, useMemo 본문

학습/kakao X goorm 풀스택12회차

[React] React.memo, useCallback, useMemo

Saaad 2025. 1. 8. 11:54

1. React.memo (컴포넌트의 재렌더링 방지)

  • 불필요하게 렌더링이 일어나지 않도록 해준다.
  • 부모 컴포넌트가 렌더링되어도, props가 변경되지 않은 자식 컴포넌트의 렌더링을 방지합니다.

  • 위 사진은 App, Form, Lists, List 컴포넌트로 이루어진 페이지이다
  • 그런데 타이핑을 할때마다 불필요하게 다른 컴포넌트들이 재 렌더링 되고 있다. App - Form - Lists - Lists의 순서로 결합되어있다. App 컴포넌트와 Form컴포넌트는 다시 렌더링 되는게 맞지만, Lists 컴포넌트의 List 는 렌더링 될 필요가 없다.

사용 방법

방법은 간단하다 아래와 같이 React.memo를 컴포넌트를 정의할 때 붙여주면 된다( 소괄호로 전체를 감싸줘야한다. )

  • Lists 컴포넌트도 똑같이 해준다.

  • React.memo 적용결과 타이핑을 해도 불필요한 랜더링이 발생하지 않고 App, Form 컴포넌트만 랜더링 된다.


2. useCallback ( 함수의 재 생성 방지 )

  • 컴포넌트가 렌더링 될 때 그 안에 있는 함수도 다시 생성하게 된다. 하지만 똑같은 함수를 컴포넌트가 렌더링 된다고 해서 계속해서 다시 만드는 것은 좋은 현상은 아니다.
  • 컴포넌트가 리 렌더링 될때마다 부모 컴포넌트가 갖고 있는 함수를 자식 컴포넌트에 props로 내려준다면 이 함수를 사용하는 자식 컴포넌트들은 부모 컴포넌트가 리 렌더링 될때마다 함수를 다시 생성하기 때문에 함께 리 렌더링 되게 됩니다.
  • 함수 메모이제이션을 제공합니다.
  • 함수를 재생성하지 않고, 동일한 함수 참조를 유지합니다.

사용 방법

  • useCallback 적용은 useCallback 안에 콜백함수와 의존성 배열을 순서대로 넣어주면 된다.
  • 함수 내에서 참조하는 state, props가 있다면 의존성 배열에 추가해주면 된다.
  • 보통 자식 컴포넌트가 사용할 함수를 부모 컴포넌트에서 정의하고 props로 내려주게 될 때 사용한다.

설명

  • useCallback으로 인해서 todoData가 변하지 않는다면 함수는 재생성되지 않는다.
  • 새로 생성되지 않기 때문에 메모리에 새로 할당되지 않고 동일 참조값을 사용하게 된다.
  • 의존성 배열에 아무것도 없다면 컴포넌트가 최초 렌더링 시에만 함수가 생성되고, 그 이후에는 동일한 참조 값을 사용하는 함수가 된다.
  • 이제 부모가 리렌더링되어도 handleClick의 참조값이 변하지 않으므로 자식 컴포넌트는 재렌더링되지 않는다!

차이점 요약

항목 React.memo  useCallback
주요 목적 컴포넌트 재렌더링 방지 함수 재생성 방지
대상 React 컴포넌트 함수
작동 방식 props를 얕은 비교하여 동일하면 렌더링 생략 의존성 배열을 기준으로 함수 참조를 메모이제이션
주로 사용 위치 부모-자식 컴포넌트 관계 props로 함수를 전달할 때
의존성 관리 기본적으로 없음 (custom comparison 가능) 의존성 배열로 관리

 

 

❓강의에서 말하기를 .. 보통 함수를 정의할 때 최상위 컴포넌트에서 만든다고 하는데 띠용 이거 맞나 ?

더보기
  • (GPT) 답변 : 강의에서 말하는 내용은 **"일반적인 패턴"**일 뿐, 반드시 따라야 하는 규칙은 아닙니다. 각 방법에는 장단점이 있으며, 상황에 따라 선택하면 됩니다.
    • 상태와 로직의 중앙화
      • 최상위 컴포넌트에서 상태를 관리하고, 상태를 조작하는 함수를 자식으로 내려보내는 구조는 상태 관리의 일관성을 유지할 수 있습니다.
      • 특히, 여러 자식 컴포넌트가 같은 상태를 공유하거나 수정해야 할 경우 매우 유용합니다.
    • 재사용성과 테스트 용이성
      • 동일한 로직을 여러 자식 컴포넌트에서 공유하거나 활용할 수 있습니다.
      • 함수를 한 곳에서 정의하므로, 로직 변경 시 관리와 테스트가 더 쉽습니다.
    • React의 단방향 데이터
      • React의 데이터 흐름은 부모 → 자식 방향으로 내려갑니다.부모 컴포넌트에서 상태와 함수를 관리하고 자식에게 props로 전달하는 패턴은 React의 기본 철학에 부합합니다.
    자식 컴포넌트에서 함수를 생성해서 사용하는 경우
    • 로컬 로직의 독립성
      • 자식 컴포넌트가 독립적인 역할을 할 때, 함수가 해당 컴포넌트에 국한되어 있으면 더 직관적입니다.
      • 로직이 자식 내부에서만 사용될 경우 부모로 함수를 끌어올릴 필요가 없습니다.
    • 불필요한 props 전달 제거
      • 부모로부터 함수가 props로 내려오지 않으면 props의 복잡성이 줄어들고 코드가 간결해질 수 있습니다.
    단점
    • 부모와 자식 간의 상태 및 로직 공유가 어렵습니다.
    • 여러 자식 컴포넌트가 동일한 로직을 필요로 한다면, 이를 중복 정의해야 하거나 상태 동기화가 어려울 수 있습니다.
    결론단방향 데이터 흐름과 상태 중앙화가 관리에 유리하기 때문입니다.그러나, 자식 컴포넌트의 역할이 독립적이라면상황에 따라 유연하게 선택하는 것이 중요합니다!
  • </aside>
  • 자식에서 함수를 정의하는 방식이 더 적합할 수 있습니다.
  • 강의에서 설명한 방식이 일반적인 이유는 React의
  • 이 방식이 일반적인 이유

 


3. useMemo

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

  • Component 내의 compute 함수가 만약 복잡한 연산을 수행하면 결과 값을 리턴하는데 오랜 시간이 걸리게 된다. 이럴 시에 컴포넌트가 계속 리 렌더링 된다면 연산을 계속 수행하는데 오랜 시간이 걸려서 성능 저하가 발생하게 되며, UI 지연 현상이 일어나게 된다.
  • useMemo를 이용하면 매개변수로 받는 a,b 값이 이전과 동일하다면 컴포넌트가 리 렌더링 되더라도 연산을 다시 하지 않고 이전 렌더링 때 저장해두었던 값을 재활용하게 된다.

사용 방법

  • useMemo로 감싸준 후에 첫번째 인수에 의존성 배열에 compute 함수에서 사용하는 값을 넣어준다.