React의 성능 튜닝(개선 편)

15158 단어 React

개시하다


ReactNative의 성능 튜닝(측정 편)
계속
계속된다고 하지만 이번엔 단순한 리액트 얘기일 뿐이야
인터넷에서 리액션을 쓰고 싶은 사람도 참고할 수 있어요.
React의 성능 개선에 관한docs아주 좋은 소식입니다.가 있습니다.
그래서 이 책을 읽으면 충분하지만 영어로도 말하기 때문에 제 방식대로 씹고 요점을 대충 설명해 드리겠습니다.

React의 DOM 업데이트 알고리즘


React에서 DOM 상태를 형식의 JS 객체로 저장합니다.
예컨대
<div className="hoge">some text</div>
의 DOM 상태
{ type: 'div', props: {className: 'hoge'}, children: ['some text'] }
JS 개체를 기다립니다.
DOM을 추상화한 JS 객체를 Virtual DOM이라고 합니다.
React에서 DOM 업데이트를 진행할 때 이 Virtual DOM이 차별이 발생하는 경우에만 실제 리셋을 통해 DOM 업데이트의 효율을 높일 수 있다.
업데이트할 때 실제 DOM을 비교하는 것보다 JS 대상의 비교 속도가 빨라서 이런 공을 들인 것이다.
또한 어셈블리가 업데이트되면 모든 자손 컴포넌트가 Virtual DOM의 차분 계산을 수행합니다.
여기는 예쁘고 귀찮아요.
어느 정도 대규모의 제품이라면 한 화면의 제작은 수백 개에서 수천 개의 구성 요소를 설치할 수 있다.
예를 들어 한 화면에 5000개의 구성 요소가 설치되어 있다고 가정하자.
루트 구성 요소를 업데이트하면 그 5000개의 구성 요소에서 Virtual DOM의 차분 계산이 실행됩니다.
Virtual DOM의 컴퓨팅도 가볍지 않습니다.
이번 주제는 이곳을 효율화할 수 있느냐는 것이다.

최적화 업데이트 알고리즘

class Child extends React.Component {
  render() {
    console.log('virtual dom calculated')
    return (<h2>{this.props.text}</h2>)
  }
}
<Child text='hoge' />처럼 구성 요소를 설치합니다.
text 이 속성은 고정되어 있습니다.
부모 구성 요소 setState 등을 통해 업데이트가 발생하면 차일드 구성 요소의 render도 실행됩니다.
부모반에서 100번 뛰기 setState()
constore에 출력합니다.(즉, virtual DOM의 계산은 이미 100번 진행되었다.)
이번 경우text 속성이 바뀌지 않았기 때문에virtualDOM을 계산하지 않아도 되고 보기를 업데이트하지 않아도 됩니다.
따라서 차일드 구성 요소의 렌더 방법은 100번 실행할 필요가 없고 한 번만 실행하면 된다.
이 사례를 좀 더 일반화하여 생각해 봅시다.
React 구성 요소의 DOM은 state 및 proops에서 고유하게 결정해야 합니다.
(state와props 이외의 상황에 의존한다면 원래 다시 설계하는 것이 좋을 수도 있습니다.)
그럼state와props가 변하지 않을 때virtualDOM을 일부러 계산하지 않아도 되나요?이런 생각은 이루어질 수 있잖아.
이러한 생각에 근거하여 React의 구성 요소는 shouldComponentUpdate 방법이 있다.shouldComponentUpdate 방법은 render 방법이 호출되기 전에 실행되며, 이 방법의 반환값을 falserender 방법으로 설정하면 실행되지 않습니다 (virtual DOM을 계산하지 않음).
아래shouldComponentUpdate를 실시하면 모조품에서 100회setState()를 실행해도 한 번virtual dom calculated의 정보만 표시됩니다.
class Child extends React.Component {
  shouldComponentUpdate(nextProps) {
    if (this.props.text !== nextProps.text) {
      return true
    }
    return false
  }

  render() {
    console.log('virtual dom calculated')
    return (<h2>{this.props.text}</h2>)
  }
}
이렇게 하면 계산 원가를 1/100로 제어할 수 있다.

