거북이개발자

[웹 성능 최적화] 웹에서 가속 이끌어 내는 법 본문

Web/웹 성능 최적화

[웹 성능 최적화] 웹에서 가속 이끌어 내는 법

류정식 2021. 3. 26. 20:31

1. 웹 브라우저 현황

 

(1) 웹 브라우저 현황 :

 

 

 

 

 

 

2. 웹 브라우저 동작 이해하기

 

(1) 브라우저 동작 원리 : 

 

웹 사이트 주소를 입력함으로써 브라우저의 동작이 시작된다.

 

- 브라우저는 가장 먼저 도메인 서버와 통신하여 접속하려는 호스트의 IP를 찾는다.

 

그리고 해당 아이피를 가진 서버와 통신을 시도해 TCP 연결을 맺는다.

 

HTTPS는 암호화된 연결을 생성하려는 협의 단계가 더 추가된다.

 

브라우저는 서버로부터 필요한 리소스들을 다운로드해 이를 화면에 표현한다.

 

브라우저가 리소스를 다운로드할 때는 랜딩페이지의 HTML을 서버에 요청해 다운로드한다.

 

그리고 HTML의 구문을 분석(parsing)하면서 참조된 하위 리소스들을 차례로 다운한다.

 

(2) 브라우저 아키텍처 : 브라우저는 크게 7개 컴포넌트로 나눌 수 있다.

 

 

- 유저 인터페이스 : 사용자가 브라우저를 통해 상호 작용할 수 있도록 돕는다.

 

- 브라우저 엔진 : 유저 인터페이스와 렌더링 엔지 사이에서 렌더링 상태를 조회하고 렌더링 작업을 제어하기 위한 인터페이스를 제공한다.

 

- 렌더링 엔진 : HTML, CSS을 분석해서 실제 웹 콘텐츠를 원하는 대로 브라우저 창에 그리는 역할을 한다.

 

- 네트워킹 : 네트워크를 통해 HTTP 요청을 보내고 응답받는 역할을 한다. DNS 조회, TCP 연결 등의 작업을 수행한다.

 

- UI 백엔드 : 캄보 박스, 드롭박스 등 기본적이 UI 컴포넌트들을 제공한다.

 

- 자바스크립트 해석기 : V8, Spider Monkey 등의 엔진을 사용해 자바스크립트를 분석하고 해석한다.

 

- 데이터 저장소 : 데이터 지속성을 유지하기 위한 컴포넌트다. 쿠키 값을 로컬 디스크에 저장한다.

 

(3) 중요 렌더링 경로 : 

렌더링 엔진이 웹 페이지를 구문 분석해 화면에 표현하는 일련의 작업은 단일 스레드에 의해 수행된다.

 

1. HTML을 가장 처음 구문 분석하여 DOM 트리를 만든다.

2. CSS를 구문 분석하여 CSSOM트리를 만든다.

3. 두 개의 트리 모델을 결합해 최종적으로 렌더 트리를 만든다.

4. 렌더 트리가 생성되면 브라우저는 이를 기반으로 페이지 구조를 결정하고 화면에 표현한다.

 

- DOM 트리 생성 : 

HTML의 구문을 분석해 태그를 하나하나 해석하여 DOM이라는 객체 모델로 변환한다. 마크업 언어로 작성된 문서들은 컴퓨터가 사용하기 어려운 구조이다. DOM(Documents Object Model)은 객체 지향적 프로그램 언어들로 마크업 문서들을 손쉽게 프로그램하기 위해 표준으로 규정한 프로그램 인터페이스다. DOM은 객체 속성, 메소드, 이벤트 등을 정의한다.

 

- CSSOM 트리 생성 : 

CSSOM은 CSS를 처리하기 위한 트리 구조의 프로그래밍 인터페이스이다. 브라우저는 HTML을 구문 분석하며 CSS를 참조하기는 링크를 만나면 해당 CSS 리소스를 다운로드하고 구문 분석기가 CSS를 분석하기 시작한다. CSS 구문 분석에는 엄격한 구문 검사가 적용된다. 사용하는 구문 분석기과 동작 스레드도 다르다.

중요 렌더링 경로상에서 DOM 트리와 CSSOM 트리는 각각 별도로 생성된다.

 

