CSS 최적화

JISEUNG·2022년 6월 21일
10

Frontend-Roadmap

목록 보기
8/15
post-thumbnail

브라우저 렌더링과 CSS

브라우저는 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)이 훨씬 작아져 렌더링이 차단되는 시간이 줄어든다.

GPU 가속 (하드웨어 가속)

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에서 속성이 수행되며, 특히 모바일에서 성능이 향상된다.

  • CSS 3D Transform(translate3d, preserve-3d 등)이나 perspective 속성이 적용된 경우 (transform: translateZ(), rotate3d() 등)
  • <video> 또는 <canvas> 요소
  • CSS3 애니메이션 함수나 CSS 필터 함수를 사용하는 경우
  • 자식 요소가 레이어로 구성된 경우
  • z-index 값이 낮은 형제 요소가 레이어로 구성된 경우. 레이어로 구성된 요소의 위에 위치하면 해당 요소도 레이어로 구성된다.
  • opacity, position: fixed

GPU와 애니메이션 CSS

브라우저는 CSS 애니메이션을 처리하고 리플로우(따라서 다시 그리기)를 잘 트리거하지 않는 애니메이션 속성을 처리하도록 최적화되어 있다.

성능을 향상시키기 위해 애니메이션되는 노드를 메인 스레드에서 GPU로 이동할 수 있다.

하드웨어 가속 사용 시 고려 사항

하드웨어 가속을 사용하면 웹 페이지의 렌더링 속도가 빨라지지만
잘못 사용하면 오히려 렌더링 속도가 느려지거나 브라우저에 문제가 일어날 수 있다.

주의 사항

  • 무분별한 하드웨어 가속은 오히려 브라우저를 느리게 한다.
  • 요소에 하드웨어 가속 속성이 부여되면 즉시 대상 영역이 GPU에 업로드되며, 이때 업로드되는 영역이 크면 화면이 깜빡이는 현상이 발생될 수 있다.
  • 요소에 하드웨어 가속 속성이 부여되면 레이어로 분리되며, 레이어는 변경되는 내용이 없는 한 요소를 GPU 메모리에 다시 업로드하지 않는다.
  • 하드웨어 가속 속성을 사용한 요소의 내용이 변경되면 GPU 메모리가 갱신되므로 요소의 내용을 미리 변경한 다음 하드웨어 가속 속성을 부여한다.
  • 성능이 낮은 기기에서 하드웨어 가속을 사용하면 오히려 성능 저하를 가져올 수 있다.

고려 사항

  • 하드웨어 가속을 적용하는 요소의 크기는 작을수록 좋고, 요소의 개수는 화면에서 5~6개로 구성하는 것이 좋다.
    특히, 요소의 속성값에 따라 요소의 영역이 커질 수 있기 때문에 주의해서 적용해야 한다. 예를 들어 text-indent나 left 같은 속성에 -999em이나 -9999px과 같이 화면 영역을 지나치게 벗어나게 값을 설정하면, 콘텐츠 영역의 크기가 늘어나고 하드웨어 가속에 의해 구성된 레이어도 커지게 돼 불필요한 메모리를 사용하게 된다.
  • DOM 요소의 내용이 자주 변경되지 않는 영역에 하드웨어 가속을 적용한다.
    내용 변경이 아닌 이동이나 크기 변경이 자주 발생하는 영역에 하드웨어 가속을 적용하고, 이동이나 크기 변경은 transform 속성을 사용한다.
  • 기기에 따라 선별적으로 하드웨어 가속을 적용한다.
    JMC(Jindo Mobile Component)는 기기가 하드웨어 가속에 적합한 기기인지 확인할 수 있게 useCss3d() 메서드를 제공한다.

효율적인 하드웨어 가속을 위해 will-change 속성을 사용하는 것을 고려할 수 있다.

CSS 최적화 속성

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-display 속성

@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;
}

contain 속성

CSS contain 속성을 사용하면 요소와 해당 콘텐츠가 문서 트리의 나머지 부분과 최대한 독립적임을 나타낼 수 있다.

브라우저는 전체 페이지가 아닌 DOM의 제한된 영역에 대해 레이아웃, 스타일, 페인트, 크기 또는 이들의 조합을 다시 계산할 수 있다.

참고 자료

CSS performance optimization
하드웨어 가속에 대한 이해와 적용

profile
Frontend Web Developer

2개의 댓글

comment-user-thumbnail
2022년 7월 30일

GPU 가속화는 게임과 같이 리소스가 많이 필요한 분야에서만 사용한다고 생각했는데, 웹에서도 활용할 수 있다니 정말 놀랍네요! 좋은 내용 배워갑니다 🔥🔥🔥

1개의 답글