웹 개발자가 관심을 가져야할 핵심 웹 지표
핵심 웹 지표 3가지
LCP(Largest Contentful Paint, 최대 콘텐츠 표시 시간) 가장 큰 콘텐츠가 화면에 나타나는 데 걸리는 시간이에요
FID(First Input Delay, 첫 입력 지연 시간) 사용자가 사이트에서 처음으로 버튼을 클릭하거나 입력할 때 반응하는 시간이에요
CLS(Cumulative Layout Shift, 누적 레이아웃 이동) 페이지 내 요소(이미지, 광고, 글자 등)가 갑자기 이동하는 정도(사용자 경험 저해 요소)이에요
핵심 웹 지표 외, 특정 문제를 진단하는데 사용되는 것들
- TTFB(Time To First Byte, 최초 바이트까지의 시간)
- FCP(First Contentful Paint, 최초 콘텐츠풀 시간)
🟢 LCP
목표 : 2.5초 이내 (4초 이내 보통)
페이지가 처음으로 로드를 시작한 시점부터 뷰포트 내부에서 가장 큰 이미지 또는 텍스트를 렌더링 하는 데 걸리는 시간을 말해요. (LCP는 페이지 로딩에 따라 변화 할 수 있어요) 사용자에게 페이지의 정보를 화면에 전달하는 속도를 객관적으로 판단하기 위한 지표로 만들어졌어요.
뷰포트 내부에서 큰 이미지와 텍스트
<img><svg>내부의<image>- poster 속성을 사용하는
<video> - url()을 통해 불러온 배경 이미지가 있는 요소
- 텍스트와 같이 인라인 텍스트 요소를 포함하고 있는 블록 레벨 요소:
<p>,<div>등이 포함되어요
개선방법
LCP 예상 영역에 이미지가 아닌 문자열 넣기: 최대콘텐츠풀페인트 예상 영역에 이미지가 아닌 문자열로 넣어 가능한 한 해당 영역은 텍스트로 넣는 것이 좋아요
이미지를 불러 올 때,
<svg>내부의<img>는 프리로드 스캐너에 의해 발견되지 않아 병렬적으로 다운로드가 일어나지 않아요 이는 결국 lcp에 악영향을 미칩니다.<video>가 최대 콘텐츠풀 페인트에 영향을 받을 거 같다면 poster를 넣어주는 것이 좋아요- background-image를 비롯해서 css에 있는 리소스는 항상 느리므로 중요한 리소스에는 backround-img를 사용하지 않는 것이 좋아요.
그밖에 조심해야할 사항들
- 이미지는 가능한 한 무손실 형식으로 압축해 최소한의 용량으로 서비스하는 것이 좋아요
- loading=lazy는 리소스를 중요하지 않음으로 표시하고 필요할 때만 로드하는 전략으로 잘 응용할 수 있지만 상대적으로 중요하지 않은 이미지에서만 사용하는 것이 좋아요
- fadeIn과 같은 애니메이션들도 LCP가 느려져요.
- 클라이언트에서 빌드하는 것보다 서버에서 미리 빌드된 채로 오는 것이 좋아요
- 가능하다면 최대 콘텐츠풀 리소스는 같은 도메인에서 직접 호스팅하는 것이 좋아요
🟢 FID
목표 : 100ms 이내 (300ms 이내 보통)
웹페이지의 로딩 속도만큼 중요한 것이 웹사이트의 반응 속도에요. 이러한 웹사이트의 반응성을 측정하는 지표를 최초 입력 지연이(First Input Delay: FID)라고 부릅니다. 사용자가 페이지와 처음 상호 작용할 때 (링크/버튼을 클릭)부터 해당 상호 작용에 대한 응답으로 브라우저가 실제로 이벤트 핸들러 처리를 시작하기까지의 시간을 측정해요.
자바스크립트 실행환경은 싱글 스레드 이기 때문에 이벤트 리스너와 같은 다른 작업을 실행할 수 없어 지연이 발생하기 때문에 발생하는 시점에 최대한 메인 스레드가 다른 작업을 처리할 수 있도록 여유를 만들어 둬야 사용자에게 빠른 반응성을 보장할 수 있어요.
구글에서 정의한 사용자 경험 4가지 : RAIL
- Response : 사용자의 입력에 대한 반응 속도, 50ms 미만으로 이벤트를 처리할 것 (최초 입력지연은 여기에 해당하는 응답에 초점을 맞추고 있어요)
- AnimationL : 애니메이션의 각 프레임을 10ms 이하로 생성할 것
- Idle : 유효 시간을 극대화해 페이지가 50ms 이내에 사용자 입력에 응답하도록 할 것
- Load: 5초 이내에 콘텐츠를 전달하고 인터랙션을 준비할 것
개선 방법
메인 스레드에 이벤트를 실행할 여유를 주어 FID를 개선할 구체적인 방법
- 실행에 오래 걸리는 긴 작업을 분리: 꼭 웹페이지에서 해야하는 작업이 아니라면 서버로 옮겨서 처리하기
- 자바스크립트 코드 최소화: 당장 급하지 않은 코드는 지연 로딩 기법을 사용하기
- 타사 자바스크립트 코드 실행의 지연 GA와 같이 타사 코드를 사용할 경우 웹페이지 로드에 중요한 자원이 아닐 수 있으니 asyncs와 defer을 이용해 지연 불러오기를 하는 것이 좋아요. 또한 만약 광고와 같이 실제 사용자의 뷰포트 위치에 따라 불러와야하는 컴포넌트라면 Intersection Observer를 이용해 뷰포트에 들어오는 시점에 불러오는 것이 좋아요.
🟢 CLS
목표 : 0.1 이하 (0.25 이하인 경우 보통)
페이지의 생명주기 동안 발생하는 예기치 않은 레이아웃 이동의 누적 점수를 측적하는 지표를 말해요. 뷰포트 내부의 요소에 대해서만 측정하고 최초 렌더링이 시작된 위치에서 이동이 발생하면 점수가 기록되어요. 요소가 추가되었어도 다른 요소의 시작 위치에 영향을 미치지 않았다면 레이아웃 이동으로 간주되지 않아요. 예로 어떤 웹사이트에 접속 했을 떄 로딩이 마친 줄 알고 배너를 클릭하려했다가 그 사이 다른 요소가 로딩되면서 원래 클릭하려 했던 요소가 아닌 다른 요소를 검색하게 되었던 경험을 말할 수 있어요.
개선 방법
삽입이 예상되는 요소를 위한 추가적인 공간 확보: useEffect내부에서 요소에 영향을 미치는 작업을 최소화하기, 스켈레톤 사용, SSR 사용
폰트 로딩 최적화: 최대한 중요한 폰트의 다운로드를 우선순위에 밀어넣고 이 우선순위를 활용했음에도 빠르게 로딩하는데 실패했다면 다음을 기약하고 기본 폰트를 노출하는 방법으로 사용자가 예기치 못하게 변경된 폰트로 인해 혼선을 겪는 것을 방지하기
폰트로 발생될 수 있는 문제 FOUT(flash of unstyled text) : 기본 폰트로 보이고 있다가 뒤늦게 폰트가 적용되는 현상 FOIT(flash of invisible text) : 지정한 폰트가 보이지 않고, 기본 폰트도 없어서 텍스트가 보이지 않다가 뒤늦게 폰트가 로딩되면서 렌더링되는 현상
유념
<link>의 preload 사용하여 렌더링을 가로막거나 레이아웃 방해할 가능성 줄이기font-family: optional/auto/block/swap/fallback등 사용해서 폰트 불러오기
- 적절한 이미지 크기 설정: 반응형으로 작업하면서
img {width: 100%; height: auto}와 같은 코드를 자주 넣는데 이 경우 누적 레이아웃이 커지는 결과가 발생해요. 높이를 이미지가 완전히 다운로드되기 전까지 알수 없어서 레이아웃 이동 발생해요