본문 바로가기
General

브라우저 렌더링 성능 최적화 방법

by Awesome-SH 2021. 10. 14.

 

Reflow, Repainting

흐름

맨 처음 브라우저가 로딩될 때 렌더링 과정을 통해 화면이 그려짐

-> 그려진 화면은 자바스크립트에 의해 DOM 트리, CSSOM 트리가 변경될 때 재구성 됨

 

Reflow

DOM이 추가, 삭제 되거나 DOM 요소의 너비, 높이, 위치 등의 기하학적 영향을 주는 CSS 내용이 변경될 경우 '렌더 트리'가 재구성 된다. 이것을 'Reflow(재배치)' 라고 한다.

 

Repaint

기하학적 영향을 주지 않는 CSS 속성이 변경되었을 경우에는 Reflow 과정을 건너뛰고 Paint 과정부터 수행한다.

 

'Reflow'가 일어나면 전체 픽셀을 다시 계산하여 재배치하는 과정을 거치기 때문에 부하가 ↑

'Repaint'는 재배치 과정을 건너뛰고 화면에 그리는 작업만 수행하기 때문에 부하가 ↓

 

Reflow 되는 CSS 속성

: top, left, right, bottom, width, height, line-height, font-size 등

 

Repaint 되는 CSS 속성

: background-image, color, visibility, outline 등

 

'Reflow'와 'Repaint' 가 일어나면 렌더링 시간이 늘어나게 되기 때문에 불필요한 'Reflow'와 'Repaint'를 없애기 위해 신경써야 한다.

 

 

로딩 최적화

블록 리소스 최적화

'블록 리소스'란 HTML이 파싱될 때, CSS나 자바스크립트로 인해 파싱이 중단되는 경우가 있는데 이렇게 HTML 파싱을 막는 CSS, 자바스크립트의 리소스를 '블록 리소스'라고 한다.

 

렌더링 차단 리소스

렌더 트리를 구성하기 위해서는 DOM 트리와 CSSOM 트리가 필요하다. DOM 트리는 파싱 중에 태그를 발견할 때마다 '순차적'으로 구성을 하지만 CSSOM 트리는 CSS를 모두 해석해야 다음 순서로 넘어가게 된다. 즉, CSSOM 트리가 모두 해석되지 않고 구성되지 않으면 렌더 트리를 끝까지 만들지 못하고 렌더링이 차단된다. 이러한 이유로, CSS를 '렌더링 차단 리소스'라고 하고 렌더링이 차단되지 않도록 CSS는 가능하면 <HEAD></HEAD> 태그 안쪽에 배치해야 한다. 특정한 경우에서만 사용하는 CSS를 불러올때는 미디어쿼리를 사용하여 CSS를 분리 후, 필요할 때만 로드될 수 있도록 하는 것이 좋다.

 

예)

<link rel="stylesheet" href="main.css">

<!-- 인쇄할 경우 -->
<link rel="stylesheet" href="main_print.css" media="print">

<!-- 세로모드일 경우 -->
<link rel="stylesheet" href="main_portrait.css" media="orientation:portrait">

 

자바스크립트 최적화

자바스크립트는 DOM 트리와 CSSOM 트리를 '동적'으로 제어하고 변경할 수 있기 때문에 블록 리소스에 해당한다. <script>태그를 만나면 스크립트가 실행되고 해당 <script> 태그 이전에 생성된 DOM 에만 접근이 가능하다. 스크립트가 실행되는 동안에는 DOM 트리 생성은 중단된다.  때문에 <script> 태그는 모든 DOM 요소가 생성된 이후에 가져오는 것이 '블록 리소스'를 최소화 하는 좋은 방법이다 </body> 직전에 배치

 

예)

<body>
	<div>test</div>
	<p>test desc</p>
	<script type="text/javascript" src="src.js"></script>
</body>

 

리소스 요청 최소화

이미지 스프라이트

사용 용도에 맞게 아이콘들을 하나의 이미지로 합쳐서 이미지 스프라이트를 사용하게 되면 여러번 불러와야 할 이미지들을 한번만 불러와서 이미지 요청을 최소화 할 수 있다.

 

예)

/* background-position 값을 이용하여 이미지 위치 표현 */

.facebook{background:url(./ic_sns.png) -150px 0 no-repeat; width:150px; height:150px;}

 

리소스 용량 줄이기

  • 중복되는 코드 줄이기
  • HTML 마크업 최적화 : HTML의 DEPTH가 깊어지면 렌더링 속도에 영향을 준다
  • 간결한 CSS 선택자 사용 : DEPTH가 깊어지지 않도록

display: none 속성 사용

  • display: none; 속성을 사용해 요소를 숨기면 DOM 트리를 구성할 때

숨겨진 영역제외하고 DOM 트리 생성 리플로우나 리페인트도 발생하지 않음

초기 로딩에서 필요하지 않은 영역의 경우 display: none 으로 숨겨서 노출하는 것도 로딩 속도 향상을 위한 방법 중 하나

 

*visibility: hidden 속성은 숨김영역이 공간을 차지한 상태로 보여지지 않는 것이기 때문에 DOM 트리 구성에 포함이 되니 유의해야한다.

 

레이지 로딩(Lazy Loading)

이미지에 대한 로딩을 뒤로 미루는 것을 의미한다. 어떤 이미지를 로딩할 필요가 있으면 그 때(그 시점)에 이미지를 불러오는 것을 말한다. 일반적인 적용 예로는 스크롤 이벤트 등으로 구현 된다. 스크롤 이벤트 리스너 < 인터섹션 옵저버를 사용하는 것이 더 좋은 방법이다

 

*인터섹션 옵저버(Intersection Observer API)는 어떤 엘리먼트가 화면에 노출 되었는지 관찰, 감시할 수 있고 entries 콜백으로 타겟 엘리먼트가 들어온다. isIntersecting은 Boolean 값을 리턴하는데 현재 화면에 타겟이 들어왔는지 아닌지 판단하고 disconnect 메서드를 이용해 observer를 없앨 수 있다

 

트리 쉐이킹 (Tree Shaking)

해당 모듈에서 실제로 사용하고 있는 코드만 빌드하려면 어떻게 할 수 있을까?

이럴 때 사용하는 것이 Tree Shaking이다 불필요한 코드를 빌드하지 않도록 Shaking 하는 것을 뜻한다

이 외에도

 

 

  • Keep-Alive 커넥션연결을 통해 연속적인 리소스를 절약
  • 좋은 성능의 콘텐츠 압축률 방식인 gzip 인코딩을 통해 이미지 데이터를 전송
  • 리버스 프록시 서버 용 Nginx 활용하여 정적 파일 처리 성능 향상 및 보안성 향상
  • 자체 CDN 서버를 통해 유저 공용 캐시 서버 활용
  • 이미지를 차세대 포맷 형식인 webp 이용
  • prefetch와 XHR을 이용한 미리 가져오기 기능 활용 <link rel=prefetch>
  • XHR(XMLHttpRequest)// 새로운 XHR 요청 생성 const xhrRequest = new XMLHttpRequest(); // 리소스를 미리 가져오기 위해 요청 open xhrRequest.open('GET', '../bundle.js', true); // 요청 보내기 xhrRequest.send();

 

 


 

 

 

Ref.

https://chanyeong.com/blog/post/43 

댓글