현재 페이지의 크기를 키우거나 줄이거나 움직일경우, 페이지 내부의 블록 컴포넌트들이 다시 리렌더링이 되는 현상이 있었습니다.
아래 react devtool profiler
의 사진에 색칠한 부분을보면, Editor 내부의 블록 컴포넌트들이 매번 렌더링이 되는 것을 확인할 수 있었습니다.
현재 우리들의 코드는
위처럼 매번 화면에 보여줄때마다 블록 요소들을 읽는 리소스가 사용됩니다.
함수형 고차 컴포넌트
자식 컴포넌트의 불필요한 리렌더링을 방지할때 사용.
props 가 변경되지 않으면 이전에 렌더링된 결과를 재 사용한다.
현재 nocta
의 구조는 props를 전달받아 많은 렌더링이 발생하고 있습니다.
이와 같이 props를 많이 주고받기에 최적화 방법으로 React.memo를 사용하기로 결정했습니다.
React 훅으로, 계산 비용이 많이 드는 값의 재 계산을 방지합니다.
지정된 의존성 배열의 값이 변경될때만 값을 다시 계산합니다.
React.memo
에서 재 렌더링을 한다고 가정해보겠습니다.
Editor = memo(({ testKey, pageId, serializedEditorData }: EditorProps)
// testKey 가 바뀌었다. 재 렌더링을 해야한다!
하지만 또 serializedEditorData
데이터를 기반으로 블록 정보들을 다시 계산해야합니다.
이를 방지하기 위해 useMemo
를 사용하기로 결정했습니다.
위처럼 memo
에서 재렌더링이 일어나도, serializedEditorData
를 다시 계산하지 않도록 useMemo
를 사용했습니다.
11.3ms
→ 4.9ms
(약 56.6% 향상)1.3ms
→ 0.6ms
(약 53.8% 향상)1ms
→ 0.6ms
(약 40.0% 향상)13.6ms
→ 6.1ms
(약 55.1% 향상)하나의 페이지에서 55.1%의 페이지 렌더 개선을 이룰 수 있었습니다.
무분별한 memo사용은 메모리 리소스 낭비를 초래할 수 있다고 배웠습니다.
마침 우리 에디터의 구조가 props를 많이 사용하는 구조라 적절히 적용하여 개선을 이룰 수 있었습니다.
현재 리사이즈 중에는 내부 요소를 보이지 않게 스켈레톤 처리 하였지만, 사용성이 떨어지는 점을 발견하였고 추후 리팩토링을 통해 수정할 예정입니다.
이벤트 리스너의 경우도 페이지 별로 각 키입력별로 무수히 많이 생성되므로, 이를 최적화 하기 위한 방안을 찾을 예정입니다!