티스토리 뷰

React:

리액트에서의 shallow compare부터 React.PureComponent 까지


상황


this.state = {
 someValue: true
};

this.setState({
 someValue: true
});

리액트를 사용하여 개발할때, 위와 같은 상황에서는, setState는 무조건적으로 state를 업데이트하게 되고, 그에 따른 불필요한 렌더링을 하게 됩니다. 따라서 이를 방지하기 위해, 아래와 같이


1. React.PureComponent

2. shouldComponentUpdate 주기를 기존 클래스컴포넌트에 추가


를 적용시켜 문제를  해결할수 있습니다.



| Shallow compare란?

  • shallow compare는 equality를 체크하는것입니다.
    • 숫자나 문자열 같은 scalar 값들을 비교할때, 그들의 값을 비교합니다. 
    • 단, obejct들을 비교할때 그들의 attribute들을 비교하지 않고, 그들의 reference를 비교합니다. 
    • 위의 점이 중요한점입니다. shallow compare 에서 object들은 레퍼런스만 체크하기때문에 같은 값이 들어있는 object이더라도 항상 다른값으로 체크하게 됩니다.

Shallow compare is efficient way to detect changes. It expect you don't mutate data.


https://stackoverflow.com/questions/36084515/how-does-shallow-compare-work-in-react

위의 글을 참고하면 shallow compare에 대해서 더 쉽게 이해할수 있을것입니다.


| React.PureComponent

  • pureComponent는 shouldComponentUpdate가 이미 적용된 버전의 React.Component입니다.
  • pureComponent는 renderer에서 shouldComponentUpdate 를 수행할때 shallow compare를 수행합니다.
  • 불필요한 state 변화감지 그리고 이로인한, 재렌더링을 줄임으로써 성능을 극대화 할수 있습니다.
> react 공식 사이트 발췌

React.PureComponent’s shouldComponentUpdate() only shallowly compares the objects. If these contain complex data structures, it may produce false-negatives for deeper differences. Only extend PureComponent when you expect to have simple props and state, or use forceUpdate() when you know deep data structures have changed. Or, consider using immutable objects to facilitate fast comparisons of nested data.


> React.PureComponent를 사용할 수 있는 상황

  • state와 prop이 immutable일때
    • (위에서 scalar 값들은 shallow compare로 값을 비교하기 때문에 상관없지만 object들은 reference로 다름을 체크하기 때문에 적절치 못하게 사용될수 있다고 말하였습니다)
  • state와 prop이 계층(hierarchy) 혹은 복잡한 구조를 가지고 있지 않을때
  • shouldComponentUpdate lifecycle을 사용하지 않을 계획일때
> 예시 상황

1. scalar 값만 비교한 경우
아래와 같이, 버튼을 클릭했을때 기존에 React.Component를 extend한 클래스 컴포넌트였으면 버튼을 클릭했을때 test라는 값이 1로 같은값이 업데이트 되었더라도 무조건으로 state를 업데이트하기 때문에 재렌더링이 계속 일어났을 것입니다.

그러나, 아래와 같이 PureComponent를 상속하게 되면 ShouldComponentUpdate가 자동적으로 적용되어있고, shallow compare를 하기 때문에 재렌더링이 일어나지 않게 됩니다. 따라서 불필요한 재렌더링을 막음으로써, 성능을 극대화 할수 있게 됩니다.
import React, { PureComponent } from 'react';

class App extends PureComponent {
 
 state={
   test: 1,
}

 render() {
   console.log('render');
   return (
     <div className="App">
         <button onClick={()=>this.setState({test: 1})}>
          렌더링 체크
         </button>
     </div>
  );
}
}

export default App;

2. object 값을 비교한 경우

단, 아래와 같은 예외 상황도 있습니다. 위에서 말했듯, shallow copy는 object에서는 reference체크로 그 값을 비교하기 때문에 항상 다르다고 체크하여 재렌더링은 여전히 계속 일어나게 됩니다.


import React, { PureComponent } from 'react';

class App extends PureComponent {
 
 state={
   test: {testValue: 1},
}

 render() {
   console.log('render');
   return (
     <div className="App">
         <button onClick={()=>this.setState({test: {testValue: 1}})}>
          렌더링 체크
         </button>
     </div>
  );
}
}

export default App;
| 결론

Stateless components are not faster than the stateful

https://moduscreate.com/blog/react_component_rendering_performance/ 이 글을 참고하면 알겠지만, 함수형 컴포넌트가 클래스보다 우위에 하긴 어렵다고 합니다. 오히려, React.PureComponent가 React.Component와 함수형 컴포넌트 보다 빠른것을 알수 있습니다. 그이유는 함수형 컴포넌트도 결국엔 클래스로 wrapping 되기 때문이라고 합니다.



하지만, Pure Component는 shallow level에서만 데이터를 비교하기 때문에, 

복잡한 구조의 데이터는 비교하지 못하므로 결국엔 shouldComponentUpdate를 직접 다뤄야 하는 상황이 발생하므로, 모든 컴포넌트에 PureComponet를 사용하는것은 오히려 앱을 더 느리게도 할 수 있다니 주의를 해서 사용해야 할 것입니다.



댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함