[Web] 웹사이트 성능 최적화 방법
웹사이트 성능 최적화 방법
웹사이트 성능 최적화란?
사용자가 웹사이트를 빠르고 효율적으로 이용할 수 있도록 사이트의 로딩 속도를 향상시키고, 자원 사용을 최소화하는 작업을 의미함
웹사이트 성능 최적화를 진행하면 사이트에 대한 UX(사용자 경험)을 개선하고 SEO에도 영향을 줌
실제로 구글에서 했던 유저 이탈률에 관한 조사를 보면 로딩 시간이 3초 이상이면 웹 서비스의 33퍼센트나 이탈률이 증가함
이런 서비스적 관점까지 고려해 웹 사이트 성능 최적화를 고려해야함
Google의 Core Web Vital
그러면 웹사이트의 성능을 어떻게 측정할 수 있을까?
이에 관한 측정 지표로 구글의 core web vitals를 사용함
- LCP(최초 콘텐츠 렌더링 시간, Largest Contentful Paint)
- LCP는 사용자에게 가장 큰 콘텐츠를 보여주는 데 걸리는 시간을 뜻함
- 자세하게 말하자면 사용자가 URL을 요청한 시점부터 가장 큰 시각 콘텐츠 요소(ex: 이미지, 비디오, 큰 블록 수준의 텍스트 등)를 렌더링하는 데 걸린 시간을 말함
- 이 측정항목은 방문자가 URL이 실제로 로드되는 것을 확인하는 속도를 표시하므로 중요함
- 페이지가 로드되기 시작한 지 첫 2.5초 안에 LCP가 발생해야 이상적임
- CLS(레이아웃 변경 횟수, Cumulative Layout Shift)
- 웹페이지의 시각적 안정성을 측정함
- 사용자가 페이지에 방문한 후 상주한 시간을 모두 측정하고, 해당 시간 동안 페이지 내부에서 발생하는 레이아웃 및 개별적인 레이아웃 요소들의 변화가 몇 번이나 변경되었는지 측정함
- 숫자가 클수록 레이아웃이 많이 변경되었음을 나타냄
- 팝업과 같이 가독성을 해치는 요소가 얼마나 자주 표시되는지 측정하기 위해서 해당 항목이 있고, 팝업 등이 많은 뉴스 사이트의 경우 CLS값이 높게 평가됨
- CLS 점수가 0.1 미만이 되어야 좋은 사용자 환경을 제공한다고 할 수 있음
FID(첫 입력 지연, First Input Delay)-> INP(페인트에 대한 상호작용, interaction to next paint)
- 사용자가 렌더링이 모두 끝난 웹에서 사용자가 웹 페이지와 처음 상호작용했을 때부터(어떤 요소를 클릭하거나 링크를 클릭하는 등) 브라우저가 상호작용에 반응할 때까지의 시간을 말함
- ex: 네이버에 접근 -> 로그인 버튼 누름 -> 로그인 페이지가 모두 로딩될 때까지 경과하는 시간 측정
- 사용자와 상호작용이 많이 일어나는 페이지에서 중요함
- FID가 100ms 미만이 되어야 이상적임
그런데!!! 구글에서 2023년 5월 10일 업데이트 한 내용에 따르면 2024년 3월부터 FID가 INP로 대체 된다고 함
이유 : 처음 로드될 때의 시간보다 페이지가 로드된 후 사용자들의 이용 시간 중 90%가 사용됨. 따라서 사용자가 웹과 상호작용을 시작한 시점부터 다음 프레임이 그려질 떄까지의 시간을 최대한 짧게 하는 것이 중요해짐. 참고
FID는 사용자가 페이지와 처음 상호작용할 때의 시간만 측정함. 하지만 처음 상호작용한 시간만 가지고는 페이지 전체의 모든 상호작용하는 시간을 대표할 수 없음.
따라서 모든 상호작용을 고려해 페이지 전체에서 가장 느린 상호작용과, 상호작용 시점부터 이벤트 핸들러를 거쳐 브라우저가 다음 프레임을 그릴 수 있을 때까지의 전체 시간을 측정하는 INP로 대체되게 되었음
INP(페인트에 대한 상호작용, interaction to next paint)
INP는 사용자가 페이지를 방문하는 동안 발생하는 모든 클릭, 탭, 키보드 등의 상호작용의 지연 시간(가장 느린 인터렉션 시간 및 가장 빠른 인터렉션 시간 제외 나머지의 평균)을 관찰해 사용자자와 웹의 상호작용에 대한 페이지의 전반적인 응답성을 평가하는 항목임.
- INP가 200ms 미만 : 페이지 응답성이 좋음
- INP가 200ms 초과 ~ 500ms 미만 또는 500ms : 페이지 응답성이 개선되어야 함
- INP가 500ms 초과 : 페이지 응답성이 좋지 않음
측정 지표를 토대로 웹 사이트 성능 개선하기
- LCP
1) LCP 리소스가 HTML에서 빨리 찾아져야 함
ex: background-image를 css에 넣으면 css가 로드될 때까지 브라우저는 LCP 리소스(ex: 이미지 등)를 모르게 됨 -> HTML의 img 태그 등으로 추가해서 빨리 LCP 리소스가 로드될 수 있게 하기2) (돈이 많이 들지만 확실하게 개선되는 방법) CDN 사용요소에 src나 srcset 속성을 사용해 HTML만 다운로드 받아도 HTML에 있는 이미지가 사이트의 첫 번째 화면 렌더링에 필요하다는 것을 알 수 있게됨
- SSR을 사용해서 CSR에서의 작업을 최소화하기
브라우저에서 바로 화면을 그릴 수 있게 서버사이드에서 HTML 작업해서 보내면 LCP에 도움이 됨
- 위의 것들을 하기 위해 실제로 할 수 있는 것들
- 2) HTML에서 LCP 리소스를 찾았으면 우선해서 다운로드할 수 있도록 하기
- 외부 리소스를 참조해서 사용하는 경우인데, 만약 이 외부 리소스를 사용해서 그려야하는 영역이 LCP라면 HTML
부분에 <Link rel="preload">
와 같이 rel=preload라는 속성을 지정해서 빨리 리소스를 다운로드 받으라고 알려줄 수 있음 - LCP 이미지로 사용될
태그에 fetchpriority='high' 속성을 추가해 브라우저가 우선적으로 다운로드할 수 있게 함
- 사용자에게 바로 보여야할 이미지가 아닌 경우(ex: 스크롤해야 보이는 아래쪽에 위치한 이미지들)에
속성을 추가해 브라우저가 당장 다운로드해야할 리소스가 줄어들어 LCP에 도움이 됨
- CLS
- 로드될 컨텐츠의 크기를 명확하게 정해주기
width, height 같은 속성을 이용해서 할 수 있음
반응형 같은 경우에는 정확한 이미지 높이를 알기 어려우니까 aspect-ratio라는 속성을 이용해 비율로 이미지 높이를 설정해주면 좋음
컨텐츠가 너무 동적이어서 높이를 잘 모르겠다 싶으면(ex: 텍스트 길이에 따라서 달라지는 배너 등) min-height라도 정해줘서 조금은 영역이 밀리더라도 최소한의 높이라도 브라우저가 알 수 있게해서 준비할 수 있게하기
배너나 광고 등의 동적인 요소의 자리를 레이아웃 시프트를 사용하기 보다는 height, width 등의 속성(이와 비슷한 속성도 ㄱㅊ)을 미리 정해주면 CLS를 향상시킬 수 있음 -> 물론 미리 영역을 확보해둔 자리는 로딩이 되기 전까지 하얗게 됨 -> 하지만 이미 영역이 확보되어있기 때문에 광고나 배너로 인해 컨텐츠가 밀리지 않아 사용자가 잘못 클릭하거나 인터렉션을 할 확률이 줄어듦
- 처음 화면이 렌더링될 때 animation, transition 등의 레이아웃을 건드는 css는 지양하기
- bfcache가 되는지 확인하기
뒤로가기나 앞으로 가기를 할 때 브라우저들이 페이지들의 정보를 캐싱해놓음 -> 네트워크 요청 다시 x
기본적으로 브라우저에서 bfcache가 되지만 가끔가다가 막아놓는 곳도 있으니 체크하기
- FID
- 오래 걸리는 작업을 여러 개로 나누기(왜냐하면 자바스크립트엔진은 싱글스레드인데 오래 실행되는 작업이 있다면 사용자 입력을 처리하는데 지연이 생길 수 있기 때문에)
- code splitting을 통해 통째로 파일을 받아오는 것이 아니라 필요한 부분만 다운로드 받을 수 있게 함
- 불필요한 자바스크립트 없애기
그런데 무엇이 필요한 건지 아닌지 알기 어려워서 지속적으로 관찰하면서 관리해야함
(데브툴에서 볼 수 있긴한데 사용자가 사이트를 사용할 수록 많아질수록 달라짐) - DOM 사이즈를 작게 유지하기
- 트래킹들을 위한 분석툴을 많이 사용할수록 느려짐 -> 지속적으로 관찰해서 더이상 사용하지 않는 분석툴에서 제공하는 태그들을 지우기
참고