[개발자되기: 최적화] Day-56

Kyoorim LEE·2022년 8월 4일
0

최적화

(컴퓨터 공학) 가능한 적은 리소스를 소모하면서 가능한 한 빠르게 원하는 결과를 얻을 수 있도록 하는 것

(웹개발) 주어진 조건 아래 최대한 빠르게 화면을 표시하도록 하는 것

최적화 필요성 및 효과

이탈률 감소

화면 로딩 시간이 길어지면 사용가의 페이지 이탈확률도 높아짐

전환율 증가

전환율: 웹사이트 방문자 중 회원가입, 상품구매, 게시글 조회, 다운로드 등의 행위를 한 방문자의 비율

수익 증대

UX 향상

로딩이 빠를 수록 UX는 향상됨
로딩이 오래 걸릴 경우 progress bar, skeleton과 같이 로딩 중임을 알려주는 UI를 표시하여 방문자에게 최대한의 정보를 주는 것도 방법



HTML & CSS 최적화 기법

1. HTML 최적화 방법

1) DOM 트리 가볍게 만들기

DOM 트리가 깊을 수록, 자식 요소가 많을 수록 DOM 트리의 복잡도는 커짐

// 수정 전
<div>
	<ol>
		<li> 첫 번째 </li>
		<li> 두 번째 </li>
		<li> 세 번째 </li>
	</ol>
</div>

// 수정 후 : 불필요한 div 요소 제거
<ol>
	<li> 첫 번째 </li>
	<li> 두 번째 </li>
	<li> 세 번째 </li>
</ol>

2) 인라인 스타일 사용하지 않기

CSS 파일을 따로 작성하면 한 번의 리플로우만 발생하지만, 인라인 스타일은 리플로우를 계속 발생시켜 렌더링 완료 시점을 늦춤

//수정 전
<div style="margin: 10px;"> 마진 10px </div>
<div style="margin: 10px;"> 이것도 마진 10px </div>

//수정 후 : class와 CSS로 대체
<div class="margin10"> 마진 10px </div>
<div class="margin10"> 이것도 마진 10px </div>

.margin10 {
	margin: 10px;
}

2. CSS 최적화 방법

1) 사용하지 않는 CSS 제거하기

2) 간결한 셀렉터 사용하기

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

// 필요한 경우에는 어쩔 수 없지만, 가능한 한 간결하게 작성해줍니다.
.cart_item { ... }

리소스 로딩 최적화

1. CSS 파일 불러오기

CSSOM 트리는 CSS 코드를 모두 해석해야 구성할 수 있음. CSSOM 트리를 빨리 구성할 수 있도록 HTML 문서 최상단에 배치하는 것이 좋음

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

2. JavaScript 파일 불러오기

JavaScript는 DOM과 CSSOM 트리를 동적으로 변경할 수 있음
1. HTML 코드 파싱 진행
2. <script> 요소 만나면 해당 스크립트 실행됨
3. <script> 요소 이전까지 생성된 DOM까지만 접근할 수 있음

<script>요소를 HTML 코드 중간에 넣으면, 해당 요소 이후에 생성될 DOM을 수정할 코드가 있는 경우 화면에 의도하지 않는대로 표시될 수 있음

또한, JavaScript 파일을 다운받아와서 사용하는 경우 다운로드 및 스크립트 실행이 완료될 때까지 DOM트리 생성이 중단됨 => 렌더링 완료시간 늦춰짐

따라서 JavaScript 파일은 DOM 트리 생성 완료되는 시점인 HTML문서 최하단에 배치해야 함

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

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

브라우저 이미지 최적화

페이지 대부분의 용량은 이미지파일과 같은 미디어 파일이 차지함(전체 페이지 용량의 51% 차지).
=> 이미지 용량을 줄이거나 요청 수 줄이기 노력!

1. 이미지 스프라이트

이미지 스프라이트 기법:
여러개의 이미지를 하나로 모아 스프라이트 이미지로 만들고 CSS의 background-position속성을 사용하여 이미지 일정 부분만 클래스 등으로 구분하여 사용

장점

많은 이미지를 개별로 관리할 필요가 없음
한번의 이미지 요청으로 개별이미지를 사용할 수 있으므로 네트워크 로딩 시간을 줄일 수 있음

2. 아이콘 폰트 사용하기

아이콘을 이미지로 사용하지 않고 아이콘 폰트 사용하기
Font Awesome 사용하기

3. WebP 또는 AVIF 이미지 포맷 사용하기

JPEG, PNG <<<< WebP, AVIF
단, 브라우저 별로 지원하지 않는 경우도 있음

<picture> 태그 사용하여 각 브라우저의 호환에 맞도록 분기를 대체

<picture>: img 요소의 다중 이미지 리소스(multiple image resources)를 위한 컨테이너를 정의할 때 사용한다.

만약 <source> 태그 내 srcset에 정의한 webp포맷을 지원하지 않는다면 해당 <source>태그는 무시됨

<picture>
  <source srcset="logo.webp" type="image/webp">
  <img src="logo.png" alt="logo">
</picture>

캐시 사용하기

캐시: 다운로드 받은 데이터나 값을 미리 복사해놓는 임시 장소 => 데이터 접근시간이 오래걸리거나 값을 다시 계산하는 시간을 절약하고 싶을 때 사용함

