개인 노트 정리) 마크업17 - 덩어리 콘텐츠 빨리 그리기

2023. 10. 4. 18:54개인노트-인강

The RED 견고한 UI 설계를 위한 마크업
Part 3. Performance
02. 덩어리 콘텐츠 빨리 그리기

 

# 덩어리 콘텐츠 빨리 그리기

- LCP(Largest Contentful Paint)는 구글의 성능지표에 포함되는 한 가지 항목이다.

- LCP를 좋아지게 하기 위해서는 우리들이 알고있는 성능에 관한 모든 지식을 총 동원해서 이 부분에 집약해서 적용해야만, LCP의 문제를 해결할 수 있습니다.

- 구글은 핵심 성능 지표에 해당하는 LCP를 구글 검색 결과 순위에 반영하겠다고 발표했다.

- 우리의 목표는 LCP 점수를 2.5초 이내로 단축시키는 것이다. 가장 큰 덩어리 콘텐츠를 2.5초 이내로 로딩시켜야만 사용자에게 좋은 사용자 경험을 줄 수 있다.

## Core Web Vitals

- 핵심 성능 지표를 측정하는 많은 다양한 도구들이 있다. 그 중에서 lighthouse를 추천한다.

TBT는 FID와 거의 대동소이하다.

## LCP (가장 큰 덩어리 콘텐츠)

lighthouse를 통해서 LCP를 측정한 화면
LCP에 해당하는 엘리먼트를 확인할 수 있다.

- 대부분의 웹사이트에서 뷰포트 초기화면에 보이는 덩어리 콘텐츠는 이미지일 확률이 높다. 이 요소가 늦게 로딩되는 이유는 이미지가 무겁기 때문만은 아니다. 여러가지 원인 중 한가지일 뿐이다. 이 이미지를 그리기 전에 나타나는 모든 과정들의 성능을 개선해야만 LCP 성능을 개선할 수 있다.

- 이미지를 표시하기 전 발생하는 모든 성능 이슈가 LCP문제를 해결하는 열쇠이다.

## LCP 개선 사례 (LCP 3.6초 단축한 이야기)

### 라이브러리 의존 줄이기 (jquery, lodash, normalize...)

- jquery가 FCP를 상당히 지연시키고 있다. jquery를 제거할 수 있다면 제거하는 것을 추천한다.

- 사이트 추천 : https://youmightnotneed.com/ jquery나 lodash 대신 사용할 수 있는 바닐라 스크립트를 찾아볼 수 있다. 이 것을 사용해서 javascript 라이브러리를 제거하는데 도움을 받을 수 있다.

### Remove unused CSS

<head>
    <!-- <link rel="stylesheet" href="normalize.css"> -->
</head>

- normalize나 reset과 같이 잘 사용하지 않거나 필요하지 않은 stylesheet 들을 과감하게 버리자.

### Preconnect / Preload 기법

- 아래는 일반적으로 css코드를 참조하는 방법.

<head>
    <link rel="stylesheet" href="*.css"> <!-- css를 로딩하고 해석하는 동안 웹 페이지가 차단된다. -->
</head>

- 아래처럼 수정하자.

<head>
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link rel="preload" as="style" href="*.css" onload="this.onload=null;this.rel='stylesheet'">
</head>

- preconnect 란 값은 href에 적힌 url을 미리 연결하는 기능이다.

    - 미리 연결하여 준비하고 있다가 필요한 내용을 다운로드 받을 수 있게 도와준다.

- preload를 사용하면 css파일을 다운로드하면서 웹페이지 렌더링을 방해하지 않고, 웹 페이지를 렌더링하는 동시에 css 파일을 다운로드하게 되어 있다.

    - 그리고 onload script를 이용하여 css 다운로드가 끝나면 preload 값을 stylesheet로 바꿔서 stylesheet를 웹페이지에 적용하게 된다. 즉, 지양적용이다.

 

<정리>

<link rel="preconnect">

- 도메인을 알지만 자원의 최종 경로를 모르는 경우 서버와의 연결을 미리 설정.

- DNS(Domain Name Server), TCP(Transmission Control Protocol), TLS(Transfer Layer Security) 왕복에 필요한 시간을 단축.

- 서드 파티 자원 연결에 적합. preconnect를 구글 웹폰트를 참조하고 load 하는데 사용하고 있다.

 

<link rel="preload">

- 필요한 자원을 병렬 다운로드.

- 자원을 로딩하는 동안 렌더링을 차단하지 않음.

- as 속성을 함께 명시해 주어야 정상적으로 동작한다. 예) as="style", as="script", as="image".

