일단 일반적인 CRP 과정부터 이야기 해보자.
CRP에 대해 이야기 하기전에 개념부터 잡자
DOM (DOCUMENT OBJECT MODEL)은 문서객체모델 트리는 완전히 구분 분석된 HTML 페이지를 의미한다.
쉽게 우리는 개발자도구를 통해 DOM을 볼수 있다. 이 DOM은 HTML이 브라우저의 렌더링 엔진에의해 파싱되면서 구문을 위에서 아래로 분석하는데 이 구문 분석이 모두 끝나고 HTML파일이 DOM이다. DOM이 CSSOM과 다른점은 부분적으로 문서를 로드할 수 있다는 점.
CSS (CSS OBJECT MODEL)은 DOM과 관련된 스타일의 객체표현. CSS는 렌더링 차단 리소스로 간주되서 이 CSS리소스가 완전히 구문분석되지 않고는 렌더 트리를 구성할 수 없다. 즉 DOM과 달리 완전히 CSSOM이 만들어질때까지 렌더트리에 포함되지 않는다.
단 orientation:lanscape 같은 속성이 있는 스타일의 경우 해당 속성일 경우만 적용되기 때문에 이런경우는 렌더링 차단으로 간주되지 않는다. 즉 현재장치에 적용되는 경우에만 렌더링 차단으로 간주됨.
또한 CSS는 스크립트차단 리소스가 될 수 있다.
왜냐하면 렌더링 엔진이 자바스크립트가 실행되는 구문에 도달하게되면 렌더링엔진은 자바스크립트 런타입엔진에 역할을 내어준다. 왜냐하면 브라우저는 싱글쓰레드이기 때문에
자바스크립트파일을 다운받고 실행이 되기전까지 DOM, CSSOM은 진행되지 않는다. 따라서 자바스크립트소스는 가장 마지막에 참조되는 것이 좋다
어차피 자바스크립트가 dom을 조작하려고 하는경우라면, dom과 cssom이 없으면 제대로 동작하지 않기에...
하지만 dom조작을 하지 않는 스크립트의 경우 가장 상단에 오는 경우가 있을 수 있지만 알다시피 이 스크립트 부분에 구문분석이 되면 다운로드 및 실행전까지 렌더링엔진은 동작을 하지 않는다.
자바스크립트는 파서차단 리소스
이다. 즉 HTML문서 자체의 구분분석이 javascript에 의해 차단되기 때문이다. 파서가 태그에 도달하면 실행을 중단한다. 하지만 만약 이를 async속성을 적용하면 비동기적로드를 할수있다.
<script async src="script.js">
그림을 보면 알겠지만 서버로부터 html을 받아오면 렌더링엔진으로부터 DOM이 빌드되는데 구분분석이 시작되면서 CSS, JS와 관련된 구문을 만나면 DOM렌더링은 각각의 실행이 끝날때까지 중단되고 이후 DOM빌드를 마무리한다.
아래 과정은 링크에서 발췌한 내용입니다. 엄청 정리가 잘 되어 있습니다.
렌더트리는 DOM과 CSSOM의 조합이다. 페이지에서 최종적으로 렌더링될 내용을 나타내는 트리인데. 보이는 부분만 적용되고 display:none
과 같이 보이지 않는 부분은 포함되지 않는다.
DOM과 동일한 과정을 통해 CSSOM이 변환된다.
이렇게 생성된 DOM과 CSSOM이 만나서 렌더트리가 만들어진다. 즉 렌더트리는 화면에 표시되는 모든 노드의 콘첸츠 및 스타일 정보를 모두 포함한다.
이렇게 렌더트리가 마무리 된 과정까지를 construction 파트 이후 단계를 operation 파트로 구분한다.
렌더트리에는 노드와 노드의 스타일만 계산되어 있다. Layout에서는 화면에 표시될 노드의 정확한 위치와 크기를 게산한다.
이후 다음 과정을 통해 화면포출이 완료된다.
사용자의 화면이 변경될때 다음 3가지 단계가 있을 수 있다.
3-1. 만약 레이아웃(width, height, left, top 등 layout속성)에 영향을 주는 스타일 속성이 변한다면
화면은 리플로우(가장 안좋은..)를 수행한다. 즉 렌더트리 생성이후 단계를 반복한다는 의미이다.
js > style > layout > paint > composition
3-2. 레이아웃에 영향을 주지 않는 배경이미지, 텍스트 색상 그림자 등 paint속성만 변경한다면
화면은 layout을 건너띄고 아래와 같이 동작한다.
js > style > paint > composition
3-3. 레이아웃과 페인트 속성의 변경이 없다면
화면은 layout, paint단계를 건너띄고 다음과 같이 동작한다.
js > style > composition
Navigation Timing API는 웹사이트의 성능을 측정하는데 사용할 수 있는 데이터르 제공한다.
// 로딩시간 측정법
function onLoad() {
var now = new Date().getTime();
var page_load_time = now - performance.timing.navigationStart;
console.log("User-perceived page loading time: " + page_load_time);
}
// 어떤 페이지를 로딩하는데 필요한 전체 시간 계산하기
var perfData = window.performance.timing;
var pageLoadTime = perfData.loadEventEnd - perfData.navigationStart;
// 요청 응답 시간 계산하기.
var connectTime = perfData.responseEnd - perfData.requestStart;
processing
domLoading
domInteractive
domContentLoaded
domComplete
Load
loadEvent