[최적화] 핵심적인 웹 지표(LCP,FID,CLS) 개선하기

hsecode·2022년 3월 31일
46

최적화

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

📚 핵심적인 웹 지표 최적화하기

검색엔진최적화 포스팅을 통해 핵심적인 웹 지표를 최적화하면 웹 성능을 개선할 수 있다는 것을 알았다. 성능 최적화에는 여러가지 방법이 있고, 분류 또한 여러가지이다.

??? : LCP, FID, CLS 에 대해서도 정리해주신다고 했잖아요!


그랬지요..!(기다렸습니다. 누추한 곳에 귀한 손님.)
그리하여 웹 성능 최적화 포스팅의 연장. LCPCLS를 중심으로 마크업개발자가 웹성능 향상에 적극적으로 도움을 줄 수 있는 방법을 알아보자. 웹 성능 최적화 V2 ⚡️: 핵심적인 웹 지표 개선하기.

✏️ 핵심적인 웹 지표(LCP,FID,CLS)란 ?

핵심적인 웹 지표(Core web vitals)란 실제 사용 데이터에 따른 페이지의 성능을 보여주는 지표이다. LCP, FID, CLS 세 가지 항목으로 구성되어있다.

이전 포스팅에도 작성 되어있는 내용이지만 다시 한번 읽어보자.

📎 LCP (Largest Contentful Paint)

사용자가 URL을 요청한 시점부터 페이지 내에서 시각적으로 가장 큰 콘텐츠를 그리는데에 걸리는 시간이다.
사용자는 콘텐츠가 보여지면서 URL이 실제로 로드되고 있구나를 알기때문에 빨리 그려지는 것이 중요하다.
좋음: 2.5초 이하
개선필요: 4초 이하
느림: 4초 초과

📎 CLS (Cumulative Layout Shift)

누적 레이아웃 변경. 페이지가 덜컥거리면서 로딩됨에 따라 측정되는 점수이다. 사용자는 원하는 곳에 빠르게 접근할 수 없다.
좋음: 0.1 이하
개선필요: 0.25 이하
느림: 0.25 초과

📎 FID (First Input Delay)

웹 페이지가 사용자의 동작(링크 클릭, 버튼 탭 등)에 반응할 때까지 걸리는 시간이다.
좋음: 100밀리초 이하
개선필요: 300밀리초 이하
느림: 300밀리초 초과

📚 핵심적인 웹 지표 개선 방법

⚡️ LCP (Largest Contentful Paint)

페이지에서 가장 큰 콘텐츠를 2.5초 이내로! 빨리! 보여주려면 어떻게 해야할까?
그 방법은 바로.. 이미지 최적화 기법을 사용해서 이미지가 빨리 출력되게 하는 것이다!

안타깝지만 당연하게도.. 그렇게 간단할리 없다. 세상 쉬운일 없다.
LCP를 최적화하기 위해선 웹성능 최적화 기술 중 많은 방법들이 집약적으로 사용되어야한다. 단순히 이미지만의 문제가 아니기때문에 이미지 최적화 방법을 사용한다는 답은 맞는 말이지만 충분한 답은 아니다.

📎 측정도구

먼저 LCP 수치는 Lighthouse를 통해 확인할 수 있다. 하단 이미지의 경우 4초로 개선필요 항목이 되겠다.

LCP가 저하되는 원인은 보통 느린 렌더링과 로딩시간이다. 따라서 렌더링과 로딩 속도를 개선하면 LCP도 자연스럽게 성능이 향상될 수 있다.

📎 렌더차단 리소스 제거

✔️ 사용하지 않는 css 제거

css는 렌더링 차단 리소스이기 때문에 사용하지 않는 css는 제거하는 것이 좋다. 이를테면 이미 사용되지 않는 스타일이 잔뜩 쌓여있는 common.css나 불필요한 스타일 리셋까지 포함된 reset.css 등.
사용하지 않는 스타일은 그때그때 정리하는 것이 좋고, 불필요한 리셋은 줄이고 해당 프로젝트에 맞는 공통 스타일을 작성하는 것이 좋다.

✔️ 간결한 스타일 작성

셀렉터는 간결하게 사용한다. 복잡하게 스타일을 작성하면 특이성이 높아져서 비슷한 UI여도 계속해서 새로 스타일을 작성하게되고, 이는 유지보수도 어렵게 만든다. css가 복잡하고 방대할수록 레이아웃을 그리는 데에 시간이 많이 소요된다. 특이성은 최대한 낮게 유지하도록 노력하는 것이 좋다.

✔️ css/js 파일 최소화

웹팩 등 모듈 번들러나 빌드 도구를 사용해 css와 js 파일을 번들링해서(하나의 파일들로 묶어서) 리소스 요청을 줄일 수 있다. 불필요한 공백이나 주석 삭제, 코드를 최소화한다.

