웹 성능 최적화
브라우저는 상단부터 차례대로 로드된다. HTML파일을 읽어온 후, 위에서부터 아래로 한 줄 씩 해석한다. 이 과정에서 css 파일이나 js 파일을 만나면 해당 파일을 해석하는 동안 웹 페이지 렌더링은 일시적으로 차단된다. 이러한 화면을 사용자가 보게 되면 페이지를 이탈하거나흰 화면의 대기 화면을 보게 되는것.. 좋은 성능의 웹을 만들기 위해서 웹 성능 최적화는 필수로 거쳐야 하는 과정이다.
성능 최적화 = 렌더링 최적화 + 로딩 최적화
렌더링 최적화
렌더링 차단 리소스란 브라우저 렌더링을 막는 소스들로 일반적으로 css, js를 말한다.
웹페이지 렌더링 최적화의 목표는 리플로우를 최대한 적게 발생시키면서, 빠르게 화면을 그리는 것
리플로우
브라우저의 스타일이 그려질 때, 레이아웃의 넓이, 높이, 위치 등에 영향을 주는 css 속성을 변경할 경우 Layout부터 다시 그려지게 되는데 이를 ‘리플로우’라고 한다.
리페인트
레이아웃에 영향을 주지않는 속성을 변경하면 레이아웃을 건너뛰고 페인트 작업부터 다시 수행하게 되는데 이를 ‘리페인트’라고 한다.
리플로우가 일어나면 브라우저가 전체 픽셀을 다시 계산해야하기 때문에 되도록 리페인트 속성을 사용해 스타일을 작성하는 것이 성능면에서 좋다.
리플로우(Reflow)를 발생시키는 속성
position / width / height / margin / padding / display / top / left / right / bottom / box-sizing / border-color / text-align / border / border-width / font-family / float / font-size / font-weight / line-height / vertical-align / white-space / word-wrap / text-overflow / text-shadow ...
리페인트(Repaint)를 발생시키는 속성
color / border-style / visibility / background / background-color / background-image / background-position / background-repeat / background-size / text-decoration / outline / outline-style / outline-color / outline-width / border-radius / box-shadow ...
리플로우와 리페인트를 발생시키지 않는 속성
opacity / transform / cursor / z-index ...
✔️사용하지 않는 css 제거
구글 크롬 라이트하우스(Lighthouse)구글 라이트하우스는 개발자도구 - Lighthouse 탭에서 확인할 수 있다.Performance와 Mobile에 체크한 후 Generate report 버튼을 클릭하면 해당 페이지의 성능이 측정된다.구글 라이트하우스(
Lighthouse
)는 2KB 이상 사용되지 않은 css가 있을 시 오류로 표기한다.그리고 스크롤을 조금 내려 목록을 보면 Remove unused CSS 항목을 확인할 수 있다. (위 이미지에서는 Remone 경고단계 이전인 Reduce unused CSS로 출력)Potential Savings 항목을 통해 잠재적으로 어느정도 절약 가능한지 보여준다.!https://velog.velcdn.com/images%2Fhsecode%2Fpost%2F3ff343c5-854a-4a04-a914-df3c17189a49%2Fimage.png
!https://velog.velcdn.com/images%2Fhsecode%2Fpost%2F72bc4e60-fec5-423f-9713-fab7b43fc419%2Fimage.png
📎 JS(Javascript) 최적화
✔️ 강제 동기 레이아웃 피하기 / 레이아웃 스래싱(thrashing) 피하기
레이아웃 단계가 완료되기 전에 요소의 위치나 크기를 변경 후 바로 가져오려고 하면 강제로 레이아웃이 발생하는데 이것을 강제 동기 레이아웃 이라고한다.
그리고 이 레이아웃을 반복적으로 발생시키는 것이 레이아웃 스레싱이다.
JS 최적화에 대해서는 이곳의 링크를 첨부한다.
📌 로딩 최적화
📎 렌더 블로킹 최적화
✔️ css는 head, js는 body 하단에서 불러온다
웹 페이지가 로드되면 html과 css가 동시에 파싱된다. html과 css는 바로 눈에 보이는 시각적 부분을 구현하기때문에 빠르게 그려질수록 좋다. 그래서
css는 head 내에서 임포트
한다.웹 페이지는 파싱을 실행하면서 script를 만나면 html 파싱을 멈추고 해당 파일을 다운로드한 뒤 실행한다. 따라서 js를 제외한 구조들의 로드가 끝나고 js가 들어오는 것이 좋다. 일반적으로
body 태그를 닫기 직전에 script를 임포트
한다.✔️ media 속성 사용
media
속성을 사용하면 조건별로 css를 불러올 수 있다.반응형 웹 제작시 유용하게 사용될 수 있다.
구글 크롬 라이트하우스는(
Lighthouse
) media 속성이 없는 < link rel=”stylesheet” >태그를 렌더 블로킹 리소스로 판단한다.media
속성이 없는 스타일시트는 해당 스타일시트를 브라우저가 해석하는 동안 화면에 스타일을 불러오지 않는다.<link href="style.css" rel="stylesheet"> <!-- 🔺 --> <link href="style.css" rel="stylesheet" media="(min-width:320px) and (max-width:768px)"> <!-- 브라우저의 넓이가 320이상 769미만일때 스타일시트 해석 --> <link href="style.css" rel="stylesheet" media="print"> <!-- 프린트할때만 스타일시트 해석 -->
✔️ async / defer
async
와defer
속성은 스크립트 파일을 병렬로 다운로드하게 해준다. 즉, 로딩 시 웹페이지 해석을 멈추지 않고 스크립트를 다운로드 하는것이다.async는
다운로드 후 즉시 실행한다.defer
는 웹페이지가 모두 그려지고 DOM이 들어왔을 때 스크립트를 실행한다.<!-- 병렬 다운로드 & 즉시실행 --> <script async src="test.js"></script><!-- 병렬 다운로드 & 지연실행 --> <script defer src="test.js"></script>
이 내용을 그림으로 확인 시 아래와 같다.■ HTML 파싱■HTML 파싱 멈춤■Script 다운로드■Script 실행
< script >
!https://velog.velcdn.com/images%2Fhsecode%2Fpost%2F76c68104-33b6-4711-a2b9-30f8fc639028%2Fimage.png
< script async > : 병렬 다운로드 & 즉시실행
!https://velog.velcdn.com/images%2Fhsecode%2Fpost%2Fbc448ded-05a7-4895-86b2-71ff400f6d55%2Fimage.png
< script defer > : 병렬 다운로드 & 지연실행
!https://velog.velcdn.com/images%2Fhsecode%2Fpost%2Fbd7fe070-fbd9-430e-84af-cd8fc28bfc98%2Fimage.png
[[출처 - growing with the web]](https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html)
```
즉,
<script> - 반드시 순서대로 실행되어야 할때
<script async> - 빨리 실행되어야 할때
<script defer> - 마지막에 파싱해도 상관없을때
사용하면 된다.
```
## 📎 이미지 최적화
### ✔️ picture 태그 사용하기
- `picture` 태그의 `type` 속성을 통해 사용자 환경에 맞는 이미지를 제공할 수 있다.
- webp - IE 미지원, jpg/png 대비 30~70% 수준의 용량
- avif - 크롬/삼성인터넷 지원, 저용량이면서 고품질
```
<!-- 브라우저가 avif를 지원하면 avif를 사용하고,
그렇지 않은 경우 webp,
둘 다 지원하지 않을 경우 jpg 이미지를 사용한다. -->
<picture><source srcset="aaa.avif" type="image/avif"><source srcset="aaa.webp" type="image/webp"><img src="aaa.jpg" alt></picture>
```
- `media` 속성을 사용해서 브라우저 사이즈에 맞는 이미지를 제공할 수 있다.media의 조건 즉, `해상도`에 따라 출력할 이미지를 지정할 수 있다.
```
<picture><source srcset="mob.webp" media="(max-width: 760px)"> <!-- 브라우저의 넓이가 760px 이하일때 mob.webp 이미지 출력-->
<img src="pc.webp" alt></picture>
```
- picture 나 source 요소는 화면에 출력되는 요소가 아니다.
### ✔️ img 지연로딩 활용하기
- `loading` 속성을 사용해서 이미지를 브라우저 화면에 지연/병렬 로딩할 수 있다.
- 사용 가능한 값으로 `auto`, `lazy`, `eager`가 있다.
- `auto`: 디폴트 값. `loading` 속성을 쓰지 않은 것과 같다.
- `lazy`: 화상에 보이는 부분만 먼저 출력하고 화면 바깥쪽 이미지들은 로딩하지 않는다. 사용자가 화면을 위로 올리면 아래쪽에 있던 이미지가 올라오면서 로딩된다.
- `eager`: 화면 위치에 상관없이 페이지가 로딩되자마자 이미지를 로드한다.
```
<img src="item.jpg" loading="lazy" alt>
```
### ✔️ 스프라이트 이미지 사용
- 여러개 이미지를 `하나의 이미지`로 만들어서 css의 `background-position` 속성을 사용해 부분적으로 이미지를 사용하는 방법이다.
- 이미지 파일 개수 자체를 줄이므로 리소스 요청 개수를 줄일 수 있다.
!https://velog.velcdn.com/images%2Fhsecode%2Fpost%2Fdc3ae954-a350-4c8b-aa29-017606bddadc%2Fimage.png
```
.icon_rotate{...width:15px;height:15px;background-position:-23px -50px;}
.icon_del{...width:10px;height:13px;background-position:-65px -15px;}
...
```
## 📎 웹팩(Webpack) 사용
- 모듈 번들러 웹팩(Webpack)을 사용해서 css와 js 파일을 `번들링`해(하나의 파일들로 묶어서) 리소스 요청을 줄일 수 있다
```
<html><head><link href="main.css" rel="stylesheet"><link href="sub.css" rel="stylesheet"><link href="sub2.css" rel="stylesheet"></head><body><div id="content">
...
</div><script async src="sample1.js" type="text/javascript"></script><script async src="sample2.js" type="text/javascript"></script></body></html>
```
⬇️ 웹팩 등을 통한 css/js 번들링 후 ⬇️
```
<html><head><link href="bundle.css" rel="stylesheet"></head><body><div id="content">
...
</div><script async src="bundle.js" type="text/javascript"></script></body></html>
```
## 📎 Gzip 사용
- `Gzip`을 사용해 텍스트 기반의 리소스로 압축한다.
- 이미지, pdf 등은 이미 압축된 파일일 경우가 많아서 Gzip을 사용하지 않는다.
## 📎 js 압축
- `UglifyJS` 등을 사용해서 js 파일을 압축한다.
- 불필요한 공백이나 줄바꿈을 제거해서 파일의 용량이 감소하며, 난독화를 하면 민감한 코드를 알아보기 어렵게 만들 수 있다.
## 📎 CDN 사용
- `CDN(Content Delivery Network)`은 유저에게 많은 콘텐츠를 손실없이 빠르게 전달하는 서비스이다.
- 대용량 콘텐츠 다운 또는 스트리밍 등에 사용
- 사용한 만큼 비용을 지불한다.
## 📎 캐싱
- 캐쉬란 사용자가 요청하는 html, css, js, image 등을 첫 요청 시에 내려받은 뒤 특정 위치에 복사본을 저장하고, 이후 동일한 URl의 리소스 요청이 왔을 때 이전에 저장해둔 파일을 사용해서 더 빠르게 로딩하는데에 사용된다.
- 브라우저가 다운로드할 파일의 개수 자체를 줄이므로 시간적 측면에서 이득이 크다.
'한번쯤 들어본 FE 기술' 카테고리의 다른 글
성능 최적화 (0) | 2025.03.12 |
---|---|
HTML link 태그의 rel 속성, preconnect, preload, prefetch (0) | 2025.02.12 |
vue.js 번들 크기 줄이기 (0) | 2024.09.23 |
[react] state와 생명주기 (2) | 2024.09.17 |
[react] jsx (2) | 2024.09.17 |