프론트엔드 성능 최적화를 진행하기 전에 어떤 시기에 최적화를 진행해야 하며, 성능을 어떻게 측정하는지 알아보자.
🟢 make it work - 컴파일하고, 실행시키고, 대략적으로 올바른 종류의 출력물을 뱉어내는지 확인하라.
🟢 make it right - 테스트하고 올바르게 작동하는지 확인해야 한다.
🟢 make it fast - 올바르게 만들면 코드의 구조와 성능이 변경될 수 있으므로 완료되기 전에 속도를 최적화하는 것은 의미가 없다. 그리고 코드를 빨리 만들면 더 깔끔하지 않고 읽을 수 없게 되는 경우가 많다. 따라서 읽기가 가장 쉬울 때 최적화를 수행하는 것이 좋다.
kent beck님이 하신 말이다. 나는 아직 2단계를 진행 중이기에 최적화를 할 단계는 아니라는 것을 인지하였다. 하지만 올바르게 하는 과정에서도 얼만 큼의 개선이 이루어지는지 측정하고 싶었으며 그 과정을 적어나갈 예정이다.
✅ 1. 측정
성능 측정에 주로 사용되는 것은 Lighthouse와 PageSpeed Insights 이 두 가지이다. 나는 Lighthouse를 이용해 성능 측정할 예정이다. 개발자 도구에서 쉽게 사용할 수 있다. 공식 문서를 살펴보면 개발자 도구를 사용하는 것을 권장하고 있다.
모드 설명
Navigation | 사용 사례 ✅Lighthouse 성능 점수와 모든 성능 메트릭을 얻습니다. ✅Progressive Web App 기능을 평가합니다. ✅페이지 로딩 직후 접근성을 분석합니다. 제한 사항 🤔양식 제출 또는 단일 페이지 앱 전환을 분석할 수 없습니다. 🤔페이지 로드 시 즉시 사용할 수 없는 콘텐츠는 분석할 수 없습니다. |
Timespan | 사용 사례 ✅상호 작용을 포함하여 시간 범위에 따른 레이아웃 변화 및 JavaScript 실행 시간을 측정합니다. ✅수명이 긴 페이지 및 SPA의 경험을 개선할 수 있는 성능 기회를 발견하십시오. 제한 사항 🤔전체 성능 점수를 제공하지 않습니다. 🤔순간 기반 성능 메트릭(예: 가장 큰 콘텐츠 페인트)을 분석할 수 없습니다. 🤔페이지 상태 문제를 분석할 수 없음(예: 접근성 카테고리 없음) |
Snapshot | 사용 사례 ✅현재 상태에서 페이지를 분석합니다. ✅SPA 또는 복잡한 양식 내에서 접근성 문제를 찾아보십시오. ✅상호 작용 뒤에 숨겨진 메뉴 및 UI 요소의 모범 사례를 평가합니다. 제한 사항 🤔전체 성능 점수 또는 메트릭을 제공하지 않습니다. 🤔현재 DOM 외부의 문제를 분석할 수 없습니다(예: 네트워크, 기본 스레드 또는 성능 분석 없음). |
현재 진행 중 인 프로젝트의 성능을 측정해 보았다. 성능과 접근성 측면에서 좋지 않은 평가를 받았다. 결과는 그때그때 조금씩 변할 순 있다.
위 내용이 무엇인지 알아보자.
✅ 2. 메트릭
👉 FCP(First Contentful Paint)
페이지 로드가 시작된 후 뷰포트 내의 의미 있는 콘텐츠 일부가 처음 화면에 렌더링 될 때까지의 시간을 측정한다.
Speed Index
뷰포트 내의 콘텐츠가 눈에 띄게 채워지는 속도를 보여주는 페이지 로드 성능을 측정한다. "더 넓은 영역의 콘텐츠를 빠르게 보여줬다는 것”
👉 LCP(Largest Contentful Paint)
뷰포트의 콘텐츠 중 가장 큰(넓은) 영역을 차지하는 이미지나 텍스트 요소가 처음 로딩되는 시점을 의미한다. 가장 큰 영역을 차지하는 요소를 페이지의 주요 콘텐츠로 판단하며, 이 지표를 기준으로 사용자 중심의 페이지 로드 속도를 판단하고 있다.
알고 있어야 하는 점
위에서 간단히 언급했듯이 가장 큰 영역을 차지한다고 해서 모든 요소를 측정하는 것은 아니다. 고려되는 요소 유형을 살펴보자.
- <img> 요소
- <svg> 요소 안의 <image> 요소
- poster 속성을 사용하는 <video> 요소
- url 함수를 통해 이미지를 로딩하는 backgrond 가 사용된 요소
- 텍스트 노드를 포함하는 블록 레벨 요소
요소를 제한한 이유는 작업을 좀 더 단순하게 처리하기 위해 제한했으며 이후 추가 요소가 생길 수 있다고 한다.
👉 TTI(Time to interactive)
페이지가 완전히 사용자와 상호 작용할 수 있는 상태가 되는 데 걸리는 시간을 의미한다.
Long Task
Long Task는 이름에서도 알 수 있듯이 긴 작업을 의미한다. 다시 말해서, 오랜 기간 동안 메인 스레드를 독점해서 UI가 고정되도록 하는 JS 코드를 의미한다. 이렇게 오랜 기간 동안 메인 스레드를 독점하고 있으면 사용자는 페이지가 로드되었지만 클릭이나 입력이 불가능해진다.
Long Task에 관해 이야기한 이유는, TTI는 이 Long Task를 기준으로 사용자와 완전히 상호작용하는 시점을 계산하게 된다.
- 시작 시점은 위에서 살펴본 FCP이다. 사용자가 로딩이 되고 있다라고 처음 인지하는 시점이 될 것이다.
- 최소 5초 이상의 quiet window를 찾는다. 여기서 말하는 quiet window는 long task가 존재하지 않고 진행 중인 Get 요청이 두 개 이상 존재하지 않는 상태를 의미한다.
- 더 이상 Long Task가 존재하지 않으면 quiet window 이전의 가장 마지막 Long Task를 찾습니다. 이 Long Task 가 종료된 시점이 TTI이다. 만약 LCP 이후 Long Task가 없다면 LCP 시점이 TTI가 된다. 즉, 마지막 Long Task가 마무리되면 메인 스레드를 오래 점유하는 작업들이 끝났다는 것을 의미하고 사용자와 완전히 상호 작용할 수 있다고 판단하게 된다.
👉 TBT(Total Blocking Time)
메인 스레드가 입력 응답을 막을 만큼 오래 차단되었을 때 First Contentful Paint(FCP)와 Time to Interactive(TTI) 사이 총시간을 측정한다.
메인 스레드에서 50밀리초(ms) 이상 실행되는 작업, 즉 긴 작업이 있을 때마다 메인 스레드는 "차단"된 것으로 간주된다. 메인 스레드가 "차단"되었다고 하는 이유는 브라우저가 진행 중인 작업을 중단할 수 없기 때문이다. 따라서 사용자가 긴 작업 중 페이지와 상호 작용한 경우 브라우저는 일단 해당 작업이 끝나기까지 기다린 후에야 응답할 수 있다.
타임라인에는 5개의 작업이 있으며 그중 3개는 지속 시간이 50ms를 초과하기 때문에 Long Task로 간주된다.
메인 스레드에서 작업을 실행하는 데 소요된 총시간은 560ms이지만 Blocking time은 작업에서 Long Task의 기준이 되는 50ms를 뺀 값을 모두 더하게 된다. 이 예시에서는 345ms가 TBT가 된다.
TBT는 TTI와는 달리 페이지가 안정적이게 상호작용 할 수 있는 시점을 알려주는 것이 아닌 안정적이게 되기까지 사용자가 얼마나 상호작용하지 못하는지 시간의 총합을 나타내준다. web.dev의 예시처럼 실제 51ms의 작업이 10개 들어있다면 TTI는 좋지 않은 점수를 받겠지만 TBT의 점수는 매우 좋을 것이다. 두 지표를 균형적으로 파악하고 문제를 해결해야 한다.
👉 CLS(Cumulative Layout Shift)
페이지 콘텐츠의 예기치 않은 이동은 일반적으로 리소스가 비동기식으로 로드되거나 DOM 요소가 기존 콘텐츠 위의 페이지에 동적으로 추가되기 때문에 발생한다. 원인은 알 수 없는 크기의 이미지나 동영상, 대체 크기보다 크거나 작게 렌더링 되는 글꼴, 동적으로 크기가 조정되는 타사 광고 또는 위젯일 수 있다.
이것이 더욱 큰 문제가 되는 이유는 개발 중인 사이트가 기능하는 방식이 종종 사용자가 경험하는 방식과 상당히 다르다는 것이다. 대부분 개인화된 콘텐츠나 타사 콘텐츠는 프로덕션 환경에서는 개발 환경과 동일하게 작동하지 않고, 테스트 이미지는 이미 개발자의 브라우저 캐시에 존재하며, 로컬에서 실행되는 API 호출이 너무 빨라 지연이 눈에 띄지 않는 경우가 많기 때문이다.
CLS 메트릭은 실제 사용자에게 이러한 일이 발생하는 빈도를 측정하여 이 문제를 해결하는 데 도움을 준다.
CLS의 경우 5% 비중을 가지고 있던 메트릭이 Lighthouse 8에 들어서면서 15%로 꽤나 높은 비중을 가지게 되었다. 추가적인 내용은 Docs로 확인하자.
'기본 지식' 카테고리의 다른 글
브라우저 동작 원리의 모든 것. (0) | 2022.09.22 |
---|---|
캐시(cache)와 쿠키(cookie) (0) | 2022.08.18 |