shouldComponentUpdate()와 React.PureComponent

Dodam·2024년 3월 8일
0

[React]

목록 보기
7/12
post-thumbnail
post-custom-banner

리액트 최적화를 위해서는 렌더링되는 부분을 제대로 이해해야 한다.
class 함수는 render 부분이 리렌더링되고, 함수 컴포넌트는 전체가 리렌더링이 된다.

아래 예제에서 버튼을 클릭했을 때 변하는 state는 없어도 class는 리렌더링이 된다.

리액트는 Props와 State를 변경하게 되면 보통 리렌더링이 일어난다.
바꾸는 State가 없어도 setState 함수를 호출하게 되면 리렌더링이 일어나기 때문이다.

이때, class는 두 가지의 방법으로 리렌더링을 막고 최적화를 할 수 있다.

React의 라이프 사이클 ShouldComponentUpdate

리액트의 라이프 사이클인 shouldComponentUpdate를 추가한다.
shouldComponentUpdate 함수는 현재 state와 변경되는 state를 비교하여 리렌더링을 할 것인지를 결정하는데,
위의 코드에서 nextState가 변경되는 state이고 this.state가 현재 state이다.

코드의 반환 값이 true일 경우에 리렌더링이 일어나며, false일 경우에 리렌더링이 일어나지 않는다.
따라서 내부에 비교하는 코드를 추가하여 최적화를 할 수 있다.

PureComponent

만약에 ShouldComponentUpdate가 복잡하다고 느낄 때에는 간단히 PureComponent를 사용할 수 있다.
Component 대신에 PureComponent를 import하여 extends 해준다.

이때, ShouldComponentUpdate를 작성해주지 않아도 리렌더링이 일어나지 않게 되는데, 이는 PureComponent 내부에서 ShouldComponentUpdate를 자동으로 구현하기 때문이다.

여기서 주의해야 할 점은 Props와 State를 비교하도록 구현되어 있기는 하나, 얕은 비교이기 때문에 복잡한 자료 구조일 경우에 의도치 않는 결과가 나올 수도 있다.
그리고 PureComponent 내부에서도 ShouldComponentUpdate를 쓸 수 있다.

setState할 경우에 주의해야 할 점이 있는데, 배열이나 객체같은 참조형 타입의 불변성 유지이다.
만약 다음과 같이 배열에 직접 push할 경우에는 기존 배열을 참조하고 있기 때문에 PureComponent가 변화를 알아차리기 어렵다.
따라서 불변성을 유지하여 setState를 해야 한다.

PureComponent에서 자동으로 ShouldComponentUpdate를 구현하기 때문에 PureComponent만 써도 되지 않을까 싶은 생각이 들지만, 각각 필요할 때 사용해야 한다.
복잡한 구조일 때 정밀한 작업을 하거나 특정 state가 변경되어도 리렌더링을 방지하고 싶은 경우, ShouldComponentUpdate를 통해 의도적으로 이를 막을 수 있기 때문이다.

Class에서는 PureComponent 또는 ShouldComponentUpdate를 통해 최적화를 하며 Hooks에서는 memo(Memoization)를 사용하여 최적화한다.
memo는 고차 컴포넌트(Higher Order Component)이며 함수 컴포넌트이다. 부모 컴포넌트에서 전달한 props의 변화에 의한 리렌더링을 방지할 때 사용한다. (useState나 useContext 훅을 사용하면 리렌더링이 일어난다.)

memo도 얕은 비교로 동작하기 때문에 복잡한 자료구조일 경우 원치않는 동작이 발생할 수 있다.
만약 얕은 비교의 기본 동작이 아닌 다른 동작을 원할 경우, 두 번째 인자를 별도로 제공하면 된다.

PureComponent나 ShouldComponentUpdate 그리고 memo는 모두 성능 최적화를 위해 사용한다.
따라서 단순히 렌더링을 방지하기 위해 사용하거나 성능적인 이점이 없다면 사용하지 않는 것이 좋다.

참고: https://ko.legacy.reactjs.org/docs/react-api.html

profile
Good things take time
post-custom-banner

0개의 댓글