1. React.memo( ), useMemo( ), useCallback( )
각각 함수 컴포넌트, 함수 컴포넌트 내 변수, 함수 컴포넌트 내 함수를 메모이제이션하기위해 사용한다. 위 세가지 메소드들을 활용하면 불필요한 리렌더링을 방지할 수 있다. 이미 관련 내용들에 대한 포스팅을 한 기억이 있으니 간략하게 넘어가겠다. (마지막으로 useCallback( )의 중요성을 한 번만 더 강조하고 싶다. 함수를 props로 넘겨줄 때 익명 arrow function을 경우가 종종 있는데 이는 해당 익명 함수를 전달해주는 컴포넌트가 리렌더링될 때마다 새로운 함수 인스턴스를 만들어줘야 한다. 그렇기 때문에 동일한 함수 내용이더라도 다른 인스턴스이기 때문에 해당 함수를 전달받은 자식 컴포넌트는 부모 컴포넌트가 리렌더링될 때마다 함께 리렌더링이 일어나게 된다. useCallback( )을 활용하면 자식 컴포넌트의 리렌더링 이슈와 전달하는 부모 컴포넌트의 함수 인스턴스 생성과 관련된 리소스 낭비를 모두 막아줄 수 있다.)
2. ShouldComponentUpdate Life Cycle
Class 컴포넌트의 라이프 사이클 중에서 ShouldComponentUpdate라는 것이 있다. 이는 해당 컴포넌트가 리렌더링되어야하는지 여부를 판별해주며 첫 번째 인자로 갱신될 props, 두 번째 인자로 갱신될 state를 사용한다. 아주 간단한 예시로 다음과 같이 코드를 작성하게 되면 React.memo( )와 같이 불필요한 컴포넌트 리렌더링을 방지할 수 있다. 당연한 이야기이지만 여기서는 === 연산자를 사용하기 때문에 shallow 비교가 이루어진다.
3. React.pureComponent
위에서 언급한 ShouldComponentUpdate와 유사한 기능을 수행하지만 더 간단한 방법이다. 클래스 컴포넌트를 선언할 때 그냥 Component가 아닌 React.PureComponent를 확장하면 이전 state과 props를 비교하여 불필요한 리렌더링을 막을 수 있다. 마찬가지로 비교는 얕은 비교로 이루어진다. (ex. class MyComponent extends React.PureComponent)
4. Reselect selectors
reselect를 활용하면 컴포넌트가 의존성이 있는 redux state을 얕게 비교함으로써 최소한의 리렌더링을 수행할 수 있다. redux js toolkit의 createSelector( ) 메소드를 활용하면 간단하게 구현 가능하다. 예를 들어서 아래 코드의 thingsTodo1과 thingTodo2는 동일하게 아직 완료되지 않은 todo들을 가져온다. 그러나 첫 번째의 경우 filter 함수가 매번 새로운 배열 객체를 생성하기 때문에 실제로 thingsTodo1에 담기는 값이 변화하지 않아도 전역 state이 변경되면 컴포넌트의 리렌더링이 이루어진다. 반면 Reselect selector을 활용하면 첫 번째 인자로 전달된 selector의 결과값이 변경될 때에만 그 다음 selector가 수행되므로 실제 state.todos가 변경되지 않으면 filter 함수가 실행될 일이 없어서 불필요한 리렌더링을 막을 수 있다.
5. Lazy Loading
Lazy Loading은 부하를 경감시키는 대표적인 방법 중 하나이다. React.lazy( ) API를 활용하면 되며 이는 동적 import를 활용하기 때문에 번들링 과정에서 모듈 분리를 수행해준다. Lazy Loading은 컴포넌트 로딩 과정에서 발생하는 오류들 역시 확인해줄 수 있다. 한편 Lazy Loading은 이미지 등의 컨텐츠에서도 종종 활용되는 기법이다. Intersection Observer API를 활용하면 요소의 가시성을 검사하여 해당 요소가 화면에 올라오기 전까지는 로딩하지 않는 최적화 기법을 수행할 수 있다.
6. Virtualized List
위에서 언급한 바와 같이 화면에 여러 컨텐츠를 보여줘야 할 때 처음부터 전체 요소들을 로딩하는 것은 매우 비효율적이다. 따라서 이미지 Lazy Loading과 비슷한 명목으로 화면에 보여지기 전까지는 렌더링을 수행하지 방식을 'windowing'이라고 부르며 이러한 방법을 활용한 리스트를 Virtualized List라고 부른다. 이미 많은 리액트 라이브러리들이 존재하며 대표적인 예시로 react-window와 react-virtualized가 있다.
7. Web Worker
Web Worker은 백그라운드 스레드에서 스크립트를 실행할 수 있도록 해준다. 다들 알다시피 자바스크립트는 단일 스레드이다. 한편 브라우저는 단일 스레드가 아니다. 따라서 무거운 작업을 메인 쓰레드로부터 분리시켜서 백그라운드 쓰레드에서 처리되도록 지시한다면 메인 쓰레드의 성능에 영향이 없이 여러 작업을 수행할 수 있다. 메인 쓰레드의 성능에 영향을 끼친다면 UI적으로 영향을 받을 수 있기 때문에 메인 쓰레드에 부하를 제공하지 않는 것은 매우 중요한 작업이다.
'프론트엔드 기본개념 복습 > React' 카테고리의 다른 글
[React] useLayoutEffect vs useEffect (0) | 2022.04.11 |
---|---|
[React Native] React Native의 작동 원리 (0) | 2022.03.10 |
[React] state 갱신하기 (0) | 2022.03.02 |
[React] 에러 경계 (Error Boundaries) (0) | 2022.02.24 |
[React] 코드 분할 (Code Splitting) (0) | 2022.02.24 |