웹 성능 최적화(feat.Front End)

MODAC·2023년 2월 1일
0

01. What Optimization?


최적화, 最適化, optimization
주어진 상황에서 원하는 가장 알맞은 결과를 얻을 수 있도록 처리하는 과정.
최적화는 허용된 자원의 한계 내에서 주어진 요구사항을 만족시키면서 최선의 결과를 얻는 과정이다. 수익과 관련되는 분야에서는 이익을 최대로 내는 과정을 말하기도 한다. 다양한 분야와 때에 따라 다르게 정의할 수 있고 물류(logistics), 설계(design) 문제 등에 응용된다.

웹개발에서 최적화는 주어진 조건 아래에서 최대한 빠르게 화면을 표시하도록 만드는 것입니다.

웹 최적화의 효과


1. 이탈률 감소
웹페이지의 로딩이 길어질수록 유저들의 이탈율은 기하급수적으로 증가합니다.

웹사이트 성능 최적화를 통해 로딩 속도를 줄이면 사용자 이탈률을 효과적으로 감소시킬 수 있습니다.


2. 전환율 증가
전환율은 실제로 서비스를 가입하고 사용하는 방문자 비율을 의미합니다.

이탈률이 줄어들면 자연스레 방문자의 서비스 이용도 증가합니다.


3. 수익 증대
로딩 속도가 1초 빨라졌을 때 아마존 판매량은 1%, 구글 검색량은 0.2%, 월마트의 전환율은 2% 증가했다고 합니다.

성능개선으로 유의미한 수익효과를 기대할 수 있습니다.


4. UX 개선
최적화는 효과적인 UX 개선 수단입니다.

페이지 로딩이 빠를수록 사용자 경험이 향상되고 뒤이어 이탈율 감소, 전환율 증가, 수익 증대로 이어지게 됩니다.

02. Optimization techniques


웹성능 최적화에는 다양한 방법이 있습니다. 그 중 프론트엔드의 최적화 기법에 대해 알아보겠습니다.

1. HTML

DOM 트리 경량화
DOM 트리의 복잡도가 높을수록 계산에 필요한 브라우저 파워가 더 많이 소요됩니다. HTML 요소 중 불필요한 요소를 정리합니다.


인라인 스타일 지양
개별 요소에 인라인 스타일을 반복해서 작성하면 불필요한 반복으로 인해 파일 크기가 커지게 됩니다. 또한 인라인 스타일은 웹 표준에 맞지 않고 리플로우를 발생시키기 때문에 최대한 지양해야 합니다.

2. CSS

사용하지 않는 CSS 제거
미사용된 CSS를 정리하여 CSSOM 트리의 완성 속도를 향상시킵니다. 요소를 삭제할 때 Style을 적용하지 않았는지 한번 더 확인해봅니다.


간결한 셀렉터 사용
셀렉터가 복잡할수록 스타일 계산과 레이아웃 구축이 오래걸립니다. 최대한 간결하게 작성해줍니다.

복잡한 CSS 셀렉터 예시
.cart_page .cart_item #firstItem { ... }

가능한 한 간결하게 작성
.cart_item { ... }

3. 리소스 로딩 최적화

CSS 파일 불러오기
CSSOM 트리는 CSS 코드를 모두 해석한 후에 생성되기 때문에 가능한 한 빠르게 구성할 수 있도록 HTML 문서 최상단에서 CSS파일을 불러옵니다.

// CSS 파일은 HTML 파일 상단의 head 요소 안에서 불러오는 것이 좋습니다.
<head>
	<link href="style.css" rel="stylesheet" />
</head>

JS 파일 불러오기
JS 파일이 요소를 만나면 DOM 트리 생성이 중단되고 앞서 생성된 DOM까지만 실행됩니다. 만약 JS파일이 HTML의 중간에서 파싱되면 의도와 다른 랜더링이 발생하거나 완료 시간이 지연될 수 있습니다. 이런 이유로 JS파일은 항상 HTML 문서의 최하단에 배치하는 것이 권장됩니다.

<body>
	<div>...</div>
	...

	// JavsScript 파일은 body 요소가 닫히기 직전에 작성하는 것이 가장 좋습니다. 
	<script src="script.js" type="text/javascript"></script>
</body>

4. 미디어 파일 최적화

페이지의 대부분 용량은 미디어 파일로 인해 늘어납니다.

1. 이미지 스프라이트
이미지 용량을 줄이기 위해 여러 이미지를 하나의 이미지로 묶고 background-position 속성으로 이미지의 일정 부분만 셀렉터로 구분하여 사용합니다.

2. CDN 사용
CDN은 콘텐츠를 좀 더 빠르고 효율적으로 제공하기 위해 설계되었습니다. Font Awesome, unsplash 등 다양한 무료 미디어 사이트에서 CDN을 제공합니다. 혹은 라이브러리를 설치해서 사용하는 방법도 가능합니다. REACT에서는 아래의 패키지를 설치패서 Font Awesome을 사용합니다.

