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

0
post-thumbnail

10장에서 만들었던 To-do App에서 데이터가 많아지면 애플리케이션이 느려질 것이다.
App.js파일을 좀 수정해서 많은 데이터를 렌더링 해보자!

1. 많은 데이터 렌더링

(1) useState의 기본값을 함수로

#createBulkTodos는 반복문을 통해 많은 데이터를 추가하는 함수이다.

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

useState의 기본값을 createBulkTodos()로 지정하면, 리렌더링 될때마다 createBulkTodos함수가 실행되지만 괄호 없이 createBulkTodos로 지정하면, 처음 렌더링 될때만 createBulkTodos 함수가 실행된다.

2. 느려지는 원인 분석

컴포넌트가 리렌더링 되는 경우는 아래와 같다.
1. 전달받은 props가 바뀔 때
2. 자신의 state가 바뀔 때
3. 부모 컴포넌트가 리렌더링 될 때
4. forceUpdate 함수가 실행될 때

따라서 컴포넌트가 불필요하게 리렌더링 되는걸 방지해야 한다.

3. 컴포넌트 성능 최적화

(1) React.memo 사용

컴포넌트를 내보내는 구문에 React.memo(컴포넌트명)으로 간단하게 수정하면 된다.

이렇게 함으로써, 컴포넌트의 props가 바뀌지 않을 경우에는 리렌더링을 하지 않도록 설정한다.

따라서 아래 사진의 경우 TodoListItem컴포넌트의 props인 todo, onRemove, onToggle이 바뀌지 않으면 리렌더링되지 않는다.


수 많은 일정 데이터 중 하나만 업데이트 되어도 매번 함수가 새롭게 생성되는 것은 비효율적이다.
따라서 함수가 계속 만들어지는 상황을 방지하는 방법은 (2), (3)번을 참고하자.

(2) useState의 함수형 업데이트 기능

기존의 useState에서의 세터 함수를 사용할때는 파라미터로 새로운 상태를 넣어줬다.

아래 사진은 새로운 일정을 추가했을때 실행되는 함수이다.
물론 이전에도 함수가 매번 생성되는 것을 막기 위해 todos 배열이 변경될때만 생성되도록 두번째 파라미터를 사용했다.

하지만, 세터 함수의 파라미터에 새로운 상태를 넣는것이 아니라 업데이트 함수를 넣어주면 두 번째 파라미터에 todos 배열을 넣지 않아도 된다. 그냥 기존의 파라미터 앞에 todos => 만 추가하고 두 번째 파라미터 속 배열을 지우기만 하면 된다.

(3) useReducer

위에 (2)번 방법의 대체 방법으로 사용할 수 있다.

const [todos, dispatch] = useReducer(todoReducer, undefined, createBulkTodos);

useReducer를 사용할 때, 두 번째 파라미터로 초기값을 넣어주는데 위와같이 undefined를 넣게 되면 맨 처음 렌더링 될 때만 createBulkTodos 함수를 호출한다.

useReducer의 제일 큰 장점은 상태 업데이트 로직을 모아서 컴포넌트 외부로 뺄 수 있다는 점이다.

useReducer를 사용하는 예시로 일정을 추가하는 함수 코드를 보면 아래와 같다.

4. react-virtualized를 이용한 렌더링 최적화

아래 사진을 보면 일정 2500개 중에 9개만 보이는 상황이다. 이렇게 9개만 보임에도 불구하고, 나머지 2491개의 일정도 스크롤 전에 이미 렌더링 되어있기 때문에 비효율적이다.

따라서 react-virtualized 라이브러리를 이용해서 스크롤 되기 전에는 렌더링 되지 않은 상태에서 크기만 차지하고, 스크롤 될 때! 해당 스크롤 위치에서 보여지는 컴포넌트를 렌더링 하게끔 해볼 것이다.

$ yarn add react-virtualized

react-virtualized에서 제공하는 List컴포넌트를 사용하면 된다. List컴포넌트를 사용하기 위해 새로운 함수를 작성하고 해당 함수를 List컴포넌트의 props로 설정해주면 된다.

나는 react-virtualized의 List 컴포넌트에서 일정 하나하나를 렌더링 할때 사용할 rowRenderer 함수를 생성했다.

참고로 List컴포넌트의 props로 넣어주기 위해 미리 일정의 크기나 높이를 개발자 도구를 통해 확인해야 한다.


리액트 컴포넌트 렌더링은 기본적으로 빠른 편이기 때문에 매번 컴포넌트의 성능을 최적화 하기 위해 스트레스 받지 않아도 되지만, 리스트와 관련된 컴포넌트가 있고 업데이트가 자주 발생한다면 꼭 최적화 하는게 좋다.

profile
재미있는 아이디어 떠올리는 것을 좋아하고, 이를 구현하여 세상에 즐거움을 선물하고 싶은 사람입니다.

0개의 댓글