일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- EnhancedFor
- 환경설정
- 다형성
- 생성자오버로드
- 자바
- 예외미루기
- 컬렉션프레임워크
- abstract
- Java
- 추상메서드
- 정수형타입
- 한국건설관리시스템
- GRANT VIEW
- 자동차수리시스템
- oracle
- 대덕인재개발원
- 오라클
- NestedFor
- cursor문
- 메소드오버로딩
- 어윈 사용법
- 참조형변수
- 인터페이스
- exception
- 객체 비교
- 집합_SET
- 사용자예외클래스생성
- 예외처리
- 컬렉션 타입
- 제네릭
- Today
- Total
거니의 velog
(1) 컴포넌트 성능 최적화 1 본문
* 이전에는 학습한 지식을 활용하여 멋진 일정 관리 애플리케이션을 만들어 보았다. 현재까지는 이 애플리케이션을 사용할 때 불편하지 않았다. 추가되어 있는 데이터가 매우 적기 때문이다. 그러나 데이터가 무수히 많아지면, 애플리케이션이 느려지는 것을 체감할 수 있을 정도로 지연이 발생한다.
* 이번 실습은 다음과 같은 흐름으로 진행한다.
1. 많은 데이터 렌더링하기
* 우선 실제로 랙(lag)을 경험할 수 있도록 많은 데이터를 렌더링해 보자. 물론 데이터를 하나하나 직접 입력하지 않고 코드를 사용하여 쉽게 추가할 수 있다.
* App 컴포넌트를 다음과 같이 수정해 보자.
import React, { useCallback, useRef, useState } 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: `할 일 ${i}`,
checked: false,
});
}
return array;
}
const App = () => {
const [todos, setTodos] = useState(createBulkTodos);
// 고윳값으로 사용될 id
// ref를 사용하여 변수 담기
const nextId = useRef(4);
const onInsert = useCallback(
(text) => {
const todo = {
id: nextId.current,
text,
checked: false,
};
setTodos(todos.concat(todo));
nextId.current += 1; // nextId 1씩 더하기
},
[todos],
);
const onRemove = useCallback(
(id) => {
setTodos(todos.filter((todo) => todo.id !== id));
},
[todos],
);
const onToggle = useCallback(
(id) => {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, checked: !todo.checked } : todo,
),
);
},
[todos],
);
return (
<TodoTemplate>
<TodoInsert onInsert={onInsert} />
<TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} />
</TodoTemplate>
);
};
export default App;
* 데이터를 하나하나 직접 입력할 수는 없으므로 createBulkTodos 라는 함수를 만들어서 데이터 2,500개를 자동으로 생성했다.
* 여기서 주의할 점은 useState의 기본값에 함수를 넣어 주었다는 것이다. 여기서 useState(createBulkTodos()) 라고 작성하면 리렌더링될 때마다 createBulkTodos 함수가 호출되지만, useState(createBulkTodos)처럼 파라미터를 함수 형태로 넣어 주면 컴포넌트가 처음 렌더링될 때만 createBulkTodos 함수가 실행될 것이다.
* 자, 이제 코드를 저장하면 다음과 같이 데이터 2,500 개가 나타날 것이다.
* 데이터 2,500 개가 렌더링되었다면 항목 중 하나를 체크해 보자. 이전보다 느려진 것이 느껴지는가?
2. 크롬 개발자 도구를 통한 성능 모니터링
* 성능을 분석해야 할 때는 느려졌다는 느낌만으로 충분하지 않다. 정확히 몇 초가 걸리는지 확인해야 하는데, 크롬 개발자 도구의 Performance 탭을 사용하여 측정하면 된다. 크롬 개발자 도구의 Performance 탭을 열면 다음과 같이 녹화 버튼이 나타난다.
* 이 버튼을 누르고 '할 일 1' 항목을 체크한 다음, 화면에 변화가 반영되면 Stop 버튼을 누르자. 그러면 다음과 같이 성능 분석 결과가 나타난다.
* 성능 분석 결과에 나타난 Timing을 열어 보면 각 시간대에 컴포넌트의 어떤 작업이 처리되었는지 확인할 수 있다.
* App [update] 박스에 커서를 올려 보니 이 작업이 처리되는 데 1.02초가 걸렸다고 나타났다(처리 시간은 컴퓨터 환경에 따라 결과가 다르게 나타날 수 있다).
* 데이터가 2,500개 밖에 안 되는데도 불구하고 1.02초나 걸린다는 것은 성능이 매우 나쁘다는 의미이다. 이제 이를 최적화하는 방법을 알아보자.
3. 느려지는 원인 분석
* 컴포넌트는 다음과 같은 상황에서 리렌더링이 발생한다.
1. 자신이 전달받은 props가 변경될 때
2. 자신의 state가 바뀔 때
3. 부모 컴포넌트가 리렌더링 될 때
4. forceUpdate 함수가 실행될 때
* 지금 상황을 분석해 보면, '할 일 1' 항목을 체크할 경우 App 컴포넌트의 state가 변경되면서 App 컴포넌트가 리렌더링된다. 부모 컴포넌트가 리렌더링되었으니 TodoList 컴포넌트가 리렌더링되고 그 안의 무수한 컴포넌트들도 리렌더링된다.
* '할 일 1' 항목은 리렌더링되어야 하는 것이 맞지만, '할 일 2'부터 '할 일 2500' 까지는 리렌더링을 안 해도 되는 상황인데 모두 리렌더링되고 있으므로 이렇게 느린 것이다. 컴포넌트의 개수가 많지 않다면 모든 컴포넌트를 리렌더링해도 느려지지 않는데, 지금처럼 약 2,000개가 넘어가면 성능이 저하된다.
* 이럴 때는 컴포넌트 리렌더링 성능을 최적화해 주는 작업을 해 주어야 한다. 즉, 리렌더링이 불필요할 때는 리렌더링을 방지해 주어야 하는데, 어떻게 방지하는지 알아보도록 하자.
'React > React_리액트 응용' 카테고리의 다른 글
(6) 리액트 라우터로 SPA 개발하기 2 (0) | 2023.12.11 |
---|---|
(5) 리액트 라우터로 SPA 개발하기 1 (1) | 2023.12.08 |
(4) immer를 사용하여 더 쉽게 불변성 유지하기 (1) | 2023.12.08 |
(3) 컴포넌트 성능 최적화 3 (0) | 2023.12.07 |
(2) 컴포넌트 성능 최적화 2 (1) | 2023.12.07 |