사용자를 생각한 한 걸음, LCP

55555-Jyeon·2024년 8월 18일
1

Deep Dive

목록 보기
7/8
post-thumbnail
post-custom-banner

이전 게시글 <React, 성능 최적화(feat. DevTools)>에서 성능 최적화에 대해 간략하게 포트폴리오의 lighthouse 점수를 올리며 다뤄본 적이 있습니다.

해당 게시글에서는 프로젝트를 진행하면서 가장 이미지가 많아 최적화가 시급했던 LCP에 대해서 자세히 다뤄보려고 합니다.


✓ 본격적인 내용 시작 전 간단히 짚고 넘어가기

🤷🏻‍♀️ 왜 최적화를 해야 하는가

프로젝트를 해봤다면 '최적화를 처음부터 신경써야지'하고 초반에 마음을 먹었더라도 금방 뒷전으로 밀리게 되는 경험을 해본 적이 있을 겁니다.

버그나 에러를 해결하고 쌓인 일을 처리하다보면 자연스레 뒷전으로 밀려버리게 되기도 하고 성능 개선 자체도 한두 개를 고친다고 해결되는 문제가 아니기도 합니다.
또한 사용하고 있는 기기가 일반적인 사용자들에 비해 좋아 성능 이슈를 체감하지 못하는 경우가 있을 수도 있습니다.


하지만 사용자는 웹 페이지를 방문했을 때 빠르게 정보를 볼 수 있기를 기대합니다.
그리고 해당 웹 페이지를 방문한 목적을 달성하는데 문제가 없어야 하며 보안이 철저해 개인정보 유출과 같은 사고가 발생하지 않아야 합니다.


이렇게 개발자와 사용자가 서로 중요하게 생각하는 부분이 다를 수 있습니다.
사용자는 최신 기술로 만들어진 웹사이트인지 오래된 기술로 만들어진 웹사이트인지보다 사용하는데 불편함을 초래하는지가 더 중요하게 느껴질 것입니다.

예를 들면 리액트나 넥스트와 같은 최신 프레임워크 기반의 초기 렌더링 시간이 약 6초 정도 걸리는 웹 사이트보단 LAMP 스택 기반의 초기 렌더링 시간이 1초인 웹 사이트가 더 이용하기 편하게 느껴질 것이라는 겁니다.

특히 국내 사용자들은 외국에 비해 더욱 속도에 민감할 것이라 생각됩니다.


🩺 핵심 웹 지표

Core Web Vital, 핵심 웹 지표는 구글에서 만든 것으로 웹 사이트에서 뛰어난 사용자 경험을 제공하는 데 필수적인 지표를 말합니다.


LCP

그 중에서도 이번에 자세히 알아볼 내용은 Largest Contentful Paint(LCP)로 FID, CLS와 함께 세 가지 핵심 웹 지표로 꼽히는 항목입니다.

LCP는 페이지가 처음으로 로드(load)되는 시점부터 뷰 포트(view port) 내부에서 가장 큰 컨텐츠를 렌더링하는데 걸리는 시간을 뜻합니다.


뷰 포트 내부에서 가장 큰 컨텐트란 아래와 같은 항목들로 정의되어 있습니다.
아래 5가지 항목들을 기준으로 측정되며 뷰 포트를 넘어가는 요소는 고려되지 않는다는 특징이 있습니다.

<img /><svg /> 내부의 <img /><video poster="" />
	poster 속성을 가진 video 태그

④ url()을 통해 불러온 배경 이미지가 있는 요소

⑤ <p>, <div />와 같이 inline text 요소를 포함하고 있는 block-level 요소


👩🏻‍💻 LCP 점수 올리기

1️⃣ 웬만하면 텍스트로

좋은 점수를 얻기 위한 가장 확실하고 간단한 방법은 뷰 포트 영역에 이미지가 아닌 문자열을 넣는 것입니다.

최적화가 된 이미지보단 아무래도 추가적인 리소스가 필요없는 텍스트가 더 빠르게 노출되기 때문입니다.
따라서 텍스트로 대체가 가능한 부분은 웬만하면 전부 텍스트를 사용하는 것이 좋습니다.


2️⃣ 이미지 최적화하기

