🐶 브라우저는 CSS를 어떻게 읽을까?
브라우저에서 DOM을 만들게 되면, 우리가 정의한 CSS를 병합해서 CSSOM을 만든다. 즉, 브라우저가 html파일을 읽고 DOM을 만들었다면, 모든 style과 관련된 정보들을 DOM과 합해서 CSSOM 트리를 다시 만들게 된다. 그리고 우리가 정의한 style 뿐만 아니라 브라우저에서 기본적으로 설정된 모든 속성값들을 cascading rule에 따라서 정의한다. 따라서, cascading rule에 따라 부모 요소에 설정한 값이 자식요소에도 적용된다. CSSOM에는 모든 계산된 style에 관련된 속성들이 다 포함되어 있다.
🐶 Render Tree는 무엇일까?
브라우저가 Html파일을 읽게 되면 DOM트리를 만들고, 그 다음 CSS파일을 읽고 style을 계산해서 CSSOM 트리를 만든다. 이제 그다음, DOM과 CSSOM을 합해서 최종적으로 브라우저에 표기될 아이들만 Render Tree에 선별되어져 보이게 된다. 즉, 결과적으로 사용자에게 보여지는 아이들만 선별되어져 DOM과 CSSOM이 합쳐져서 최종적인 Render Tree가 만들어진다. 예를 들면 DOM트리에 있는 head태그는 사용자 눈에 보이지 않기 때문에 Render Tree에 없다. 그리고 만약 어떤 요소가 display가 none이 되면 사용자에게 보여지지 않으므로 Render Tree에 포함되지 않는 것도 같은 이치다. 그런데 만약 opacity가 0이나, visibility가 hidden으로 설정되어 있다면, 사용자 눈에는 보이지 않지만 사실 요소는 그대로 있는 것(투명일뿐이거나 숨겨져있거나)이라서 Render Tree에서 볼 수 있다.
🐶 CRP는 무엇인가?
지금 우리가 보고 있는 화면의 모든 것들을 나타내기 위해 브라우저가 일하는 순서. 말그대로 렌더링순서.
순서는 그럼 어떻게 진행될까?
url입력 -> request / response -> loading -> scripting -> rendering -> layout -> painting 의 순서로 진행된다.
✏️ request / response : 브라우저가 서버에게 html 파일을 요청하거나 서버에 request를 하면 가장 먼저 index.html파일을 받아오고 그 파일안에서 링크된 필요한 파일들(css, js)을 받아오고, 필요한 리소스(이미지, 폰트 등)들을 순차적으로 서버에서 받아온다.
✏️ loading : html파일을 서버에서 받아 로딩한다.
✏️ scripting : html파일을 읽고 DOM트리를 생성하고, css스타일을 모두 계산해서 CSSOM트리를 생성한다.
✏️ rendering : 브라우저에 표기될 요소들만 선별하여 Render Tree를 생성한다.
✏️ layout : Render Tree 각 요소들의 위치와 크기를 계산한다. (Render Tree를 이용해서 윈도우에서 어디에 배치해야할지 레이아웃을 구상한다. DOM요소와 CSS스타일 등 최종적으로 계산된 CSS로 어디에 어떻게 그려야할지 계산)
✏️ painting : 브라우저에 그리기
_
DOM 과 SSOM 과정은 scripting 단계이고, Render Tree는 rendering 단계, Layout은 layout 단계, Paint와 Composition은 painting 단계 라고 할 수 있다.
✏️ Layout 단계 : 요소들이 어떻게 그려져야 될지 계산되어지고,
✏️ Paint 단계 : 계산한 요소들을 어떻게 배치했냐에 따라서 각각의 부분을 조금씩 나누어서 이미지를 준비해놓는다. 그리고 다양한 속성값에 따라 브라우저 엔진마다 성능 개선을 위해 레이어를 만든다. 예를 들어, z-index가 있는 요소라면 따로 레이어를 만들어 놓거나 will-chiange가 스타일로 적용된 요소라면 따로 레이어를 만들어놔서 미리 변할 것을 준비시킨다. 각요소에 레이어를 만들면 수정이 쉬우므로 브라우저는 paint과정을 거쳐 출력한다.
✏️ Composition 단계 : 미리 준비한 레이어를 순서대로 차곡차곡 브라우저 위에 표기한다.
그리고 우리는 DOM, CSSOM, Render Tree 단계들을 묶어서 "Construction"이라고 하고 Layout, Paint, Composition 단계들을 묶어서 "Operation"이라고 한다.
✏️ Construction : html파일을 브라우저가 이해할 수 있도록 브라우저의 언어로 바꾸는 부분 (time to first render)
✏️ Operation : construction part에서 생성된 Render Tree를 이용해서 브라우저에 표기할 요소의 위치, 크기 등을 계산하고 사용자에게 보여줄 것을 그리는 부분 (performance user interaction)
💡 will-change : 변경될 요소를 따로 작성하면 레이어를 따로 만들어서 paint 한다. (성능향상을 위해 레이어 단위로 준비하여 그 부분만 다시 그린다)
브라우저가 렌더링 하기 전 CSSOM을 만들고나서, 요소들의 특징에 따라 브라우저 렌더링이 효율적일 수 있게 레이어를 만들어준다. 그걸 유일하게 강제 할 수 있는게 "will-change"이다. will-change 말고 레이어를 분리할 수 있는 속성은 따로 명확하게 나와있지 않지만, 또 브라우저마다 다르지만 보통은 video태그, canvas태그, 3d filter 관련 css 속성들, z-index가 있다.
(z-index를 준다고 레이어가 항상 따로 분리되는 것은 또 아니다. 레이어가 많으면 많을수록 메모리를 많이 차지하기 때문에 개별 레이어로 개별적으로 페인트가 다시 되어야하지 않는다면 같은 레이어로 묶여서 표기될 수 있다.)
: 자바스크립트나 CSS로 DOM요소를 조작할 때, Composition 과정만 다시 일어나게 하는게 좋다.
why?
예를 들어, 브라우저의 성능을 고려한다고 할 때, translate을 이용하여 한 요소를 옮기면 레이어의 위치만 바꾸면 되는 Composition만 일어난다. 하지만 위치가 바뀌면서 무언가 그림이 더해진다면 Paint가 다시 발생하고 Composition이 일어난다. 게다가 레이어의 위치가 바뀌면서 주변의 요소들도 바뀌어야 한다면 Layout이 다시 시작 되어야 하고, Paint, Composition 단계가 다시 시작되어야하므로 성능이 나빠질 수 밖에 없다.
그렇기 때문에 우리는 Composition만 다시 일어나게 하는게 좋다. (Paint단계로 다시 돌아가는 것은 괜찮지만, Layout 단계까지 돌아가는 것은 좋지 않다.)
tip: transform-tanslatedms composition만 거치면 됨.
출처
드림코딩아카데미 브라우저 101