[CodeStates-Section4]U8.최적화- Optimization

hameee·2023년 2월 1일
0

CodeStates_Frontend_42기

목록 보기
39/39
post-thumbnail

후기

다양한 최적화 기법들을 학습했다. Lighthouse를 통해 웹페이지 성능 검사를 하는 것이 신기했다. 해결책까지 제시해준다니 유용한 툴인 것 같다.

Chapter1. Optimization
-1. Optimization(최적화)란
-2. 최적화의 효과
Chapter2. Optimization 기법
-1. 최적화 기법
-2. Cache
-3. Tree Shaking
-4. Lighthouse

<Chapter1. Optimization>

1.Optimization(최적화)란

일반: 주어진 조건으로 최대 효율을 낼 수 있도록 하는 것
컴퓨터 공학: 가능한 적은 리소스를 소모하면서 가능한 빠르게 원하는 결과를 얻을 수 있도록 하는 것
웹 개발: 주어진 조건 아래에서 최대한 빠르게 화면을 표시하도록 만드는 것

2.최적화의 효과

① 이탈률 감소, 전환율 증가
전환율: 웹 사이트를 방문한 사용자 중 회원가입, 상품 구매, 게시글 조회, 다운로드 등의 행위를 한 방문자의 비율
② 수익 증대
③ 사용자 경험(UX) 향상

<Chapter2. Optimization 기법>

1.최적화 기법

1) HTML, CSS 코드 최적화하기

(1) HTML 최적화 방법

① DOM 트리 가볍게 만들기
DOM 트리 -> 최대한 얕게
DOM 트리의 자식 요소 -> 최대한 적게

② 인라인 스타일 사용하지 않기
인라인 스타일을 사용하면 코드 중복, 계속된 리플로우 가능성이 있음
class와 CSS로 대체

(2) CSS 최적화 방법

① 사용하지 않는 CSS 제거하기
② 간결한 셀렉터 사용하기

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

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

2) 리소스 로딩 최적화하기

CSS,JavaScript 파일을 불러오는 위치에 따라 렌더링 완료 시점이 달라질 수 있음

(1) CSS 파일 <head>에서 불러오기

CSSOM 트리 -> 코드를 한 줄 한 줄 읽으면서 순차적으로 구성 불가, 코드를 모두 해석해야 구성 가능
CSSOM 트리를 가능한 한 빠르게 구성할 수 있도록 <link>는 HTML 문서 최상단인 <head>에 배치하는 것이 좋음

(2) JavaScript 파일 불러오기

DOM 트리 -> <script>를 만나면 생성 중단

① defer 속성 사용하여 <head> 에서 불러오기(권장)
script를 background에서 다운로드 하고 실행은 파싱 완료 후에 하므로 파싱이 가장 빠름

<body> 최하단에서 불러오기
DOM 트리 생성 완료된 후 script를 불러 옴

참고.<script> -> 이미 생성된 DOM에만 접근 가능
script 파싱 전에 생성되었던 타겟1, 타겟2, 타겟3, 타겟4에만 접근 가능

3) 브라우저 이미지 최적화하기

(1) 이미지 스프라이트

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

<style>
    .up, .down, .right, .left { background: url("/examples/images/img_image_sprites.png") no-repeat; }
    .up { width: 21px; height: 20px; background-position: 0 0; }
    .down { width: 21px; height: 20px; background-position: -21px 0; }
    .right { width: 22px; height: 20px; background-position: -42px 0; }
    .left { width: 22px; height: 20px; background-position: -65px 0; }

</style>

② 장점
-한 번의 이미지 요청으로 여러 개의 개별 이미지를 사용할 수 있으므로 서버 요청 수 줄일 수 있음
-이미지 파일을 개별로 관리할 필요 없이 특정 스프라이트 이미지 파일만을 관리하면 되므로 관리가 용이

(2) 아이콘 이미지를 아이콘 폰트로 대체(Font Awesome)

① 방식
-CDN으로 사용하기: 가입 시 발급받은 키트를 활용하는 방식
-Font Awesome 모듈 설치하기: 라이브러리처럼 설치해서 사용하는 방식(React 환경에서 사용할 경우)

② 장점
용량 감소

(3) 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>

4) CDN 사용하기

① 정의
Content Delivery(Distribution) Network(콘텐츠 전송 네트워크)
콘텐츠를 효율적으로 전달하기 위해 여러 노드를 가진 네트워크에 데이터를 저장하여 제공하는 시스템

