브라우저는 CSS를 다운로드하고 CSS 개체 모델을 빌드해 페이지를 그릴 수 있다.
스타일이 지정되지 않은 페이지를 페인팅한 다음,
스타일이 구문 분석된 후 다시 페인팅하면 나쁜 사용자 경험이 된다.
브라우저는 특정 렌더링 경로를 따른다.
브라우저 렌더링은 페인트는 레이아웃, 렌더링 트리가 생성된 후에 발생한다. (DOM과 CSSOM 트리가 모두 필요하다.)
CSSOM 구성을 최적화하려면
1. 불필요한 스타일을 제거하고
2. 축소, 압축 및 캐시하고
3. 페이지 로드 시 필요하지 않은 CSS를 추가 파일로 분할하여 CSS 렌더링 차단을 줄여야 한다.
CSS는 미디어 쿼리를 사용하여 특정 조건에 대한 스타일 범위를 지정할 수 있다.
미디어 쿼리는 반응형 웹 디자인에 중요하며, 렌더링 경로를 최적화하는 데 도움이 된다.
브라우저는 이러한 모든 스타일을 구문 분석할 때까지 렌더링을 차단하지만
사용하지 않을 것으로 알고 있는 스타일(ex. 인쇄 스타일 시트)에 대한 렌더링은 차단하지 않는다.
CSS를 미디어 쿼리를 기반으로 여러 파일로 분할하여
사용하지 않는 CSS를 다운로드하는 동안 렌더링 차단을 방지할 수 있다.
비차단 CSS 링크를 생성하려면 아래처럼 명시해서 쓴다.
<link rel="stylesheet" href="styles.css"> <!-- blocking -->
<link rel="stylesheet" href="print.css" media="print"> <!-- not blocking -->
<link rel="stylesheet" href="mobile.css" media="screen and (max-width: 480px)"> <!-- not blocking on large screens -->
기본적으로 브라우저는 지정된 각 스타일 시트가 렌더링 차단이라고 가정한다.
media
와 함께 속성을 추가하여 스타일 시트를 적용해야 하는 시기를 브라우저에 알린다.CSS를 여러 파일로 분리하면 기본 렌더링 차단 파일(이 경우 styles.css
)이 훨씬 작아져 렌더링이 차단되는 시간이 줄어든다.
HTML 소스가 로딩되고 파싱되면 브라우저는 태그를 DOM 트리로 구성한다.
DOM 트리는 화면에 표현되는 요소와 화면에 표현되지 않는 요소로 이루어져 있다.
예를 들어 <head>나 <script> 등은 화면에 표현되지 않는 DOM 트리의 요소다.
브라우저는 화면에 표현되는 요소를 RenderObject 트리
로 구성한다.
RenderObject 트리
의 노드는 z-index 속성이나 중첩 등을 처리하기 고안된 RenderLayer에 대응된다.
RenderLayer 중 실제 화면에 출력돼야 하는 노드는 다시 GraphicsLayer
를 생성한다.
최상위(root) 노드
나 <canvas>
, <video>
등이 GraphicsLayer
를 생성하는 RenderLayer다.
하드웨어 가속은 GraphicsLayer 단위로 렌더링된 이미지를 GPU를 이용해 한 장의 이미지로 합성(composition)해서 화면에 출력하는 기술이다.
GPU에 이미지가 업로드되면 이미지는 3차원 그래픽 표면에 다양한 형태로 매핑될 수 있으며, 위치 이동이나 변형 등 다양한 작업을 이미지를 매핑하는 형태로 적용할 수 있다.
그래서 더 적은 비용으로 다양한 변형과 요소의 합성을 실행할 수 있게 된다.
다음 중 하나에 부합되면 GraphicsLayer로 설정되어 GPU에서 속성이 수행되며, 특히 모바일에서 성능이 향상된다.
transform: translateZ()
, rotate3d()
등)<video>
또는 <canvas>
요소opacity
, position: fixed
브라우저는 CSS 애니메이션을 처리하고 리플로우(따라서 다시 그리기)를 잘 트리거하지 않는 애니메이션 속성을 처리하도록 최적화되어 있다.
성능을 향상시키기 위해 애니메이션되는 노드를 메인 스레드에서 GPU로 이동할 수 있다.
하드웨어 가속을 사용하면 웹 페이지의 렌더링 속도가 빨라지지만
잘못 사용하면 오히려 렌더링 속도가 느려지거나 브라우저에 문제가 일어날 수 있다.
주의 사항
고려 사항
효율적인 하드웨어 가속을 위해
will-change
속성을 사용하는 것을 고려할 수 있다.
CSS will-change 속성은 브라우저에서 요소의 속성이 변경될 것으로 예상해 요소가 실제로 변경되기 전에 최적화를 설정할 수 있도록 하여 필요하기 전에 잠재적으로 비용이 많이 드는 작업을 수행하여 성능을 향상시킨다.
*어떤 특정한 요소에 하드웨어 가속을 적용하고 싶을 때 사용한 방법이 레이어 핵(layer hack)이다. 레이어 핵은 하드웨어 가속을 위해 요소에 CSS 3D 속성을 부여해 요소를 GraphicsLayer로 만드는, 일종의 '핵(hack)'이다. transform 속성의 값으로 translate3d(0,0,0)나 translateZ(0) 등을 지정한다.
will-change: opacity, transform;
/* <div style="transform:translateZ(0);"> text </div> */
will-change
속성은 이러한 기본적인 브라우저의 동작을 덮어쓰고 최적화된 작업을 일정 시간 동안 내부적으로 유지하기 때문에 불필요하게 오래 유지되지 않도록 작업이 끝난 이후에는 속성을 제거해야 한다.
상황에 따라 변경이 완료된 이후 제거하지 않고 유지하는 것이 필요할 때도 있다.
@font-face 규칙에 적용되는 font-display 속성은 브라우저에서 글꼴 파일을 로드하고 표시하는 방법을 정의하여 글꼴이 로드되거나 로드되지 않는 동안 텍스트가 대체 글꼴로 표시되도록 힌다.
이렇게 하면 빈 화면 대신 텍스트를 표시할 수 있으므로 스타일이 지정되지 않은 텍스트가 번쩍거리는 단점이 있다.
@font-face {
font-family: someFont;
src: url(/path/to/fonts/someFont.woff) format('woff');
font-weight: 400;
font-style: normal;
font-display: fallback;
}
CSS contain 속성을 사용하면 요소와 해당 콘텐츠가 문서 트리의 나머지 부분과 최대한 독립적임을 나타낼 수 있다.
브라우저는 전체 페이지가 아닌 DOM의 제한된 영역에 대해 레이아웃, 스타일, 페인트, 크기 또는 이들의 조합을 다시 계산할 수 있다.
GPU 가속화는 게임과 같이 리소스가 많이 필요한 분야에서만 사용한다고 생각했는데, 웹에서도 활용할 수 있다니 정말 놀랍네요! 좋은 내용 배워갑니다 🔥🔥🔥