[CS 지식] FCP, TTI, LCP는 무엇인가
🎈 FCP
First Contentful Paint(이하 FCP)는 웹 성능 메트릭 지표 중 하나이다. 페이지가 로드되기 시작한 시점부터 페이지에서 최초로 '의미 있는 컨텐츠가 렌더링 되는 순간’ 까지를 측정한다.
측정되는 최소단위는 다음과 같다.
- 단일 텍스트 문자
- 하나의 이미지
- SVG의 한 부분
- 흰색이 아닌 Canvas 요소
✨ 위의 요소 중 하나가 렌더링 완료되면 FCP로 측정한다.
측정되지 않는 요소는 다음과 같다.
- 페이지 레이아웃을 위한 빈 컨테이너
- 컬러나 사이즈가 설정이 되어 있더라도 해당 요소가 렌더링 되었을 때는 FCP로 측정하지 않는다.
- 로딩 스피너나 스켈레톤 UI
- 사실 처음 이 부분은 스피너가 애니메이션으로 작동하고 화면 영역을 구성하고 있기 때문에 FCP로 측정이 될 줄 알았으나 아래와 같이 코드를 구현했을 때 라이트하우스에서 측정하지 못하는 것을 확인할 수 있었다.
-
더보기
HTML 코드
<!DOCTYPE html> <html> <head> <style> /* 스피너 스타일 */ .spinner { width: 50px; height: 50px; border: 5px solid #f3f3f3; border-top: 5px solid #3498db; border-radius: 50%; animation: spin 1s linear infinite; margin: 20px auto; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* 스켈레톤 UI 스타일 */ .skeleton-wrapper { max-width: 600px; margin: 20px auto; padding: 20px; } .skeleton-header { height: 30px; background: #e0e0e0; margin-bottom: 20px; border-radius: 4px; animation: pulse 1.5s infinite; } .skeleton-text { height: 20px; background: #e0e0e0; margin-bottom: 10px; border-radius: 4px; animation: pulse 1.5s infinite; } .skeleton-text:last-child { width: 80%; } @keyframes pulse { 0% { opacity: 0.6; } 50% { opacity: 1; } 100% { opacity: 0.6; } } </style> </head> <body> <!-- 로딩 스피너 --> <div class="spinner"></div> <!-- 스켈레톤 UI --> <div class="skeleton-wrapper"> <div class="skeleton-header"></div> <div class="skeleton-text"></div> <div class="skeleton-text"></div> <div class="skeleton-text"></div> </div> </body> </html>
라이트하우스에서 FCP 시간별 색상 구분(속도)는 다음과 같다.
FCP 시간 | 색상 구분 |
0 ~ 1.8 | 녹색(빠름) |
1.8 ~ 3 | 주황색(중간) |
3 초과 | 빨간색(느림) |
👓 FCP의 속도가 중요한 이유
FCP가 빠르면 사용자 이탈률이 감소하게 된다. 그 이유는 다음과 같다.
1️⃣ 첫인상과 신뢰도
- 웹 사이트가 빠르게 첫번째 컨텐츠를 보여주게 되면 사용자는 웹 사이트가 정상적으로 잘 작동하고 있다는 인상을 받게 된다.
- 빈 화면이나 로딩 화면을 오래 보면 사이트가 느리거나 문제가 있다고 인식하게 된다.
2️⃣ 인지적 측면
- 사람의 집중력은 보통 3초 정도가 한계이다.
- FCP가 3초를 넘어가면 사용자는 지루함을 느끼고 다른 사이트로 이동할 가능성이 증가한다.
- 구글 연구에 따르면 페이지 로딩이 1초에서 3초로 늘어나면 이탈률이 32% 증가한다고 한다.
🛒 FCP를 최적화 하는 방법
FCP는 의미있는 첫번째 컨텐츠를 대상으로 최적화를 진행하면 된다. 그래서 이미지와 같은 리소스의 경우 보통 FCP 측정의 대상으로 선정되기는 어렵고 보통 텍스트 요소가 측정의 대상이 될 가능성이 높다. 그래서 텍스트를 중점적으로 최적화해주어야 한다.
1️⃣ 서버 응답 시간 단축
네트워크를 통해서 데이터 또는 리소스를 전달받는 경우, 네트워크 시간을 최적화해주어야 한다.
- CDN 활용아여 타겟이 되는 사용자에 가까운 서버를 사용하여 네트워크 시간을 단축시킨다.
2️⃣ 렌더링 차단 리소스 제거
CSS 및 자바스크립트를 로드하는 동안 요소의 렌더링을 블로킹하게 된다. 다음과같은 최적화를 진행해주어야 한다.
- 사용하지 않는 CSS / 자바스크립트 삭제
- CSS / 자바스크립트 축소 및 압축
- 자바스크립트 로드는 DOM 요소가 렌더링 된 후 로드 될 수 있도록 지연
3️⃣ 웹폰트 최적화
FCP의 대상이 될 가능성이 높은 텍스트에서 폰트의 로드 속도는 중요한 요소이다.
- font-display: swap 사용. 이는 글꼴이 로드되는 동안에도 글자가 정상적으로 렌더링되게 해준다.
- 폰트 용량 최적화
4️⃣ DOM 크기 및 요청 수 최소화
- DOM 구조를 간소화하고, 불필요한 요소를 제거하여 렌더링 효율성을 높인다.
- 초기 로드 시 필요한 최소한의 리소스만 요청하도록 설정한다.
📯 TTI
Time to Ineractive(이하 TTI)는 웹 페이지가 완전히 상호작용 가능한 상태가 되는 시점을 측정하는 성능 메트릭이다.
TTI가 측정되는 조건은 다음과 같다.
- FCP가 발생했고,
- 마지막 긴 작업이 완료되고 5초의 네트워크 및 메인 스레드가 비활성화된 시점
TTI의 경우 외부 네트워크 요청 및 긴 작업에 지나치게 민감하여 측정항목의 변동성이 높아 라이트하우의 측정항목에서 삭제되었다.
✨ LCP, TBT와 같은 대체 측정항목을 사용하는 것이 좋다.
🚩 LCP
Largest Contentful Paint(이하 LCP)는 웹 페이지의 주요 컨텐츠가 사용자 화면에 완전히 렌더링되는데 걸리는 시간을 측정하는 웹 성능 지표이다.
LCP는 페이지 로드 중 뷰포트에 표시되는 가장 큰 이미지 또는 텍스트 블록의 렌더링 시간을 측정한다.
LCP를 결정할 때 아래 요소가 포함되어 측정된다.
- <img> 요소
- SVG 내부의 <image> 요소
- <video> 요소의 포스터 이미지
- background-image가 있는 요소
- <p>와 같은, 텍스트 노드 그룹
라이트하우스에서 LCP를 시간별 색상 구분(속도)는 다음과 같다.
FCP 시간 | 색상 구분 |
0 ~ 2.5 | 녹색(빠름) |
2.5 ~ 4 | 주황색(중간) |
4 초과 | 빨간색(느림) |
⚽ LCP 최적화 하는 방법
LCP는 가장 오래걸리는 리소스에 대한 최적화가 필요로 하다. FCP랑 어느정도 겹치는 부분이 존재할 수는 있지만 최적화 해야하는 대상이 다르다. FCP는 가장 빠르게 렌더링 될 요소에, LCP 가장 렌더링 시간이 오래걸리는 요소를 최적화 대상으로 삼는다.
1️⃣ 리소스 로드 지연 제거.
- LCP 리소스가 뷰포트영역 밖에 존재하고 대상이 이미지라면 "loading=lazy"로 설정하는 것이 좋다.
- LCP 리소스가 뷰포트영역에 포함되고 대상이 이미지라면 fetchpriority="high"로 설정하여 우선순위를 높게 설정하는 것이 좋다. 가장 오래 걸리는 요소이기 때문에 페이지 로드와 동시에 리소스 로드를 준비해서 완료 시간을 줄이는 방법이다.
2️⃣ 요소 렌더링 지연 제거
CSS 및 자바스크립트를 로드하는 동안 요소의 렌더링을 블로킹하게 된다. 아래와 같이 CSS 및 자바스크립트 파일에 대한 최적화를 통해 로드 시간을 줄여야 한다.
- 사용하지 않는 CSS / 자바스크립트 삭제
- 중요하지 않은 CSS / 자바스크립트 지연
- CSS / 자바스크립트 축소 및 압축
3️⃣ 서버 응답 시간 개선
네트워크를 통해 리소스를 전송받는 경우 걸리는 시간을 줄이는 것이 좋다. 다음과 같은 최적화 방법을 사용할 수 있다.
- 리소스 압축
- 리소스가 이동할 거리 단축. CDN을 사용한다면 타겟 사용자와 가까운 거리의 CDN 서버 사용.
- 캐싱활용