- 렌더 트리 생성 : 

위 두 개의 트리를 병합해 렌더 트리를 생성한다. 렌더링을 위한 최종 정보를 가진 렌더 객체들을 생성해 이들의 상하 관계를 트리 모양으로 구성한 것이 렌더 트리이다. <body> 태그는 아무런 의미가 없어서 제외되것을 볼 수 있다. 또한 display : none 설정되어 있는 것은 렌더 트리에서 제외된다. 한 개의 렌더 객체는 한 개의 사각형 모양 영역을 표현할 수 있으며 그 영역에 모든 저보를 포함한다.

 

- 레이아웃 : 레이아웃은 렌더 트리 노드들의 위치 정보가 계산되는 단계이다. 렌더 객체는 사각형 영역을 표시하는데 맨 왼쪽 위에서 시작하여 아래, 오른쪽으로 이동하며 각 사각형 영역의 너비와 높이를 계산한다.  렌더 트리의 루트 노드부터 계산이 시작되는데 루트 노드의 너비는 뷰포트의 크기로 지정된다. 높이 계산은 역으로 자식 노드의 높이에 따라 부모 노드의 높이를 계산한다.

 

- 페인트 : 페인트는 렌더 트리 정보를 바탕으로 브라우저 창에 표현하는 단계이다. GPU를 이용해 그리기만 한다.

 

 

 

 

 

3. 브라우저 렌더링 최적화하기

 

(1) DOM 최적화하기 : 

 

HTML을 DOM으로 전환하는 과정은 구문 분석이 관대하다. 그래서 문법 오류가 발생해도 브라우저에는 정상적으로 표현되는 경우가 많다.

 

많은 오류 사항에 대한 예외 처리방안을 구현한다. (중첩된 태그 제거, 적절한 위치에서 태극 닫기, 겹친 테이블 분리). 오류가 많을수록 브라우저는 더 많은 메모리와 CPU 파워를 소모한다.

 

-최소화하기 위해서 스마트한 웹 페이지 개발, 편집 도구들, 태그 중첩 피하기 등을 해야 한다.

 

-chrome.google.com/webstore/detail/dom-monster/hlimphkgopfdlelabkioalhfjfblnclk

 

DOM Monster

DOM Monster is a bookmarklet that will analyze the DOM & other features of the page you're on, and give you its bill of health.

chrome.google.com

DOM을 분석해 최적화 방안을 알려준다.

 

(2) 자바스크립트와 CSS 배치 :  

 

자바스크립트는 이미 생성한 DOM과 CSSOM을 언제든 변경시킬 수 있다.

 

HTML을 해석하는 중 JS 만나면 이를 다운로드하고 수행이 완료될 때까지 DOM 생성 작업을 중단한다.

 

하지만 그때 CSSOM 생성 작업이 진행 중이라면 JS는 CSSOM 생성이 완료될 때까지 수행을 중지하고 대기한다.

 

결론적으로 CSS가 JS보다 더 높은 우선순위를 가진다.

 

CSS를 최대한 소스 위쪽에 배치하여 CSSOM이 가능한 한 빨리 생성되도록 한다.

 

- JS는 최대한 아래쪽에 배치한다.

 

(3) 자바스크립트 최적화하기 :

 

자바스크립트 수행이 렌더링 스레드를 방해하지 않도록 벼로 스레드로 자바스크립트를 수행시켜야 한다.

 

- async 속성 : 

<script src="async_script.js" aysnc> </script>

async 속성은 HTML 구문 분석과 동시에 자바스크립트를 다운로드하고 수행되도록 한다. 

 

- defer 속성 : 

<script src="defer_Script.js" defer> </script>

구문 분석 중에 별도의 스레드로 JS를 다운로드하고 구문 분석이 끝난 이후에 수행되도록 한다.

 

- async, defer 적용 : 페이지에 사용되는 자바스크립트들을 초기 렌더링에 꼭 필요한 그룹과 그렇지 않은 그룹으로 분류해 후자의 그룹에 async, defer 속성을 적용해야 한다.

 

(4) CSS 최적화하기 :

 

- CSSOM이 만들어지기까지 렌더링을 멈추므로 CSS는 렌더링 순위가 높고, 렌더링을 가장 방해하는 리소스다.

 

