렌더링 성능

사용자는 사이트와 앱이 제대로 실행되지 않는 것을 알아차리므로 렌더링 성능 최적화는 매우 중요합니다.

폴 루이스

오늘날의 웹 사용자는 방문하는 페이지가 대화형이고 원활히 작동할 것으로 기대하므로 개발자는 시간과 노력을 집중해야 합니다. 페이지는 빠르게 로드될 뿐만 아니라 전체 수명 주기 동안 사용자 입력에 빠르게 응답해야 합니다. 실제로 이러한 사용자 환경 측면은 다음 페인트와의 상호작용 (INP) 측정항목이 측정하는 것입니다. 우수한 INP는 페이지가 사용자 요구에 일관되고 안정적으로 반응했다는 의미입니다.

페이지를 간결하게 만드는 주요 요소는 사용자 상호작용에 응답하여 실행하는 자바스크립트의 양이지만, 사용자는 사용자 인터페이스의 시각적 변화를 예상합니다. 사용자 인터페이스의 시각적 변경사항은 종종 렌더링이라고 통칭하는 여러 유형의 작업의 결과이며, 사용자 환경이 빠르고 안정적이라고 느껴지도록 이 작업은 최대한 빨리 이루어져야 합니다.

사용자 상호작용에 빠르게 응답하는 페이지를 작성하려면 브라우저에서 HTML, 자바스크립트, CSS를 처리하는 방법을 이해하고 작성하는 코드 및 포함된 다른 서드 파티 코드가 최대한 효율적으로 실행되도록 해야 합니다.

기기 새로고침 빈도에 관한 참고사항

휴대전화로 웹사이트와 상호작용하는 사용자
디스플레이의 새로고침 빈도는 사용자 입력에 반응하는 느낌의 웹사이트를 구축할 때 중요한 고려사항입니다.

오늘날 대부분의 기기는 초당 60회의 빈도로 화면을 새로고침합니다. 새로고침할 때마다 표시되는 시각적 출력이 생성되며 일반적으로 프레임이라고 합니다. 다음 동영상에서는 프레임의 개념을 보여줍니다.

Chrome DevTools의 성능 패널에 표시된 프레임입니다. 커서가 상단 근처의 필름 스트립 위로 스크러빙되면 모바일 탐색 메뉴가 '열림' 상태로 애니메이션 처리되면서 도움말 내에 각 프레임이 확대된 상태로 표시됩니다.

기기의 화면은 항상 일정한 속도로 새로고침되지만, 기기에서 실행되는 애플리케이션은 화면 재생 빈도에 맞추기에 충분한 프레임을 생성할 수 없을 수도 있습니다. 예를 들어 실행 중인 애니메이션 또는 전환이 있는 경우 브라우저는 기기의 새로고침 빈도와 일치시켜 화면이 새로고침될 때마다 하나의 프레임을 생성해야 합니다.

일반적인 디스플레이가 초당 60회 새로고침된다는 점을 감안할 때 몇 가지 간단한 계산을 통해 브라우저가 각 프레임을 생성하는 데 16.66밀리초의 시간이 필요함을 알 수 있습니다. 하지만 실제로는 브라우저에 각 프레임에 대한 자체 오버헤드가 있으므로 모든 작업을 10밀리초 내에 완료해야 합니다. 이 예산을 충족하지 못하면 프레임 속도가 떨어지고 화면에서 페이지 콘텐츠가 떨어집니다. 이 현상을 버벅거림이라고 합니다.

그러나 타겟은 실행하려는 작업 유형에 따라 변경됩니다. 화면의 객체가 두 지점 사이에 일련의 프레임에 보간되는 애니메이션의 경우 10밀리초 임계값을 충족하는 것이 중요합니다. 사용자 인터페이스의 개별 변경사항(즉, 중간에 움직임 없이 한 상태에서 다른 상태로 진행하는 경우)에 관해서는 사용자에게 즉각적으로 느슨한 기간 내에 이러한 변경을 실행하는 것이 좋습니다. 이와 같은 경우 100밀리초가 자주 인용되는 수치이지만 INP 측정항목의 '정상' 기준은 200밀리초 이하로 설정되어 기능이 다양한 기기를 수용할 수 있습니다.

