[react] 성능 최적화

eunbi·2020년 5월 2일
7

React

목록 보기
7/22

최적화란 ?

  • 사용자가 편리한가 (UX)
  • 첫 페이지 로딩을 빠르게 하기, 반응성올리기, 부드럽게 이어져보이기

최적화 작업 진행 방법

  • 진단
    어디가 왜 얼마큼 느린가?
    -> 병목시점을 찾아 프로파일링(Profiling) 한다.
    -> 어느부분이 오래걸리는가, 시간 측정
    -> 함수 시작, 마지막에 console.time이나 new Date를 사용해서 시간을 측정한다.

  • 개선

  • 테스트
    side effect는 없는가?
    -> A를 수정 시 의존성이 있는 B, C는 잘 동작을 하는가

  • 진단
    어디가 얼마큼 빨라졌는가?

  • 브라우저, 디바이스 별로 진단한다.

React에서의 해결

React 에서도 로딩지연, 반응지연, 애니메이션 지연등은 생긴다.

1. 첫 페이지 로딩 지연문제 해결

  • build를 통한 코드 최적화 (압축, 파일합치기)
  • SSR (Server Side Rendering) / pre-rendering
    -> 초기화면을 server에서 생성 한다면 좀 더 빠른 렌더링이 가능하다.
  • Dynamic Component Loading (lazy loading)

2. 반응 지연, 애니메이션 지연 해결

  • 메인쓰레드를 blocking하지 않기 위한 내부조치들(Fiber architecture)
  • Re-rendering 최소화
  • 중복계산 줄이기
  • 네트워크 요청 기억하기

shouldComponentUpdate

shouldComponentUpdate(nextProps, nextState, nextContext){
	if(this.state.conuter !== nextState.counter 
 counter { //미래의
    	return true
    }
    
    return false;
}

현재 counter와 미래의 counter가 바뀌면 렌더링한다. (return true가 렌더링하는 것)

  • (참고) Context란?
    props는 부모에서 자식으로 전달이 되는데 a -> b -> c 이런식으로 a에서 c로 전달을 하려면 차례대로 전달을 해야 하지만 context는 a에서 c로 바로 전달 가능하다

pureComponent

  • shouldComponentUpdate를 구현하지 않아도 변화가 있을때만 렌더링 해준다. (자동으로 shouldComponentUpdate를 실행)

  • state의 값이 바뀌었는지 안바뀌었는지 판단

하지만 객체나 배열은 새로운 배열이나 객체가 아니면 값이 바뀐지 모른다는 것을 주의하자!
(같은 배열이나 객체는 같은 주소값을 참조 하기 때문에 변화를 react가 알 수 없다.)
push를 사용한 배열의 변화는 알아차리지 못한다.

  • 때문에 기존 배열을 펼치고 새로운 값을 추가해주어야 한다
    예) [...array, 새로운 값]

웬만하면 자료구조를 복잡하게 하지 말고 state를 간단하게 한다.

  • state가 바뀌면 render 함수안에 있는것들은 다 같이 다시 실행되기 때문에 같이 렌더링이 일어나지 않아도 되는 것들은 component로 따로 분리하도록 한다.

memo

  • hooks에서 pureComponent이다
const Try = memo(() => {})

앞에 memo로 감싸준다.

  • 자식이 pureComponent이면 부모에서도 적용 가능

React 렌더링 최적화 8가지

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버튼'을 눌러서 렌더링과정을 녹화한다.

profile
프론트엔드 개발자입니다 :)

0개의 댓글