컴포넌트 성능 최적화

로선생·2021년 9월 16일

해당 책은 리액트를 다루는 기술 11장을 기반으로 작성된 글입니다.

데이터가 무수히 많아지면 애플리케이션이 느려지는 것을 체감할 수 있을 정도로 지연이 발생한다.

실제 랙이 걸릴 정도의 많은 데이터를 렌더링해 보자.
App.js 컴포넌트를 다음과 같이 수정해 보자.

import React, { useState, useRef, useCallback } from ‘react‘;
import TodoTemplate from ‘./components/TodoTemplate‘;
import TodoInsert from ‘./components/TodoInsert‘;
import TodoList from ‘./components/TodoList‘;


function createBulkTodos() {
  const array = [];
  for (let i = 1; i <= 2500; i++) {
    array.push({
      id: i,
      text: </span><span class="cd2 co31"></span> <span class="cd2 co31"></span> <span class="cd2 co49">${</span><span class="cd2 co33">i</span><span class="cd2 co49">}</span><span class="cd2 co31">,
      checked: false,
    });
  }
  return array;
}



const App = () => {
  const [todos, setTodos] = useState(createBulkTodos);



// 고윳값으로 사용될 id
  // ref를 사용하여 변수 담기
  const nextId = useRef(2501);



(…)
};



export default App;

할 일이 2500개가 된다.

useState에 useState(createBulkTodos())라고 작성하면 리렌더링 될 때마다 함수가 호출되지만, useState(createBulkTodos)처럼 함수 형태로 넣어 주면 컴포넌트가 처음 렌더링될때만 createBulkTodos함수가 실행된다.

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

크롬 개발자 도구의 Performance탭을 사용하면 몇 초가 걸리는지 확인할 수 있다.

느려지는 원인 분석

컴포넌트는 다음과 같은 상황에서 리렌더링이 발생한다.
1. 자신이 전달받은 props가 변경될 때
2. 자신의 state가 바뀔 때
3. 부모 컴포넌트가 리렌더링 될 때
4. forceUpdate함수가 실행될 때

지금 상황을 분석하면, 할 일1항목을 체크할 경우, App 컴포넌트의 state가 변경되면서 App컴포넌트가 리렌더링 된다. 부모 컴포넌트가 리렌더링 되었으니 TodoList 컴포넌트가 리렌더링 되고, 그 안의 무수한 컴포넌트들도 리렌더링 된다.

할 일1 항목만 리렌더링 되어야 하는데, 할 일2~할 일2500까지 리렌더링 되고 있으니 느린 것이다.

이 때 컴포넌트 리렌더링 성능 최적화 작업이 필요하다.

React.memo를 사용하여 컴포넌트 성능 최적화

컴포넌트의 래렌더링 방지를 위해 7장에서 배운 shouldComponentUpdate라는 라이프사이클을 사용하면 된다.
다만 함수형 컴포넌트에는 라이프사이클 메서드를 사용할 수 없으므로, React.memo 함수를 사용한다. 컴포넌트의 props가 바뀌지 않았다면, 리렌더링 하지 않도록 설정하여 함수형 컴포넌트 리렌더링 성능을 최적화해줄 수 있다.

컴포넌트를 만들고 나서 감싸주기만 하면 React.memo를 사용할 수 있다.

import React from ‘react‘;
import {
  MdCheckBoxOutlineBlank,
  MdCheckBox,
  MdRemoveCircleOutline,
} from ‘react-icons/md‘;
import cn from ‘classnames‘;
import ‘./TodoListItem.scss‘;


const TodoListItem = ({ todo, onRemove, onToggle }) => {
  (…)
};



export default React.memo(TodoListItem);
profile
이제는 이것저것 먹어요

0개의 댓글