Optimization

jisooo·2022년 10월 7일
0

Optimization이란?
주어진 조건으로 최대 효율을 낼 수 있도록 하는 것을 의미한다.
개발에서의 최적화는 주어진 조건 아래에서 최대한 빠르게 화면을 표시하도록 만드는 것을 의미한다.

최적화의 필요성 및 효과

1. 이탈률 감소

구글의 조사 결과에 따르면 페이지 로드가 3초 이상 걸리면 53%의 사용자가 사이트를 이탈한다고 한다. 페이지 로드 속도가 1초에서 3초로 늘어나면 이탈률은 32%, 5초로 늘어나면 90%, 6초로 늘어나면 106%, 10초로 늘어나면 123%까지 증가하는 것으로 나타났는데, 이는 웹 사이트의 성능 최적화를 통해 페이지 로딩 속도를 줄이면, 사용자의 이탈률을 효과적으로 줄일 수 있다는 의미이기도 하다.

2. 전환율 증가

전환율이란, 웹 사이트를 방문한 사용자 중 회원가입, 상품 구매, 게시글 조회, 다운로드 등의 행위를 한 방문자의 비율을 의미한다. 이탈률이 줄어들면, 전환율이 높아질 확률이 커지고, 전환율을 늘려 서비스 사용자를 늘리기 위해서는 이탈률을 줄여야 한다.

3. 수익 증대

웹 사이트 로딩 속도는 수익 증대까지 이어질 수 있다. 이탈률 감소, 전환율 증가는 트래픽 증대 및 회원 수 증가로 이어지고, 이는 곧 수익 증대를 의미한다. 실제로 로딩 속도가 1초 빨라졌을 때 아마존 판매량은 1%, 구글 검색량은 0.2%, 월마트의 전환율은 2% 증가했다고 한다.

4. 사용자 경험(UX) 향상

페이지 로딩이 빠를수록 UX는 향상되기 때문에 이미 페이지 로드 속도가 빠른 편이라고 해도 최적화를 통해 UX가 더욱 향상할 수 있다.

Optimization(최적화) 기법

A. HTML, CSS 코드 최적화하기

1. HTML 최적화 방법

(1) DOM 트리 가볍게 만들기

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

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

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

2. CSS 최적화 방법

(1) 사용하지 않는 CSS 제거하기
(2) 간결한 셀렉터 사용하기

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

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

B. 리소스 로딩 최적화하기

1. CSS 파일 불러오기

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

2. JavaScript 파일 불러오기

JavaScript 파일은 DOM 트리 생성이 완료되는 시점인 HTML 문서 최하단에 배치하는 것이 좋다. HTML 코드 파싱 중 script 요소를 만나는 순간 해당 스크립트가 실행되어 script 요소 이전까지 생성된 DOM까지만 접근할 수 있다. script 요소를 HTML 코드 중간에 넣는다면, 해당 요소 이후에 생성될 DOM을 수정하는 코드가 있는 경우에는 화면이 의도한 대로 표시되지 않게 되기 때문에 HTML 문서 최하단에 배치하는 것이 좋다.

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

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

캐시 사용하기

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

서버에서 이미지를 받아오는 요청을 보낼때 첫 번째 요청에서는 이미지를 통째로 받아오게 된다. 해당 이미지를 받아온 적이 없기 때문이다. 이때 HTTP 헤더의 용량이 0.1M, 이미지의 용량이 1.0M라면 응답의 총 용량은 1.1M이 된다.

문제는 두 번째 요청부터이다. 완전히 똑같은 파일을 또 다시 받아오는 일이 발생하는데, 똑같은 데이터를 굳이 다시 받을 필요없이 전에 받아두었던 파일을 재사용할 수 있다면, 첫 번째 요청을 보냈을 때처럼 1.1M의 응답을 통째로 받아올 필요없이 HTTP헤더의 용량인 0.1M만 받아도 될 것 이다. 이럴 때 캐시를 활용하면 이러한 리소스 낭비를 막을 수 있다.

브라우저 캐시를 활용하면 다음과 같은 효과를 볼 수 있다.

  1. 캐시가 유효한 시간 동안 네트워크 리소스를 아낄 수 있음
  2. 파일을 다시 받아올 필요가 없기 때문에 브라우저 로딩이 빨라짐
  3. 로딩이 빨라진 만큼 빠른 사용자 경험 제공 가능

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

캐시 검증 헤더

캐시에 저장된 데이터와 서버의 데이터가 동일한지 확인하기 위한 정보를 담은 응답 헤더

