컴포넌트 최적화[useMemo, useCallback, React.memo]_React

miin·2022년 3월 15일
0

React

목록 보기
38/52
post-thumbnail

useMemo

정의

불필요할때에도 호출하여서 자원이 낭비되고 있다
이러한 상황에는 useMemo 라는 Hook 함수를 사용하면 성능을 최적화 할 수 있다

  • 성능을 최적화할 때 사용한다.
  • memo는 memorized의 약자이다.
  • 첫번째 인수에는 함수, 두번째 인수에는 배열을 넣어주면 된다.
  • 두번째 인수에 넣어준 배열의 값이 바뀔때만 함수가 실행된다.
  • 그렇지 않다면 이전의 값을 재사용한다.
const countActiveUsers = users => {
  console.log('확인...');
  return users.filter(user => user.active).length;
}

  const count = useMemo(() => countActive(users), [users]);
 //input에서 값이 입력하는 와중에도 함수가 호출됨
  // const count = countActive(users);

useCallback

정의

useMemo 는 특정 결과값을 재사용 할 때 사용하는 반면,
useCallback 은 특정 함수를 새로 만들지 않고 재사용하고 싶을때 사용한다.
useCallback 을 사용한다고 해서 바로 최적화가 되는것이 아니고, 컴포넌트 렌더링 최적화 작업을 해주어야만 성능이 최적화된다.

  • 주의 할 점, 함수 안에서 사용하는 상태 혹은 props 가 있다면 꼭, deps 배열안에 포함시켜야 된다는 것이다.
    (만약에 deps 배열 안에 함수에서 사용하는 값을 넣지 않게 된다면, 함수 내에서 해당 값들을 참조할때 가장 최신 값을 참조 할 것이라고 보장 할 수 없다. props 로 받아온 함수가 있다면, 이 또한 deps 에 넣어주어야 한다.)
  • useCallback 은 useMemo 를 기반으로 만들어졌다. 다만, 함수를 위해서 사용 할 때 더욱 편하게 해준 것 뿐, 이런식으로도 표현 할 수 있다.
  • 의존성이 변경되는 경우, 이전에 기억하고 있던 함수 자체와 비교해서 다른 경우에만 리렌더링을 한다.
  • useRef와의 차이는, useRef는 DOM element의 특정 속성 값을 기억한다면, useMemo는 특정 함수의 리턴값을 기억하는 것이다.
const onToggle = useMemo(
  () => () => {
    /* ... */
  },
  [users]
);
  const onModify = useCallback(
    () => {
      setInputs({
        username: users.username,
        email: users.email,
        id: users.id,
      });
    },
    [inputs]
  );

계속 바뀔 수 밖에 없는 state를 degs에 넣으면, 배열이 바뀔때마다 함수가 새로 만들어진다

최적화 -> 함수형으로 바꾸고 degs에서 없애기

//전
  const onRemove = useCallback(
    id => {
      setUsers(users.filter(user => user.id !== id));
    },
    [users]
  );
//후
  const onRemove = useCallback(
    id => {
      setUsers(users => users.filter(user => user.id !== id));
    },
    []
  );

React.memo

정의

컴포넌트의 props 가 바뀌지 않았다면, 리렌더링을 방지하여 컴포넌트의 리렌더링 성능 최적화를 해줄 수 있다
이 함수를 사용한다면, 컴포넌트에서 리렌더링이 필요한 상황에서만 리렌더링을 하도록 설정해줄수있다.

그냥 감싸주면 된다.
export default React.memo(UserList);

참고

  • button 에 onClick 으로 설정해준 함수들은, 해당 함수들을 useCallback 으로 재사용한다고 해서 리렌더링을 막을 수 있는것은 아니므로, 굳이 그렇게 할 필요 없다.

  • 추가적으로, 렌더링 최적화 하지 않을 컴포넌트에 React.memo 를 사용하는것은, 불필요한 props 비교만 하는 것이기 때문에 실제로 렌더링을 방지할수있는 상황이 있는 경우에만 사용.

  • 추가적으로, React.memo 에서 두번째 파라미터에 propsAreEqual 이라는 함수를 사용하여 특정 값들만 비교를 하는 것도 가능.

export default React.memo(
  UserList,
  (prevProps, nextProps) => prevProps.users === nextProps.users
);

하지만, 이걸 잘못사용한다면 오히려 의도치 않은 버그들이 발생하기 쉽다.
예를 들어, 함수형 업데이트로 전환을 안했는데 이렇게 users 만 비교를 하게 된다면,
onToggle 과 onRemove 에서 최신 users 배열을 참조하지 않으므로 심각한 오류가 발생 할 수 있다

0개의 댓글