프론트엔드 성능 최적화

hyeongjundev·2022년 3월 27일
0

웹 사이트를 만드는건 누구든지 할 수 있는 일 입니다. 하지만 웹 사이트를 최적화하고 효율적으로 만드는 것은 개발자만이 할 수 있습니다. 그러면 프론트엔드 성능 최적화를 위해서 개발자는 무엇을 해야 할까요?

먼저, 프론트 엔드 성능은 로딩과 렌더링으로 크게 2가지로 나눌 수 있습니다.

로딩과 렌더링 중 본 포스트에서는 로딩만을 다루겠습니다.

로딩(브라우저 기준)

브라우저에서 로딩 성능은 Navigation Timing을 이용하여 측정합니다.

초록색 부분으로 색칠된 앞 부분은 프론트엔드가 관여하는 부분이 없습니다. 그러므로 뒷 부분만 고려하시면 됩니다. 더 확대 해보겠습니다.

Processing과 Load 과정을 거치며 Processing이 끝났을 때는 DOMContentLoaded 이벤트가 Load가 끝났을 때는 Load 이벤트가 발생하는 모습을 볼 수 있습니다.

DOMContentLoaded 이벤트
- HTML과 CSS 파싱이 끝나는 시점
- 렌더 트리를 구성할 준비가 된(DOM 및 CSSOM 구성이 끝난)상황

load 이벤트
- HTML 상에 필요한 모든 리소스가 로드된 시점

Processing과 Load의 시간을 줄이고 DOMContentLoaded, load 이벤트가 빠르게 fire 되는 것이 프론트엔드 성능 최적화의 목표입니다.

블록 리소스 처리 최적화

브라우저 로딩 초기 단계에서 HTML 파싱이 일어날 때 CSS 또는 자바스크립트로 인해 파싱이 중단될 수 있습니다. 이렇게 파싱이 중단되는 상황을 HTML 파싱이 블록되었다라고 표현하며, 블록 상태의 원인이 되는 리소스를 블록 리소스(Block resource) 라고 부릅니다. 블록 리소스는 브라우저 로딩 단계 중 페인트 과정을 지연시키므로, 블록 리소스가 HTML 파싱을 막는 상황이 발생하지 않도록 해야합니다. 구글에서는 주요 렌더링 경로(Critical Rendering Path)를 최적화하면 페인팅을 빠르게 하고 로딩 속도를 개선할 수 있다고 설명합니다.

CSS 최적화
렌더 트리를 구성하기 위해서는 DOM 트리와 CSSOM 트리가 필요합니다. DOM 트리는 파싱 중에 태그를 발견할 때마다 순차적으로 구성할 수 있지만, CSSOM 트리는 CSS를 모두 해석해야 구성할 수 있습니다. 즉, CSSOM 트리가 구성되지 않으면 렌더 트리를 만들지 못하고 렌더링이 차단됩니다. 이러한 이유로 CSS는 렌더링 차단 리소스라고 하며, 렌더링이 차단되지 않도록 CSS는 항상 HTML 문서 최상단(<head> 아래)에 배치합니다.

<head>
  <link href="style.css" rel="stylesheet" />
</head>

또한 외부 스타일시트를 병렬로 다운로드 할 수 없기 때문에 인라인 스타일을 사용합니다.

<head>
  <style type="text/css">
    .wrapper {
      background-color: red;   
    }
  </style>
</head>

자바스크립트 최적화
자바스크립트는 DOM 트리와 CSSOM 트리를 동적으로 변경할 수 있기 때문에 HTML 파싱을 차단하는 블록 리소스입니다. <script> 태그를 만나면 스크립트가 실행되며 그 이전까지 생성된 DOM에만 접근할 수 있습니다. 그리고 스크립트 실행이 완료될 때까지 DOM 트리 생성이 중단됩니다. 외부에서 가져오는 자바스크립트의 경우에는 모든 스크립트가 다운로드되고 실행될 때까지 DOM 트리 생성이 중단됩니다. 이러한 이유로 자바스크립트도 렌더링 차단 리소스라고 하며, HTML 문서 최하단( 직전)에 배치합니다.

<body>
  <div>...</div>
  <div>...</div>
  <script src="app.js" type="text/javascript"></script>
</body>

또는 async, defer 옵션을 사용할 수 있습니다.

<html>
  <head>
    <script async src="https://google.com/analatics.js" type="text/javascript"></script>
  </head>
  <body>
    <div>...</div>
    <div>...</div>
  </body>
</html>

그러나 개발 패러다임이 변화하면서 DOMContentLoaded, load 이벤트 발생 시점만 가지고 성능을 판단하기 어려워졌습니다. 최근에 많이 사용되는 SPA(Single Page Application)에서는 웹 페이지에 포함된 적은 양의 HTML로 DOMContentLoaded, load 이벤트가 일찍 발생할 수 있으나, 이벤트가 발생한 이후에도 수많은 스크립트 실행으로 인해 여전히 "느린 로딩"이 존재합니다. 이러한 이유로 사용자 기준의 새로운 성능 측정 방식이 필요하게 되었습니다.

사용자 기준 최적화

사용자 기준의 성능 측정은 사용자에게 콘텐츠를 보여주는 여러 시점을 기반으로 합니다. 의미 있는 콘텐츠가 처음 보이는 시점이 빠를수록 성능이 좋다고 판단하며, 이 시점을 앞당길 수 있도록 최적화해야합니다.

아래는 구글에서 주요 렌더링 경로에 대한 그림입니다.

여기서 중요한 것은 FMP(First Meaningful Paint) 입니다. FMP는 사용자에게 의미있는 콘텐츠가 그려지기 시작하는 첫 순간입니다. 콘텐츠를 노출하는데 필요한 CSS, 자바스크립트 로드가 시작되고 스타일이 적용되어 주요 콘테츠를 읽을 수 있습니다.

서버사이드 렌더링, 프리 렌더러와 같은 툴을 이용하여 주요 렌더링 과정을 적용할 수 있습니다.

참고자료

0개의 댓글