pile·
프론트엔드·트렌비트렌비·

FE Lazy Loading 적용기

트렌비 세일스캐너 페이지가 상품 이미지 증가로 모바일에서 앱이 뻗을 정도로 느려지자 Intersection Observer 기반 지연 로딩을 적용한 기록이다. 원인을 좁히기 위해 시도한 두 가지 검증과 검토했다 접은 대안들이 앞에 나온다. 최초 로딩 리소스가 120MB에서 평균 9.6MB로 줄었다.

핵심 포인트
  • MD가 엄선한 카테고리와 상품을 모두 진열하면서 이미지가 급증했다.
  • 카테고리 수를 제한해보니 안정적으로 로딩되는 한계가 30개였다. 한 번에 많은 콘텐츠를 부르는 것이 문제였다.
  • 데스크톱에서 속도를 제한해보니 느리긴 해도 로딩은 됐으므로 네트워크 속도는 근본 원인이 아니었다.
  • 이미지 컴포넌트에만 지연 로딩을 걸면 빈 공간이 잠깐 보이므로 목록 컴포넌트 자체를 지연시켰다.
  • 최초 호출 리소스가 120MB에서 평균 9.6MB로, 첫 페이지 로딩이 약 30초에서 평균 5.5초로 줄었다.
상세 정리
  • 문제 상황: 데스크톱에서는 기다리면 로딩이 됐지만 모바일에서는 오래 걸리는 로딩과 과도한 리소스 요청으로 앱이 아예 뻗었다.
  • 검증 1: API 응답의 카테고리 개수를 제한해봤다. 카테고리별로 상품을 6~12개 보여주는데 안정적으로 감당되는 카테고리가 30개였다.
  • 검증 1의 결론: 한 번에 너무 많은 콘텐츠를 로딩하는 것이 원인이라는 방향을 잡았다.
  • 검증 2: 모바일에서만 문제라면 네트워크 속도 탓인지 확인하려 데스크톱 속도를 제한해봤다.
  • 검증 2의 결론: 오래 걸렸을 뿐 로딩은 완료됐으므로 속도는 근본 원인이 아니었다.
  • 대안 1 검토: 리소스를 다 가져온 뒤 20개만 보여주고 더 보기를 붙이는 방법은, 애초에 많은 이미지를 최초에 부르는 것이 문제라 증상이 나아지지 않는다.
  • 대안 2 검토: API에 페이지네이션을 걸어 스크롤 위치마다 요청하는 방법은 백엔드 공수가 필요해 최후의 선택지로 뒀다.
  • 대안 3 선택: 최초에는 필요한 만큼만 이미지를 부르고 나머지는 필요한 시점에 부르는 방식이 공수가 가장 적고 리소스 문제까지 줄일 수 있었다.
  • 개념 정리: 지연 로딩은 첫 화면에 필요한 섹션만 로드하고 나머지는 사용자가 필요로 할 때까지 로딩을 미루는 것이다.
  • 적용 시 고민 1: 이미지에만 걸어도 되는지 따져봤다.
  • 적용 시 고민 2: 이미지만 늦게 채워지면 그 사이 빈 공간이 보이는데 이를 어떻게 없앨지 고민했다.
  • 결정: 이미지 컴포넌트가 아니라 목록을 그리는 컴포넌트 자체를 지연시키기로 했다.
  • 사용 기술: 대상 요소와 뷰포트의 교차 변화를 비동기로 관찰하는 Intersection Observer를 썼다.
  • 동작 원리: 목록 컴포넌트마다 관찰자를 붙여 화면에 보이는 것만 실제 목록을 렌더링하고 나머지 자리에는 공용 로딩 컴포넌트를 놓는다.
  • 구현 1 순수 자바스크립트: ref로 대상을 잡고 IntersectionObserver를 만들어 교차 여부를 확인해 상태를 켠 뒤, 정리 함수에서 관찰을 해제한다.
  • 구현 2 리액트 훅: react-intersection-observer의 useInView를 쓰면 ref와 교차 여부를 받아 같은 동작을 짧게 쓸 수 있고, 임계값과 한 번만 실행 옵션을 지정할 수 있다.
  • 결과 1: 최초 로딩 시 호출되는 리소스가 이미지 전체 120MB에서 필요한 만큼인 평균 9.6MB로 줄었다.
  • 결과 2: 첫 페이지 로딩 완료가 약 30초에서 평균 약 5.5초가 되어 시간 기준 약 500% 개선됐다.
  • 저자의 단서: 이미지 호출이 극단적으로 많은 페이지라 효과가 더 두드러진 면이 있다고 스스로 밝힌다.
왜 읽나이미지가 많은 목록 페이지가 모바일에서 죽는다면, 원인을 좁히는 두 가지 검증과 컴포넌트 단위로 지연시키는 선택의 근거를 그대로 참고할 수 있다.
트렌비
트렌비 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 프론트엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    항공 프론트엔드 구축기 (7/10): 창구를 하나만 두었습니다

    여기어때 항공 서비스 프론트엔드가 웹과 앱 웹뷰 두 환경에서 동일한 함수 호출로 동작하는 앱 브릿지 추상화 레이어를 설계한 과정을 다룬다. iOS·안드로이드 규약 차이와 "웹에 존재하지 않는 브릿지를 어떻게 호출하나"라는 문제를 단일 추상화 층으로 해결한 구현 사례다.

    요약 이어보기
    #react#typescript#webview+2