Last-Modified : 데이터가 마지막으로 수정된 시점을 의미하는 응답 헤더로, 조건부 요청 헤더인 If-Modified-Since 와 묶어서 사용한다.
Etag : 데이터의 버전을 의미하는 응답 헤더로, 조건부 요청 헤더인 If-None-Match 와 묶어서 사용한다.

조건부 요청 헤더

캐시의 데이터와 서버의 데이터가 동일하다면 재사용하게 해달라는 의미의 요청 헤더

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

Tree Shaking

트리쉐이킹(Tree Shaking)이란?
나무를 흔들어 잔가지를 털어내듯 불필요한 코드를 제거하는 것을 의미한다. 불필요한 코드들을 찾아 제거하면 웹 사이트 성능 최적화에 큰 도움이 되는데, 특히 JavaScript는 다음과 같은 이유로 가능하면 트리쉐이킹을 해주는 것이 좋다.

  1. JavaScript 파일의 크기
    JavaScript 파일 크기의 증가, 요청 횟수의 증가는 그만큼 파일이 오고 가는 동안 화면 표시가 늦어진다는 것을 뜻하고, 네트워크 속도가 느린 환경에서는 더 큰 병목현상을 유발한다. 따라서 트리쉐이킹을 통해 파일 크기를 가능한 줄이는 것이 최적화에 도움이 된다.
  2. JavaScript 파일의 실행 시간
    JavaScript 파일이 실행되기 위해서는 많은 과정을 거쳐야 한다. 다운로드부터 필요한 경우에는 우선 요청을 보내어 파일을 다운받아 온 다음 압축을 해제해야 합니다. 그다음에는 JavaScript 코드를 파싱하여 DOM 트리를 생성한다. 파싱이 끝나면 컴파일하여 컴퓨터가 이해할 수 있는 언어로 바꿔줘야 하고 이 컴파일 과정까지 거쳐야지 비로소 코드를 실행할 수 있다. 이처럼 코드 실행까지 거쳐야 하는 과정이 많기 때문에 JavaScript는 다른 리소스에 비해서 실행까지 상대적으로 많은 시간을 소모하게 된다.

JavaScript 트리쉐이킹
웹팩 4버전 이상을 사용하는 경우에는 ES6 모듈(import, export를 사용하는 모듈)을 대상으로는 기본적인 트리쉐이킹을 제공하고 CRA를 통해 만든 React 애플리케이션도 웹팩을 사용하고 있기 때문에 트리쉐이킹이 가능하다. 웹팩을 사용하는 환경에서 효과적으로 트리쉐이킹을 수행하는 방법에 대해서 알아보자.

1. 필요한 모듈만 import 하기

//실제로 사용하지 않는 코드들까지 불러오기
import React from 'react'
//실제로 사용 할 필요한 코드만 불러오기
import { useState, useEffect } from 'react'

불필요한 코드가 포함되어 코드의 크기가 커지는것을 방지하기 위해서 import 해올 때 위와 같이 실제로 사용할 코드만 불러와 주면 된다.

2. Babelrc 파일 설정하기

Babel은 자바스크립트 문법이 구형 브라우저에서도 호환이 가능하도록 ES5 문법으로 변환하는 라이브러리 인데 ES5문법은 import를 지원하지 않아 commonJS 문법의 require로 변경시키는데, 이 과정은 트리쉐이킹에 큰 걸림돌이 된다. require는 export 되는 모든 모듈을 불러오기 때문이다. 필요한 모듈만 불러오기 위한 코드를 작성해도 소용이 없어지는 것이다.

이를 방지하기 위해서 Barbelrc 파일에 다음과 같은 코드를 작성해주면 ES5로 변환하는 것을 막을 수 있다.

{
  “presets”: [ 
    [
      “@babel/preset-env”,
      {
	    "modules": false
      }
    ]
 ]
}
//modules 값을 true로 설정하면 항상 ES5 문법으로 변환하므로 주의해서 작성해야 한다.

3. sideEffects 설정하기

웹팩은 사이드 이펙트를 일으킬 수 있는 코드의 경우, 사용하지 않는 코드라도 트리쉐이킹 대상에서 제외시킨다.

const crews = ['kimcoding', 'parkhacker']

const addCrew = function (name) {
	crews.push(name)
}

위 코드에서 addCrew 함수는 순수 함수가 아니기 때문에 트리쉐이킹을 통해 제외하는 경우 문제가 생길 수도 있다고 판단해 웹팩은 이 코드를 제외시키지 않는다.
이럴 때 package.json 파일에서 sideEffects를 설정하여 사이드 이펙트가 생기지 않을 것이므로 코드를 제외시켜도 됨을 웹팩에게 알려줄 수 있다.

{
  "name": "tree-shaking",
  "version": "1.0.0",
  "sideEffects": false
}

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

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

0개의 댓글

관련 채용 정보