// 핵심 패키지 설치
npm i --save @fortawesome/fontawesome-svg-core

// 아이콘 패키지 설치 (해당 코드는 무료 아이콘들입니다. 유료 아이콘을 사용할 경우 추가로 설치가 필요합니다.)
npm i --save @fortawesome/free-solid-svg-icons
npm i --save @fortawesome/free-regular-svg-icons
npm i --save @fortawesome/free-brands-svg-icons

// Font Awesome React 구성 요소 설치
npm i --save @fortawesome/react-fontawesome@latest

3. WebP & AVIF 확장자
WebP는 PNG와 비교해 26% 용량이 감소되며 JPEG와 비교했을 땐 25-35% 더 감소됩니다.
AVIF는 JPEG와 비교했을 때 무려 용량의 50%가 감소되며 WebP와 비교했을 땐 20% 감소됩니다.
WebP & AVIF 이미지 포멧은 비교적 최신에 등장한 이미지 포멧이기 때문에 어떤 브라우저에서는 호환이 되지 않을 수도 있습니다. 이 경우에는 Picture 태그를 사용하여 분기를 대체할 수 있습니다.

<!-- 접속한 브라우저에서 <source>태그 내의 srcset에 정의한 WebP 포맷을 지원하지 않는다면 해당 <source> 태그는 무시됩니다.  -->
<picture>
 <source srcset="logo.webp" type="image/webp">

 <img src="logo.png" alt="logo">
</picture>

5. 캐시 관리

캐시(Cache)는 다운로드 받은 데이터나 값을 미리 복사해 놓는 임시 장소를 뜻하며, 데이터에 접근하는 시간이 오래 걸리는 경우나 값을 다시 계산하는 시간을 절약하고 싶은 경우에 사용합니다.


1. 캐시 사용 효과
만약 캐시를 사용하지 않고 이미지를 서버에 요청하면 첫번째 요청 이후에도 매 요청 시 똑같은 데이터를 서버에서 받아와야 합니다. 이러한 리소스 낭비를 막기 위해 캐시를 활용하면 캐시가 유효한 시간 동안 다운로드 받은 파일을 캐시에서 불러오기 때문에 네트워크 리소스를 아낄 수 있으며 파일을 다시 받아올 필요가 없기 때문에 브라우저 로딩이 빨라지고 UX의 개선으로 이어집니다.


2. 캐시 검증 헤더와 조건부 요청 헤더
요청하려는 데이터가 캐시에 저장되어 있을 때 캐시의 유효기간이 만료되면 캐지 검증 헤더와 조건부 요청 헤더를 사용하여 재사용할 수 있습니다.

6. JavaScript 트리쉐이킹

1. 필요한 모듈만 사용
라이브러리를 사용할 때 필요한 모듈만 불러오면 번들링 과정에서 사용하는 부분의 코드만 포함시키기 때문에 트리쉐이킹이 가능해집니다.

import { useState, useEffect } from 'react'

2. Babelrc 파일 설정
ES5 문법으로 변환해주는 라이브러리인 Babel은 import를 지원하지 않는 ES5 문법을 require로 변경시킵니다. require은 export되는 모든 모듈을 불러오기 때문에 자원의 소모량이 많아지게 됩니다. 이를 방지하기 위해 Bablerc 파일에 모듈 변환을 막아줍니다.

{
  “presets”: [ 
    [
      “@babel/preset-env”,
      {
	    "modules": false
      }
    ]
 ]
}

3. sideEffects 설정
웹팩은 사이드 이펙트를 일으킬 수 있는 코드의 경우 사용되지 않아도 트리쉐이킹에서 제외시킵니다. package.json 파일에서 sideEffects를 설정하여 사이드 이펙트가 생기지 않을 것이므로 코드를 제외시켜도 됨을 웹팩에게 알려줄 수 있습니다.

// 애플리케이션 전체에 적용
{
  "name": "tree-shaking",
  "version": "1.0.0",
  "sideEffects": false
}
// 특정파일에만 적용
{
  "name": "tree-shaking",
  "version": "1.0.0",
  "sideEffects": ["./src/components/NoSideEffect.js"]
}

4. ES6 문법을 사용하는 모듈 사용
트리쉐이킹이 적용되지 않는 라이브러리가 있다면, 해당 라이브러리가 어떤 문법을 사용하고 있는지 확인해볼 필요가 있습니다. ES5 문법을 사용하는 모듈을 통째로 사용하는 상황이라면 상관없지만, 일부만 사용하는 경우라면 해당 모듈을 대체할 수 있으면서 ES6를 지원하는 다른 모듈을 사용하는 것이 트리쉐이킹에 유리합니다. ES6 문법을 사용하는 모듈을 사용하면 해당 모듈에서도 필요한 부분만 import해서 사용하지 않는 코드는 빌드할 때 제외되기 때문입니다.