목표가 무엇이든, 버벅거림을 방지하기 위해 애니메이션에 필요한 많은 프레임을 생성하는 것이든, 가능한 한 빨리 사용자 인터페이스의 개별 시각적 변화를 생성하는 것이든 브라우저의 픽셀 파이프라인이 작동하는 방식을 이해하는 것은 작업에 필수적입니다.

픽셀 파이프라인

웹 개발자로 일하면서 알아야 하고 유념해야 하는 다섯 가지 주요 영역이 있습니다. 이 다섯 가지 영역은 개발자가 가장 많이 제어할 수 있는 영역으로, 각각 픽셀-화면 파이프라인의 핵심 지점을 나타냅니다.

JavaScript, 스타일, 레이아웃, 페인트, 합성의 5단계가 포함된 전체 픽셀 파이프라인
전체 픽셀 파이프라인(그림)
  • JavaScript: JavaScript는 일반적으로 사용자 인터페이스의 시각적 변화를 일으키는 작업을 처리하는 데 사용됩니다. 예를 들어 jQuery의 animate 함수, 데이터 세트 정렬, 페이지에 DOM 요소 추가 등이 될 수 있습니다. JavaScript가 시각적 변경을 트리거하는 데 반드시 필요한 것은 아니지만 CSS 애니메이션, CSS 전환, Web Animations API는 페이지 콘텐츠에 애니메이션을 적용할 수 있습니다.
  • 스타일 계산: 일치하는 선택기에 따라 어떤 CSS 규칙을 어떤 HTML 요소에 적용할지 계산하는 프로세스입니다. 예를 들어 .headlineheadline 클래스가 포함된 class 속성 값이 있는 모든 HTML 요소에 적용되는 CSS 선택기의 예입니다. 여기에서 규칙이 알려지면 적용되고 각 요소의 최종 스타일이 계산됩니다.
  • 레이아웃: 브라우저가 요소에 적용되는 규칙을 인식하면 페이지의 도형(예: 요소를 차지하는 공간의 크기 및 화면에 표시되는 위치)을 계산할 수 있습니다. 웹의 레이아웃 모델은 한 요소가 다른 요소에 영향을 줄 수 있음을 의미합니다 예를 들어 <body> 요소의 너비는 일반적으로 트리의 위아래까지 하위 요소의 크기에 영향을 미치므로 이 프로세스는 브라우저에 상당한 영향을 줄 수 있습니다.
  • 페인트: 페인트는 픽셀을 채우는 프로세스입니다. 여기에는 페이지의 레이아웃 계산 후 텍스트, 색상, 이미지, 테두리, 그림자, 요소의 모든 시각적 측면을 그리는 작업이 포함됩니다. 그리기는 일반적으로 레이어라고 하는 여러 표면에서 이루어집니다.
  • 합성: 페이지의 일부가 잠재적으로 여러 레이어에 그려졌으므로 페이지가 예상대로 렌더링되도록 올바른 순서로 화면에 적용되어야 합니다. 이는 실수로 인해 한 요소가 다른 요소 위에 잘못 표시될 수 있으므로 다른 요소와 겹치는 요소의 경우 특히 중요합니다.

픽셀 파이프라인의 이러한 각 부분은 애니메이션에 버벅거림이 발생하거나, 사용자 인터페이스의 개별적인 시각적 변경 시에도 프레임 페인팅을 지연시킬 수 있음을 나타냅니다. 따라서 코드가 트리거하는 파이프라인의 어떤 부분을 정확히 이해하고, 변경을 렌더링하는 데 필요한 픽셀 파이프라인의 부분으로만 변경을 제한할 수 있는지 조사하는 것이 중요합니다.

'페인트'와 함께 사용된 '래스터화'라는 용어를 들어보셨을 것입니다. 페인트가 실제로

  1. 그리기 호출 목록 만들기
  2. 픽셀 채우기

