본문 바로가기

React

#4. React 성능과 렌더링

Avoid Reconciliation



 앞서 설명한 대로 React는 Reconciliation에서 O(n)의 시간복잡도를 가지고 있으며, 필요 이상의 DOM 접근이나 업데이트를 피하기 때문에 성능에 대한 고민을 할 필요가 없다.


하지만 컴포넌트가 렌디링하는 엘리먼트가 수천 수만개라면? O(n)도 느리다.


 개발자는 일부 경우에 실제 렌더링이 필요 없는 상황을 알고 있다. 그래서 컴포넌트가 렌더링 전에 호출하는 라이플사이클 메서드  shouldComponentUpdate()  를 오버라이드하여 성능을 향상시킬 수 있다. 기본 구현을 return true이기 때문에, 항상 Reconciliation을 포함한 렌더링 작업을 수행한다. 개발자는 컴포넌트 렌더링이 필요 없는 때에만 return false를 통해 React의 불필요한 렌더링 작업을 방지할 수 있다.


ShouldComponentUpdate in Action



아래와 같은 엘리먼트 트리의 렌더링 과정을 보자.


should-component-update


C2에서 ShouldComponentUpdate가 return false를 반환하여 렌더링을 시도하지 않고 C4,C5의 SCU는 발생하지 않는다.


C1,C3는 ShouldComponentUpdate에서 true를 반환한다. 그래서 React는 자식 컴포넌트를 순회하며 렌더링 여부를 확인한다.C6은 SCU에서 true를 반환하고, 이전 상태의 엘리먼트와 새로운 상태의 엘리먼트의 차이를 감지하여 DOM 업데이트를 수행한다.


C8과 같은 경우 ShouldComponentUpdate에서 true를 반환하여 엘리먼트가 차이를 비교해 보았더니 아무 차이가 없어 DOM을 업데이트 하지 않는다. 이런 경우 React의 렌더링 과정은 불필요하고 성능 저하를 유발한다. ( 즉, 괜히 render()만 호출한 것이다. )



분리되지 않은 컴포넌트

컴포넌트의 분리가 적절하게 이루어지지 않는다면 가독성, 유지보수 뿐만 아니라 성능상의 문제도 일어날 수 있다. 다음 예시를 살표보자. App 컴포넌트는 Root 컴포넌트로 자신의 titlelistItems를 관리한다. 따라서 다음과 같은 state를 가지고 있다.

state = {
  listItmes: [],
  title: 'Test app'
};



다음은 List를 하나의 컴포넌트로 분리하지 않은 코드이다.

// 아래는 간단히 나타낸 App 컴포넌트의 render 메서드이다.

render() {
  <div className="app">
    ...
    <div className="app-intro">
      {this.state.title}
    </div>
    <div className="list-container">
      <ul>
      {
        this.state.items.map((item) => {
          return <Item key={item.id} {...item} />
        })
      }
      </ul>
    </div>
  </div>
}



다음은 List를 하나의 컴포넌트로 분리한 코드이다.

// 아래는 간단히 나타낸 App 컴포넌트의 render 메서드이다.
render() {
  <div className="app">
    ...
    <div className="app-intro">
      {this.state.title}
    </div>
    <List items={this.state.items} />
  </div>
}

두 애플리케이션의 App 컴포넌트에서 componentWillUpdate()부터 componentDidUpdate()까지 시간을 UserTimingAPI로 측정하였다.


  • List 컴포넌트로 분리 되지 않은 경우(App-bad)

    app-bad

  • List 컴포넌트로 분리된 경우(App)

    app


  • App의 트리
    app-tree
더테스트용 앱은 간단한 앱임에도 불구하고 약 30~40배의 확연한 차이가 있따. 조금 더 큰 어플리케이션인 경우 더 심각한 문제가 발생할 것이다.


'React' 카테고리의 다른 글

Redux 기초 - (2) 스토어(Store), 데이터 흐름  (0) 2017.11.21
Redux 기초 - (1)액션, 리듀서  (0) 2017.11.20
#4. React 성능과 렌더링  (0) 2017.06.19
Tip  (0) 2017.05.23
#3. Redux  (0) 2017.05.23
TroubleShooting  (0) 2017.05.22