[React] 컴포넌트 성능 최적화

✨ 강은비·2022년 1월 13일
1

React

목록 보기
17/36

react 스터디에서 리액트를 다루는 기술이라는 책을 선정했고 이 책을 읽고 배운 것을 바탕으로 작성되었다.


💡 크롬 개발자 도구를 통한 성능 모니터링

  • 크롬 확장 프로그램으로 React Developer Tools 설치
  • Profiler 탭 분석

주로 업데이트가 발생한 컴포넌트랑 관계없는 컴포넌트들도 리렌더링 되는 문제 발생


📌 컴포넌트의 리렌더링

컴포넌트는 다음과 같은 상황에서 리렌더링이 발생함

  • 자신이 전달받은 props가 변경될 때
  • 자신의 state가 바뀔 때
  • 부모 컴포넌트가 리렌더링될 때
  • forceUpdate함수가 실행될 때

불필요한 리렌더링이 발생하지 않도록 해야 한다.


📌 React.memo

  • 컴포넌트의 리렌더링을 방지할 때는 life cycle methodshouldComponentUpdate 사용하면 된다.
  • 하지만, 함수형 컴포넌트에서는 생명주기 메서드를 사용할 수 없으므로 React.memo라는 함수를 사용한다.
  • 컴포넌트가 전달받은 props가 바뀌지 않았다면 리렌더링하지 않도록 하여 컴포넌트의 리렌더링 성능을 최적화할 수 있다.
export default React.memo(MyComponent);

📌 함수 생성 횟수 줄이기

✨ useState 함수형 업데이트

  • useCallback을 이용하여 특정 함수가 리렌더링마다 새로 생성되지 않고 재사용할 수 있도록 하지만, useCallback과 더불어 useState의 함수형 업데이트를 이용하여 함수 생성 횟수를 더욱 더 줄여 리렌더링 성능을 최적화할 수 있다.
const [number, setNumber] = useState(0);

// Before: number 상태 값이 바뀔 때 마다 등록된 함수가 새로 생성됨.
const onIncrese = useCallback(
    () => setState(number + 1);,
    [number]
);


// After 
const onIncrease = useCallback(
    () => setState(prevNumber => prevNumber + 1);,
    []
);
  • setState함수에 함수인자를 넣으면 그 함수는 이전 상태값을 인자로 받아 참조하여 상태값을 업데이트시킬 수 있다.
  • 현재 상태값에 의존하지 않아도 되므로 useCallback의 두번째 인자로 빈 배열을 넣어 초기렌더링 시에만 함수를 생성하고 리렌더링될 때마다 처음에 생성된 함수를 재사용하도록 한다.

✨ useReducer 사용

function reducer(state, action){
    switch(action.type){
        case "INCREMENT":
            return { number : state.number + 1};
        default:
            return state;
    }
}

...


const [state, dispatch] = useReducer(reducer, { number : 0 });

const onIncrese = useCallback(
    dispatch({ type: "INCREMENT" });,
    []
);
  • useReducer의 장점은 컴포넌트의 state 업데이트 로직을 바깥으로 빼낼 수 있다는 것이다.
  • 컴포넌트 바깥에 있는 reducer 함수는 첫번째 인자로 항상 현재 상태값을 가져오기 때문에 컴포넌트 내부에서는 dispatch함수를 이용하여 action 인자를 받아 reducer함수를 호출하면 된다.
  • 즉, useCallback으로 등록된 함수 내부에서는 현재 상태값에 의존하지 않아도 되므로 두 번째 인자로 빈 배열을 전달하여 초기 렌더링 시 생성된 함수를 리렌더링될 때마다 재사용할 수 있도록 한다.

📌 react-virtualized

  • react-virtualized 라이브러리를 이용하면 스크롤되기 전에 보이지 않는 컴포넌트는 렌더링하지 않고 크기만 차지하게끔 할 수 있다.
  • 시스템 자원을 낭비하지 않고 아낄 수 있다.

📌 useMemo와 useCallback

  • useMemouseCallback은 주로 컴포넌트 성능을 최적화하기 위해 사용된다.
  • 하지만 퍼포먼스 최적화에는 trade-off가 존재한다. 퍼포먼스를 최적화시켰지만, 컴퓨터 자원 등 소모되는 자원이 있다.
  • 항상 소모되는 자원에 비해 퍼포먼스 최적화로 얻는 이득이 더 크진 않다.
  • useMemouseCallback을 이용하면 컴포넌트 성능을 최적화할 수 있지만 의존성 배열의 값을 관리하고 메모이제이션을 위해 메모리를 소모해야 한다. 어쩌면 이득보다 더 큰 대가를 치러야 할 수 있다.

✨ useMemo와 useCallback을 언제 사용할까?

  • 메모리 주소 값이 동일한지 비교 - Referential Equality
  • 성능에 문제가 있다는 것이 인지되었을 때
책임감 있게 최적화해야 한다 ❗
적재적소에 사용하자 ❗

0개의 댓글