Riot API를 활용해 OP.GG 클론하는 토이 프로젝트를 진행했다.
상태는 위와 같으며 "더 보기" 버튼을 클릭했을 때 추가 경기 정보를 4개씩 요청한다.
동작은 의도대로 되지만 React Developer Tools Profiler를 확인 해보니 모든 commit에 이전 4개의 기록이 함께 렌더링 되는 것이 보였다. (다른 유저 아이디를 렌더링하는 FollowPlayersNames 컴포넌트가 총 8번 그려짐)
"더 보기" 버튼을 누를 때마다 이전 기록들이 다시 렌더링 된다고 하면 경기 정보를 받아 올수록 성능상의 부담이 가중되는 상태였다!
원인을 찾아보니 기본적으로 부모 컴포넌트(MatchList)가 가지고 있는 경기 정보 state가 변경되어 하위의 자식 컴포넌트(MatchItem)가 다시 렌더링 되는 것을 알았다. 하지만 각각의 자식 컴포넌트는 부모에게서 전달받는 props가 같기 때문에 렌더링 될 필요는 없었다.
class 기반의 컴포넌트를 작성했다면 React lifecycle 중 shouldComponentUpdate 메서드를 활용해 이슈를 해결할 수 있을 것이다.
이번 프로젝트는 함수 기반의 컴포넌트를 작성했기 때문에 React.memo를 활용했다.
함수 컴포넌트가 동일한 props로 동일한 결과를 렌더링해낸다면, React.memo를 호출하고 결과를 메모이징(Memoizing)하도록 래핑하여 경우에 따라 성능 향상을 누릴 수 있습니다. 즉, React는 컴포넌트를 렌더링하지 않고 마지막으로 렌더링된 결과를 재사용합니다.
렌더링되는 주체인 MatchItem 컴포넌트를 React.memo로 감싸 결과를 메모이징 하게 했다.
import React, { memo } from "react";
const MatchItem = ({ matchInfo }) => {
...
return (
...
);
};
export default memo(MatchItem);
Profiler를 다시 확인해보니 "더 보기" 버튼을 눌러 추가 정보를 요청했을 때 추가된 경기 데이터 정보에 한해서 컴포넌트가 렌더링 되는 것을 확인했다.
결과적으로 원하는 기능을 구현한 것이긴 한데 React 공식 문서에서 우려하는 상황에서 사용한 것 같아 찜찜하다.
이 메서드는 오직 성능 최적화를 위하여 사용됩니다. 렌더링을 “방지”하기 위하여 사용하지 마세요. 버그를 만들 수 있습니다.
공식 문서에 있는 문장이다. props로 함수를 자식 컴포넌트에 넘길 때 예상하지 못한 사이드 이펙트가 발생할 수 있는 것 같다. 추가 학습이 필요한 부분