React의 Hook - 메모이제이션 hook

eeensu·2023년 8월 3일
0

React 기본

목록 보기
12/22
post-thumbnail

react에서 가장 많이 사용되는 훅은 useState()useEffect()가 있다. 이 외에도 같이 자주 사용하는 hook들을 살펴보자.



메모이제이션

메모이제이션이란 컴퓨터 프로그래밍이 동일한 계산을 반복적으로 할 때, 초기에 계산된 값을 메모리에 저장함으로써 다음 호출시에 계산을 수행하지 않고 메모리에 저장된 값을 참조하여 값을 사용하는 방식이다. 불필요한 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술이다.


memo()

memo() 는 컴포넌트를 렌더링할 때, 함수 컴포넌트를 memo() 안에 감싸서 해당 컴포넌트를 메모이제이션하는 함수이다. 컴포넌트의 props가 변경되지 않으면 해당 컴포넌트를 이전의 결과와 재사용하여 리렌더링을 최적화한다.

얼핏 보면 모든 컴포넌트에 이를 적용시켜 최적화 랜더링의 이점을 누려야할 것 같지만, 메모이징된 컴포넌트의 결과를 저장하기 위한 추가적인 메모리 공간을 할당하는 것 자체도 컴퓨터의 자원을 소비하는 것이기 때문에 굳이 성능적으로 이득을 보지 못하는 상황이면 사용하지 않는 것이 좋다.

import React, { memo } from 'react';

const MemoizedComponent = ({ value }) => {
  console.log('Component rendered');

  return (
    <div>
      {value}
    </div>
  );
});

export default memo(MemoizedComponent);		// 컴포넌트를 추출할 때, memo()로 감싼다.



useMemo()

useMemo() 역시 memo() 와 함께 메모이제이션을 제공하는 hook이다. memo() 는 컴포넌트를 메모이제이션한다면, useMemo() 는 컴포넌트 내부에서 사용될 수 있는 특정 값에 적용할 수 있다.

const result = useMemo(() => {
  console.log('Expensive calculation');
  return count * 2;
}, [count]);

useMemo() 의 첫 번째 인자에는 결과값을 리턴하는 함수를 넣어주고, 두 번째 인자에는 의존성 배열을 넣어준다. 의존성 배열에 들어있는 변수값이 변경되면 메모이제이션을 다시 한다.

useMemo() 로 전달된 함수는 렌더링 중에 실행된다. 통상적으로 렌더링 중에는 하면 안 되는 것을 이 함수내에서 하면 안된다. 렌더링 이후에 하는 일은 useEffect() 에서 하는것이 좋다

또한 두 번째 인자에 없는 경우 매 렌더링 때마다 새 값을 계산하게 된다.




useCallback()

useMemo() 는 값을 메모이제이션 한다면, useCallback()은 함수를 메모이제이션한다. 이 기능은 함수를 메모이제이션 하여 불필요한 반복적인 렌더링을 줄이고자 사용한다.

const [count, setCount] = useState(0);

const increment = useCallback(() => {
  setCount(count + 1);
}, [count]);

return (
  <div>
    <p>Count: {count}</p>
    <button onClick={increment}>Increment</button>
  </div>
);

useCallback() 에 들어가는 인자의 방식은 useMemo() 와 비슷하다. 첫 번째 인자에는 함수를 넣어주고, 두 번째 인자에는 의존성 배열을 넣어준다.

또한 memo() 로 적용된 컴포넌트의 부모에서, 인라인으로 호출하는 함수가 있을 때, memo()의 메모이제이션 효과는 적용되지 않는다. 왜냐하면 다른 props의 결과가 같더라도, 함수를 인라인으로 작성하면 랜더링 될 때마다 다시 쓰여지기 때문에 이전과는 다른 상태이기 때문이다.

따라서 정확하게 memo()를 구현하려면, 인라인으로 쓰여지는 함수를 useCallback() 에 넣어줘야 한다. 인라인이 아닌, 함수를 정의하여 변수로 등록해도 결과는 동일하다. 왜냐하면 부모 자체가 리랜더링 되기 때문이다.

정리하자면, 컴포넌트를 memoization하는 것은 memo(), 함수는 useCallback(), 값은 useMemo() 이다. 중요한 것은, 이 세가지 memoization을 무조건 남발하는 것이 아니라, 필요한 상황에 시기적절하게 맞춰 효율적으로 사용해야하는 것이 중요하다. 무조건 사용하면 과도하게 memory를 차지하기 때문에 역으로 비효율이 발생하기 때문이다. 이러한 최적화와 관련된 중요성을 제대로 살펴보기 위해 이 포스트에서 자세히 확인해보자.

profile
안녕하세요! 26살 프론트엔드 개발자입니다! (2024/03 ~)

0개의 댓글