03. Lighthouse


Lighthouse는 구글에서 개발한 오픈소스로서 사이트를 검사하여 성능 측정을 할 수 있는 도구입니다. 다양한 지표를 이용하여 웹페이지의 성능 검사를 해줄 뿐만 아니라 그에 대한 개선책도 제공해줍니다.

1. 사용하기

Chrome
크롬에서 개발자도구를 열고 Lighthouse 탭에서 실행합니다.

Node CLI
Lighthouse를 전역 모듈로 설치합니다.

npm install -g lighthouse

다음의 명령어로 검사를 실행할 수 있습니다.

lighthouse <url>

Lighthouse 노드모듈을 이용해 동적으로 프로그래밍하여 페이지 검사 리포트를 생성할 수도 있습니다. 이를 이용해 성능 테스트를 자동화할 수 있습니다.

2. 분석 항목

Performance
웹 성능을 측정합니다. 화면에 콘텐츠가 표시되는데 시간이 얼마나 걸리는지, 표시된 후 사용자와 상호작용하기 까진 얼마나 걸리는지, 화면에 불안정한 요소는 없는지 등을 확인합니다.

Accessibility
웹 페이지가 웹 접근성을 잘 갖추고 있는지 확인합니다. 대체 텍스트를 잘 작성했는지, 배경색과 콘텐츠 색상의 대비가 충분한지, 적절한 WAI-ARIA 속성을 사용했는지 등을 확인합니다.

Best Practices
웹 페이지가 웹 표준 모범 사례를 잘 따르고 있는지 확인합니다. HTTPS 프로토콜을 사용하는지, 사용자가 확인할 확률은 높지 않지만 콘솔 창에 오류가 표시 되지는 않는지 등을 확인합니다.

SEO
웹 페이지가 검색 엔진 최적화가 잘 되어있는지 확인합니다. 애플리케이션의 robots.txt가 유효한지, meta 요소는 잘 작성되어 있는지, 텍스트 크기가 읽기에 무리가 없는지 등을 확인합니다.

PWA (Progressive Web App)
해당 웹 사이트가 모바일 애플리케이션으로서도 잘 작동하는지 확인합니다. 앱 아이콘을 제공하는지, 스플래시 화면이 있는지, 화면 크기에 맞게 콘텐츠를 적절하게 배치했는지 등을 점수가 아닌 체크리스트로 확인합니다.

3. Perfomance Metrics

Lighthouse는 Perfomance 분석결과를 시각화해서 보여줍니다.

First Contentful Paint
FCP는 성능(Performance) 지표를 추적하는 메트릭입니다. 사용자가 페이지에 접속했을 때 브라우저가 DOM 컨텐츠의 첫 번째 부분을 렌더링하는 데 걸리는 시간을 측정합니다.

Largest Contentful Paint
LCP는 뷰포트를 차지하는 가장 큰 콘텐츠(이미지 또는 텍스트 블록)의 렌더 시간을 측정합니다. 이를 이용해 주요 콘텐츠가 유저에게 보이는 시간까지를 가늠할 수 있습니다.

LCP time(in seconds)Color-coding
0-2.5Green (fast)
2.5-4Orange (moderate)
Over 4Red (slow)

Speed Index
Speed Index는 성능(Performance) 지표를 추적하는 메트릭입니다. Speed Index는 페이지를 로드하는 동안 얼마나 빨리 컨텐츠가 시각적으로 표시되는 지를 측정합니다.

Speed Index(in seconds)Color-coding
0–3.4Green (fast)
3.4–5.8Orange (moderate)
Over 5.8Red (slow)

Time to interactive
TTI는 페이지가 로드되는 시점부터 사용자와의 상호작용이 가능한 시점까지의 시간을 측정합니다.

TTI metric(in seconds)Color-coding
0–3.8Green (fast)
3.9–7.3Orange (moderate)
Over 7.3Red (slow)

Total Blocking Time
TBT는 페이지가 유저와 상호작용하기까지의 막혀있는 시간을 측정합니다. Lighthouse에서는 FCP와 TTI 사이에 긴 시간이 걸리는 작업들을 모두 기록하여 TBT를 측정합니다.

Cumulative Layout Shift
CLS는 사용자에게 컨텐츠가 화면에서 얼마나 많이 움직이는지(불안정한 지)를 수치화한 지표입니다. 이 지표를 통해 화면에서 이리저리 움직이는 요소(불안정한 요소)가 있는 지를 측정할 수 있습니다.

4. 개선 방향 제시

Lighthouse는 성능을 측정할 뿐 아니라 무엇이 시간을 많이 소모하는지, 어떻게 개선하여 최적화를 할 수 있을지 해결책도 제시해줍니다. Opportunities 항목을 확인하면 각 메트릭별 문제를 확인할 수 있습니다.

0개의 댓글