✔️ 라이브러리 의존도 줄이기

간단한 작업은 jquery를 사용하기보다는 스크립트로 작성하는 것이 좋다.

<head>
	<link rel="preload" href="stylesheet.css" as="style" onload="this.rel='stylesheet'">
</head>

✔️ 지연 로드 Preload

바로 필요하지 않은 image,css,js의 경우 rel="preload"를 사용해 렌더링과 병렬로 다운받고, 다운로드가 완료되면 웹페이지에 적용한다. onload 속성과 as 속성을 함께 작성한다.

✔️ 미리 연결 Preconnect

rel="preconnect"는 현재 페이지에서 외부 도메인 리소스를 참고하는 것을 브라우저에게 알려 DNS, TCP, TLS 왕복에 필요한 시간을 단축한다. 서드파티 자원을 연결할때 활용하면 좋다.

<head>
	<link rel="preconnect" href="https://www.mamamomo.com">
</head>

✔️ 미리 가져오기 Prefetch

앞으로 사용될 것이라고 예상되는 리소스를 미리 가져온다. 브라우저는 rel="prefetch"가 적용된 리소스들을 가져와 캐시에 저장한다.
예를들어 게시판 리스트 검색 시 사용자가 다음에 클릭할 부분은 첫 번째 게시글 또는 검색 리스트 2페이지일 확률이 높다. 이러한 경우 첫 번째 게시글의 상세페이지 또는 2페이지를 prefetch 적용할 수 있다.

<head>
	<link rel="prefetch" href="listpage_2.html">
</head>

📎 이미지 최적화

✔️ picture 태그 사용하기

picture 태그의 type 속성을 통해 사용자 환경에 맞는 타입의 이미지를 제공할 수 있다. 또한 media 속성을 사용해서 브라우저 사이즈에 맞는 이미지를 제공할 수 있다.

<picture>
    <source srcset="mob.avif" type="image/avif" media="(max-width: 760px)">
    <source srcset="pc.avif" type="image/avif">
    <source srcset="mob.webp" type="image/webp" media="(max-width: 760px)">
    <source srcset="pc.webp" type="image/webp">
   	<img src="mob.jpg" alt>
</picture>

✔️ 이미지 지연로딩 활용하기

loading 속성을 사용해서 이미지를 브라우저 화면에 지연/병렬 로딩할 수 있다. 이미지를 지연로딩하게되면 뷰포트 밖에있는 이미지는 로딩되지 않는다.

<img src="item.jpg" loading="lazy" alt>

✔️ 스프라이트 이미지 사용하기

아이콘 등의 이미지를 하나의 이미지로 묶어서 처리하면 이미지 파일 개수 자체를 줄이므로 리소스 요청 개수를 줄일 수 있다.

⚡️ CLS (Cumulative Layout Shift)

메뉴를 누르려다 갑자기 뜬 배너때문에 광고를 클릭하게 된다면..?🙄 ..유쾌한 기분은 아닐것이다.
CLS는 첫 페인팅 이후 뷰포트 내 콘텐츠 위치 변화에 대한 수치이다. LCP가 성능에 대한 지표라면 CLS는 사용자 경험에 대한 지표가 될 수 있다.
점수 범위는 0~1이고, 수치가 높을수록 좋지 않다. 0.1 이내로 유지하는 것이 좋다.

CLS는 보통

  • 크기가 정해지지 않은 이미지, 영상, 광고, iframe 등의 요소
  • 동적으로 추가된 콘텐츠 (기존 콘텐츠를 밀어서 떨어트릴 때)
  • FOIT/ FOUT 를 유발하는 웹폰트

등의 요소들이 발생시킨다. 간단히 말해 화면이 로딩될 때 콘텐츠들이 떨어지면서가 아닌, 제자리에서 로딩되도록 하면 CLS 수치를 개선할 수 있다.

📎 측정도구

LCP와 마찬가지로 구글 크롬의 Lighthouse를 통해 확인할 수 있다. 하단 이미지의 경우 0.062로 CLS 수치가 0.1 이내로 측정되었다.

📎 이미지,영상 요소에 비율 명시

✔️ 이미지와 비디오 요소에 width,height 값 적기

초기 웹에서는 페이지에 충분한 공간이 할당되었는지 확인하기위해 width와 hegiht값을 명시했지만 웹이 발전하고 반응형 웹이 등장하면서 css를 사용해서 이미지 사이즈를 조정하게 되었다.

하지만 CLS 수치 개선을 위해서는 width와 height 값을 명시해서 웹에 이미지 비율을 알려주는 것이 좋다. width와 height 값은 그대로 적용되지 않아도 되며, 비율을 알려주는 용도로 사용한다.

