ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React.memo와 useCallback, useMemo
    Web/React 2021. 12. 13. 19:20
    반응형

    React.memo

    React.memo는 고차 컴포넌트.
    컴포넌트의 렌더링 결과를 Memoizing 함으로써, 이후의 불필요한 리렌더링을 건너뛴다.
    이전 렌더링과의 비교는 'props가 같은지'로 판단. (이전 렌더링 때와 props가 동일하다면 Memoizing 결과 재사용)
    props 객체를 비교할 때는 얕은(shallow) 비교를 사용한다.
    비교 방식을 수정하고 싶다면 두 번째 인자로 비교 함수를 만들어 넘겨주면 된다.

    export const Component = ({ prop, anotherProp }) => {
      return (
        <div>
          <div>prop1: {prop}</div>
          <div>prop2: {anotherProp}</div>
        </div>
      );
    }
    
    export const MemoizedComponent = React.memo(Component);
    export const MemoizedComponent2 = React.memo(Component, comparingFunctionIfYouWant);

     

    props로 콜백함수가 전달되는 경우는 계속 동일한 값이 전달되더라도
    함수의 인스턴스는 렌더링마다 매번 달라지므로 Memoization이 적절하게 수행되지 않는다.
    그래서 useCallback(콜백함수, [])를 통해 해당 콜백함수 인스턴스를 보존해줘야 한다.

    가상 DOM에서 달라진 부분을 확인하지 않으므로 성능상의 이점을 누릴 수 있다.
    특정 함수 컴포넌트가 '동일한 props로 자주 렌더링 될거라고 예상될 때' 사용해주면 좋다.
    ex) 주기적으로 서버에서 데이터를 폴링(Polling)해서 특정 컴포넌트의 props로 사용할 때

    그런 경우가 아니라면, 사실 React.memo는 적절하게 사용되기 힘들다.
    오히려 Memoizing 관련한 비교 로직이 더해지기 때문에 성능적으로 악화될 가능성이 높다.

     

    useCallback과 useMemo

    컴포넌트는 자신의 state가 변경되거나 부모로부터 물려받는 props가 변경될 때 리렌더링된다.

    (최적화를 해주지 않으면 props가 변경되지 않더라도 부모 컴포넌트가 리렌더링되면 자식도 리렌더링되는 게 default)

    컴포넌트가 리렌더링될 때, 내부에 있는 변수나 함수 등의 표현식들은 전부 다시 선언되고 할당된다.

    이 때, 변수나 함수가 다시 생성되어 할당되는 것을 방지하기 위한 훅이 바로 useMemo와 useCallback.

    둘의 역할은 거의 비슷하다. 형태도 거의 비슷하다.

     

    둘의 차이는 useMemo는 값을 반환하고 useCallback은 함수를 반환한다는 것.

    그래서 특정 함수를 계산한 결과값을 받아 변수에 할당하는 방식이면 useMemo를,

    특정 함수 자체를 사용하는 방식(명시적인 return값 없이 계산만 수행)이면 useCallback을 사용해주면 된다.

    const someValue = useMemo(() => reusedCallback(a, b), [a, b]);
    const someFunction = useCallback(() => reusedCallback(a, b), [a, b]);

    첫 번째 인자로 들어가는 로직을 Memoizing해서 다시 수행되는 것을 방지한다.

    이 때, 첫 번째 인자로 들어가는 함수가 다시 계산되는 경우는 두 번째 인자의 배열에 들어간 값들이 변경되는 경우이다.

    두 번째 인자로 들어가는 값들이 변경되지 않는 한, 해당 함수 혹은 값은 다시 계산되지 않는다.

    영영 재계산할 필요가 없다면 두 번째 인자의 배열을 비워주면 된다.

     

    복잡한 이벤트 핸들러 함수나 API 요청 함수에 사용해주는 경우도 많다.

    React.memo와 마찬가지로 복잡한 계산이 아니라면 오히려 낭비일 가능성이 높다.

     

    위의 React.memo에서도 말했듯, 하위 컴포넌트가 React.memo로 최적화되어 있을 때

    해당 함수의 props로 내려가는 콜백함수를 useCallback으로 최적화해주는 경우가 많다.

     

    참고로, 함수 컴포넌트도 결국 값을 반환하는 함수이므로 useMemo의 첫 번째 인자로 넣는 것이 가능하다.

    React.memo와의 차이라면 React.memo는 이론적으로는 클래스 컴포넌트와 함수 컴포넌트에 모두 사용이 가능하지만

    (클래스 컴포넌트는 이론적으로는 가능하지만, 그보다는

    PureComponent를 확장하거나 shouldComponentUpdate() 메서드를 구현하는 것이 권장된다고 함)

    useMemo는 함수 컴포넌트에밖에 사용을 못한다는 것 정도인 듯.


    React.memo는 컴포넌트 자체의 렌더링을 최적화하고 싶을 때 컴포넌트를 감싸주는 고차 컴포넌트.

    useMemo 혹은 useCallback은 컴포넌트 내부의 값 또는 함수의 계산을 재사용하고싶을 때 사용해주는 훅.

     

    면접 보는데 헷갈리길래 다시 한 번 정리했다. 떼잉...!

     

     

     

    출처

    TOAST UI: React.memo 현명하게 사용하기 - https://ui.toast.com/weekly-pick/ko_20190731

    이화랑 블로그: 이제는 사용해보자 useMemo & useCallback - https://leehwarang.github.io/2020/05/02/useMemo&useCallback.html

     

    반응형

    댓글

Designed by Tistory.