ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React.memo, useMemo, useCallback 진짜로 언제 사용해야 할까?
    ReactJS 2023. 10. 14. 05:56

    일단 당연한 사실들을 한번 짚어보자

    React.memo: 컴포넌트 매핑 함수로 컴포넌트를 캐싱해서, 컴포넌트의 state 가 변경되지 않았음에도 쓸데없이 리렌더링을 방지함

    useMemo: 컴포넌트가 렌더링 중에 생성하는 변수를 캐싱하여, 변수를 생성할 때 관여하는 인자가 바뀌지 않으면 변수를 새로 생성하지 않음

    useCallback: useMemo 의 함수 버전

     

    useMemo 로 객체를 캐싱하고, useCallback 으로 이벤트 핸들러 함수를 캐싱해서 컴포넌트의 prop 으로 전달해주면, memo로 캐싱한 컴포넌트는 prop 이 바뀌지 않은 것을 제대로 인식하고 리렌더링 하지 않는다.

    (안그러면 React.memo 의 prop 비교 방식이 shallow copy 이기 때문에, 단순히 이전 prop 과의 주소값만 비교해서 다르다고 인식하고 리렌더링을 해버린다)

     

     


    근데 나는 왜 지금까지 프로젝트를 하면서 한번도 캐싱을 사용하지 않았을까?

     

    일단 캐싱은 불필요한 리렌더링을 줄여 성능을 최적화하는 무결의 도구처럼 보일 수 있지만, 그렇지 않다.

    캐싱에도 당연하고 엄연한 단점이 있는데, 바로 메모리를 잡아먹는다.

    C를 공부할 때에도, 알고리즘을 공부할 때에도 캐싱은 실행 속도를 빠르게 하기 위해 많이 썼다.

    하지만, 프로그램의 메모리가 너무 커지면 그것은 그것대로 성능에 문제가 발생했다.

    극단적으로 생각해서, 만약 모든 컴포넌트와 모든 객체를 전부 캐싱해버리면, 어마어마한 메모리를 잡아먹게 되어 성능은 오히려 더 안 좋아질 것이 자명하다.

     

    더군다나, 리액트의 렌더링 성능은 최적화가 매우 잘 되어있다.

    (물론 내가 리액트 개발자처럼 리액트의 렌더링 과정을 상세히 알고 있는 것은 아니다)

    따라서, 정말 빈번하게 리렌더링이 일어나면서 state 가 바뀌지 않는 컴포넌트가 아닌 경우 캐싱은 불필요하다고 생각한다.

    아니면 컴포넌트의 크기가 큰 경우, 리렌더링 하는데 느끼는 사용자의 불편함과 메모리의 사이에서 적당히 타협할 고민은 해 볼 것 같다.

     

     

    그렇다면 캐싱이 필요할 정도로 빈번하게 리렌더링이 일어나는 경우는 언제일까?

    내 생각에는 버튼처럼 사용자가 클릭할 때마다 컴포넌트가 리렌더링 되는 경우는 '빈번함'의 범주에 절대 들 수 없다고 생각한다. (버튼 클리커 웹게임을 만들지 않는 이상은)

     

    1초 혹은 그 이하에 한번씩 리렌더링이 되는 컴포넌트의 정도면 꽤나 빈번하다고 느낄 것 같다.

    500ms에 한 번씩 리렌더링 되는 컴포넌트가 어느 정도 깊이의 상태가 변경되지 않는 하위 컴포넌트들을 가지고 있으면, 캐싱의 필요성을 매우 체감할 것 같다.

    아직까지 내 프로젝트에는 그런 경우가 없었다.

     

     


    내 프로젝트의 컴포넌트들이 리렌더링 되는 빈도를 체크해서, 상대적으로 state 가 바뀌지 않음에도 불필요한 리렌더링이 많이 일어나는 컴포넌트들을 캐싱해서 성능 비교를 해 보면 재미있겠다.

    'ReactJS' 카테고리의 다른 글

    "클린 코드" 는 "방어운전" 과 같다.  (0) 2023.10.21

    댓글

Designed by Tistory.