후자를 '래스터화'라고 합니다. 따라서 DevTools에서 페인트 레코드를 볼 때마다 래스터화를 포함한 것으로 간주해야 합니다. 일부 아키텍처에서는 여러 스레드에서 그리기 호출과 래스터화 목록을 만들지만, 이는 개발자가 제어할 수 없습니다.

항상 모든 프레임에서 파이프라인의 모든 부분을 건드릴 필요는 없습니다. 실제로 JavaScript, CSS 또는 Web Animations API를 사용하여 시각적 변경을 할 때 파이프라인이 정상적으로 주어진 프레임에서 작동하는 세 가지 방법이 있습니다.

1. JS / CSS > 스타일 > 레이아웃 > 페인트 > 합성

생략된 단계가 없는 전체 픽셀 파이프라인

너비, 높이, 위치 (예: left 또는 top CSS 속성)와 같은 요소의 도형을 변경하는 속성과 같은 'layout' 속성을 변경하면 브라우저에서 다른 모든 요소를 확인하고 페이지를 '리플로우'해야 합니다. 영향을 받은 영역을 다시 페인트해야 하고 최종적으로 페인트한 요소를 다시 합성해야 합니다.

2. JS / CSS > 스타일 > 페인트 > 합성

레이아웃 단계가 생략된 픽셀 파이프라인

CSS에서 요소의 '페인트 전용' 속성(예: background-image, color 또는 box-shadow)을 변경한 경우 페이지에 시각적 업데이트를 커밋하기 위해 레이아웃 단계가 필요하지 않습니다. 가능한 경우 레이아웃 단계를 생략하면 다음 프레임 생성 시 상당한 지연 시간을 초래할 수 있는 잠재적으로 비용이 많이 드는 레이아웃 작업을 방지할 수 있습니다.

3. JS / CSS > 스타일 > 합성

레이아웃 및 페인트 단계가 생략된 픽셀 파이프라인

레이아웃이나 페인트가 하나도 필요하지 않은 속성을 변경하면 브라우저에서 합성 단계로 바로 건너뛸 수 있습니다. 이 방법은 애니메이션 또는 스크롤과 같이 페이지 수명 주기에서 압력이 높은 지점에 픽셀 파이프라인을 통과하는 가장 저렴하고 바람직한 방법입니다. 재미있는 사실: Chromium은 가능한 경우 컴포지터 스레드에서만 페이지 스크롤이 발생하도록 페이지 스크롤을 최적화합니다. 즉, 페이지가 응답하지 않더라도 계속 페이지를 스크롤하고 이전에 화면에 그려진 부분을 볼 수 있습니다.

웹 성능은 필요한 작업의 효율성을 최대한 높이는 동시에 작업을 방지하는 기술입니다. 대부분의 경우 문제가 아닌 브라우저에서 일하는 것입니다. 이전에 파이프라인에 표시된 작업은 계산 비용 측면에서 다르다는 점에 유의해야 합니다. 일부 작업은 기본적으로 다른 작업보다 비용이 많이 듭니다.

파이프라인의 여러 부분을 살펴보겠습니다. 일반적인 문제와 진단 및 해결 방법을 살펴봅니다.

브라우저 렌더링 최적화

Udacity 과정 스크린샷

성능은 사용자에게 중요합니다. 따라서 우수한 사용자 환경을 빌드하기 위해서는 웹 개발자가 사용자 상호작용에 빠르게 반응하고 원활하게 렌더링되는 웹사이트를 빌드해야 합니다. 성능 전문가인 폴 루이스가 버벅거림을 없애고 초당 60프레임 성능을 유지하는 웹 앱을 만들 수 있도록 도와드립니다. 이 과정에서 앱을 프로파일링하는 데 필요한 도구를 계속 살펴보고 최적의 렌더링 성능이 저하된 원인을 파악할 수 있습니다. 또한 브라우저의 렌더링 파이프라인을 살펴보고 사용자가 즐겁게 사용할 빠른 웹사이트를 더 쉽게 빌드할 수 있게 해주는 패턴을 발견합니다.

Udacity를 통해 제공되는 무료 과정이며 언제든지 수강할 수 있습니다.