# Component 최적화

## 성능 최적화하기

> React는 컴포넌트를 먼저 렌더링한 뒤 이전 렌더링된 결과와 비교해서 실제 DOM에 업데이트를 할지 말지 결정한다. \
> 비교한 결과가 서로 다르다면 React는 DOM을 업데이트 한다.

### React.memo

* `React.memo()`를 컴포넌트에 감싸면 React는 해당 컴포넌트의 렌더링한 결과를 메모이징 한다.&#x20;
* 다음 렌더링에서 컴포넌트의 `props` 가 같다면, 메모이징된 결과를 재사용한다.
* `props` 가 같다면 렌더링된 결과도 같다라고 판단

{% hint style="info" %}
**메모제이션 (Memozation)이란?**\
주어진 입력값을 저장하고 같은 입력값이 주어졌을 때 함수가 한 번만 실행되는 것을 보장한다.
{% endhint %}

#### React.memo()의 props 비교 방법

* 기본적으로 props 객체를 비교할 때 얕은 비교를 한다.
* 비교 방식을 수정하고 싶을 땐 `React.memo()`의 두 번째 인자로 비교함수를 넣어서 커스텀 가능

```javascript
React.memo(Component, [compareFn(prevProps, nextProps)])

const compareFn = (prev, next) => prev.a === next.a && prev.b === next.b
```

{% hint style="info" %}
**React.memo()가 능사는 아니다.**&#x20;

* memo()로 감싸면 이전 props값을 메모제이션 및  매 렌더링마다 비교함수를 실행한다.
* props가 자주 변경되는 컴포넌트들은 대부분 false를 반환하게 되므로 성능상 이점을 얻기 힘들다
* 리렌더링 방지용으로 사용하기보다는 실제로 성능 개선되는 점을 확인하고 개선되는 경우에만 사용하자.
  {% endhint %}

### React.useCallback

* 함수는 실행이 되면 매번 해당 함수 스코프 내의 변수나 함수 등이 다시 만들어지게 된다.&#x20;
* 마찬가지로 함수형 컴포넌트도 함수이므로 리렌더링되면 동일하게 해당 스코프 내에 변수나, 함수등이 다시 만들어진다.
* 이 때 함수들을 자식 컴포넌트에게 props로 전달하고 있다면 자식 컴포넌트들이 memo()로 감싸고 있더라도 함수가 새로만들어져 참조하는 메모리값이 달라지므로 리렌더링 되는 사이드 이펙트가 생기게 된다.
* 이런 사이드 이펙트를 방지하기 위해서 사용하는 것이 `useCallback()`
* 함수 내에 참조되는 state, props들이 있다면 의존성(dependency) 배열에 추가

```javascript
// dependency로 설정해둔 값이 바뀌기 전에는 메모제이션된 값을 재사용하여 새로 생성하지 않는다
const memozationFn = useCallback(fn, [dependency])
```

### React.useMemo

* 비용이 많이 드는 로직을 메모이제이션하여 매 렌더링 마다 재 계산하는 대신 캐싱된 값을 활용하여 렌더링 최적화를 수행

```javascript
const memozationValue = useMemo(fn, [dependency])
```
