No Story, No Ecstasy

리액트를 다루는 기술 개정판 [컴포넌트 성능 최적화] 본문

Frontend Series

리액트를 다루는 기술 개정판 [컴포넌트 성능 최적화]

heave_17 2021. 4. 22. 01:58

11. 컴포넌트 성능 최적화

  - useState 기본값에 함수를 넣어주면, 처음 렌더링될 때만 함수가 실행된다.

    . ex) useState(createBulkTodos()) -> 리렌더링마다 호출, useState(createBulkTodos) -> 최초 렌더링 때만 호출

 

  - 크롬 개발자도구 > Performance 메뉴에서 성능 모니터링

 

  - 느려지는 원인 분석 (렌더링이 발생하는 상황)

    1. 자신이 전달받은 props가 변경될 때

    2. 자신의 state가 바뀔 때

    3. 부모 컴포넌트가 리렌더링될 때

    4. forceUpdate 함수가 실행될 때

      -> 최대한 리렌더링 횟수를 줄여야 한다.

 

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

    . 리렌더링을 방지할 때는 shouldComponentUpdate 라이프사이클을 활용한다.

    . But, 함수형 컴포넌트에서는 라이프사이클 메서드를 사용할 수 없으므로, React.memo라는 함수를 사용한다.

    . 이 경우, 컴포넌트의 props가 바뀌지 않았다면 리렌더링하지 않도록 설정하여, 성능을 최적화할 수 있다.

    . React.memo의 사용법: 컴포넌트를 만들고 나서 감싸 주기만 하면 된다.

      ex) export default TodoListItem -> export default React.memo(TodoListItem)

 

  - data가 수정될 때마다 함수가 새로 만들어지는 것 또한 개선할 수 있다.

    . useState의 함수형 업데이트 기능 사용 or useReducer 사용

    . 함수형 업데이트: set함수에 새로운 상태가 아닌, 상태를 어떻게 업데이트할지 정의하는 업데이트 함수를 넘겨준다.

      ex) setNumber(number+1) -> setNumber(prevNumber => prevNumber +1)

    . useReducer: 코드를 많이 고쳐야 하지만, 상태 업데이트 로직을 모아서 컴포넌트 바깥에 둘 수 있다.

 

  - 불변성의 중요성 (불변성: 기존 값을 직접 수정하지 않으면서 새로운 값을 만듦)

    . 불변성이 지켜지지 않으면 객체 내부의 값이 새로워져도 바뀐 것을 감지하지 못한다.

      -> React.memo에서 서로 비교하여 최적화하는 것이 불가능

    . 얕은 복사는 가장 바깥에 있는 값만 복사되기 때문에, 내부의 값이 객체 혹은 배열이라면 내부의 값 또한 따로 복사해야 한다.

    . immer라는 라이브러리의 도움을 받으면 불변성을 유지하면서 업데이트하는 작업을 정말 편하게 작업할 수 있다.

 

  - List 컴포넌트 최적화하기

    . 리스트 최적화 시, 리스트 내부 컴포넌트 최적화와 리스트 컴포넌트 최적화를 모두 수행하는 것이 좋다.

    . 결국 모든 컴포넌트를 export할 때 React.memo를 씌우는 것이 좋다.

 

  - react-virtualized를 사용하여 렌더링 최적화

    . react-virtualized: 리스트 컴포넌트에서 스크롤되기 전에 보이지 않는 컴포넌트는 렌더링하지 않고 크기만 차지하게끔 한다.

    . 크롬 개발자 도구를 활용해서 각 컴포넌트(CSS)의 크기를 알아낼 수 있다. (맨 왼쪽 상단)

    . 마찬가지로 List와 List Item 모두 설정해줘야 한다.