본문 바로가기
개발/React

컴포넌트 최적화 : React.memo(), useSelector(callback,equalityFn)

by 안뇽! 2021. 10. 17.
반응형

새로 알게 된 것 : 컴포넌트 최적화

React.memo

컴퍼넌트가 React.memo()로 래핑될때 React는 컴퍼넌트를 렌더링하고 결과를 메모이징한다.
그 다음 렌더링의 결과가 이전과 같다면 React는 메모이징 이전 내용을 제시한다.
같은 props로 렌더링이 자주 일어나는 컴퍼넌트 에서는 React.memo를 사용하는 것이 더 좋은 성능을 나타낸다.(불필요한 리렌더링을 줄인다.)

다음을 보자. TodoItem 컴퍼넌트를 다음과 같이 정의한다.

function TodoItem({ todo, onToggle }){
    return (
        <li 
        style = {{ textDecoration : todo.done ? 'line-through' : 'none'}}
        onClick = {()=> onToggle(todo.id)}
        >
            {todo.text}
        </li>
    );
}

 

위 영상에서 보다시피 기존에 렌더링되어 있던 TodoItem컴퍼넌트들도 계속 렌더링된다.

이번엔 TodoItemReact.memo()로 래핑하여 사용해보자.

const TodoItem = React.memo(function TodoItem({todo,onToggle}){
    return (
        <li 
        style = {{ textDecoration : todo.done ? 'line-through' : 'none'}}
        onClick = {()=> onToggle(todo.id)}
        >
            {todo.text}
        </li>
    );
}
);

 

기존에 렌더링된 TodoItemprops가 변경되지 않은 것들은 리렌더링되지 않는다.

이런식으로 React.momo()를 사용하면 리렌더링 낭비를 줄이면서 성능을 높힐 수 있다.

useSelectorequalityFn

상태가 바뀌지 않았을 때 useSelector 를 통해 매번 렌더링하는 것은 낭비렌더링이다.

이를 최적화 하는 방법으로는 두가지 방법이 있다.

 

useSelector 를 여러번 사용한다.

다음과 같이 useSelector 하나를 통해 객체를 리턴할 때, 객체는 메모리주소를 참조하기 때문에 매번 다른 값으로 인식된다.

const { number, diff } = useSelector(state => ({
  number: state.counter.number,
  diff: state.counter.diff
}));

 

즉, 매번 새로운 객체 { number, diff } 를 만든다. 상태가 바뀌었는지 않았는지 확인을 할 수 없어 매번 렌더링이 이루어진다.

 

반면, 다음과 같이 state 개수만큼 useSelector를 사용하면 해당 값이 바뀌었을 때에만 컴포넌트가 리렌더링 된다.

값을 비교하기 때문에 전,후가 같을때는 리렌더링을 하지 않는다.

const number = useSelector(state => state.counter.number);
const diff = useSelector(state => state.counter.diff);

 

react-reduxshallowEqual 함수를 useSelector의 두번째 인자로 전달한다.

import { useSelector, useDispatch, shallowEqual } from 'react-redux';
.
.
const { number, diff } = useSelector(
  state => ({
    number : state.counter.number,
    diff : state.counter.diff
    }), shallowEqual );
.
.

useSelector의 두번째 파라미터는 이전값과 다음값을 비교하여 boolean값을 리턴하는 equalityFn이다.
true가 나오면 리렌더링을 하지 않고, false가 나오면 리렌더링을 한다.
shallowEqualreact-redux에 내장되어 있는 함수로서, 가장 겉에 있는 "값" 들을 비교한다.

즉, 이전값과 다음값을 비교하여 같다면 true를 리턴하여 리렌더링을 하지 않고, 다르다면 false를 리턴하여 리렌더링한다.

반응형