Critical Render Path(CRP)
브라우저가 HTML, CSS, Javascript 를 화면에 픽셀로 변화하는 일련의 단계를 말한다. 이를 최적화 하는 것이 어플리케이션 응답속도를 개선할 수 있다. Critical Render Path
는 Document Object Model(DOM), CSS Object Model(CSSOM), Render Tree 그리고 Layout을 포함한다.
Critical Render Path(이하 CRP)
를 최적화하는 것은 첫번째 렌더링 시간(First Contentful Paint, FCP)를 개선시킨다. Critical Render Path를 이해하는 것은 사용자 상호작용을 보장하며, 버벅거림을 피할 수 있도록하며, 1초당 60 프레임에 리플로우와 리페인트가 발생할 수 있도록 하는데 중요하다.
CRP 이해하기
웹성능은 서버의 요청과 응답, 로딩, 스크립팅, 렌더링, 레이아웃 그리고 화면에 픽셀 그리기를 포함한다.
브라우저 주소창에 URL을 입력하여 요청을 보내면 서버로부터 HTML 문서를 받아오게 된다. 이것을 파싱하기 시작하면서 브라우저가 데이터를 화면에 그리는 과정이 시작된다.
브라우저는 HTML을 분석하고 수신된 bytes를 DOM Tree로 변환하기 시작한다. 불러온 assets을 핸들링할 때까ㅣ 나머지 HTML을 분석하는 작업하는 일부 요청은 중단되며 차단된다. 브라우저는 CSSOM을 구축하는 작업이 끝날때까지 요청을 만들고 DOM을 생성하는 HTML을 계속해서 분석한다. 즉, DOM, CSSOM Tree 구축 과정은 병렬로 이루어진다. 모든 작업이 완료되면 렌더 트리를 생성하고 보여지는 컨텐츠를 위해 스타일을 계산한다. 렌더트리가 완료된 이후 렌더트리 요소들에 대한 계산된 위치와 크기를 적절하게 배치시킨다. 이렇게 레이아웃이 만들어진다. 레이아웃 생성을 완료하면 페이지는 렌더링되거나 화면에 그려진다.
과정
- HTML 데이터 파싱
- DOM 트리 만들기
- CSSOM 트리 만들기
- Render 트리 만들기
- 레이아웃(Reflow) 생성하기
- 페인팅
Document Object Model(DOM)
DOM 구성은 점진적으로 증가한다. HTML응답은 토큰으로, 토큰은 노드로, 노드는 DOM트리로 변환된다. 노드들은 HTML 요소에 대한 모두 연관성 있는 정보를 포함하고 있다. 해당 정보는 토큰을 통해 설명된다.
DOM 트리는 브라우저가 HTML 문서를 로드한 후 파싱하여 생성하는 모델을 의미
- 문서 노드(Document node): DOM의 진입점(시작점)으로 트리의 최상위에 존재한다.
- 요소 노드(Element node): 태그, HTML 요소
- 속성 노드(Attribute node): 요소의 자식이 아닌 요소의 일부로 표현. 해당 요소 노드를 찾아 접근하면 어트리뷰트를 참조, 수정이 가능
- 텍스트 노드(Text node): 요소내의 문자열. 자식 노드를 가질 수 없고, 트리의 끝에서 잎 노드가 된다.
- 주석 노드(Comment node): 주석
DOM 트리의 루트에서 시작하여 표시되는 각 노드를 트래버스한다. 일부 노드는 (script, meta, style 태그 등) 렌더링 출력에 반영되지 않으므로 생략한다. 일부 노드는 CSS를 통해 숨겨지며, 렌더링 트리에서도 생략한다.
많은 수의 노드는 CRP에서의 이벤트를 더 오래 발생시킬 것이다. 몇개의 노드를 추가하는 것은 많은 차이를 만들어내는것 같지만, 이러한 노드가 많아질 수록 버벅거림을 유발할 수 있다.
CSS Object Model(CSSOM)
CSS내용을 파싱하여 자료를 구조화한 것을 CSSOM 이라 한다. DOM은 페이지의 모든 컨텐츠를 포함하고, CSSOM은 DOM을 스타일링 하기 위한 페이지의 모든 스타일정보를 포함한다. DOM의 구조는 점진적으로 증가하지만, CSSOM은 그렇지않다. CSS는 렌더링을 막는다. CSS를 처리하고 수신할때까지 페이지 렌더링을 막는다. 왜냐하면 CSS는 규칙을 덮을 수 있기 때문에 렌더링을 막는다.
CSS는 유효한 토큰들을 인식하기 위해 스스로 규칙 세트를 갖고 있다. CSS규칙은 하위에 종속된다. 연속적인 규칙들이 이전의 규칙들에 덮어 쓰여질 수 있기 때문에, 증감처리 기술은 HTML처럼 CSS에 적용되지 않는다. CSS 개체 모델은 CSS 분석할 때 빌드되지만 나중에 분석되어 덮어쓸 스타일들은 화면에 렌더링 할 수 없기 때문에 완전히 분석될 때까지 렌더트리를 생성하는데 사용할 수 없다.
규칙이 더 구체적이고 길어질수록 DOM트리 안에서 더 많은 노드들을 지나야 하기 때문에 더 높은 비용이 든다. 하지만 최근 브라우저는 엄청난 속도로 CSS 분석을 하기 때문에 선택자 성능 최적화를 한다고 해도 오직 microsecond 수준의 개선 밖에 되지 않을 것이다. CSS를 논-블로킹 요청하여분리하는 것과 같은 CSS 최적화 방법도 있다.
Render 트리 만들기
렌더 트리는 DOM과 CSSOM을 합한 후 최종으로 브라우저에 표기될 것들만 렌더 트리에 선별되어 생성된다. 출력되는 화면은 모든 컨텐츠와 스타일정보를 포함하는데, 렌더링 트리가 이 정보를 모두 갖고 있다. 렌더 트리를 구성하기 위해 브라우저는 DOM 트리의 root에서 시작해 모든 노드는 확인하면서 어떤 CSS 규칙들을 첨부할지 결정한다. 렌더 트리는 표시되는 각 요소의 레이아웃을 계산하는데 사용되고, 픽셀을 화면에 렌더링하는 페인트 프로세스에 대한 입력으로 처리가 된다. 렌더링 트리가 준비되면 레이아웃 단계(Reflow)를 진행 가능하다
레이아웃 단계
표시해야할 노드와 스타일을 계산했지만, 기기의 표시 영역 내에세 노드의 정확한 위치와 크기를 계산하진 않았다. 레이아웃은 화면 크기에 의존되며, 레이아웃 프로세스의 출력은 상자모델(box model)
로 표시 영역 내 각 요소의 정확한 위치와 크기를 정확하게 캡처한다. 표시되는 노드와 해당 노드의 계산된 스타일 및 도형을 알고 있으므로 이 정보를 최종 단계인 페인트 단계로 전달한다.
레이아웃 성능은 DOM의 영향을 받는다. 노드의 수가 많을수록 레이아웃은 더 길어지며, 스크롤링 또는 다른 애니메이션이 필요하다면 병목현상이 발생할 수 있다. 노드에 박스모델 업데이트, 컨텐츠 대체 그리고 노드 추가와 같은 수정은 언제든지 렌더 트리를 수정할 수 있다.
페인트 단계
렌더링 트리의 각 노드를 각 화면의 실제 픽셀로 변환하는 단계이다. 래스터화
라고 부르기도 한다. 렌더 트리가 생성되고, 레이아웃이 구성되기 시작하면 화면에 픽셀을 그릴수 있다. 페인팅은 매우 빠르게 진행되는 과정이기 때문에 성능향상에 집중해야 하는 큰 영향범위의 부분은 아닐 수 있다.
요약
- DOM트리와 CSSOM 트리가 결합되어 렌더링 트리를 형성
- 렌더링트리에는 페이지를 렌더링하는데 필요한 노드만 포함
- 레이아웃은 각 객체의 정확한 위치와 크기를 계산
- 마지막 단계는 최종 렌더링 트리에서 가져와 화면에 픽셀을 표시하는 페인트 단계