본문 바로가기
CSS

CSSOM이란? (브라우저 렌더링 과정에 대하여)

by F.E.D 2021. 2. 14.

DOM과 CSSOM

첫째, 브라우저에는 자바스크립트 엔진과 렌더링 엔진이 포함되어 있다는 것을 이해하는 것이 중요합니다.

우리는 후자에 초점을 맞출 것입니다.

예를 들어 WebKit (Safari), Blink (Chrome), Gecko (Firefox) 및 Trident / EdgeHTML (IE / Edge)과 관련된 세부 정보를 논의 할 것입니다.

브라우저는 DOM 및 CSSOM을 구성하는 Conversion, Tokenization, Lexing 및 Parsing 프로세스를 거칩니다.

 

  • Conversion : HTML 및 CSS에서 원시 바이트를 읽어냅니다.
  • Tokenization : 입력단위를 청크단위로 나눕니다. (시작태그, 종료태그, 속성이름, 속성값 등). 공백 및 줄바꿈과 같은 관련 없는 문자를 없앱니다.
  • Lexing : Tokenization과 비슷하지만 유형도 식별합니다. (같음 연산자, 숫자, 문자열 등)
  • Parsing : Token화 된 스트림을 가져와서 해석하고 추상 구문 트리로 변환시킵니다.

HTML 및 CSS 트리구조가 모두 생성이 되면 렌더링 엔진은 레이아웃 프로세스의 일부로 데이터 구조를 렌더 트리라고 하는 곳에 연결합니다.

 

렌더트리는 다음과 같은 순서로 동작합니다.

  1. DOM 트리 상의 루트부터 시작해서 각 노드를 순회합니다.
  2. 보이지 않는 노드를 생략합니다.
  3. 표시되는 각 노드에 대해 적절하게 일치하는 CSSOM 규칙을 찾아 적용합니다.
  4. 계산된 스타일과 함께 보이는 노드를 내보냅니다.
  5. 마지막으로 화면에 계산된 스타일을 포함하는 렌더트리를 출력합니다.

* CSSOM은 렌더 트리에 큰 영향을 미칠 수는 있지만, DOM 트리에는 영향을 주지 않습니다.

 

Rendering

레이아웃 및 렌더 트리 구성에 따라 브라우저는 마침내 화면의 실제 페인팅 및 합성을 진행할 수 있습니다. 

  • Layout : 요소가 차지할 공간과 화면의 위치 계산이 포함됩니다.
    부모 요소는 자식 요소에 영향을 미칠 수 있으며 때로는 그 반대의 경우도 마찬가지입니다.
  • Painting : 렌더 트리의 각 노드를 화면의 실제 픽셀로 변환시킵니다.
    DOM을 변경하는 Javascript가 로드되어 여러 번의 페인팅이 발생할 수 있습니다.
  • Compositing : 모든 레이어를 화면에 표시하게되는 최종 이미지로 병합하는 작업입니다.
    합성을 마치면 일부 레이어는 여러 레이어로 그릴 수 있으므로 올바른 순서로 화면에 그려야 합니다.

페인팅 시간은 렌더 트리 구성에 따라 다르며 요소의 너비와 높이가 클수록 페인팅 시간이 길어집니다.

 

다른 효과를 추가하면 페인팅 시간이 늘어날 수도 있습니다.

페인팅은 나중에 Z-Index에 대해 이야기 할 때 다룰 스택 컨텍스트 (뒤에서 앞으로)에서 요소가 스택되는 순서를 따릅니다.

합성을 사용하면 컴퓨터의 CPU를 사용하던 이전 방식에 비해 상당히 큰 속도 향상이 가능합니다. 

will-change 속성은 이를 활용할 수 있는 속성 중 하나입니다.

이를 통해 일부 그리기 및 합성 작업을 GPU로 오프로드 할 수 있으므로 애니메이션이 많은 페이지의 성능이 크게 향상 될 수 있습니다.

스크롤 위치, 내용, 불투명도 및 위쪽 또는 왼쪽 위치에 대해 이점이 있습니다.

 

특이성

<div class="container">
 <div id="main">
  <p>
   <a href="">노엘</a>
  </p>
 </div>
</div>
#main a { 
  color: green;
}
p a { 
  color: yellow;
}
.container #main a {
  color: pink;
}
div #main p a { 
  color: orange;
}
a { 
  color: red;
}

위의 예에서 어떤 색상이 결정될까요?

 

답은 1,1,1의 값을 가진 분홍색입니다. 나머지 결과는 다음과 같습니다.

 

  • div #main p a: 1,0,3
  • #main a: 1,0,1
  • p a: 2
  • a: 1

결정할 수 있는 계산법은 다음과 같습니다.

  1. 첫번째 숫자 : ID 선택자
  2. 두번째 숫자 : 클래스 선택자, 속성 선택자들([rel="nofollow"] [type="text"] 등), 그리고 가상클래스 선택자(:hover, :visited 등)의 개수입니다.  
  3. 세번째 숫자 : 유형(태그)선택자와 가상 엘리먼트들(::before, ::after)의 숫자입니다.
#header .navbar li a:visited

해당 선택자의 포인트는 1,2,2 가 됩니다.

하나의 id와 하나의 클래스, 하나의 의사클래스 및 두개의 유형선택자(li, a)가 있으므로 1, 2, 2 입니다.

Positioning

레이아웃은 전역 스타일 변경의 결과로 전체 렌더 트리에서 트리거되거나 페이지의 더티 부분만 배치되는 점진적으로 트리거 될 수 있는 재귀 프로세스 입니다.

렌더트리를 다시 생각해보면 주목해야할 한가지 흥미로운 점은 절대 위치를 지정하면 배치되는 객체가 DOM트리와 다른 위치에 있는 렌더트리에 배치된다는 것입니다.

flexbox와 float을 동일한 요소에 적용하면 flexbox 레이아웃은 약 3.5ms로 렌더링되는 반면 float 레이아웃은 약 14ms가 걸릴 수 있습니다. 

Z-Index

위치가 지정되지 않은 요소에 Z-Index를 설정하려고하면 아무 작업도 수행되지 않습니다.

Z-Index 문제를 디버깅하기위한 핵심은 스택 컨텍스트를 이해하고 항상 스택 컨텍스트는 루트 요소에서 시작하는 것을 인지하는 것입니다.

하지만, 스택 컨텍스트가 뒤바뀔 수 있습니다.

불투명도는 값이 1보다 작을 때 값이 없음이 아닌 경우 필터링하고 값이 정상이 아닌 경우 혼합

혼합 모드는 실제로 새로운 스택 컨텍스트를 생성합니다.

참고로 블렌드 모드는 특정 레이어의 픽셀이 그 아래 레이어의 보이는 픽셀과 상호 작용하는 방식을 결정합니다.

또한 transform 속성은 값이 none이 아닐 경우 새 스택 컨텍스트를 트리거 합니다.

예를 들어, scale(1) 및 translate3d(0,0,0). 다시 말하지만, scale 속성은 크기를 조정하는 데 사용되며 translate3d는 CSS 전환을 위해 GPU를 작동시켜 더 매끄럽게 만듭니다.

해당 Z-Context 라는 크롬 개발자 확장 도구를 사용하면 Stacking 요소들과 그렇게 된 이유를 알 수 있습니다.

 

출처 : medium.com/free-code-camp/its-not-dark-magic-pulling-back-the-curtains-from-your-stylesheets-c8d677fa21b2

댓글