다음 내용은 책 '리액트를 다루는 기술'을 바탕으로 작성된 글입니다.
컴포넌트는 다음과 같은 상황에서 리렌더링이 발생한다.
1. 자신이 전달받은 props가 변경될 때
2. 자신의 state가 변경될 때
3. 부모 컴포넌트가 리렌더링될 때
4. forceUpdate 함수가 실행될 때
리렌더링이 되지 않아도 되는 컴포넌트까지 위의 상황을 만족한다는 이유로 리렌더링이 되다 보면, 성능이 심하게 저하 되는 경우가 발생 된다. 이럴 때는 컴포넌트 리렌더링 성능을 최적화해 주는 작업을 해 주어야 한다.
즉, 리렌더링이 불필요할 때에는 리렌더링을 방지해 주어야 한다.
React.memo를 사용하여 컴포넌트 성능 최적화
컴포넌트의 리렌더링을 방지할 때는 shouldComponentUpdate라는 라이프사이클을 사용하면 된다.
그렇지만 함수 컴포넌트에는 라이프사이클 메서드를 사용할 수 없으므로 대신 React.memo 라는 함수를 사용한다.
React.memo 함수를 통해 컴포넌트의 props가 바뀌지 않았다면, 리렌더링 하지 않도록 설정할 수 있다.
사용법은 컴포넌트를 만들고 나서 export문에서 컴포넌트를 React.memo로 감싸주면 된다.
export default React.memo(TodoListItem);
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],
);
위의 함수 onRemove와 onToggle은 가장 상단의 부모 컴포넌트의 state인 todos 배열이 업데이트가 될 때마다 함수가 새로 만들어진다.
이렇게 함수가 계속 만들어지는 상황을 방지하는 방법은 두 가지이다.
첫 번째 방법은, 함수형 업데이트 기능을 사용하는 것
두 번째 방법은 useReducer을 사용하는 것이다.
useState의 함수형 업데이트
const [todos, setTodos] = useState([ {....} ,{....},{....} ]);
위와 같이 useState를 이용해 생성된 state를 변경할 때(setTodos),
새로운 상태를 파라미터로 넣는 대신 상태 업데이트를 어떻게 할지 정의하는 업데이트 함수를 넣는 방법이다.
이를 함수형 업데이트라고 한다.
다음은 예시이다.
const [number,setNumber] = useState(0);
const onIncrease = useCallback( ()=> {
setNumber(prevNumber => prevNumber+1),
[],
);
단순히 setNumber(number+1)가 아닌 위의 코드처럼 작성하면 useCallback을 사용할 때 두 번째 파라미터로 넣는 배열에 number를 넣지 않아도 된다.
따라서 number가 변하는 매 순간마다 onIncrease 함수가 불필요하게 재생성되지 않으므로 성능 저하를 막을 수 있다.
userReducer 사용
useReducer를 사용하는 방법은 기존 코드를 많이 고쳐야 한다는 단점이 있지만, 상태를 업데이트 하는 로직을 모아서 컴포넌트 바깥에 둘 수 있다는 장점이 있다. 성능상으로는 두 방법이 비슷하기 때문에 어떤 방법을 선택할지는 각자의 취향에 따라 결정하면 된다.
나는 아직 Reducer의 개념을 공부하지 않아 useReducer를 사용하는 방법은 리덕스를 공부하고 난 뒤 다시 알아볼 생각이다.
'Front-End > React' 카테고리의 다른 글
[React] 중첩된 라우트 , Outlet (0) | 2022.03.01 |
---|---|
[React] URL 파라미터와 쿼리스트링 (0) | 2022.02.25 |
[React] 리액트 라우터 (0) | 2022.02.25 |
[React] 컴포넌트 성능 최적화 : 불변성의 중요성 (0) | 2022.02.24 |
[React] useCallback 함수 (0) | 2022.02.24 |