Rendering optimization
렌더링은 React가 DOM을 변경해야 하는지 확인하는 프로세스이지만, 렌더 단계에서 수행한 작업과 계산이 의미 없는 경우에는 (결국 구성 요소의 렌더 출력이 동일하면 ) DOM 업데이트가 없으므로 작업이 필요하지 않습니다.
렌더의 아웃풋은 항상 "props"와 "state"의 현재 값에 기반해야 하며, 따라서 구성요소의 랜더 결과가 "props"와 "state"가 변경되지 않으면 같다입니다. 따라서 이 개념을 머리에 두고 기반으로 React 렌더링을 최적화하는 것의 기초가 되는 중요한 포인트!!
최적화 방법들
React는 렌더링 프로세스를 최적화할 수 있는 몇 가지 API를 제공하고 있습니다.
1. shouldComponentUpdate
- 렌더링 전에 호출되는 수명 주기 메서드, 부울 반환(렌더링을 건너뛰려면 false, 평소대로 진행하려면 true)
- Logic은 필요에 따라 달라질 수 있지만, 가장 일반적인 경우는 구성 요소의 props와 state가 변경되었는지 확인.
2. React.PureComponent
- willComponentUpdate 수명 주기 메서드에서 이전에 설명한 속성 및 상태 변경 검사를 구현하는 기본 클래스
3. React.memo()
- 주어진 요소들을 감싸는 HOC (고차 컴포넌트 )
- PureComponent 와 같은 종류의 기능을 구현하지만 함수 구성 요소를 감쌀 수 있다.
이러한 테크닉들은 비교할 때 shaloow equality를 사용합니다.
추가) input에 onChange 최적화 ( ref 이용 )
<input
ref={searchRef}
type="text"
placeholder="아무 내용이나 입력하세요."
onKeyUp={() => {
let searchQuery = searchRef.current.value.toLowerCase();
setTimeout(() => {
if (searchQuery === searchRef.current.value.toLowerCase()) {
setText(searchQuery);
}
}, 500);
}}
/>
Reference memoization
React에서는 새 references(참조)를 하위 components에 "props"로 전달해도 상위 components가 변경될 때 다시 렌더링되므로 일반적으로 문제가 되지 않습니다. 그러나 하위 components의 속성이 변경되었는지 확인하여 하위 components의 렌더링을 최적화하려는 경우 새 참조를 전달하면 render가 발생합니다. 이러한 동작은 새 참조가 업데이트된 데이터인 경우 정상이지만, 부모에 의해 전달되는 동일한 콜백 함수에 대한 새로운 참조인 경우에는 원치 않은 렌더링일 수 있습니다.
이러한 문제는 class Components에서는 문제가 되지 않습니다. 왜냐하면 참조가 변경되지 않는 인스턴스 메소드를 가지고 있기 때문이죠. 하지만 함수형 Components에서는 이를 위해 useMemo, useCallback hook을 사용해서 memoization을 해야 합니다.
다음은 제가 사용하는 방식의 일부 입니다.
// isshow는 모달창의 visible 여부 state
const memoRenderModalContent = useCallback(renderModalContent, [isshow]);
const renderPage = <> ..... </>
const memoRenderPage = useMemo(() => renderPage, []);
return memoRenderPage();
위처럼 하나의 기능 또는 컴포넌트를 메모리제이션을 통해 최적화 할 수 있는 부분을 분리하여 사용합니다. 하지만 이러한 기능들은 성능상의 이점은 줄 수 있지만, 다른 memoization 처럼 기능의 필요성과 순이익을 고려하며 사용해야합니다.
저 같은 경우에는 무거운 계산을 수행, 동일한 props에서 렌더링하는 경우를 피하기 위해 사용합니다. ( 남용 했을 때, 예상치 못한 side Effect가 만만치 않았습니다. )
마지막으로, 리액트의 개발 빌드는 실제 빌드에 상당히 느립니다, 개발 시 절대적인 시간이 유용한 측정 기준이 아니므로 이것을 고려해서 모든 측정을 수행해야합니다. 저는 불필요한 렌더링, 메모화 및 최적화 기회같은 것에 집중하는 편입니다.
추가 ) 최적화만이 좋은 코드는 아니다
처음부터 성능에 최적화된 애플리케이션을 고려하는 것 자체가 비효율적이다. 하지만 컴포넌트를 적절히 분리하는 것은 중요하다. 아무리 간단한 엘리먼트와 로직이라도 기능, 책임, 재사용성 등으로 컴포넌트를 적절히 분리하여 이슈를 빠르게 파악하고 대응할 수 있도록 개발하는 것은 중요하다.
'Front-end > React' 카테고리의 다른 글
React Hook의 모든 것 (2) - useState를 직접 구현해보자 (0) | 2022.02.28 |
---|---|
React Hook의 모든 것 (1) (0) | 2022.02.21 |
React 프로젝트 설정 및 확장성 이야기 (0) | 2022.02.15 |
React 랜더링 기본 (0) | 2022.02.10 |