진단
어디가 왜 얼마큼 느린가?
-> 병목시점을 찾아 프로파일링(Profiling) 한다.
-> 어느부분이 오래걸리는가, 시간 측정
-> 함수 시작, 마지막에 console.time이나 new Date를 사용해서 시간을 측정한다.
개선
테스트
side effect는 없는가?
-> A를 수정 시 의존성이 있는 B, C는 잘 동작을 하는가
진단
어디가 얼마큼 빨라졌는가?
브라우저, 디바이스 별로 진단한다.
React 에서도 로딩지연, 반응지연, 애니메이션 지연등은 생긴다.
1. 첫 페이지 로딩 지연문제 해결
2. 반응 지연, 애니메이션 지연 해결
shouldComponentUpdate(nextProps, nextState, nextContext){
if(this.state.conuter !== nextState.counter
counter { //미래의
return true
}
return false;
}
현재 counter와 미래의 counter가 바뀌면 렌더링한다. (return true가 렌더링하는 것)
shouldComponentUpdate를 구현하지 않아도 변화가 있을때만 렌더링 해준다. (자동으로 shouldComponentUpdate를 실행)
state의 값이 바뀌었는지 안바뀌었는지 판단
하지만 객체나 배열은 새로운 배열이나 객체가 아니면 값이 바뀐지 모른다는 것을 주의하자!
(같은 배열이나 객체는 같은 주소값을 참조 하기 때문에 변화를 react가 알 수 없다.)
즉 push를 사용한 배열의 변화는 알아차리지 못한다.
웬만하면 자료구조를 복잡하게 하지 말고 state를 간단하게 한다.
const Try = memo(() => {})
앞에 memo로 감싸준다.
1. 참조타입 render밖에 선언하기
return (
<>
<Title>{title is..}</Title>
<ShowPost postClick={()=>{console.log('click handler')}} />
</>
)
2. children 컴포넌트 갯수를 동일하게 유지하기
<div>
<Header />
{ state.isToggle && <Subheader /> }
<Content />
</div>
렌더링이 될때마다 children 갯수가 달라지지 않도록 한다.
3. useEffect 매번 실행되지 않게 하기
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
두 번째 인자는 아래 다른 Hook에서도 콜백함수의 실행에 대한 조건으로 활용된다.
=> useEffect, useMemo, useCallback
4. React.memo : 컴포넌트 렌더링 결과 재사용
매번 동일한 컴포넌트를 렌더링해야 하는 경우가 꽤 많다.
이를 캐시해서 사용하도록 할 수 있다.
5. useCallback : 함수 캐시
새로운 함수를 계속 생성하지 않고 기존함수를 기억해서 사용하고, 이를 props로 전달하는 것이 React에서는 권장되는 방법이다.
6. React.memo, UseCallback을 활용한 시나리오
먼저 props로 함수를 전달하고 싶은 경우에는, useCallack을 통해 감싼 함수를 전달한다.
전달받은 컴포넌트는 React.memo를 통해서 감싼다. React.memo는 props가 동일하다면 다시 렌더링되지 않도록 한다.
따라서 useCallback을 통해서 동일한 props를 전달받았다면 컴포넌트가 다시 렌더링 되지 않고, 렌더링 결과를 재사용하게 된다
7. useMemo : 연산 결과 캐시
비용이 많이 필요한 알고리즘을 구현해야 하는 경우가 있다.
같은 결과를 반복적으로 연산하지 않기 위해서는 캐시전략이라고 볼 수 있는 memoization 패턴이 유용하다.
memoization 패턴을 직접 구현할 수도 있지만, useMemo를 활용하면 깔끔하다.
8. Profiling : 렌더링 최적화 확인
개발자도구-React의 Profiler 패널을 확인한다.
'profiling버튼'을 눌러서 렌더링과정을 녹화한다.