① 장점
유저와 서버의 물리적 거리를 줄여 네트워크 지연(latency) 감소 가능

2.Cache

1) Cache(캐시)란

다운로드 받은 데이터나 값을 미리 복사해 놓는 임시 장소
데이터에 접근하는 시간이 오래 걸리는 경우나 값을 다시 계산하는 시간을 절약하고 싶은 경우에 사용

2) Cache 사용하지 않을 경우 vs Cache 사용할 경우

① Cache 사용하지 않을 경우
이전과 동일한 데이터를 요청할 경우, 서버에서 매번 다시 받아와야 함

① Cache 사용할 경우
이전과 동일한 데이터를 요청할 경우, Cache의 유효기간이 남았다면 캐시에 있는 데이터 사용 가능

ex.
-첫 번째 요청 -> 이미지 파일, Cache-Control(유효기간) 받음
-두 번째 요청 -> 캐시 조회 -> 유효기간 남은 경우 캐시의 데이터 사용, 유효기간 만료된 경우 서버에서 다시 이미지 파일과 Cache-Control 받음

3) 캐시 검증 헤더와 조건부 요청

Cache-Control이 지난 경우에도 Cache의 데이터를 재사용하기 위해 사용
2가지 방식이 있지만 재사용 가능성을 높이기 위해 보통 두 방식을 동시에 사용

Last-ModifiedIf-Modified-Since
Last-Modified(캐시 검증 헤더): 데이터가 마지막으로 수정된 시점(response header)
If-Modified-Since(조건부 요청 헤더): 캐시 된 리소스의 Last-Modified 값 이후에 서버 리소스가 수정되었는지 확인, 수정되지 않았다면 캐시된 리소스를 사용(request header)

ex.
-첫 번째 요청 -> 이미지 파일, Cache-Control, Last-Modified 받음
Cache에 저장되는 것: 이미지 파일, Last-Modified 값
-두 번째 요청 시 If-Modified-Since: Last-Modified 값 포함하여 요청 -> 서버에서 서버 데이터의 Last-Modified 값과 요청으로 온 Last-Modified 값을 비교 -> 동일하다면 304 Not Modified 받음, Cache 데이터의 유효기간 갱신됨

EtagIf-None-Match
Etag(캐시 검증 헤더): 데이터의 버전(response header)
If-None-Match(조건부 요청 헤더): 캐시 된 리소스의 ETag 값과 현재 서버 리소스의 ETag 값이 같은지 확인, 같으면 캐시된 리소스를 사용(request header)

ex.
-첫 번째 요청 -> 이미지 파일, Cache-Control, Etag 받음
Cache에 저장되는 것: 이미지 파일, Etag 값
-두 번째 요청 시 If-None-Match: Etag 값 포함하여 요청 -> 서버에서 서버 데이터의 Etag 값과 요청으로 온 Etag 값을 비교 -> 동일하다면 304 Not Modified 받음, Cache 데이터의 유효기간 갱신됨

3.Tree Shaking

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

1) JavaScript에서 Tree Shaking을 해야 하는 이유

-JavaScript 파일 크기 증가, JavaScript 파일을 요청하는 HTTP 요청 수 증가로 이전보다 더 큰 병목현상 유발하기 때문
-JavaScript는 다른 리소스에 비해 실행하기까지 오래 걸리기 때문에(JS 파일 다운 -> 압축 해제 -> 파싱하여 DOM 트리 생성 -> 컴파일 -> 코드 실행)

2) webpack을 사용하는 환경에서의 JavaScript 트리쉐이킹

webpack 4버전 이상 -> ES6 모듈(import, export를 사용하는 모듈)을 대상으로 기본적인 Tree Shaking 제공(React에 webpack이 내장되어 있으므로 RCA로 만든 React App도 포함)

(1) 필요한 모듈만 import 하기

import하지 않은 코드는 빌드할 때 제외되므로 코드의 크기를 줄일 수 있음

import React from 'react';// ❌
import { useState, useEffect } from 'react'// ✅

(2) Babelrc 파일 설정하기

Babel(라이브러리): 최신 문법 -> ES5 문법으로 변환(브라우저 호환성 때문)
ES5: import❌, require✅ -> require은 필요한 모듈만 부분적으로 불러오는 것이 불가
Babelrc 파일에 다음과 같은 코드를 작성해주면 ES5로 변환하는 것을 막을 수 있음

