[React] memoization 그리고 더 많은 Hooks

박감자·2024년 11월 6일

Memoization 등장 이유

React 리렌더링 발생 조건

  1. 컴포넌트의 state가 바뀐 경우
  2. 컴포넌가 내려받은 props가 변경되었을 때
  3. 부모 컴포넌트가 리렌더링 된 경우 자식 컴포넌트 모두

최적화

React에서 리렌더링이 자주 발생하게 되는 것을 줄이기 위해 Optimization (최적화)가 필요하다. 대표적 3가지 방법이

  • memo - 컴포넌트 캐싱
  • useCallback - 함수 캐싱
  • useMemo - 값 캐싱

memo (React.memo)

부모 컴포넌트가 렌더링 된 경우 모든 자식 컴포넌트에서 바뀐것이 없음에도 리렌더링이 된다. 이를 방지하는 것이 React.memo!

사용법

const Box = () => {
	return <div>Box</div>;
};

export default React.memo(Box);

export 전에 React.memo로 감싸주면 Box의 부모 컴포넌트가 아무리 많이 리렌더링 되어도 Box도 리렌더링 되지는 않는다.

useCallback

props로 들어오는 함수 자체를 기억할때 필요한 hook. 예를 들면 App->Box 의 부모자식 관계의 컴포넌트가 있을 때, App에서 props로 함수를 내려주면, 이 함수 인자가 콜 될때마다 Box도 다시 리렌더링 된다.

하지만 함수만 자식에서 콜 한 것 뿐이고 리-렌더링을 할 필요가 없었다면 이는 불필요한 리렌더링이 되므로 함수 자체도 memoization을 적용할 수 있다.

// App.jsx

...
  // count를 초기화해주는 함수
  const initCount = () => {
    setCount(0);
  };

  return (
    <>>
      <p>현재 카운트 : {count}</p>
      <button onClick={onPlusButtonClickHandler}>+</button>
      <button onClick={onMinusButtonClickHandler}>-</button>
      <div style={boxesStyle}>
        <Box initCount={initCount} />
      </div>
    </>
  );
}

// Box.jsx
function Box({ initCount }) {
  const onInitButtonClickHandler = () => {
    initCount();
  };

  return (
    <div style={boxStyle}>
      <p>이거슨 박스</p>
      <button onClick={onInitButtonClickHandler}>초기화</button>
    </div>
  );
}

위와 같은 경우 Box에서 디자인이 바뀌거나 상태가 바뀌는 경우가 없음에도 initCount를 부모로부터 받아왔기 때문에 초기화 버튼을 누를때 리렌더링이 된다. 이를 방지하는 것이 useCallback이다

사용법은 아래와 같다

// App.jsx
const initCount = useCallback(() => {
  setCount(0);
}, []);		// 빈 배열을 두어서 최초 렌더링 후 리렌더링 되지 않도록

이렇게 지정해주면 Box에서 초기화를 눌러도 App만 리렌더링된다.

useMemo

변수 혹은 어떠한 값도 memoization이 가능하다. 예를 들어 특정한 값을 도출해내는데 오래 걸리고 이 값이 렌더링 될때마다 실행되지만 값에 변화가 없다면 사실 초기 값만 저장해주고 렌더링을 막는 것이 효율적이다. 이러한 경우에 쓰이며 사용법은 아래와 같다

const heavyWork = () => {
  for (let i = 0; i < 100000000000000; i++) {
    // 별다른 일 안 하기
  }
  return 100;	// 반환값 고정
}

// 계산값 저장
const result = useMemo(() => heavyWork(), []);

Memoization 주의점

리렌더링을 막기에는 효율적인 방법이지만 모든 컴포넌트, 함수, 값등을 기억 저장하게 된다면 메모리를 불필요하게 많이 차지하게 된다. 따라서 필요한 요소들에 대해서만 memoization을 사용하고 무분별한 사용은 지양해야한다.

Custom Hooks

주어진 hooks 말고도 개발자의 상황에 맞게 커스터마이징이 가능하다. 중복되는 로직 혹은 코드를 커스텀 훅을 통해서 관리하는 방식이다.

https://ko.legacy.reactjs.org/docs/hooks-custom.html

profile
코딩하는 감자

0개의 댓글