FE에서 캐시 사용하려면 HTTP 요청을 보낼 때 조건부 요청 헤더를 작성하여 캐시 재사용여부 확인하면 됨

  • If-Modified-Since : 캐시된 리소스의 Last-Modified 값 이후에 서버 리소스가 수정되었는지 확인하고, 수정되지 않았다면 캐시된 리소스를 사용
  • If-None-Match : 캐시된 리소스의 ETag 값과 현재 서버 리소스의 ETag 값이 같은지 확인하고, 같으면 캐시된 리소스를 사용합니다.

CDN 사용하기

CDN: Content Delivery Network

CDN은 유저와 가까운 곳에 위치한 데이터 센터(서버)의 데이터를 가져옴

ex) CloudFront, Cloudflare



Tree Shaking

나무를 흔들어 잔가지를 털어내듯 불필요한 코드를 제거하는 것

  1. 점점 커지는 JavaScript 파일 크기
  2. 길어지는 JavaScript 파일 실행 시간

JavaScript Tree Shaking

1. 필요한 모듈만 import 하기

2. Babelrc 파일 설정하기

Babel은 ES5문법으로 변환하는 라이브러리
ES5는 import를 지원하지 않으므로 commonJS문법의 require로 변경함 => requireexport되는 모든 모듈을 불러오므로 트리쉐이킹 측면에서 좋지 않음

ES5로 변환하는것을 막을 수 있는 코드

{
  “presets”: [ 
    [
      “@babel/preset-env”,
      {
	    "modules": false
        //true로 설정하면 항상 ES5문법으로 변환함
      }
    ]
 ]
}

3. sideEffect 설정하기

sideEffect를 일으킬 수 있는 코드의 경우, 웹팩은 이 코드가 사용하지 않는 코드라도 일단 Tree Shaking에서 제외시켜버림

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 문법을 사용하는 모듈 사용하기

3번까지 했는데도 트리쉐이킹이 적용되지 않는 라이브러리가 있다면 어떤 문법사용하는지 확인하기

일부 ES5문법을 사용하는 모듈을 쓰고 있는 경우 그냥 아예 통째로 ES6을 지원하는 모듈로 바꾸는 것이 트리쉐이킹에 유리함



Ligthhouse

구글에서 개발한 오픈소스.
웹페이지 품질개선할 수 있는 자동화툴.

  1. 해당 페이지에서 개발자 도구
  2. lighthouse 탭 클릭
  3. Generate report 클릭

  • Performance: 웹성능.
    화면에 콘텐츠 표시되는데 시간이 얼마나 걸리는지, 표시된 후 사용자와 상호작용 하는데 얼마나 걸리는지, 화면에 불안정한 요소는 없는지 등
  • Accessibility: 웹 접근성.
    대체 텍스트(alt)를 잘 작성했는지, 배경색과 콘텐츠 색상 대비가 충분한지, 적절한 WAI-ARIA 속성 사용했는지
  • Best Practices: 웹 표준 모범사례.
    HTTPS 프로토콜 사용하는지, 콘솔창에 오류가 표시되지는 않는지
  • SEO: 검색엔진 최적화
    애플리케이션의 robots.txt가 유효한지, <meta> 요소는 잘 작성되어 있는지, 텍스트 크기는 적당한지
  • PWA (Progressive Web App): 모바일 호환성
    앱 아이콘 제공여부, 스플래시 화면 여부, 화면크기와 콘텐츠 배치 조화 등

Lighthouse의 Performance 측정 매트릭

FCP(First Contentful Paint): 성능 측정 지표

페이지 접속 시 브라우저가 DOM 컨텐츠의 첫 번째 부분을 렌더링하는데 걸리는 시간 측정. FCP가 1.8초 이하면 우수

페이지의 이미지와 <canvas> 요소, SVG 등 모두 DOM 콘텐츠로 구분되며 <iframe>요소의 경우 이에 포함되지 않음

LCP(Largest Contentful Paint): 가장 큰 뷰포트를 차지하는 콘텐츠의 렌더링 시간

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

Speed Index: 페이지 로딩 동안 얼마나 빨리 컨텐츠가 시각적으로 표시되는 지

Lighthouse는 페이지의 로딩과정을 각 프레임마다 캡쳐함. 프레임 간 화면에 보이는 요소들을 계산하여 Speed Index 점수를 그래프 형태로 나타냄

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

TTI(Time to interactive): 페이지 로드시점부터 사용자와의 상호작용 가능시점까지의 시간

  • 페이지에 FCP로 측정된 컨텐츠가 표시되어야함
  • 이벤트 핸들러가 가장 잘보이는 페이지의 엘리먼트로 등록됨
  • 페이지가 0.005초 안에 사용자의 상호작용에 응답함
TTI metric(in seconds)Color-coding
0–3.8Green (fast)
3.9–7.3Orange (moderate)
Over 7.3Red (slow)

Total Blocking Time: 페이지와 유저가 상호작용하기까지 막혀있는 시간

Cumulative Layout Shift: 컨텐츠가 얼마나 많이 움직이고 불안정한지 측정

화면에서 이리저리 움직이는 요소(불안정한 요소)여부 확인

profile
oneThing

0개의 댓글