PureComponent


추가 범용 설치shouldComponentUpdate는 다음과 같습니다.
shouldComponentUpdate(nextProps, nextState) {
  for (let propKey in this.props) {
    if (this.props[propKey] !== nextProps[propKey]) {
      return true
    }
  }

  for (let stateKey in this.state) {
    if (this.state[stateKey] !== nextState[stateKey]) {
      return true
    }
  }

  return false
}
모든 props와state가 같으면, 가상 DOM의 계산을 하지 않고 되돌아옵니다.
React에서 이 실현은 하나의 모델이기 때문에 이미 이와 같은 방법false류가 설치되어 있다.(실제 설치는 좀 복잡합니다.)
따라서 아까 차일드 등급React.PureComponent을 계승하려면 특별히 실시할 필요가 없다React.PureComponent.

class Child extends React.PureComponent {
  render() {
    console.log('virtual dom calculated')
    return (<h2>{this.props.text}</h2>)
  }
}

주의점

shouldComponentUpdate 사용 시 몇 가지 주의점이 있는데 아래에 몇 가지를 소개합니다.

1. 퓨어컴퍼니일 텐데, 매번 virtual DOM 계산을 해요!


PureComponent의 Child 구성 요소PureComponent를 props로 보유 대상입니다.
차일드가 부모 클래스에 다음과 같이 설치되어 있으면 Parent에서 업데이트 계산을 할 때 차일드style가 반드시 출력됩니다.
class Parent extends React.Component {
  ...
  render() {
    return (
      <Child style={{color: 'red'}} text='hello' />
    )
  }
}
도대체 왜일까?virtual dom calculated의 일반 설치를 생각해 보세요.shouldComponentUpdate().
그리고 이번 상황에서 매번 새로운 대상을 스타일 속성에 넘기는 것을 주의하세요.if (this.props[propKey] !== nextProps[propKey]){color: 'red'} !== {color: 'red'}임을 감안하면 반드시trueshouldComponentUpdate는 언뜻 보면 같은 프로포즈를 건네준 것 같아서 다른 프로포즈로 여겨진다.
이번 경우 아래와 같이 반 밖에서 스타일을 정의하면 매번 같은 대상을 주기 때문에 파렌트반이 업데이트돼도 차일드반에서는 출력되지 않는다true.
class Parent extends React.Component {
  ...
  render() {
    return (
      <Child style={childStyle} text='hello' />
    )
  }
}

const childStyle = {color: 'red'}

2. 프로포즈를 바꿨는데도 겉모습은 변하지 않았다!


다음 코드를 작성할 때virtual dom calculated 차일드 구성 요소의 색상은 변경되지 않습니다.그런 현상이 일어날 수 있다.

class Parent extends React.Component {
  ...
  render() {
    childStyle.color = this.state.color
    return (
      <Child style={childStyle} text='hello' />
    )
  }
}

const childStyle = {color: 'red'}
나는 직감이 좋은 사람이 알아차렸다고 생각한다.
이번 상황은 아까와 반대되는 함정, 즉'대상의 내용을 바꿔도 ObjectId는 같다'는 것이다.
다음 코드의 성립과 요점은 같다.
const a = {color: 'red'}
b = a
b.color = 'blue'
a === b // true

최후


따라서 this.state.color를 사용하면 React의 성능을 향상시킬 수 있다.
주의사항에 열거된 바와 같이 React.PureComponent 예상치 못한 오류가 발생할 수 있으니 주의하고 조심스럽게 사용하십시오.
또 이런 오류를 일으키기 쉬우므로 함부로 쓰는 것을 권장하지 않는다PureComponent.
ReactNative의 성능 튜닝(측정 편)
하지만 구글 크롬의 퍼포먼스 측정 도구 등을 사용해 병목을 확인할 수 있는 단계에서 사용하라고 소개했다.
그나저나 PureComponentImmutable.js가 잘 어울려 버그를 밟기 쉽지 않으니 관심 있으신 분들은 시도해 보세요!

좋은 웹페이지 즐겨찾기