Next.js 기반 전자 상거래 웹 사이트에서 CLS 문제 해결(사례 연구)
게시 됨: 2022-03-10Fairprice는 싱가포르에서 가장 큰 온라인 식료품점 중 하나입니다. 우리는 사용자의 온라인 쇼핑 경험을 개선할 수 있는 기회 영역을 지속적으로 찾고 있습니다. 성능은 사용자가 장치나 네트워크 연결에 관계없이 즐거운 사용자 경험을 누릴 수 있도록 하는 핵심 측면 중 하나입니다.
TTFB, domInteractive
및 onload
와 같이 웹 페이지의 수명 주기 동안 여러 지점을 측정하는 핵심 성과 지표(KPI)가 많이 있지만 이러한 측정항목은 최종 사용자가 페이지를 경험하는 방식을 반영하지 않습니다.
우리는 최종 사용자의 실제 경험과 밀접하게 일치하는 몇 가지 KPI를 사용하기를 원했기 때문에 이러한 KPI 중 하나라도 제대로 수행되지 않으면 최종 사용자 경험에 직접적인 영향을 미친다는 것을 알고 있습니다. 우리는 이 목적에 완벽하게 부합하는 사용자 중심의 성능 메트릭을 찾았습니다.
FCP, LCP, FID, CLS 등과 같은 페이지 수명 주기의 여러 지점을 측정하기 위한 사용자 중심 성능 메트릭이 많이 있습니다. 이 사례 연구에서는 주로 CLS에 중점을 둘 것입니다.
CLS는 페이지가 로드되기 시작할 때와 언로드될 때까지 발생하는 모든 예상치 못한 레이아웃 이동의 총점을 측정합니다.
"
따라서 페이지에 대해 낮은 CLS 값을 사용하면 사용자 불만을 야기하는 임의의 레이아웃 이동이 없습니다. Barry Pollard는 CLS에 대한 훌륭한 심층 기사를 작성했습니다.
제품 페이지에서 CLS 문제를 발견한 방법
우리는 CLS를 측정하기 위한 성능을 위한 합성 테스트 도구로 Lighthouse와 WebPagetest를 사용합니다. 또한 web-vitals 라이브러리를 사용하여 실제 사용자의 CLS를 측정합니다. 그 외에도 Google Search Console Core Web Vitals 보고서 섹션을 확인하여 모든 페이지에서 잠재적인 CLS 문제에 대한 아이디어를 얻습니다. 보고서 섹션을 탐색하는 동안 제품 세부 정보 페이지의 많은 URL에 0.1 CLS 값보다 큰 값이 있어 주요 레이아웃 전환 이벤트가 발생하고 있음을 알 수 있습니다.
다른 도구를 사용하여 CLS 문제 디버깅
이제 제품 세부 정보 페이지에 CLS 문제가 있다는 것을 알았으므로 다음 단계는 문제를 일으키는 요소를 식별하는 것이었습니다. 처음에는 합성 테스트 도구를 사용하여 몇 가지 테스트를 실행하기로 결정했습니다.
그래서 우리는 등대를 실행하여 주요 레이아웃 변경을 유발할 수 있는 요소를 찾을 수 있는지 확인했습니다. CLS는 상당히 낮은 .004로 보고되었습니다.
Lighthouse 보고서 페이지에는 진단 섹션이 있습니다. 그것은 또한 높은 CLS 값을 유발하는 요소를 보여주지 않았습니다.
그런 다음 WebpageTest를 실행하고 영사슬라이드 보기를 확인하기로 결정했습니다.
이 기능은 레이아웃이 이동한 시점의 요소를 찾을 수 있기 때문에 매우 유용합니다. 그러나 테스트를 실행하여 레이아웃 변경이 강조 표시되는지 확인하면 거대한 LCS에 기여하는 것이 없었습니다.
CLS의 단점은 페이지의 전체 수명 동안 개별 레이아웃 전환 점수를 기록하고 추가한다는 것입니다.
"
참고 : 2021년 6월부터 CLS 측정 방법이 변경되었습니다.
Lighthouse와 WebpageTest는 주요 레이아웃 변경을 유발하는 요소를 감지할 수 없었기 때문에 초기 페이지 로드 이후에 일부 사용자 작업으로 인해 발생했을 수 있습니다. 따라서 사용자가 페이지와 상호 작용하는 동안 페이지에 CLS를 기록할 수 있기 때문에 Web Vitals Google Chrome 확장 프로그램을 사용하기로 결정했습니다. 다른 작업을 수행한 후 사용자가 이미지 확대 기능을 사용할 때 레이아웃 이동 점수가 증가하는 것을 발견했습니다.
이미지에 마우스 오버가 있는 동안 레이아웃 이동이 발생하는지 교차 확인하기 위해 https://web.dev/cls/에서 레이아웃 이동이 발생할 때 console.log
를 추가하는 아래 코드 스니펫을 사용했습니다.
let cls = 0; new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { if (!entry.hadRecentInput) { cls += entry.value; console.log('Current CLS value:', cls, entry); } }}).observe({type: 'layout-shift', buffered: true});
추가 조사에서 우리는 ASDA가 비슷한 종류의 문제에 직면했다는 것을 발견하고 크롬에 대해 제기했습니다.
근본 원인
제품 세부 정보 페이지에서 사용자는 제품 이미지 위로 마우스를 이동하여 실제 제품 이미지와 나란히 확대된 이미지 섹션을 볼 수 있습니다. 이 비디오는 우리가 말하는 내용을 정확히 보여줍니다.
이미지 확대 기능은 사용자가 제품의 모양과 느낌을 파악하고 구매하려는 제품의 올바른 변형인지 확인하는 데 도움이 됩니다.
react-image zoom
라이브러리를 사용하여 이 이미지 확대 기능을 구축했습니다.
Image Magnify 라이브러리에는 일반적으로 렌즈(마우스가 이미지 내에서 움직일 때 움직이는 사각형)가 있습니다. 이 렌즈는 마우스의 움직임에 따라 상하좌우 위치를 변경하기 때문에 CLS를 트리거하는 레이아웃 이동으로 감지됩니다. 라이브러리 페이지와 다른 유사한 반응 라이브러리( react-image-magnify
, react-image-zoom
, react-image-magnifiers
)를 확인했으며 모두 동일한 CLS 문제를 겪고 있음을 발견했습니다.
우리가 그것을 고친 방법
react-image-zoom
이 js-image-zoom
라이브러리를 사용하고 있음을 확인했습니다. 따라서 문제를 해결하기 위해 js-image zoom
라이브러리를 수정해야 했습니다.
솔루션은 매우 간단합니다. 마우스가 제품 이미지 위로 이동하는 동안 이미지 렌즈 요소는 왼쪽 및 위쪽 위치를 변경하여 이동합니다. 문제를 해결하기 위해 요소를 새 레이어로 이동하는 transform translate
을 사용했습니다. 즉, 이 새 레이어에서 발생하는 모든 이동은 더 이상 레이아웃 이동을 일으키지 않습니다.
또한 이 라이브러리를 사용하는 다른 개발자가 CLS 문제를 제거할 수 있도록 원래 리포지토리에 대한 PR을 만들었습니다.
변경의 영향
코드가 프로덕션에 배포된 후 제품 세부 정보 페이지에서 CLS가 수정되었고 CLS의 영향을 받는 페이지 수가 98% 감소했습니다.
transform
을 사용했기 때문에 이미지가 사용자에게 더 부드러운 경험을 확대하도록 하는 데도 도움이 되었습니다.
참고 : Paul Irish는 이 주제에 대한 훌륭한 기사를 작성했습니다.
CLS에 대한 기타 주요 변경 사항
CLS에 기여하는 웹 사이트의 많은 페이지를 통해 직면한 다른 문제도 있습니다. 이러한 요소와 구성 요소를 살펴보고 이러한 요소에서 발생하는 레이아웃 변경을 완화하기 위해 어떻게 노력했는지 살펴보겠습니다.
웹 글꼴:
글꼴을 늦게 로드하면 콘텐츠가 깜박이기 때문에 사용자가 좌절감을 느끼고 일부 레이아웃이 변경된다는 사실을 알게 되었습니다. 이를 최소화하기 위해 몇 가지 변경 사항을 적용했습니다.- 타사 CDN에서 로드하는 대신 글꼴을 자체 호스팅했습니다.
- 글꼴을 미리 로드합니다.
- 글꼴 표시를 선택 사항으로 사용합니다.
이미지:
이미지에 높이 또는 너비 값이 없으면 이미지가 로드되면 이미지 뒤의 요소가 이동합니다. 이것은 결국 CLS의 주요 기여자가 됩니다. Next.js를 사용하고 있기 때문에next/images
라는 내장 이미지 구성 요소를 활용했습니다. 이 구성 요소는 여러 이미지 관련 모범 사례를 통합합니다.<img>
HTML 태그 위에 구축되었으며 LCP 및 CLS를 개선하는 데 도움이 될 수 있습니다. RFC 사용의 주요 기능과 이점을 알아보려면 이 RFC를 읽는 것이 좋습니다.무한 스크롤:
당사 웹사이트에서 제품 목록 페이지는 무한 스크롤됩니다. 따라서 처음에 사용자가 페이지 맨 아래로 스크롤하면 다음 데이터 세트가 로드되기 전에 몇 초 동안 바닥글이 표시되고 이로 인해 레이아웃이 이동합니다. 이 문제를 해결하기 위해 몇 가지 조치를 취했습니다.- 사용자가 목록의 절대 하단에 도달하기 전에도 API를 호출하여 데이터를 로드합니다.
- 로딩 상태를 위한 충분한 공간을 확보했고 로딩 상태 동안 제품 골격을 보여줍니다. 따라서 이제 사용자가 스크롤할 때 제품이 로드되는 동안 몇 초 동안 바닥글이 표시되지 않습니다.
Addy Osmani는 이 접근 방식에 대한 자세한 기사를 작성했으며 확인하는 것이 좋습니다.
주요 내용
- Lighthouse와 WebpageTest는 페이지가 로드될 때까지 발생하는 성능 문제를 발견하는 데 도움이 되지만 페이지 로드 후에는 성능 문제를 발견할 수 없습니다.
- Web Vitals 확장 프로그램은 사용자 상호 작용에 의해 트리거된 CLS 변경 사항을 감지할 수 있으므로 페이지에 높은 CLS 값이 있지만 Lighthouse 또는 WebpageTest가 낮은 CLS를 보고하는 경우 Web Vitals 확장 프로그램은 문제를 정확히 찾아내는 데 도움이 될 수 있습니다.
- Google Search Console 데이터는 실제 사용자의 데이터를 기반으로 하므로 페이지 수명 주기의 어느 시점에서든 잠재적인 성능 문제가 발생할 수 있습니다. 문제가 감지되고 수정되면 보고서 섹션을 다시 확인하면 성능 수정의 효과를 확인하는 데 도움이 될 수 있습니다. 변경 사항은 웹 vitals 보고서 섹션에 며칠 이내에 반영됩니다.
마지막 생각들
CLS 문제는 디버그하기가 비교적 어렵지만 페이지 로드(Lighthouse, WebPageTest) 및 Web Vitals 확장(페이지 로드 후)까지 다른 도구를 함께 사용하면 문제를 정확히 찾아내는 데 도움이 될 수 있습니다. 또한 다양한 시나리오를 다루기 위해 많은 개발이 활발히 진행되고 있는 메트릭 중 하나이며, 이는 향후 측정 방법이 변경될 것임을 의미합니다. 향후 변경 사항에 대해 알기 위해 https://web.dev/evolving-cls/를 팔로우하고 있습니다.
우리는 다른 Core Web Vitals도 개선하기 위해 지속적으로 노력하고 있습니다. 최근에 반응형 이미지 사전 로드를 구현하고 WebP 형식으로 이미지를 제공하기 시작하여 이미지 페이로드를 75%, LCP를 62%, 속도 지수를 24% 줄이는 데 도움이 되었습니다. LCP 및 속도 지수 개선을 위한 최적화에 대한 자세한 내용을 읽거나 엔지니어링 블로그를 팔로우하여 우리가 하고 있는 다른 흥미로운 작업에 대해 알아볼 수 있습니다.
제품 페이지에서 CLS 문제를 디버그하고 next/images
구현의 문제를 해결하는 데 도움을 준 Alex Castle에게 감사드립니다.