안녕하세요
오늘은 웹사이트 성능을 올리기 위한 몇 가지 방법을 소개해드리겠습니다.
Lazy loading
화면에 보이는 이미지들만 다운로드하고 화면 밖에 있는 이미지들은 다운로드를 지연시킵니다.
스크롤을 감지하여 이미지들이 화면 안으로 들어오면 그때 다운로드합니다.
<img /> 태그에 loading="lazy" 속성을 주거나, 이전 글에서 소개해드린 Intersection Observer API를 사용하시면 구현하실 수 있습니다.
Sprite sheet
스프라이트 시트는 여러 개의 이미지들을 하나의 시트에 모은 것을 의미합니다.
하나씩 이미지를 다운로드하는 것보다 HTTP 요청 수가 줄기 때문에 메모리와 네트워크 사용량 측면에서 효율적입니다.
css의 background, background-position 속성으로 지정할 수 있습니다.
CDN
CDN (Content Delivery Network)란 지리적 제약 없이 콘텐츠를 전송하는 기술입니다.
서버를 하나만 두는 것이 아닌 각 지역에 분산합니다.
사용자가 요청을 하면 가장 가까운 서버와 연결하여 콘텐츠를 다운로드하는 시간을 최소화합니다.
script
스크립트 태그를 body 최하단에 위치시키거나 head에 추가합니다.
body 하단에 두면 html 파일의 사이즈가 커질수록 스크립트 다운받는 시점이 지연됩니다. 따라서 head에 넣기도 합니다.
head에 넣는 경우 defer, async 속성을 추가해야 합니다.
defer와 async 모두 스크립트를 다운로드하며 html을 파싱을 진행합니다.
자세한 내용은 이 글에 정리하였습니다.
이외에도 스크립트 관련 몇 가지 최적화 방법이 있습니다.
* 스크립트 파일을 gzip 등으로 압축시켜 파일 크기를 축소합니다.
* 불필요한 선언, 공백을 전부 제거하여 파일 크기를 축소합니다. (Minify)
* 스크립트를 병합하여 요청 횟수를 줄입니다.
CSS
CSSOM이 있어야 렌더 트리가 구상되기 때문에 CSS는 head안에 있어야 합니다.
외부 스타일시트를 가져올 때 @import보다 <link> 태그를 사용하는 게 좋습니다.
@import는 스타일시트를 병렬로 다운로드할 수 없기 때문에 로드 시간이 늘어납니다.
특정 조건에서만 필요한 CSS는 미디어 쿼리를 사용하여 불필요한 블로킹을 방지합니다.
브라우저는 렌더링 차단 여부와는 관계없이 모든 CSS 리소스는 다운로드합니다.
"렌더링 차단"은 해당 리소스가 초기 렌더링을 보류해야 하는지 여부만 나타냅니다.
<link href="style.css" rel="stylesheet" />
<link href="style.css" rel="stylesheet" media="all" />
<link href="portrait.css" rel="stylesheet" media="orientation:portrait" />
<link href="print.css" rel="stylesheet" media="print" />
미디어 속성은 이곳에서 확인 가능합니다.
* media="all" -> 기본값, 모든 미디어 타입의 장치
* media="orientation" -> 디스플레이 방향을 명시 (portrait는 세로 방향, landscape는 가로 방향)
* media="print" -> 인쇄 미리 보기 기능 또는 페이지 출력
Optimizing for CRP
브라우저가 렌더링 되는 가정을 이해하시면 최적화하는데 도움이 됩니다.
스크립트 혹은 CSS로 UI를 변경할 때를 가정해봅시다.
레이아웃 속성을 변경하면 너비, 높이와 같은 모든 요소를 확인하고 페이지를 리플로우 해야 합니다.
배경 이미지, 텍스트 색상, 그림자 같은 레이아웃에 영향을 주지 않는 페인트 속성을 변경하면 레이아웃 과정을 생략합니다.
합성(composite) 속성을 사용하여 레이아웃과 페인트 단계를 하지 않습니다. 이는 애니메이션이나 스크롤링과 같은 이벤트에 효과적입니다. 합성 속성은 opacity, transform 속성이 있습니다.
csstriggers 사이트에서 각 속성들을 확인하실 수 있습니다.
접속하시면 이러한 웹 브라우저 오픈 소스 응용 프로그램 프레임워크가 있습니다.
아래는 각 대표적인 브라우저들입니다.
Blink -> 구글 크롬 v28+, 오페라, 웨일, 삼성 인터넷
Gecko -> 모질라 파이어폭스
Webkit -> 사파리, 구글 안드로이드
EdgeHTML -> 엣지
이외에도 브라우저는 Element.offsetTop 값을 읽기만 해도 최신 값을 가져와 반환하기 위해 레이아웃을 다시 해야 합니다. 이때는 값을 캐싱하는 방법이 좋습니다.
캐싱
브라우저에 파일을 캐싱하여 다운로드할 파일의 개수를 줄입니다.
result 값이 항상 동일한 api통신 또한 캐싱 처리를 하여 요청 수를 줄일 수 있습니다.
로드 UI
로딩 애니메이션이나 스켈레톤 UI를 활용합니다.
똑같은 로드 시간이 걸리더라도 위 사항들을 활용하면 사용자 경험 측면에서 좋아집니다.
(엘리베이터를 기다리는 시간을 줄이는 것도 좋지만, 기다리는 시간을 지루하지 않게 하는 것도 중요하다는 말이 생각나네요)
* 스켈레톤 UI란
실제 데이터가 화면에 로드되기 전 사용자에게 로드 중임을 나타내는 UI입니다.
이외에도 다양한 방법들이 있습니다.
* 불필요한 서버통신이 일어나고 있지 않은지 확인합니다.
* 리소스 용량 줄이기
* react의 경우 useMemo, useCallbak, memo를 활용한다.
감사합니다.
참고 :
https://bearjin90.tistory.com/21
https://ui.toast.com/fe-guide/ko_PERFORMANCE
https://web.dev/rendering-performance/
https://www.youtube.com/watch?v=G1IWq2blu8c
https://www.stevy.dev/frontend-web-performance-guide-1/
'Front-end > 깊게 파고들기' 카테고리의 다른 글
Javascript Event Loop 이벤트 루프 정리 (2) | 2022.04.16 |
---|---|
React Hook에서 클로저는 어디서 쓰일까? (0) | 2022.04.16 |
javascript . 어떻게 무한 스크롤을 구현하시나요? (0) | 2022.04.10 |
<script>는 정말 body 뒤에 들어가야 하는가 (0) | 2022.04.06 |
Javascript 클로저(Closure) 정리 (0) | 2022.04.05 |