{
  “presets”: [ 
    [
      “@babel/preset-env”,
      {
	    "modules": false // ❗️true이면 항상 ES5로 변환하므로 주의
      }
    ]
 ]
}

(3) sideEffects 설정하기

webpack은 sideEffects를 일으키지 않는 코드만 Tree Shaking 대상에 포함함
package.json 파일에서 애플리케이션 전체 혹은 특정 파일에서 sideEffects을 false로 설정하여 Tree Shaking 대상에 포함해도 된다고 알려줄 수 있음

// 애플리케이션 전체
{
  "name": "tree-shaking",
  "version": "1.0.0",
  "sideEffects": false
}

// 특정 파일
{
  "name": "tree-shaking",
  "version": "1.0.0",
  "sideEffects": ["./src/components/NoSideEffect.js"]
}

(4) ES6 문법을 사용하는 모듈 사용하기

ES5는 import를 지원하지 않기 때문에 Tree Shaking에 불리. ES5로 작성된 모듈이 있다면 해당 모듈을 대체할 수 있으면서 ES6를 지원하는 다른 모듈을 사용하는 것이 좋음.

4.Lighthouse

1) 역할

구글에서 개발한 오픈소스로서 웹 페이지의 품질을 개선할 수 있는 자동화 툴
웹페이지 성능 검사 실시, 개선책 제공

2) Lighthouse 실행 방법

(1) Chrome 개발자 도구에서 실행하기

검사하고 싶은 사이트 접속 -> 개발자 도구 -> lighthouse 탭 클릭 -> Analyze page load 버튼 클릭

(2) Node CLI에서 실행하기

// Lighthouse 설치
npm install -g lighthouse

// 검사 실행
lighthouse <url>

// 모든 옵션 보기
lighthouse --help 

Lighthouse 노드모듈을 이용해 동적으로 프로그래밍하여 페이지 검사 리포트를 생성도 가능
https://github.com/GoogleChrome/lighthouse/blob/main/docs/readme.md#using-programmatically

3) Lighthouse 분석 결과 항목

Performance: 웹 성능
Accessibility: 웹 접근성
Best Practices: 웹 표준 모범 사례
SEO: 검색 엔진 최적화
PWA(Progressive Web App): 모바일 애플리케이션으로서도 잘 작동하는지 확인, 점수가 아닌 체크리스트로 확인

4) Lighthouse의 Performance 측정 메트릭

(1) First Contentful Paint(FCP)

사용자가 페이지에 접속했을 때 브라우저가 DOM 컨텐츠의 첫 번째 부분을 렌더링하는 데 걸리는 시간을 측정(<iframe> 요소는 제외). 우수한 사용자 경험을 제공하려면 FCP가 1.8초 이하여야 함.

출처: https://web.dev/i18n/ko/fcp/

(2) Largest Contentful Paint(LCP)

뷰포트를 차지하는 가장 큰 콘텐츠(이미지 또는 텍스트 블록)의 렌더 시간을 측정

(3) Speed Index

페이지를 로드하는 동안 얼마나 빨리 컨텐츠가 시각적으로 표시되는 지를 측정
Lighthouse가 브라우저의 페이지 로딩 과정을 각 프레임마다 캡쳐 -> 프레임 간 화면에 보이는 요소들을 계산 -> Speedline Node.js module을 이용하여 Speed Index 점수를 그래프의 형태로 나타냄

(4) Time to interactive(TTI)

-페이지가 로드되는 시점부터 사용자와의 상호작용이 가능한 시점까지의 시간을 측정
-사용자와의 상호작용이 가능한 시점의 기준
페이지에 FCP로 측정된 컨텐츠가 표시
이벤트 핸들러가 가장 잘 보이는 페이지의 엘리먼트에 등록됨
페이지가 0.05초안에 사용자의 상호작용에 응답

(5) Total Blocking Time(TBT)

-FCP와 TTI 사이의 차단 시간을 측정
-차단의 기준
50ms 이상 실행되는 작업이 있을 겨우

ex.

출처: https://web.dev/tbt/

TBT = (250 - 50) + (90 - 50) + (165 - 50) = 345ms(0.345초)

(6) Cumulative Layout Shift(CLS)

전체 수명 동안 발생하는 모든 예기치 않은 레이아웃 이동을 측정

5) Opportunities

Opportunities 항목을 확인하여 메트릭별 문제와 개선점 확인 가능

0개의 댓글