useCallback, memo, useMemo

BlackBean·2025년 4월 27일

React

목록 보기
6/6

React 에서 Component 는 언제 랜더링을 할까.

그 전에 Component 의 순수성에 대해 집고 넘어가야한다.

React component 는 항상 순수한 렌더링 로직을 가져야 합니다. 이는 Props, State 그리고 Context 가 변경되지 않으면 항상 동일한 결과를 반환해야 함을 의미합니다.

사이드와 사이드이펙트
함수형 프로그래밍은 순수성에 크게 의존하지만, 언젠가는, 어딘가에서, 무언가가 바뀌어야 합니다. 그것이 프로그래밍의 요점입니다! 화면을 업데이트하고, 애니메이션을 시작하고, 데이터를 변경하는 이러한 변화들을 사이드 이펙트라고 합니다. 렌더링중에 발생하는 것이 아니라 “사이드에서” 발생하는 현상입니다.
React에서, 사이드 이펙트는 보통 이벤트 핸들러에 포함됩니다. 이벤트 핸들러는 React가 일부 작업을 수행할 때 반응하는 기능입니다. 예를 들면 버튼을 클릭할 때처럼 말이죠. 이벤트 핸들러가 컴포넌트 내부에 정의되었다 하더라도 렌더링 중에는 실행되지 않습니다! 그래서 이벤트 핸들러는 순수할 필요가 없습니다.
다른 옵션을 모두 사용했지만 사이드 이펙트에 적합한 이벤트 핸들러를 찾을 수 없는 경우에도, 컴포넌트에서 useEffect 호출을 사용하여 반환된 JSX에 해당 이벤트 핸들러를 연결할 수 있습니다. 이것은 React에게 사이드 이펙트가 허용될 때 렌더링 후 나중에 실행하도록 지시합니다. 그러나 이 접근 방식이 마지막 수단이 되어야 합니다.
가능하면 렌더링만으로 로직을 표현해 보세요. 이것이 당신을 얼마나 더 나아가게 할 수 있는지 알면 놀라게 될겁니다!

https://ko.react.dev/learn/keeping-components-pure

결론적으로 사이드를 통해 화면이 렌더링되는 과정을 거친다. 이 과정은 수수함수를 지향하는 React를 생각하면 결국 컴포넌트를 새로 만드는 과정과 비슷할 것이다. 우리가 useHook 의 dependency 에 값을 추가하지 않으면 매 함수 렌더링 과정마다 내부인자들(변수, 함수, 자식컴포넌트)을 새로 만들게 된다.

이 과정에서 매번 새로만드는 컴포넌트들에 대한 부하를 줄이기 위해 아래와 같은 방법을 react 에서 제공한다.

useCallback

useCallback 은 리렌더링 간에 함수 정의를 캐싱해 주는 React Hook 이다.

const cachedFn = useCallback(fn, dependencies)

fn: 캐싱할 함수값. React 는 첫 렌더링에서 이 함수를 반환함 (호출하는 것이 아님!)

dependencies: fn 내에서 참조되는 모든 반응형 값의 목록. 반응형 값은 props, state, 컴포넌트내 선언된 변수와 함수

용법

  • 컴포넌트 리렌더링 건너뛰기
  • Memoized 콜백에서 상태 업데이트하기
    • memo 로 감싸진 컴포넌트에 prop으로 넘길 함수가 있다면 함수를 useCallback 으로 감싸기
  • Effect 가 너무 자주 실행되는 것을 방지하기
    • useCallback, useEffect의 dependency 가 a 함수에 의존성이 있을 때 a를 useCallback 으로 감싸기
  • 커스텀훅 최적화
    • 커스텀훅에서 반환하는 모든 함수는 useCallback 으로 감싸기

자바스크립트에서 function() {} 나 () ⇒ {} 는 항상 다른 함수를 생성합니다. 이것은 {} 객체 리터럴이 항상 새로운 객체를 생성하는 방식과 유사합니다. → 컴포넌트가 리렌더링 될 때마다 내부 함수들도 모두 새로 객체를 생성하게 된다.

memo

컴포넌트의 Props 가 변경되지 않은 경우 리렌더링을 건너뛸 수 있다.

const MemoizedComponent = memo(SomeComponent, arePropsEqual?)

useMemo

재렌더링 사이에 계산 결과를 캐싱할 수 있게 해주는 React Hook 입니다.

const cachedValue = useMemo(calculateValue, dependencies)

useCallback과 useMemo 의 차이

  • useMemo 는 호출한 함수의 결과값을 캐싱
  • useCallback 은 함수 자체를 캐싱 // (React 내부의) 간단한 구현 function useCallback(fn, dependencies) { return useMemo(() => fn, dependencies); }

디버깅

브라우저 디버깅 탭에서 메모리를 누르고 타임라인별로 녹화해서 보면 문제가 있는 함수가 많이 찍혀있었다.

이걸 보고 원인을 찾아갈 수 있을듯.

profile
React, React-native, Web developer

0개의 댓글