React.memo

gak·2023년 4월 19일
0

React Memo

1. React Memo 는 왜 필요한걸까?

사용자는 반응이 빠른 UI 를 선호한다. 성능 이슈로 브라우저의 동작이 잠시동안 멈춘다면 사용자는 불편함을 느낄 것이다.
UI 성능을 향상시키기 위해서 React는 고차컴포넌트(일반적으로 hoc 라고 부른다.)인 React.memo() 를 제공한다.

이 글을 통하여 여러분은 언제 React.memo() 를 사용하여 성능 향상을 할 수 있는지 알 수 있게 될 것이다.

2. React.memo()

DOM 을 업데이트 할지, 말지 결정하기 위해서 리액트는 먼저 컴포넌트를 렌더링을 한다.
그 뒤, 이전 렌더링 결과값과 비교한다. 만약 렌더링의 결과가 다르다면 리액트는 DOM 을 업데이트한다.

현재와 과거의 렌더링 결과값을 비교하는건 굉장히 빠르다. 하지만, 특정 상황에서 이 과정을 더 빠르게 할 수도 있다.

어떤 컴포넌트가 React.memo() 라는 고차 컴포넌트(hoc) 로 래핑되어 있다면, 리액트는 해당 컴포넌트의 렌더링 결과값을 기억한다(memorize). 그리고 다음 렌더링전에, 만약 props 가 동일하다면 다음 렌더링을 스킵한다.

실제 메모리제이션 동작을 살펴보자.

위 코드에서 Music 이라는 컴포넌트는 React.memo() 에 의해 wrapping 되어 있고, 리액트는 메모된 Music 컴포넌트를 렌더링하고 그 결과를 저장한다.
다음 렌더링 직후에 만약 새로운 props 가 이전의 props 와 같다면, 리액트는 메모된 결과값을 재활용하고다음 렌더링은 스킵한다.

3. 리액트 메모 테스트

리액트 메모가 잘 작동하는지 테스트를해보자.

3-1. 리액트 메모를 사용하지 않았을 경우

콘솔을 보면, 음악 추가 버튼을 눌러서 새로운 Music 컴포넌트를 추가하면 기존에 있던 Music 컴포넌트도 전부 다 리렌더링 됨을 알 수 있다.

3-2. 리액트 메모를 사용했을 경우

콘솔을 보면, 음악 추가 버튼을 누르면 새로 추가된 Music 컴포넌트만 렌더링 됨을 알 수 있다.

꿀팁 : 컴포넌트의 렌더링을 확인할때 console.log 로 확인할수도 있지만, 크롬 확장 프로그램인 react-dev tools 를 써서 확인할 수도 있다.

4. 리액트 메모의 동작원리

React.memo 는 기본적으로 prevProps, nowProps 를 비교할 때 얕은 복사로 재랜더링 여부를 결정한다. 리액트 공식문서 를 보면,
props 의 key 를 바탕으로 iteration 을 돌면서 현재 value 들을 이전 value 들과 얕은 비교하는 것이다.

5. 비교함수 커스텀

React.memo() 의 명세는 아래와 같다.

React.memo(Component: ReactComponent, copyFunction?: (prevProps, currProps) => boolean);

만약에 두번째 인자인 copyFunction 을 넘겨주지 않을 경우 위에서 언급했듯이 얕은 비교를 통해 컴포넌트의 리렌더링 여부를 결정한다.

하지만, 특정 상황의 경우 copyFunction 을 커스텀해서 넘겨줄 수 있다.
예를들어, 아래와 같이 비교함수를 커스텀해서 넘겨줄 수 있다.

function moviePropsAreEqual(prevMovie, nextMovie) {
  return prevMovie.title === nextMovie.title
    && prevMovie.releaseDate === nextMovie.releaseDate;
}

React.memo(Movie, moviePropsAreEqual);

6. 결론

리액트 메모는 컴포넌트의 쓸데없는 리렌더링을 방지해준다.
리액트 메모를 사용하기에 적합한 컴포넌트는, props 가 잘 변화하지 않는 컴포넌트이다.
이런 컴포넌트에 사용하면 렌더링을 최적화 할 수 있다.

하지만, React.memo 를 사용하는 것은 그만큼 비교를 하는 계산 로직이 더 추가되는 것이기 때문에 모든 컴포넌트에 남용하는 건 오히려 퍼포먼스를 나쁘게 만들 수 있다는 점을 알고 현명하게 사용해야한다.

출처

리액트 공식문서

profile
Hello. I'm Front-End Developer Trying to Create Valuable Things.

0개의 댓글