프로젝트를 진행하던 중 성능 관련 이슈가 발생했습니다. 이런 저런 시도를 해가며 성능 개선을 하기 위해 노력했고 그 과정에서 배운 일부분을 공유하고자 글을 적게 되었습니다.

문제 상황 🤷‍♂️

이미 문제를 해결한 이후에 글을 적게 되어 비슷한 상황을 예시로 보이고자 합니다.
issue example

위의 화면에서 사각형으로 Highlight가 되는 부분이 리액트가 리렌더링을 하는 부분들 입니다. 문제점이 보이시나요?

입력이 이루어진 곳은 email 입력칸 뿐인데 회원가입 form 전체가 리렌더링이 되고 있는 것을 확인할 수가 있습니다. 현재 예시 화면에는 debounce가 적용되어 있어 입력이 끝난 후 한 번만 전체적으로 리렌더링을 하기 때문에 크게 문제가 없어 보일 수 있지만 debounce가 적용되어 있지 않은 일반적인 경우라면 입력이 발생할 때마다 회원가입 form이 전체적으로 리렌더링이 될 것입니다. debounce의 적용 여부와 상관없이 성능적으로 개선이 될 수 있는 여지가 있어보입니다.

리액트에서 리렌더링이 될 때는? 🙄

리액트에서 리렌더링이 될 때는 다음과 같습니다.

  • 부모 컴포넌트가 렌더링 될 때
  • 상태(state)가 변했을 때
  • props가 변했을 때

위와 같은 경우는 하나의 컴포넌트에서 email, password 등 모든 state를 관리하고 있기 때문에 하나의 상태가 바뀌면 관계없는 다른 컴포넌트도 리렌더링이 되는 경우입니다.

렌더링 확인하기 🧐

리렌더링이 되는 이유를 알았으니 렌더링이 되는 과정을 확인할 수 있으면 좋을 것 같습니다. 위에서 언급한 Highlight Update 기능을 활용하면 이를 확인할 수 있습니다.
Highlight Update 기능을 사용하기 위해선 우선 React 개발자 도구를 구글 확장 프로그램에 추가해야 합니다. 아래 링크를 클릭하면 설치하실 수 있습니다.

리액트 개발자 도구

설치가 끝난 후 리액트로 개발된 페이지에서 F12를 눌러보면 Components와 Profiler가 추가 된 것을 확인할 수 있습니다.

Components에서 옵션을 클릭하여 Highlight update 기능에 체크를 해주시면 됩니다.

how to use highlight update

구조 바꿔보기 🔨

위의 회원가입 폼은 예시로 보여드린 내용이고 실제 프로젝트에서 리팩토링 했던 내용을 공유해보고자 합니다.

다음 사진은 제가 진행하고 있는 프로젝트에서 강의 목록을 보여주기 위해 제작한 LectureList라는 컴포넌트입니다.

lecture list

이미지에서 보이는 것과 같이 크게 Wrapper, Header, Body로 구분할 수 있을 것 같습니다.

처음에는 Wrapper에서 Header와 Body에 필요한 정보들을 주입시키는 구조로 코드를 짰습니다. Wrapper에 state가 저장되어 있으니 state가 변할 때마다 Wrapper에서 리렌더링이 발생했고 자식 컴포넌트인 Header와 Body 역시 리렌더링이 되는 문제가 있었습니다.

하지만 Header와 Wrapper는 리렌더링이 될 이유가 없는 정적인 요소들입니다. 따라서 Body에 대한 상태나 비즈니스 로직을 관리하기 위한 BodyContainer를 하나 더 제작하여 Body를 분리시켜줬습니다. 그 결과 다음과 같이 Body만 리렌더링 되는 것을 확인할 수 있습니다.

good case

결론 😊

이번 글의 예시들이 좋은 예시는 아닌 것 같습니다. 관리해야 하는 상태나 로직들이 최상위 컴포넌트가 아닌 하위 컴포넌트로 찢어지게 되면서 오히려 직관적이지 못한 코드로 변할 위험도 있습니다.

하지만 예시와 다르게 정적인 요소가 수십, 수백개가 있는 경우가 있다면 위와 같은 구조 개선을 통해 성능을 개선시킬 수 있을 것 같습니다.

또한 개발자라면 항상 최적화에 신경을 써야 하기 때문에 highlight 옵션을 통해 컴포넌트들의 렌더링을 확인해가며 개발을 한다면 좀 더 좋은 결과물을 낼 수 있을 것이라고 생각합니다.