중요 렌더링 경로(Critical Rendering Path) 개념 정리

2022. 9. 30. 11:32Front-end

중요 렌더링 경로(Critical Rendering Path)란?

Critical Rendering Path(CRP)는 브라우저가 서버로부터 HTML 응답을 받아 화면을 그리기 위해 실행하는 과정이다.


CRP는 6단계를 거치며 각 단계는 다음과 같다.

  1. DOM 트리 만들기
  2. CSSOM 트리 만들기
  3. JavaScript 실행
  4. Render 트리 만들기
  5. 레이아웃 생성하기
  6. 페인팅

그럼 렌더링(rendering)한다는 것은 무엇일까? 상태(state)를 변수로 받아 그 상태에 따른 화면(view)을 결과물로 출력하는 함수를 떠올려볼 수 있다.

const render = (targetElement, state) => {
	const element = targetElement.cloneNode(true) // 변화를 바로 적용하지 않음
	// DOM 조작
	return element
}

이렇게 render 함수의 결과물로 얻어진 DOM 요소는 원본을 대체하며 새로운 화면을 보여주게 될 것이다.

 

지금까지의 과정도 제법 신기하다. 하지만 HTML을 통으로 갈아 끼웠던 것이 비효율적이었던 것만큼이나 innerHTML로 DOM을 통으로 갈아 끼우는 것 또한(cloneNode로 나름의 최적화를 해보긴 했지만) 제법 비효율적으로 보인다.

 

이 과정을 효율적으로 개선하기 위한 아이디어에 공감하기 위해, 브라우저의 렌더링 과정을 살펴보자.

https://web.dev/howbrowserswork/

 

How browsers work

 

web.dev

프론트엔드 게발자에서 중요 렌더링 경로(Critical Rendering Path) 개념은 굉장히 중요하다. 프론트엔드 개발자의 개발은 결국 이 구조 위에서 일어나는 변화일 뿐이기 때문이다. 위 그림은 복잡해 보이지만 핵심은 HTML과 CSS로부터 문서의 구조와 스타일을 읽어온 뒤, 하나의 화면으로 그려내는 과정이다.

 

HTML과 CSS 파일은 그 자체로는 그냥 문자열일 뿐이며, 이 문서들을 각각 파서(Parser)로 읽어와 의미 단위로 토큰화(Tokenization)한다. 브라우저는 토큰화의 결과물들을 각각 DOM(Document Object Model)과 CSSOM(Cascading Style Sheet Object Model)으로 만들고 실제 화면을 그리기 위한 정보인 렌더 트리(Render Tree)로 변환한다. 렌더 트리에는 시각적으로 보이는 요소들만 포함된다. 즉, head, script, display: none인 요소들은 제외된다.

 

다시 브라우저는 렌더 트리를 기반으로 각 요소가 위치할 자리를 계산(Layout)하고 화면을 그린다(Painting). 중간중간 렌더 트리에 변화가 생기면 그 변화의 범위에 따라 요소가 그려질 범위를 다시 계산하거나 화면에 그린다.

 

위 그림에서 왼쪽이 DOM 트리고 오른쪽이 Render 트리다. 이때 앞서 언급한 레이아웃과 페인팅은 여러 레이어로 나뉘어 작업이 이뤄지므로(쌓임 맥락, Stacking Context ex. z-index) 최종적으로 하나의 결과물로 합치는 과정이 필요하다. 레이어 간 순서를 따져 하나의 화면으로 합성(Composite)하면 모든 과정이 마무리된다.

 

  • 레이아웃(Layout) : 엘리먼트가 화면에서 얼마만큼의 공간을 차지하고 어디에 위치해야 하는지에 대한 정보를 계산하는 단계
  • 페인트(Paint) : 엘리먼트의 색상, 이미지, 테두리, 그림자 등 시각적인 요소를 그리는 단계
  • 합성(Composite) : 페인트 단계까지 나뉘어 있던 레이어들을 하나의 평면으로 합치는 작업

 

어떤 웹 사이트에서 body 바로 밑에 있는 태그의 너비가 변경되었다고 가정해보자. 너비에 해당하는 width 속성은 레이아웃을 발생시킨다. 레이아웃이 변경되었으므로 하위 작업인 페인트와 합성이 모두 일어난다.

 

이번에는 너비 대신 색상이 바뀌었다고 가정해보자. 위치와 공간을 다시 계산할 필요가 없으므로 레이아웃은 생략하고 페인트, 합성이 다시 일어난다.

 

만약 투명도 스타일인 opacity가 변경된다면? 애초에 요소들에 칠해진 색상을 바꿀 필요 없이 레이어를 합성하는 과정에서의 변경만 일어나면 될 것이다. 현재 opacity와 transform만 composite을 트리거하는 CSS 속성인데, 놀랍게도 opacity가 1이 되는 경우는 예외라고 한다.

 

하지만 브라우저가 화면을 렌더링 하는 규칙은 대단히 복잡하고, Layout 이 일어나는 대상 엘리먼트가 최상위 document 객체인 경우가 심심찮게 발생한다. 어떤 노드가 변경되었을 때 정말 레이아웃에 변경이 있을지 없을지 확실히 알 수 없기 때문이다.

반응형