React 테이블 컴포넌트 최적화 경험 👨‍🔧

🥇 Onething (FE Developer)·2022년 3월 5일
post-thumbnail

문제 발생 💣

회사에서 서비스하고 있는 제품 중 하나인 LawShot(변호사 업무 서비스)에서 사건을 등록할 때 렌더링 이슈로 타이핑 반응속도가 느리고, 버벅대는 이슈를 확인했다.

위에 빨간색으로 표시한 EditTable에서 타이핑을 할 때마다 테이블 전체가 리렌더링 되는 이슈가 발생했다.

원인을 파악해 보자!!!


문제 원인 파악하기 🤷‍♂️

과거 사수분이 테이블 컴포넌트를 작성했는데, 사수분도 테이블 컴포넌트가 이렇게 비대(?)해질 줄 몰랐다고 한다. 테이블 컴포넌트에 기능이 하나, 둘씩 추가되면서 관련 로직들이 추가되고, 테이블에 딸린 컴포넌트들도 많아져 테이블이 리렌더링 될 때마다 버벅이는 이슈가 발생했다.

아래는 사건 등록 시 사용하는 EditTable 컴포넌트 사용 예시 코드이다.

<EditTable 
  rows={[...]}
  data={[...]}
  setData={setData}
  ...props
/>
  • rows: 테이블 컬럼 배열
  • data: 테이블 레코드 데이터 배열
  • setData: 테이블 레코드 데이터 수정 시 변경된 데이터를 전달하는 함수
  • ...props: 많은 props들이 있지만 편의상 생략

타이핑을 할 때마다 setData 함수가 동작하여 EditTable Props인 data가 변경된다. 이로 인해 테이블 전체가 렌더링 되는 슬픈 현실이...😂

타이핑할 때마다 리렌더링 되는 이 상황을 예방하는 최적화를 진행해보자!!!


문제 해결하기 💡

내가 생각한 해결 방식은 타이핑할 때마다 setData가 동작하는 방식이 문제를 일으키므로, 타이핑이 다 끝나고 focus out 이벤트가 발생할 때 setData 핸들러를 호출하면 문제가 해결될 것 같았다.

우선, 테이블 컴포넌트 내부에 InputBoxState라는 컴포넌트를 만들었다.

function InputBoxState({originValue, onBlur, maxLength, disabled}) {
  const [value, setValue] = useState(originValue);
  
  // ... 관련 로직
  
  return (
    <InputBox
      value={value}
      maxLength={maxLength}
      onChange={(e) => setValue(e.target.value)}
      onBlur={() => onBlur(value)}
      disabled={disabled}
    />
  )
}

아래 코드는 테이블 컴포넌트 내부에서 위에서 작성한 InputBoxState 컴포넌트를 사용한 예시 코드이다.

  // ... 관련 로직
   
  if(!type || type==='text') {
    displayComponent = (
      <InputBoxState 
        originalValue={row[id]}
        onBlur={(value) => editHandler(row, id, value)}
        maxLength={maxLength}
        disabled={disabled}
      />
    ) 
  }
  • editHandler: props로 전달받은 setData를 호출하는 일을 수행 (내부 로직은 생략함)

위 방식을 통해 테이블 내부 텍스트를 입력할 때는 테이블 내부 컴포넌트인 InputBoxState만 리렌더링하다가, focus out event가 발생하면 handler 함수를 통해 data를 갱신하도록 수정했다.

아래 gif 영상을 보면 확인할 수 있다 (렌더링이 발생하는 부분은 테두리 색상이 표시됨)


이 경험을 통해 📝

프로젝트 초기 컴포넌트 설계에는 생각하지 못했던 많은 기능을 덧붙이게 되면서 이런 이슈가 발생했다. 앞으로 유지 보수를 하다 보면 이런 상황을 자주 마주칠 것 같은데 컴포넌트 최적화 부분을 많이 신경 써야겠다.

포스팅을 작성하는 시점에 lodash에서 제공하는 debounce로도 문제를 해결할 수 있을 것 같다는 생각을 했다.

profile
Vires acquirit eundo.

0개의 댓글