CSS는 필요한 정보만 빠르게 다운로드하고 실행해야 브라우저 렌더링을 가속시킬 수 있다.

 

- 1 : CSS를 분리하여 필요한 페이지에 필요한 CSS 파일만 포함한다.

 

- 2 : 첫 화면에 사용될 CSS 파일과 숨겨진 화면에 사용될 CSS파일을 분리해 후자의 CSS는 지연 수행시킨다.

 

(5) 이미지 로딩 최적화하기 :

 

- 만약 이미지가 웹 사이트의 주요 이미지가 아니라면 CSS의 background-image 속성을 사용해 원하지 않는 다운로드를 피할 수 있다.

 

- JS를 이용한 지연 로딩 방식을 적용해 불필요한 다운로드를 피한다.

 

- Progressive JPG 활용해 분할 전송 하는 방식이다. 

 

 

 

 

 

5. 사용자 경험 개선

 

(1) 사용자 경험 지표 바로 알기 : 어떤 지표를 사용할지가 중요하다.

 

페이지 로딩 시간 : 많은 웹 사이트의 성능 지표로 사용되고 있지만 자바스크립트를 사용하여 onLoad 이벤트 이후에도 많은 기능들을 처리할 수 있게 됨으로써 "페이지 로딩 시간 = 시각적 완료 시간"이라는 룰은 깨졌다. 

 

사용자 중심의 지표 : 

www.webpagetest.org/

 

WebPageTest - Website Performance and Optimization Test

Select Test Location Moto G (gen 4)Moto G (gen 6)Alcatel 1X (Android Go)Moto G (gen 1)Moto E (gen 1)iPhone 8 (iOS 14)iPhone 7+ (iOS 14)iPhone 6 (iOS 12)iPhone 5c (iOS 10.3)iPad 2017 (iOS 14)iPad Mini 2 (iOS 12)Dulles, VA USA (Desktop, Android, iOS)Dulles,

www.webpagetest.org

사이트의 Speed Index는 시간에 따른 웹 사이트의 시각적 진행 상태를 수치화한 지표로, 값이 작을수록 시각적 진행 상태가 빠르다는 것을 의미한다.

 

(2) 사용자 요청에 빠르게 반응하기 :

 

-사용자 요청에 빠르게 반응하려면 서버의 응답이 빨라야한다. 일반적으로 TTFB가 300~500ms가 이상적이다. 이를 위해서는 전송되는 바이트 크기를 줄여야 한다. 또한 HTML 페이지를 캐시 하여 서버 처리 시간을 최소화해야 한다.

 

- 브라우저가 렌더링을 빠르게 시작하게 하려면 : 

1. CSS와 JS 파일들의 크기를 줄인다. 전체 리소스의 크기를 줄여야 다운로드 속도가 향상된다.

2. CSS와 JS들을 중요 리소스와 그렇지 않은 리소스로 분류한다.

3. 분류된 중요 리소스들을 가능한 빠르게 로딩시킨다.

4. 중요하지 않은 리소스들은 나중에 로딩시킨다.

 

(3) 사용자 시선 붙잡기 : 사용자가 이탈하지 않도록 시선을 붙잡으려면  Hero 이미지가 가능한 빠르게 화면에 로딩되어야 한다.

 

- Hero 이미지가 늦게 로딩되는 이유 : 페이지 로딩 시간을 개선하기 위해 모든 이미지들을 일괄적으로 지연 로딩시키기 때문이다. 일반적으로 브라우저의 프리 로더 스레드가 메인 스레드와는 별도로 페이지 내의 리소스들을 미리 다운로드할 수 있다. 이미지 지연 로딩은 Hero 이미지들을 제외한 나머지 이미지들에 적용해야 한다. 또 다른 이유는 CSS의 background-image 속성으로 지정되었을 경우다.

 

(4) 사용자 상호 작용 방해하지 않기 : 

web.dev/interactive/

 

Time to Interactive

Learn about Lighthouse's Time to Interactive metric and how to measure and optimize it.

web.dev

web.dev/fid/

 

First Input Delay (FID)

This post introduces the First Input Delay (FID) metric and explains how to measure it

web.dev

 

Comments