본문 바로가기

FrontEnd

리액트 : 리렌더링 하도록 코딩하기 (부제 : memo 대신 useMemo)

반응형

리액트의 리렌더링은 다양한 원인으로 일어난다.
그 중 가장 리렌더링을 자주 유발하는 원인은 상단 컴포넌트의 리렌더링에 의한 하위 컴포넌트들의 리렌더링이다.
(그러면서 가장 불필요한 리렌더링을 자주 발생시킨다.)
이는 구조적 리팩토링 (composition)으로 해결한다.
https://reactjs.org/docs/composition-vs-inheritance.html

Composition vs Inheritance – React

A JavaScript library for building user interfaces

reactjs.org

분명히 상태를 잘 쪼개고, 리덕스나 리액트 쿼리를 사용하는 경우 셀렉터를 아주 잘 쪼개면
관심사의 분리와 유지보수성,성능 세가지 토끼를 한번에 잡을 수 있다.

하지만 사람들은
서버에서 데이터 가져오기를 통해 가져온 10개의 필드를 가진 객체의 하나의 필드를 라벨로 렌더링하는 버튼을 위해
컨테이너 컴포넌트를 개발하지는 않는다.

이 경우 React.memo로 컴포넌트를 감싸는 것으로 타협한다만,
React.memo의 문제점은, 하단 컴포넌트의 렌더링을 막는 배리어와 같은 역할을 한다는 것이다.
서스펜스를 생각하면 편하다.
서스펜서랑 다른점은, 어디선가 렌더링을 막아야 하는데, 이게 명시적으로 보이지 않는다.
따라서 필연적으로 모든 컴포넌트를 메모하는 지경에 처하게 된다.


리렌더링 하도록 코딩하기

리렌더링은 나쁜것일까? 결론적으로는 아니다.
리렌더링은 상태, 프롭과 컴포넌트를 동기화하기 위한 수단이다
함부로 최적화하다 상태와 동기화가 망가지는 것이 더 문제이다
상태, 프롭이 바뀌면 리렌더링 하도록 코딩하라

리렌더링 하도록 코딩하기

그리고 리액트의 리렌더링은 돔 터치가 아니다.
리액트에 의해 비동기적으로 중단 가능하게 발생할 수 있으며, 훨씬 빠르다.

티액트의 리렌더링은 돔조작이 아니다

과연 리렌더링이 성능 저하의 문제인가?

기본적으로 js실행이 느리면 렌더링이 느려진다.
리렌더링보다 더 큰 문제는 js실행의 성능 저하이다.
리렌더링과 다르게 memoization은 프론트엔드 뿐만 아니라 모든 영역에서 발생한다


메모이제이션으로 메모하기

React.memo의 문제점은, 프롭 전체를 메모화한 것을 외부로부터 보통 숨기는데,
이는 잠재적으로 오류를 내부로 숨기는 역할을 한다.
차라리 컴포넌트 컨슈머가 명시적으로 의존성 배열을 통해 성능 최적화를 알아서 처리하도록 하는것이 좀 더 확장성 있다 할 수 있다.
대부분의 헤드리스 UI 컴포넌트들이 이처럼 자체적으로 memo를 통한 최적화를 지원하지 않고 있는것으로 알고 있다.

결론

컴포넌트 사용자가 useMemo로 메모하게 하라
memo를 쓰지 말자.
렌더링이 정말 성능 병목인지 생각해보자.
최적화 하기 전에 반드시 프로파일링 해보자

참고 :
https://twitter.com/tannerlinsley/status/1253001540798840837

트위터에서 즐기는 Tanner Linsley

“Also, I said *useMemo*. Not React.memo. Big difference. One of them I use every day, the other I use, well, never.”

twitter.com

https://overreacted.io/before-you-memo/

Before You memo()

Rendering optimizations that come naturally.

overreacted.io

반응형