피드로 돌아가기
예상보다 24배 많은 콘텐츠에 프론트가 대처하는 방법
리디 기술블로그리디 기술블로그
Frontend

예상보다 24배 많은 콘텐츠에 프론트가 대처하는 방법

리디 웹팀이 6,107개 작품을 처리하도록 설계된 대규모 전자책 이벤트 페이지를 react-window 가상화, gzip 압축, 필터링 로직 최적화로 10초 이상의 렌더링을 빠르게 개선

ridicorp2023년 2월 17일12intermediate

Context

리디의 연말 마크다운 이벤트는 6,107개의 작품을 한 페이지에서 표시해야 했으나, 기존 이벤트 페이지는 250개 작품만을 기준으로 설계되어 있었다. 작년에 1,000개 작품만으로도 모바일(특히 저사양 안드로이드)에서 10초 이상의 렌더링 지연과 10MB 이상의 HTML 전송 크기를 기록했다. 6,000개 작품은 315,455개의 DOM 엘리먼트를 생성했으며, 사용자의 화면에는 약 20개(0.3%)만 표시되고 있었다.

Technical Solution

  • 리스트 가상화 도입: react-window 라이브러리를 선택해 보이는 영역의 엘리먼트만 렌더링하고 비표시 영역은 DOM에서 제거
  • window 스크롤 동기화: window의 scroll 이벤트를 감지해 react-window의 scrollTo 함수를 호출하고, 전체 높이를 height 스타일로 지정해 자체 스크롤 방지
  • 동적 SVG 스켈레톤: 스켈레톤을 정적 이미지 대신 동적으로 생성한 SVG 코드로 background-image와 background-repeat을 이용해 타일링
  • gzip 압축 활성화: 전송되는 HTML 크기 감소
  • 필터링 로직 최적화: 스프레드 연산자 대신 Map 객체를 사용해 O(n²) 동작을 제거, 필터링 성능을 4,000ms에서 0.5ms로 개선
  • 사용자 기능 추가: 장바구니 기능, 작품 필터링, 장르 탭, 실시간 이벤트 참여 금액 표시

Impact

  • 필터링 성능: 4,000ms → 0.5ms (약 8,000배 개선)
  • 렌더링 최적화로 저사양 안드로이드 디바이스에서 사용 가능 수준 달성
  • 전체 DOM 엘리먼트: 315,455개 → 가상화로 실제 렌더링 엘리먼트를 약 0.3% 수준으로 감소

Key Takeaway

대규모 목록 렌더링 환경에서는 아이템 높이를 미리 알 수 있을 경우 react-window와 같은 가벼운 가상화 라이브러리로 충분하며, 성능 최적화 시 린트 규칙보다 V8 런타임의 동작 방식을 이해하고 코드를 작성해야 한다는 점이 중요하다.


수천 개 이상의 아이템을 렌더링해야 하는 전자책, 영상, 상품 목록 페이지에서 react-window 가상화를 도입하면 DOM 엘리먼트를 99% 이상 감소시킬 수 있고, 필터링 성능이 저하되는 경우 스프레드 연산자 대신 Map/배열 반복문을 사용하면 O(n²) 연산을 제거해 수 초에서 수 밀리초 단위로 개선할 수 있다.

원문 읽기