Skip to content

Todo 상세 좀 봤다고 테이블 전체가 재렌더링 되는건을 고치기😌

NaGyeong Park edited this page Dec 14, 2022 · 3 revisions

OAO의 주요 페이지 중 하나인 Table 페이지!

스크린샷 2022-12-12 오전 2 30 23

Todo의 데이터와 상태를 관리하고, 확인하기 위한 테이블 페이지는 OAO 서비스에 필수적이다. 그렇기에 테이블 컴포넌트는 첫 릴리즈에 무조건 구현해야되는 핵심 컴포넌트였다.



표의 초기구조 및 문제

Table은 Flex, Grid, Table(태그) 등 여러가지 방법으로 마크업 할 수 있다. 그 중 Grid를 이용해 테이블을 마크업하기로 하였는데, 아래의 이유와 같다.

  • grid-template-columns를 이용하면 열의 배치를 편하게 맞출 수 있음
  • grid-column으로 원하는 요소의 열의 비율을 조정할 수 있음
  • TableHeader와 TableRowHeader들의 비율을 일정하게 맞출 수 있음

Table 구조

Grid Layout 구조

image
  • TableRowHeader와 TableRowDetail가 한 GridWrapper 안에 감싸져있음
  • TalbleRow의 GridWrapper의 10번째 자식은 7칸을 차지하여 TableRowHeader와 TableRowDetail의 div태그 10개가 쌓여 2행을 차지함

Table 컴포넌트 구조

image

TableRowHeader를 클릭하면 TableRowDetail이 화면에 보였다, 안보였다 하는 기능 구현

  • TableRowHeader를 감싸고 있는 태그에 onClick 이벤트를 달아주려고 하였다...

  • BUT Grid 구조 상 TableRowHeader와 TableRowDetail이 같은 태그 안에 감싸져 있어야 하기에 TableRowHeader를 감싸는 태그가 없어 onClick 이벤트를 달 수 없었다 => 현재 클릭한 TableRow의 Id를 displayDetail이라는 전역상태로 관리하고, 해당 상태의 Id와 TableRowDetail의 Id가 같다면 TableRowDetail를 보여주게 구현하였다.

  • displayDetail(boolean)을 전역상태로 가져 상태에 따라 TableRowDetail의 렌더링 여부를 결정

  • Table 컴포넌트에서 TableRow에 onClick 이벤트 발생시 displayDetail의 상태를 변경하기 때문에 Table 관련 컴포넌트는 전부 렌더링 됨


그렇게 했더니,.. 아뿔싸!



🚨Table Component가 전체 재렌더링 되는 문제 발생🚨

rerender

Table에서 displayDetail 전역상태를 관리하다보니 TableRowHeader를 클릭 할 때마다 Table 전체가 리렌더링 되는 것이었다🥲 Todo의 개수가 많을 수록 렌더링 시간이 길어지는 것을 보고, 이 부분은 첫 릴리즈 이후 꼭 리팩터링 해야겠다고 마음을 먹었다.



Refactor

어떻게 리팩터링하면 좋을까

첫 릴리즈 이후 마이너 릴리즈 때 테이블에 정렬 기능, 필터 기능이 추가되었다. 리팩터링 시 표의 의미에 맞게 테이블 태그로 재구성해볼까 팀원들과 이야기해보았지만 추가된 기능에 사이드 이펙트를 일으킬 수도 있다는 판단을 내렸다. 그래서 현재 구조는 그대로 살리되, TableRowHeader와 TableRowDetail를 분리하는 쪽으로 리팩토링하기로 하였다.


최대한 작은 변경

Grid 구조 변경

image
  • TableRowHeader와 TableRowDetail가 다른 Wrapper에 감싸져있음
    • TableRowHeader는 8개로 한 행을 만듬
    • TableRowDetail는 2개로 한 행을 만듬
image
  • displayDetail(boolean)을 TableRow 컴포넌트에서 가지고있어 상태에 따라 TableRowDetail의 렌더링 여부를 결정
  • TableRow 컴포넌트에서 TableRowHeader에 onClick 이벤트 발생시 displayDetail의 상태를 변경하기 때문에 TableRow 관련 컴포넌트는 전부 렌더링 됨


결과

Dec-14-2022 12-33-03

클릭한 TableRow 컴포넌트만 재렌더링이 일어난다.



렌더링 성능 차이

  • Todo List에 Todo 20개 기준

구조 변경 전

Dec-12-2022 01-05-40

  • 첫 TableRow 클릭해 Detail 닫기 : 13ms
  • 첫 TableRow 클릭해 Detail 열기 : 13.7ms
  • 마지막 TableRow 클릭해 Detail 열기 : 11ms
  • 마지막 TableRow 클릭해 Detail 닫기 : 13ms
  • 총 렌더링 시간 : 50.7ms

구조 변경 후

Dec-12-2022 02-15-24

  • 첫 TableRow 클릭해 Detail 닫기 : 2.8ms
  • 첫 TableRow 클릭해 Detail 열기 : 1.4ms
  • 마지막 TableRow 클릭해 Detail 열기 : 1.8ms
  • 마지막 TableRow 클릭해 Detail 닫기 : 1.3ms
  • 총 렌더링 시간 : 7.3ms

비교

  • 첫 TableRow 클릭해 Detail 닫기 : 기존 시간의 22%
  • 첫 TableRow 클릭해 Detail 열기 : 기존 시간의 10%
  • 마지막 TableRow 클릭해 Detail 열기 : 기존 시간의 16%
  • 마지막 TableRow 클릭해 Detail 닫기 : 기존 시간의 10%
  • 총 렌더링 시간 : 기존 시간의 14% => 43.7ms 감소


교훈 및 반성 및 깨달음

  • 초기에 레이아웃을 잘 설정하고 시작해야지 이후 변경사항이 생겨도 사이드 이펙트를 최대한 줄일 수 있다
  • 원하는 기능을 구현하고 싶을 때 레이아웃이 이상하다면 레이아웃을 수정할 수 있을지 먼저 고민해보자
  • 상태의 위치에 따라서 재렌더링의 범위가 많이 달라지기 때문에 상태를 어디서 관리할지 깊게 고민하고 구현하자

💊 비타500

📌 프로젝트

🐾 개발 일지

🥑 그룹활동

🌴 멘토링
🥕 데일리 스크럼
🍒 데일리 개인 회고
🐥 주간 회고
👯 발표 자료
Clone this wiki locally