https://yrnana.dev/post/2021-03-09
주요 metrics(지표) 항목
⭐️ 표시는 Web Vital에서 중점적으로 체크하는 항목이다.
LCP
: 로딩 성능
FID
: 상호 작용력
CLS
: 시각적 안정성
TTFB (Time To First Byte)
페이지를 요청했을 때 서버에서 데이터의 첫 번째 바이트가 도착하는 시점을 나타낸다. TTFB
는 주로 서버 성능과 직결된다.
최적화 방법
- 서버 애플리케이션 로직 최적화
- DB 쿼리 최적화 또는 더 빠른 DB로 마이그레이션
- 더 많은 RAM 또는 CPU를 갖도록 서버 하드웨어 업그레이드
FCP (First Contentful Paint)
FCP는 페이지가 로드되기 시작하고 컨텐츠의 일부가 화면에 렌더링 될 때 까지의 시간을 의미한다.
최적화 방법
- 렌더링을 block 하는 리소스 제거
- CSS minify
- 사용하지 않는 CSS 제거
- 요청할 origin에 preconnect :
<link rel="preconnect">
- 서버 응답 시간 (TTFB) 줄이기
- 여러 페이지 리다이렉트 줄이기
- 키 요청 preload :
<link rel="preload">
- 지나치게 큰 네트워크 payload를 피하기
- 효율적인 캐시 정책으로 정적 자산 제공
- 과도한 DOM size를 피하기
- 중요한 요청의 depth를 최소화
- 웹 폰트 로드 중에 텍스트가 계속 보이도록 함
- 요청 수를 줄이고 전송 크기를 작게 하기
FMP (First Meaningful Paint)
브라우저가 페이지의 주요 컨텐츠들을 화면에 렌더링하기 시작하는 순간이다. 다만, FMP
는 페이지 로드의 작은 차이에 지나치게 민감하기 때문에 일관성이 떨어져서 LCP
를 측정하는 것을 권장하고 있다.
⭐️ LCP (Largest Contentful Paint)
페이지에서 가장 용량이 큰 컨텐츠가 표시되는 시점을 나타낸다. FCP
의 경우 페이지에 스플래시 화면이 표시되거나 로딩중 아이콘이 표시되는 경우도 포함하기 때문에 사용자와 그다지 관련이 없다. FMP
를 측정하는 것이 복잡하기 때문에 가장 용량이 큰 컨텐츠가 렌더링 되는 시기인 LCP
를 주요 컨텐츠가 로드되는 시기로 판단하는 것을 권장하고 있다.
최적화 방법
- 느린 서버 응답 시간 해결
- 서버 최적화
- 가까운 CDN으로 라우팅
- asset 캐싱
- cache-first HTML 페이지 서빙
- 서드파티 origin 리소스 preconnect
- 렌더링을 block 하는 JS 및 CSS 해결
- CSS block 시간 단축
- CSS minify
- 중요하지 않은 CSS는 defer로 load
- 중요 CSS는 inline 으로 load
- Javascript block 시간 단축
- 느린 리소스 (img, svg, video, ...) 로드 시간 해결
- 이미지 최적화 및 압축
- 중요한 리소스 preload
- 텍스트 파일 압축
- 적응형 리소스 서빙
- 예: 네트워크가 느린 경우 video 대신 image 서빙
- 서비스 워커를 통한 자산 캐싱
- 클라이언트 사이드 렌더링의 경우
- 중요한 자바스크립트 최소화
- 자바스크립트 minify
- 사용하지 않는 자바스크립트 defer로 load
- 사용하지 않는 polyfill 최소화
- 서버사이드 렌더링 사용
- pre-rendering 사용
TTI
는 증가할 수 있으나 TTFB
는 SSR
보다 나음
⭐️ CLS (Cumulative Layout Shift)
페이지가 로드되기 시작하는 시점과 lifecycle 상태가 숨김으로 변경되는 시점 사이에 발생하는 모든 예기치 않은 레이아웃 이동의 누적 점수를 측정한다. 일반적으로 리소스가 비동기적으로 로드되거나 DOM 요소가 기존 컨텐츠가 있는 페이지에 동적으로 추가될 때 발생한다.
최적화 방법
- 이미지나 동영상 요소에 크기를 미리 지정하거나 임시 박스같은 것으로 필요한 공간을 확보
- 사용자 interactive 응답 외에 기존 컨텐츠 위에 컨텐츠를 넣지 않기
- layout 변경을 트리거하는 css property보다 transform 애니메이션을 사용
TTI (Time To Interactive)
웹 페이지가 완전히 상호작용이 가능(interactive)하게 되는 시점을 나타낸다. 컨텐츠를 볼 수 있지만 스크롤 할 수 없거나 항목을 클릭해도 효과가 없으면 interactive 하지 않은 것이다.
최적화 방법
- JS minify
- 요청할 origin에 preconnect :
<link rel="preconnect">
- 키 요청 preload :
<link rel="preload">
- 타사 코드의 영향 범위 감소
- 중요한 요청의 depth를 최소화
- JS 실행시간 단축
- 메인 스레드 작업 최소화
- 요청 수를 줄이고 전송 크기를 작게 유지
사용자가 페이지와 처음 상호작용한(클릭 또는 키 입력 등) 시간부터 브라우저가 실제로 이벤트 핸들러 처리를 시작할 수 있는 시간까지의 시간을 측정한다.
일반적으로 입력 지연은 브라우저의 기본 스레드가 다른 작업 (예: 대용량 js 파일 파싱)을 실행 중일때 발생한다. 위와 같이 메인 스레드에서 작업중인데 user input이 발생하면 브라우저가 이에 대응하는데 FID
만큼의 시간이 소요된다.
최적화 방법
- 긴 Tasks 분할하기
- 메인 스레드를 50ms 이상 차단하는 긴 Task를 분할하기 (
TBT
개선)
- 코드 스플리팅
- 상호작용 준비를 위한 페이지 최적화
- JS 코드 및 기능을 점진적으로 load
- SSR의 경우 논리를 서버측으로 이동하고 코드 스플리팅을 고려해야 함
- cascading data fetch를 최소화
- 서드파티 코드 로딩시간 고려해야 함
- web worker 사용하기
- 백그라운드 스레드에서 자바스크립트를 실행할 수 있음
- JS 실행시간 단축
- 사용하지 않는 자바스크립트 defer로 load
- 특별한 이유가 없는 한 서드파티 스크립트는 defer 또는 async로 로드되어야 함
- 사용하지 않는 polyfill 최소화
- module / nomodule 패턴을 활용하여 개별 번들 제공
TBT (Total Blocking Time)
TBT
는 주 스레드가 input 응답을 막을 정도로 오래 차단 되었을때 FCP
와 TTI
사이의 총 시간을 나타낸다. 긴 작업의 차단 시간은 50ms를 초과하는 시간으로 계산한다. 즉 task의 작업 시간이 250ms이면 TBT
는 200ms이다.
최적화 방법
- 타사 코드의 영향 범위 감소
- JS 실행시간 단축
- 메인 스레드 작업 최소화
- 요청 수를 줄이고 전송 크기를 작게 유지
SSR과 CSR에서의 성능 메트릭
SSR (Server Side Rendering)
SSR
은 일반적으로 빠른 FP
와 FCP
를 가진다. 또한 많은 JS를 서버단에서 실행하므로 TTI
도 빠르게 수행할 수 있다. 다만 서버에서 페이지를 생성하는데 시간이 걸리기 때문에 TTFB
가 느려질 수 있다.
SSR with hydration
유려한 페이지 전환과 인터랙션을 위해 첫 페이지 렌더는 SSR
, 이후에는 CSR
로 이루어지는 SSR with hydration
이라는 기법도 존재한다. Next.js
를 활용하면 쉽게 구현할 수 있다.
CSR (Client Side Rendering)
CSR
에서는 리소스를 가져오기만 하면 되기 때문에 빠른 TTFB
를 가진다. 하지만 FCP
가 느리고 자연히 TTI
는 그보다 더 느리다는 단점이 있다.
측정방법
- lab : 개발하면서 테스트
- field : 실제 사용자 모니터링
참고