이미지가 텍스트보다 직관적이고 강한 인상을 주기 때문에 첫 렌딩 페이지에 이미지가 없긴 힘들 겁니다. 따라서 전부 텍스트로 대체하기는 어렵겠죠.

그럼 이미지는 어떻게 처리하면 좋을까요?


🟢 DO

🔖 img와 picture 태그 사용하기

이미지는 브라우저의 preload scanner에 의해 먼저 발견되어 빠르게 요청이 일어납니다. 따라서 이미지 태그 내부의 리소스는 HTML 파싱이 미처 완료되지 않았더라도 스캐너가 병렬적으로 리소스를 다운로드하기 때문에 LCP 요소를 불러오는 좋은 방법 중 하나입니다.


🧐 preload scanner ?

preload scanner란 HTML을 파싱하는 단계를 멈추지 않고
빠르게 미리 로딩하면 좋을 리소스를 찾아 함께 로딩하는 브라우저의 기능입니다.


🎥 video 태그 사용 시 poster 넣어주기

포스터는 사용자가 비디오 태그 요소를 재생 및 탐색하기 전에 보이게 되는 비디오 태그의 속성으로 적용 시 썸네일 이미지와 같은 역할을 합니다.
포스터는 이미지 태그와 마찬가지로 preload scanner에 의해 미리 로드되기 때문에 사용하는 것이 좋습니다.



🔴 DON'T

🤙🏻 svg는 꼭 필요한 곳에만

svg는 preload scanner에 의해 HTML을 파싱하는 단계에서 함께 로딩되지 않습니다.
따라서 LCP 점수를 깎기 때문에 꼭 사용해야 하는 경우가 아니라면 지양하는 것이 좋습니다.


🙂‍↔️ url로 불러오는 이미지 지양하기

background-image와 같이 url을 통해 이미지를 가져오는 경우도 LCP 점수를 깎는 요소 중 하나입니다.
CSS에 있는 리소스는 브라우저가 해당 리소스를 필요로 하는 DOM을 그릴 준비가 될 때까지 요청을 미루기 때문에 오래 걸립니다. 따라서 중요한 리소스에는 url을 통해 이미지를 가져오는 것은 지양하는 것이 좋습니다.



🟡 Cautions

① lazy loading 지양

lazy loading은 리소스를 "중요하지 않음"으로 표시하고 필요할 때만 로드하는 전략입니다.
lazy loading을 사용할 경우 로딩 속도를 늦추는 것이기 때문에 LCP 점수에는 영향이 없습니다.

다른 곳에 사용하는 것에는 큰 문제가 없지만 LCP에 적용이 될 뷰 포트 안의 이밎에 적용하는 것은 큰 의미가 없다는 것을 알아두면 좋을 것 같습니다.

🔗 모아서 해? 나눠서 해?


② CSR보다는 SSR로

서버(server)에서 빌드(build)를 해서 가져온 HTML을 스캐너가 바로 읽어 LCP가 진행되는 것이 사용자가 가장 빠르게 화면을 볼 수 있는 방법입니다.

LCP가 클라이언트(client)에서 빌드될 경우 LCP는 HTML을 다운로드한 직후가 아닌 리액트 코드가 파싱된 다음에 진행되게 되기 때문에 늦어지게 됩니다.

따라서 사용자가 될 첫 뷰 포트는 서버에서 빌드할 수 있도록 하는 것이 좋습니다.


③ 중요한 리소스는 직접 호스팅으로

Cloudinary와 같이 이미지를 최적화해주는 서비스를 이용하게 도면 이미지의 크기를 줄여주고 포맷도 변환이 가능합니다. 또한 압축해서 이미지를 관리할 수도 있습니다.

하지만 다른 출처(origin)에서 정제한 이미지를 가져오는 것은 최적화에 도움이 되지 않습니다. 다른 출처는 네트워크 연결부터 다시 수행해야 하기 때문에 그만큼 시간이 더 소요되기 때문입니다.

lazy loading과 마찬가지로 다른 출처에서 이미지를 정제하는 것은 중요한 리소스가 아닌 이미지에 적용하는 것이 좋습니다.





References.

[📚 Books]

  • 모던 리액트 DeepDive

[👩🏻‍💻 Blogs]

[🎥 Videos]

profile
🥞 Stack of Thoughts
post-custom-banner

0개의 댓글