커스텀 Hook 안의 반환 함수는 useCallback을 사용해라

김민찬·2023년 7월 15일
1

React

목록 보기
11/14
post-thumbnail

React 문서 - useCallback 커스텀 Hook 최적화하기

useCallback은 최대한 지향해라

React 공식 문서를 읽다보면 useMemouseCallback 훅을 최대한 지향하라는 말을 자주 볼 수 있다.

  • useCallback의 사용시기는 일반적으로 수천 개의 객체를 만들거나 반복하는 경우가 아니라면 사용하지 않는 것이 좋다고 한다.
  • 확신을 얻고 싶으면 console.timeconsole.timeEnd를 사용해서 소요된 시간을 측정하고 일반적으로 1ms 이상이면 useCallback을 사용하라고 한다.

  • 개인적으로 프로젝트를 하면서 useCallback을 사용해서 최적화를 시도했으나 오히려 초기 렌더링에서는 시간이 더 소요되는 것을 알 수 있었다.
    • 이러한 현상은 useCallback을 사용하면 리액트가 그 함수를 캐싱하기 때문이라고 생각한다.
  • 이렇게 캐싱하는 행위로 인해서 많은 함수에서 캐싱을 하면 초기 렌더링이 느려지는 문제와 캐싱과정에서 메모리를 사용하기 때문에 React에서 useCallback을 최소화로 사용하라고 하는 것이다.

커스텀 훅에서 반환하는 모든 함수에서 useCallback을 사용하라

  • 리액트 문서 중 useCallback 파트에서 커스텀 훅 최적화 하기라는 파트를 읽어보면 다음과 같은 문장이 있다.

커스텀 Hook을 작성하는 경우, 반환하는 모든 함수를 useCallback으로 감싸는 것이 좋습니다.

그럼 React에서도 최소한으로 사용하라 그런 useCallback에서 반환하는 함수에서는 적극 권장할까?

  • 이 문장은 최적화 그리고 협업과 관련이 있다.

최적화 관점

  • 하위 컴포넌트에게 함수를 props로 넘겨줄 때 하위 컴포넌트가 memo(React.memo)로 감싸 있어도 상위 컴포넌트에서 그 함수가 최적화가 되어 있지 않으면 최적화가 제대로 되지 않는다.

    • Hook을 사용한다는 것은 함수형 컴포넌트 이기 때문에 함수형 컴포넌트는 JSX를 반환하는 함수이기 때문이다.
    • 함수의 state가 업데이트되는 등의 이유로 리렌더링 과정이 실행되면 함수가 재 실행되면서 함수가 다시 실행되면 컴포넌트 안에 있는 함수들도 다시 실행되면서 다른 참조값을 갖는다.
    • 하위 컴포넌트에서는 memo로 감싸도 다른 참조값이 들어와서 문맥적으로는 같으나 다른 값이라고 인식하는 것이다.
  • 커스텀 Hook 에서 useCallback으로 반환 함수를 감싸놨으면 반환된 함수를 Props로 넘겨도 리렌더링을 memo로 감싼 컴포넌트에게는 부모가 리렌더링되어도 리렌더링을 유발하지 않는다.

  • useEffect의 dependecies에 커스텀 Hook 에서 반환된 함수를 넣을때도 useCallback으로 감싸져 있는 함수를 넣으면 useCallback으로 감싼 함수의 dependecies가 변하지 않는 이상 재 실행이 되지 않으므로 같은 이유에서 useCallback으로 감싸놓는 것이 좋다.

최적화 + 협업 관점

  • 위의 최적화 관점에서 커스텀 Hook에서 useCallback으로 반환되는 함수를 감싸면 좋다는 것을 알았는데 왜 React 문서에서 모든 함수를 감싸라는 것이 좋다는 것은 잘 이해가 되지 않을 것이다.

    • 그럼 커스텀 Hook에 모든 반환함수를 미리 감싸지 않고 필요할 때 감싸면 되는데 미리 작업해놓는 부분이 비효율적이고 캐싱 메모리 문제도 유발할 수 있다고 생각하게 만들기 때문이다.
  • "모든"이라는 부분은 필자는 협업의 관점에서 생각했다.

    • 커스텀 Hook은 자주 사용하는 Hook 로직을 재사용성 좋게 만드는 것이다.
    • 캡슐화 관점에서 이 커스텀 Hook의 사용자는 내부 로직을 신경쓰지 않고 쉽게써야 하는데 최적화 과정을 거치면서 반환하는 함수가 useCallback으로 감싸져 있나 찾아봐야한다.
    • 이런 관점에서 미리 useCallback을 감싸기로 약속해서 최적화할때 useCallback으로 감싸져 있는지 여부를 신경쓰지 않아도 되게 미리 모든 반환함수는 useCallback으로 감싸져 있다고 "예상 가능하게" 만드는 것이라고 생각한다.
profile
두려움 없이

0개의 댓글