<img src="banner.jpg" width="800" height="500" alt>

width 또는 height 의 값 중 하나만 알아도 다른 하나의 값을 구할 수 있다.

예를들어 16:9의 종횡비를 사용할 경우

너비가 640px이라면 16:9 = 640:x => 높이는 640 x (9/16) =360px
높이가 360px이라면 16:9 = y:360 => 너비는 360 x (16/9) =640px 

계산이 귀찮다면 종횡비 계산기를 사용해도 된다.

✔️ 반응형 유튜브(영상)의 경우 padding 56.25% 활용

유튜브 등 영상을 반응형 웹에 구현할 때에는 padding 56.25% 를 사용해서 구현한다.

왜 56.25% 인가 하면,
16:9 = 100:56.25 이기 때문이다.

📎 동적 추가되는 콘텐츠의 경우

✔️ 스켈레톤 UI 제공

스켈레톤 UI는 실제 데이터가 로딩되기 전 화면의 윤곽을 미리 보여주는 로딩화면으로 흔히 사용되고 있다.

스켈레톤 UI를 통해 데이터가 나올 자리를 표시하면서 최소값을 미리 제공하면 데이터가 로드 되었을때 화면 전환이 부드러워질 뿐더러 콘텐츠가 순차적으로 나타남에따라 덜컥거리며 로딩되는 것을 방지할 수 있다.

✔️ 기존 콘텐츠 상단에 추가하는 것은 지양한다

사용자와 상호작용을 제외하고 콘텐츠를 기존 콘텐츠의 상단에 추가해서 레이아웃이 변경되는 것은 피하는 것이 좋다. 단, 사용자 입력 후 500ms 이내에 발생하는 레이아웃 이동은 CLS에 포함되지 않는다.

📎 애니메이션의 경우

✔️ transform을 사용한다

width, height를 조정하지않고 css transform 속성을 사용해 효과를 주는것이 성능에도 이득이고 사용자 경험에도 좋다.

📎 웹폰트의 경우

FOIT(font of invisible text: 브라우저가 웹폰트를 다운로드하기 전에 텍스트가 보이지 않는 현상)와 FOUT(font of unstyled text: 웹폰트가 뒤늦게 로딩되면서 시스템 폰트가 갑자기 웹폰트로 바뀌는 현상)를 줄이는 것이 핵심이다.

✔️ 웹폰트 최적화

웹폰트 최적화에 대해서는 잘 정리되어있는 포스팅의 링크로 대체한다.

✔️ 비슷한 폰트 사용하기

자간, 줄간격, 폰트 자체의 사이즈 등이 달라지면서 콘텐츠가 떨어질 수 있다. 폰트가 가진 외적 특성이 비슷한 대체 글꼴 사용하면 이러한 현상을 줄일 수 있다.

/* before */
font-family: 'font-example', sans-serif;

/* after */
font-family: 'font-example', font-example 폰트를 대체할 폰트, sans-serif;

⚡️ FID (First Input Delay)

사용자와 첫번째 상호작용에 걸리는 시간을 측정하는 FID는 보통 JS와 관련이 깊다.
정리되지 않은 스크립트, 무거운 스크립트 등의 요소가 시간을 지연시킨다. 100ms 이내로 걸리는 것이 좋다.

FID 수치를 개선하기 위해서는

  • CSS/ JS 코드 최적화가 필수적이고,
  • 긴 JS는 세분화하여 작업하는 것이 좋다.

👏🏻 마무리


🐱 : 이번에는 마크업개발자가 직접, 빠르고, 쉽게 적용할 수 있는 웹성능 최적화 기법을 LCP, CLS 중심으로 정리해보았다. 개발자가 속해있는 환경은 개발자마다 다 다르다. 모든 경우의 수에 대비하고, 알고있는 모든 지식을 실제 서비스에 적용해보려는 시도조차 현실적으로 어려울 수 있다. 유의미한 결과를 만들어 내는 일은 더 어렵다.(나만 그럴시 눈물 한 방울 흘림)
그래도, 그럼에도 하나씩 맞춰가다보면 만족할만한 결과를 생각보다 빨리 얻을지도 모른다.

🗂 참조한 문서

profile
Markup Developer 💫
post-custom-banner

3개의 댓글

comment-user-thumbnail
2022년 3월 31일

오오!! 기다렸던 포스팅 감사합니다.
알고 계시는 지식들을 이렇게 방출해 주셔서 감사할 따름입니다. 늘 포스팅을 보며 복습 공부하고 있습니다.
무의미한 일이 아닌 유의미한 일을 만들고 있는 개발자님께 물개 박수 드립니다!

다음 포스팅도 기대하겠습니다!

1개의 답글
comment-user-thumbnail
2022년 6월 21일

포스팅 감사합니다 굿굿

답글 달기