웹 개발

주요 렌더링 경로 최적화(Optimizing the Critical Rendering Path)

spideyDev 2021. 7. 28. 18:38

주요 렌더링 경로 최적화

주요 렌더링 경로(Critical Rendering Path)

  • 브라우저가 HTML, CSS, Javascript를 화면에 픽셀로 변화하는 일련의 단계.
  • DOM(Document Object Model), CSSOM(CSS Object Model), 렌더 트리, 레이아웃 등의 데이터 구조를 생성하는 과정을 가진다.
  • 데이터 구조를 생성하는 과정이 모두 끝나고 나서야 페이지가 화면에 그려지기 때문에 웹 성능을 향상하기 위해서는 CRP 과정을 최적화해야 한다.

DOM(Document Object Model)

  • HTML 마크업을 바이트 → 문자 → 토큰 → 노드 → 객체모델로 변환하는 과정을 거쳐 만든 트리 형태의 데이터 구조
  • HTML을 DOM으로 변환하는 과정
    1. HTML의 원시 바이트를 디스크나 네트워크에서 불러와 해당 파일에 대해 지정된 인코딩에 따라 개별 문자로 변환한다. (바이트 → 문자)
    2. 브라우저가 문자열을 W3C HTML5 표준에 지정된 고유 토큰으로 변환한다. (문자 → 토큰)
    3. 변환된 토큰을 해당 속성 및 규칙을 정의하는 객체(Node)로 변환한다. (토큰 → 노드)
    4. HTML 마크업에서 정의한 태그 간의 관계에 따라 노드 트리 데이터 구조를 생성한다. (노드 → 객체 모델)
  • Javascript를 사용해 DOM에 접근하고 수정할 수 있다.

 

CSSOM(CSS Object Model)

  • HTML 마크업 대신 CSS 마크업을 사용한다는 점을 제외하고는 DOM을 생성하는 과정과 동일한 과정을 거쳐 생성된다.
  • 객체의 최종 스타일을 계산할 때 상위 노드의 스타일을 상속받는 '하향식' 방식을 사용하기 때문에 트리 구조를 가진다.

 

렌더링 트리

  • 완성된 DOM과 CSSOM을 결합하여 렌더링 트리를 생성한다.
  • 각 요소의 레이아웃을 계산하고 픽셀을 화면에 렌더링 할 때 사용된다.
  • DOM 트리에서 각 노드에 스타일 정보가 추가된 형태.
  • 스크립트 태그나 메타 태그 등 표시되지 않는 노드들은 렌더링 트리에 포함되지 않는다.
  • 스타일에 'display:none' 속성이 있는 노드 및 하위 노드들은 렌더링 트리에 포함되지 않는다.
  • 'visibility: hidden'의 경우에는 'display:none'과 다르게 렌더링 트리에 포함되고 크기가 0인 상태로 레이아웃에 포함된다.

 

레이아웃

  • 기기의 뷰포트 내에서 노드의 정확한 위치와 크기를 계산하는 단계.
  • 뷰포트 너비의 기본값은 일반적으로 960px이고, 스마트폰의 브라우저 같은 경우에는 '<meta name="Viewport" content="width=device-witdh">'를 사용해 뷰포트 너비 대신 디바이스의 너비를 사용한다.
  • 노드의 위치와 크기를 뷰포트 기준으로 계산하기 때문에 리사이즈나 디바이스 회전 등 너비가 변경되면 레이아웃을 새로 계산한다.
  • 성능을 향상하기 위해서 레이아웃 계산이 자주 일어나지 않도록 해야 한다.

 

페인트

  • 레이아웃에서 계산된 노드의 정보를 화면에 픽셀로 그리는 단계. 페인팅 또는 래스터화라고 한다.
  • 스타일이 복잡할수록 페인팅에 걸리는 시간도 늘어난다.
  • 소요시간이 매우 짧은 과정이지만 복잡한 애니메이션으로 리페인트가 자주 발생하면 성능 이슈가 발생할 수 있다.

최적화 방법

  • DOM 트리 생성, CSSOM 트리 생성, 렌더링 트리 결합, 레이아웃 계산, 페인팅 이 5가지 과정에 걸리는 시간을 최소화하는 작업.

미디어 유형, 미디어 쿼리 사용하기

<link href="style.css" rel="stylesheet"> 
<link href="print.css" rel="stylesheet" media="print"> 
<link href="other.css" rel="stylesheet" media="(min-width: 40em)">

 

  • CSS는 CSSOM이 생성되기 전에 화면을 그릴 수 없기 때문에 렌더링 차단 리소스다. 불러와야 하는 렌더링 차단 리소스의 크기가 클수록 초기 로딩이 길어진다.
  • 렌더링 트리에서는 화면에 표시되는 노드의 스타일만을 가져오지만 그전에 만들어지는 CSSOM은 DOM과 독립적이기 때문에 어떤 요소들이 화면이 표시되는지 모른다. 그래서 사용하지 않는 요소들까지 모두 포함시켜 CSSOM을 생성한다.
  • 미디어 유형, 미디어 쿼리를 사용하면 조건에 해당되지 않는 CSS 리소스를 불러오지 않기 때문에 당장 필요 없는 요소들은 CSSOM에 포함되지 않고 CSSOM을 빠르게 생성할 수 있다.

 

Javascript 최적화

  • Javascript는 DOM 및 CSSOM을 수정할 수 있다.
  • Javascript, DOM, CSSOM 간에는 의존성이 존재한다.
    • HTML을 파싱 하면서 DOM을 생성하는 중 스크립트 태그를 만나면 해당 스크립트가 DOM 구조에 영향을 줄 수 있기 때문에 DOM 생성을 중단하고 해당 스크립트를 실행한다.
    • 스크립트에서 CSSOM에 접근할 수 있기 때문에 CSSOM 생성이 완료될 때까지 스크립트 실행을 지연한다.
  • HTML의 중간에 스크립트 태그가 있으면 CSS 리소스를 가져오고 CSSOM의 생성이 완료될 때까지 HTML 파싱 및 DOM 생성이 중단된다.
  • 이러한 의존성을 고려하여 DOM 및 CSSOM에 영향을 주지 않는 스크립트는 비동기로 처리하고 스크립트 태그의 위치를 설정해야 한다.

 

script 태그의 async 속성 사용

<script src="app.js" async></script>
  • 위와 같이 스크립트 태그에 async 속성을 사용하면 HTML 파싱이 끝나고 DOM이 완성된 뒤 스크립트를 실행하게 된다.

 


 

  •  최근에는 PC, 모바일 브라우저 성능이 좋기 때문에 DOM 생성, CSSOM 생성, 렌더링 트리 생성, 레이아웃 계산 , 페인팅 과정의 소요 시간이 리소스를 다운로드하는 시간에 비해 상대적으로 짧다.
  • 그래서 HTML이나 CSS의 크기가 매우 큰 상황이 아니라면 폰트나 이미지 등 크기가 큰 리소스 최적화가 우선순위가 높다.
  • 참고한 문서들에서는 초기 렌더링 시간 최적화에 대해 얘기하기 때문에 DOM과 CSSOM의 수정이 자주 일어나는 환경에서 주요 렌더링 경로를 최적화하는 방법에 대해 추가적으로 공부해 볼 필요가 있을 것 같다.

참고자료