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

위에 빨간색으로 표시한 EditTable에서 타이핑을 할 때마다 테이블 전체가 리렌더링 되는 이슈가 발생했다.
원인을 파악해 보자!!!
과거 사수분이 테이블 컴포넌트를 작성했는데, 사수분도 테이블 컴포넌트가 이렇게 비대(?)해질 줄 몰랐다고 한다. 테이블 컴포넌트에 기능이 하나, 둘씩 추가되면서 관련 로직들이 추가되고, 테이블에 딸린 컴포넌트들도 많아져 테이블이 리렌더링 될 때마다 버벅이는 이슈가 발생했다.
아래는 사건 등록 시 사용하는 EditTable 컴포넌트 사용 예시 코드이다.
<EditTable
rows={[...]}
data={[...]}
setData={setData}
...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}
/>
)
}
위 방식을 통해 테이블 내부 텍스트를 입력할 때는 테이블 내부 컴포넌트인 InputBoxState만 리렌더링하다가, focus out event가 발생하면 handler 함수를 통해 data를 갱신하도록 수정했다.
아래 gif 영상을 보면 확인할 수 있다 (렌더링이 발생하는 부분은 테두리 색상이 표시됨)

프로젝트 초기 컴포넌트 설계에는 생각하지 못했던 많은 기능을 덧붙이게 되면서 이런 이슈가 발생했다. 앞으로 유지 보수를 하다 보면 이런 상황을 자주 마주칠 것 같은데 컴포넌트 최적화 부분을 많이 신경 써야겠다.
포스팅을 작성하는 시점에 lodash에서 제공하는 debounce로도 문제를 해결할 수 있을 것 같다는 생각을 했다.