대형 회계법인(Big4) 고객사로부터 뷰어 품질 개선을 요청받아 이슈를 정리·분담하던 중, 벡터 요소가 많은 대용량 스프레드시트에서 스크롤할 때마다 1~2초씩 멈추는 현상을 발견했습니다. 문서 탐색이라는 가장 기본적인 조작에서 프레임 드랍이 나 열람 자체가 불가능한 수준이었고, 곧 사용자 이탈로 이어지는 문제였습니다.
- 벡터 다수 문서
- 1,500ms → 75ms
- 약 95% 감소
- 일반 문서
- 100ms → 70ms
- 약 30% 감소
원인은 두 가지가 겹쳐 있었습니다. 셀별로 드로잉을 개별 호출해 드로우 콜이 셀 수에 비례해 폭증했고, 스크롤할 때마다 뷰포트 안의 전체 셀(테두리·배경·문자)을 다시 그리고 있었습니다.
1차 — 드로우 콜 배칭
호출 횟수 자체를 줄이는 작업이 가성비가 가장 높다고 판단했습니다. 개별로 호출하던 드로잉을 Path2D 객체에 경로로 모아 마지막에 한 번만 드로우 콜하도록 바꿔 평균 300ms를 줄였습니다. 다만 특정 뷰포트에서는 여전히 1초 이상 지연이 남았습니다.
2차 — 오프스크린 캔버스 캐싱
1차 개선은 드로우 콜 횟수만 줄였을 뿐, 이미 그린 셀을 스크롤마다 다시 그리는 낭비는 그대로였습니다. 재렌더링 자체를 없애야 한다고 판단해 셀 단위 오프스크린 캔버스 캐시를 도입했습니다.
뷰포트 내 렌더링 대상 셀 목록을 계산하고, 셀별로 오프스크린 캔버스에 이미 렌더링됐는지 확인한 뒤, 미렌더링 셀만 선별해 그리고, 마지막에 뷰포트에 해당하는 오프스크린 캔버스를 메인 캔버스로 일괄 전송하는 구조입니다.
한 일
- 셀별 개별 드로잉 호출을 Path2D 객체에 경로로 모아 마지막에 한 번만 드로우 콜하도록 변경 (1차, 평균 300ms 개선)
- 잔여 지연의 원인이 재렌더링 자체라고 판단해 셀 단위 오프스크린 캔버스 캐시를 도입 (2차)
- 이미 그린 셀은 재사용하고 미렌더링 셀만 선별 드로잉한 뒤 뷰포트 영역을 메인 캔버스로 일괄 전송
- 역할
- 프론트 3인 중 스크롤 지연 이슈 단독 담당