- css 뿐만 아니라 이미지, 스크립트 등 다양한 파일들을 병행로딩할 수 있다.

### 히어로 이미지 preload

- 히어로 이미지를 미리 로딩하는 기법

- 원래 이미지는 html body 요소 안쪽에 마크업이 되어있지만, 첫번째 히어로 이미지를 빨리 로딩하기 위해서 html head에서 미리 로딩을 한다.

<head>
    <link 
        rel="preload" as="image" 
        media="(max-width:640px)" href="small.avif">
    <link 
        rel="preload" as="image" 
        media="(min-width:641px)" href="large.avif">
</head>

- 해상도가 640px 보다 같거나 작은 환경에서 "small.avif" 이미지를 미리 로딩한다.

- 해상도가 641px 과 같거나 크면 태블릿이나 데스크탑 해상도에서는 "large.avif" 이미지를 미리 다운로드 받는다.

### Feature detection

- Image type 이나 Viewport width 를 감지해서 성능을 개선하는 방법이다.

- 우리가 일반적으로 사용하는 방법은 아래와 같다.

<!-- UNOPTIMIZED HERO IMAGE (이미지최적화가 되어있지 않음)-->
<img src="large.jpg" alt>

- 이미지 회적화를 한다면 아래처럼 할 수 있다.

<!-- OPTIMIZED HERO IMAGE -->
<picture>
	<!-- AVIF && SMALL SCREEN -->
    <source srcset="small.avif" type="image/avif" media="(max-width:640px)">
	<!-- AVIF && LARGE SCREEN -->
    <source srcset="large.avif" type="image/avif">
	<!-- WEBP && SMALL SCREEN -->
    <source srcset="small.webp" type="image/webp" media="(max-width:640px)">
	<!-- WEBP && LARGE SCREEN -->
    <source srcset="large.webp" type="image/webp">
	<!-- FALLBACK -->
    <img src="small.jpg" alt>
</picture>

- type 과 media라는 조건 구문을 붙여야 한다.

- 조건 : avif 타입을 지원하면서 동시에 640px 이하이면 small.avif 이미지를 출력한다. -> 이 조건이 충족된다면 <img src="small.jpg" alt> 에 small.avif를 표시하게 된다. 실행하게 되면, 나머지 요소들은 다운로드하거나 화면에 표시하지 않게 된다.

### Image Loading / Decoding

- 앞으로는 loading과 decoding 속성을 명시하는 것을 추천한다.

<!-- 최적화되지 않은 이미지 사용법 (unoptimized image) -->
<img src="example.jpg" alt>
<!-- 최적화된 이미지 (optimized image) -->
<img 
    src="example.jpg" 
    loading="lazy"
    decoding="async"
alt>

- loading="lazy"을 사용하면 뷰포트안에 들어와있지 않으면 이미지를 loading 하지 않는다. 페이지가 로딩되고, 화면 아래쪽에 있는 이미지들은 로딩되지 않은 상태로 존재하다가 사용자가 scroll 하면서 페이지 문서가 뷰포트 안쪽으로 들어올때, 모니터 뷰 포트 높이의 1배에서 2배 크기 아래쪽 부터 이미지가 로딩되기 시작해서 그 때 화면에 표시할 준비를 한다. 이것을 lazy load 기법이라고 한다. javascript를 사용하지 않고도 이미지 지연 로딩을 할 수 있다.

- decoding="async" decoding은 암호화했던 이미지를 복호화하는 방법이다. 복호화 방법으로 async 라는 값을 사용하면 화면에 다른 요소를 렌더링 하는 것을 중단하지 않고 다른 요소를 먼저 표시하고 이미지를 뒤늦게(지연해서) 화면에 표시하게 해준다.

- 이 두가지 옵션을 사용하면 가능한 다른 요소들이 빠르게 화면에 표시되기 때문에 이미지 최적화에 매우 큰 도움이 된다.

- loading 과 decoding 이라는 속성은 img속성에만 사용한다. picture나 source 요소에는 loading 과 decoding 속성을 사용하지 않아도 된다.

## 정리

1. LCP는 뷰포트에 표시하는 가장 큰 콘텐츠 렌더링 성능.
2. 가장 큰 덩어리 콘텐츠를 2.5초 이내로 표시해야 한다.
3. JS/CSS 라이브러리 의존도를 낮추어야 한다.
4. preconnect/preload 속성으로 외부 자원 최적화.
5. photo 요소의 type, media 속성으로 이미지 전송량 최적화.
6. loading/decoding 속성으로 이미지 렌더링 최적화.