여기에서는 렌더링의 구성요소가 렌더링 파이프라인이 이를 통해 흐르는 방식을 다룹니다.
가장 높은 수준에서 시작하여 렌더링 작업은 다음과 같습니다.
- 화면의 픽셀로 콘텐츠를 렌더링합니다.
- 한 상태에서 다른 상태로 콘텐츠에 대한 시각 효과를 애니메이션 처리합니다.
- 입력에 응답하여 스크롤합니다.
- 개발자 스크립트 및 기타 하위 시스템이 응답할 수 있도록 적절한 위치에 효율적으로 입력을 라우팅합니다.
렌더링할 콘텐츠는 각 브라우저 탭의 프레임 트리와 브라우저 인터페이스입니다. 터치 스크린의 원시 입력 이벤트 스트림은 마우스, 키보드 및 기타 하드웨어 기기와 관련이 있습니다.
각 프레임에는 다음이 포함됩니다.
- DOM 상태
- CSS
- 캔버스
- 이미지, 동영상, 글꼴, SVG와 같은 외부 리소스
프레임은 HTML 문서에 URL이 추가된 것입니다. 브라우저 탭에 로드된 웹페이지에는 최상위 프레임이 있으며 최상위 문서에 포함된 각 iframe의 하위 프레임 재귀 iframe 하위 요소가 있습니다.
시각 효과는 비트맵에 적용되는 그래픽 작업입니다. 또는 블렌딩, 필터, 불투명도, 블렌딩 등의 기능이 포함됩니다
아키텍처 구성요소
RenderNG에서 이러한 작업은 여러 단계와 코드에 걸쳐 논리적으로 분할됩니다. 구성할 수 있습니다. 구성 요소는 다양한 CPU 프로세스, 스레드 및 하위 구성요소를 생성할 수 있습니다. 각각은 목표를 달성하는 데 중요한 역할을 합니다. 신뢰성, 확장 가능한 성능 및 확장성을 지원합니다.
렌더링 파이프라인 구조
<ph type="x-smartling-placeholder">여러 단계와 아티팩트가 생성된 파이프라인에서 렌더링이 진행됩니다. 살펴봤습니다 각 단계는 내에서 하나의 잘 정의된 작업을 수행하는 코드를 나타냅니다. 있습니다. 아티팩트는 데이터 구조 즉, 스테이지의 입력 또는 출력입니다.
단계는 다음과 같습니다.
- 애니메이션 적용: 선언적 타임라인을 기반으로 시간이 지남에 따라 계산된 스타일을 변경하고 속성 트리를 변경합니다.
- 스타일: DOM에 CSS를 적용하고 계산된 스타일을 만듭니다.
- 레이아웃: 화면에서 DOM 요소의 크기와 위치를 결정합니다. 변경할 수 없는 프래그먼트 트리를 만듭니다.
- 페인트 전: 컴퓨팅 속성 트리 및 무효화 기존 표시 목록 및 GPU 텍스처 타일을 적절하게 설정합니다.
- 스크롤: 속성 트리를 변형하여 문서와 스크롤 가능한 DOM 요소의 스크롤 오프셋을 업데이트합니다.
- 페인트: DOM에서 GPU 텍스처 타일을 래스터하는 방법을 설명하는 표시 목록을 계산합니다.
- 커밋: 속성 트리와 표시 목록을 컴포지터 스레드에 복사합니다.
- 계층화: 독립적인 래스터화 및 애니메이션을 위해 표시 목록을 합성된 레이어 목록으로 분할합니다.
- 래스터, 디코딩, 페인트 워크렛: 표시 목록, 인코딩된 이미지, 페인트 Worklet 코드를 각각 GPU 텍스처 타일.
- 활성화: GPU 타일을 화면에 그리고 배치하는 방법을 시각 효과와 함께 나타내는 컴포지터 프레임을 만듭니다.
- 집계: 표시된 모든 컴포지터 프레임의 컴포지터 프레임을 단일 전역 컴포지터 프레임으로 결합합니다.
- 그리기: GPU에서 집계된 컴포지터 프레임을 실행하여 화면에 픽셀을 만듭니다.
렌더링 파이프라인의 단계는 필요하지 않은 경우 건너뛸 수 있습니다. 예를 들어 시각 효과와 스크롤의 애니메이션은 레이아웃, 사전 페인트, 페인트를 건너뛸 수 있습니다. 이러한 이유로 애니메이션과 스크롤은 다이어그램에서 노란색과 녹색 점으로 표시됩니다. 시각 효과를 위해 레이아웃, 프리페인트, 페인트를 건너뛸 수 있는 경우 완전히 컴포지터 스레드에서 실행되고 기본 스레드를 건너뛸 수 있습니다.
브라우저 UI 렌더링이 여기에 직접 묘사되어 있지는 않지만 이 동일한 파이프라인의 단순화된 버전으로 생각할 수 있습니다 (또한 실제로 구현에서 많은 코드를 공유합니다.) 동영상 (직접 묘사되지 않음) 일반적으로 프레임을 GPU 텍스처 타일로 디코딩하는 독립 코드로 렌더링됩니다. 그 다음 컴포지터 프레임과 그리기 단계에 연결됩니다.
프로세스 및 스레드 구조
CPU 프로세스
여러 CPU 프로세스를 사용하여 성능 및 보안 격리 달성 영향을 미치지 않으면서도 GPU 하드웨어로부터의 안정성 및 보안 격리가 포함됩니다
- 렌더링 프로세스는 단일 사이트 및 탭 조합 여러 가지 렌더링 프로세스가 있습니다.
- 브라우저 프로세스는 브라우저 UI에 대한 입력을 렌더링하고 애니메이션 처리하고 라우팅합니다. (주소 표시줄, 탭 제목, 아이콘 포함) 및 나머지 경로 모두 적절한 렌더링 프로세스에 입력할 수 있습니다. 브라우저 프로세스가 하나 있습니다.
- Viz 프로세스는 여러 렌더링 프로세스에서 합성을 집계합니다. 브라우저 프로세스입니다. GPU를 사용하여 래스터 및 그립니다. 현재 단일 Viz 프로세스입니다
서로 다른 사이트는 항상 표시됨 여러 렌더링 프로세스를 거칩니다.
동일한 사이트에 여러 브라우저 탭이나 창이 있으면 일반적으로 서로 다른 렌더링이 적용됩니다. 프로세스가 관련이 없는 경우(예: 열 수 있습니다. 데스크톱 Chromium의 강력한 메모리 압력으로 인해 Chromium에서 여러 개의 탭을 설치할 수 있음 렌더링 프로세스로 넘겨줄 수 있습니다.
단일 브라우저 탭 내에서 다른 사이트의 프레임은 항상 서로 다른 렌더링 프로세스에 있습니다. 동일한 사이트의 프레임은 항상 동일한 렌더링 프로세스에 있습니다. 렌더링의 관점에서 볼 때 여러 렌더링 프로세스의 중요한 이점은 교차 사이트 iframe이 성능 격리 서로에게 영향을 줄 수 있습니다. 또한 출처는 더 많은 격리를 선택할 수 있습니다.
일반적으로 모든 Chromium에는 GPU와 화면이 하나씩 있습니다
Viz를 자체 프로세스로 분리하면 GPU 드라이버 또는 하드웨어입니다 또한 보안 격리에도 좋고 이는 GPU API에 중요한 Vulkan 및 보안에 대한 일반적인 내용을 다룹니다.
브라우저에는 많은 탭과 창이 있을 수 있으므로 모두 그릴 수 있는 브라우저 UI 픽셀이 있고 왜 브라우저 프로세스가 정확히 하나만 있는지 궁금할 수 있습니다. 이는 한 번에 하나의 요소에만 포커스가 있기 때문입니다. 실제로 보이지 않는 브라우저 탭은 대부분 비활성화되고 GPU 메모리를 모두 삭제합니다. 그러나 복잡한 브라우저 UI 렌더링 기능이 점점 더 많이 구현되고 있습니다. 일반적인 프로세스도 마찬가지로 WebUI). 이는 성능 격리를 위한 것이 아니며 Chromium 웹 렌더링 엔진의 사용 편의성을 활용하기 위함입니다.
이전 Android 기기 WebView에서 사용될 때 렌더링 및 브라우저 프로세스가 공유됨 이는 일반적으로 Android의 Chromium에는 적용되지 않으며 WebView에만 적용됩니다. WebView에서 브라우저 프로세스는 삽입 앱과도 공유됩니다. WebView에는 렌더링 프로세스가 하나만 있습니다.
보호된 동영상 콘텐츠를 디코딩하는 유틸리티 프로세스도 있습니다. 이전 다이어그램에는 이 프로세스가 묘사되어 있지 않습니다.
스레드
스레드는 느린 작업에도 불구하고 성능 격리와 응답성을 달성하는 데 도움이 되지만 파이프라인 동시 로드와 다중 버퍼링이 포함되어 있습니다
- 기본 스레드는 스크립트, 렌더링 이벤트 루프, 문서 수명 주기,
HTML, CSS 및 기타 데이터 형식의 히트 테스트, 스크립트 이벤트 전달 및 파싱을 지원합니다.
- 기본 스레드 도우미는 인코딩 또는 디코딩이 필요한 이미지 비트맵 및 blob 생성과 같은 작업을 실행합니다.
- 웹 작업자 스크립트 실행, OffscreenCanvas의 렌더링 이벤트 루프가 포함되어 있습니다.
- 컴포지터 스레드는 입력 이벤트를 처리합니다.
웹 콘텐츠의 스크롤 및 애니메이션을 수행하고,
웹 콘텐츠의 최적 계층화를 계산하고
이미지 디코딩, 페인트 워크렛 및 래스터 작업을 조정합니다.
- 컴포지터 스레드 도우미는 Viz 래스터 작업을 조정합니다. 이미지 디코딩 작업, 페인트 워크렛 및 대체 래스터를 실행할 수 있습니다.
- 미디어, 디뮤서 또는 오디오 출력 스레드 디코딩 처리하고 동기화합니다. (동영상은 기본 렌더링 파이프라인과 동시에 실행됩니다.)
기본 스레드와 컴포지터 스레드의 분리는 성능 격리 및 기본 스레드 작업의 애니메이션과 스크롤을 제어합니다.
렌더링 프로세스당 기본 스레드는 하나만 있으므로 사용할 수 있습니다. 그러나 다양한 브라우저 API에서 수행되는 작업과 성능은 격리됩니다. 예를 들어 Canvas API에서 이미지 비트맵 및 blob 생성은 기본 스레드 도우미 스레드에서 실행됩니다.
마찬가지로 렌더링 프로세스당 컴포지터 스레드는 하나만 있습니다. 일반적으로 하나만 있는 것이 문제가 아니라 컴포지터 스레드에서는 비용이 많이 드는 작업이 모두 컴포지터 작업자 스레드 또는 Viz 프로세스에 위임되는 경우 이 작업은 입력 라우팅, 스크롤 또는 애니메이션과 동시에 수행할 수 있습니다. 컴포지터 작업자 스레드는 Viz 프로세스에서 실행되는 작업을 조정합니다. 모든 곳에서 GPU 가속 Chromium이 제어할 수 없는 이유로 실패할 수 있으며 설계할 수 있습니다 이러한 상황에서 작업자 스레드는 CPU의 대체 모드에서 작업을 수행합니다.
컴포지터 작업자 스레드 수는 기기의 기능에 따라 다릅니다. 예를 들어 데스크톱은 일반적으로 더 많은 스레드를 사용하지만 모바일 디바이스보다 CPU 코어가 더 많고 배터리 제약이 적기 때문입니다. 이것은 수직 확장 및 축소.
렌더링 프로세스 스레딩 아키텍처는 세 가지 서로 다른 최적화 패턴:
- 도우미 스레드: 장기 실행 하위 작업을 유지 관리할 추가 스레드로 보냅니다. 다른 동시 요청에 응답하는 상위 스레드입니다. 기본 스레드 도우미 및 컴포지터 도우미 스레드는 이 기법의 좋은 예입니다.
- 다중 버퍼링: 새 콘텐츠를 렌더링하는 동안 이전에 렌더링된 콘텐츠를 표시하여 지연 시간을 최소화합니다 컴포지터 스레드는 이 기법을 사용합니다.
- 파이프라인 동시 로드: 여러 위치에서 렌더링 파이프라인을 실행합니다. 동시에 사용할 수 있습니다. 스크롤과 애니메이션의 속도는 이렇습니다. 사용자가 기본 스레드 렌더링 업데이트가 발생하면 스크롤 및 애니메이션이 실행할 수 있습니다
브라우저 프로세스
- 렌더링 및 합성 스레드는 브라우저 UI의 입력에 응답합니다. 다른 입력을 올바른 렌더링 프로세스로 라우팅합니다. 브라우저 UI를 배치하고 그립니다.
- 렌더링 및 합성 스레드 도우미 이미지 디코딩 작업 및 대체 래스터 또는 디코딩 실행
브라우저 프로세스 렌더링과 합성 스레드가 비슷합니다. ML 모델을 학습시키고 기본 스레드와 컴포지터 스레드가 하나로 결합된다는 점을 제외하고는 차이가 있습니다. 이 경우에는 단일 스레드가 필요하지 않으므로 긴 기본 스레드 작업으로부터의 성능 격리, 설계상 어떤 것도 없기 때문입니다.
Viz 프로세스
- GPU 기본 스레드 래스터는 목록과 동영상 프레임을 GPU 텍스처 타일로 표시합니다. 화면에 컴포지터 프레임을 그립니다.
- 디스플레이 컴포지터 스레드는 각 렌더링 프로세스에서 합성을 집계하고 최적화합니다. 하나의 컴포지터 프레임으로 만들어 화면에 표시할 수 있습니다.
래스터와 그리기는 일반적으로 동일한 스레드에서 발생합니다. 둘 다 GPU 리소스에 의존하기 때문에 GPU를 멀티스레드로 안정적으로 사용하기는 어렵습니다. (GPU에 대한 보다 쉬운 멀티스레드 액세스는 Vulkan 표준). Android WebView에는 그리기를 위한 별도의 OS 수준 렌더링 스레드가 있습니다. WebView가 네이티브 앱에 삽입되는 방식 때문입니다. 향후 다른 플랫폼에도 이러한 스레드가 있을 가능성이 높습니다.
디스플레이 컴포지터는 다른 스레드에 있습니다. 항상 응답해야 하기 때문입니다. GPU 기본 스레드에서 속도 저하를 일으킬 수 있는 원인을 차단하지 않습니다. GPU 기본 스레드에서 속도 저하의 원인 중 하나는 Chromium이 아닌 코드를 호출하는 것입니다. 이러한 드라이버는 예측하기 어려운 방식으로 느릴 수 있습니다.
구성요소 구조
각 렌더링 프로세스 기본 스레드나 컴포지터 스레드 내에서 구조화된 방식으로 서로 상호 작용하는 논리적 소프트웨어 구성 요소가 있습니다.
렌더링 프로세스 기본 스레드 구성요소
깜박임 렌더기에서:
- 로컬 프레임 트리 프래그먼트는 로컬 프레임의 트리와 프레임 내의 DOM을 나타냅니다.
- DOM 및 캔버스 API 구성요소에는 이러한 모든 API의 구현이 포함되어 있습니다.
- 문서 수명 주기 실행기는 커밋 단계까지의 렌더링 파이프라인 단계를 실행합니다.
- 입력 이벤트 조회 테스트 및 디스패치 구성요소는 조회 테스트를 실행하여 이벤트에서 타겟팅하는 DOM 요소를 찾고 입력 이벤트를 실행 디스패치 알고리즘 및 기본 동작입니다.
렌더링 이벤트 루프 스케줄러 및 실행기가 이벤트에서 실행할 항목을 결정합니다. 지정할 수 있습니다. 기기와 일치하는 주기로 렌더링이 발생하도록 예약합니다. 디스플레이.
로컬 프레임 트리 프래그먼트는 약간 복잡합니다. 프레임 트리는 기본 페이지이며 하위 iframe이 재귀적으로 작동한다는 점을 기억하세요. 프레임은 렌더링 프로세스에서 렌더링되는 경우 렌더링 프로세스에 로컬입니다. 그 외에는 원격입니다.
렌더링 프로세스에 따라 프레임 색상을 지정하는 것을 생각해 볼 수 있습니다. 위 이미지에서 녹색 원은 하나의 렌더링 프로세스의 모든 프레임입니다. 주황색은 1초, 파란색은 3분의 1입니다.
로컬 프레임 트리 프래그먼트는 프레임 트리에 있는 동일한 색상의 연결된 구성요소입니다. 이미지에는 4개의 로컬 프레임 트리가 있습니다. 하나는 사이트 A, 나머지 하나는 사이트 B, 나머지 하나는 사이트 C입니다. 각 로컬 프레임 트리는 자체 Blink 렌더기 구성요소를 가져옵니다. 로컬 프레임 트리의 블링크 렌더기는 동일한 렌더링 프로세스에 있을 수도 있고 그렇지 않을 수도 있습니다. 다른 로컬 프레임 트리처럼 작동합니다. 앞서 설명한 대로 렌더링 프로세스가 선택되는 방식에 따라 결정됩니다.
렌더링 프로세스 합성 스레드 구조
렌더링 프로세스 컴포지터 구성요소에는 다음이 포함됩니다.
- 합성된 레이어 목록, 표시 목록 및 속성 트리를 관리하는 데이터 핸들러입니다.
- 수명 주기 실행기는 애니메이션, 스크롤, 합성, 래스터, 활성화하고 디코딩하는 과정을 거칩니다. 애니메이션과 스크롤은 기본 스레드와 컴포지터 모두에서 발생할 수 있습니다.
- 입력 및 히트 테스트 핸들러는 합성된 레이어의 해상도에서 입력 처리 및 히트 테스트를 수행합니다. 컴포지터 스레드에서 스크롤 동작을 실행할 수 있는지 확인합니다. 히트 테스트에서 타겟팅해야 하는 렌더링 프로세스와 관련된 렌더링 프로세스를 확인할 수 있습니다
실제 예시 아키텍처
이 예에는 다음과 같은 세 개의 탭이 있습니다.
탭 1: foo.com
<html>
<iframe id=one src="foo.com/other-url"></iframe>
<iframe id=two src="bar.com"></iframe>
</html>
탭 2: bar.com
<html>
…
</html>
탭 3: baz.com
<ph type="x-smartling-placeholder">html
<html>
…
</html>
</ph>
이러한 탭의 프로세스, 스레드 및 구성 요소 구조는 다음과 같습니다.
렌더링의 4가지 주요 작업 각각에 대해 한 가지 예를 살펴보겠습니다. 알림:
- 콘텐츠를 화면의 픽셀로 렌더링합니다.
- 한 상태에서 다른 상태로 콘텐츠에 대한 시각 효과를 애니메이션으로 만듭니다.
- 입력에 응답하여 스크롤합니다.
- 개발자 스크립트 및 기타 하위 시스템이 응답할 수 있도록 입력을 적절한 위치로 효율적으로 라우트합니다.
탭 1에 대해 변경된 DOM을 렌더링하는 방법은 다음과 같습니다.
- 개발자 스크립트는 foo.com의 렌더링 프로세스에서 DOM을 변경합니다.
- Blink 렌더기는 렌더링이 발생해야 한다고 컴포지터에 알립니다.
- 컴포지터는 Viz에 렌더링이 필요하다고 알립니다.
- Viz는 렌더링 시작을 컴포지터에 다시 알립니다.
- 컴포지터는 시작 신호를 Blink 렌더기에 전달합니다.
- 기본 스레드 이벤트 루프 실행기가 문서 수명 주기를 실행합니다.
- 기본 스레드가 결과를 컴포지터 스레드로 전송합니다.
- 컴포지터 이벤트 루프 실행기는 합성 수명 주기를 실행합니다.
- 모든 래스터 작업은 래스터를 위해 Viz로 전송됩니다 (이러한 작업이 두 개 이상인 경우가 많음).
- GPU의 Viz 래스터 콘텐츠
- Viz는 래스터 작업의 완료를 확인합니다. 참고: Chromium은 종종 래스터가 완료될 때까지 기다리지 않습니다. 대신 포드라는 것을 동기화 토큰 해결해야 하는 문제 래스터 태스크에 의해 수행됩니다.
- 컴포지터 프레임이 Viz로 전송됩니다.
- Viz는 foo.com 렌더링 프로세스를 위한 컴포지터 프레임을 집계합니다. bar.com iframe 렌더링 프로세스 및 브라우저 UI에 적용됩니다.
- Viz가 추첨 일정을 잡습니다.
- Viz는 집계된 컴포지터 프레임을 화면에 그립니다.
탭 2에서 CSS 변환 전환에 애니메이션을 적용하는 방법은 다음과 같습니다.
- bar.com 렌더링 프로세스의 컴포지터 스레드가 애니메이션을 틱함 컴포지터 이벤트 루프에서 <ph type="x-smartling-void-element"><br /></ph>소개합니다. 그러면 컴포지터 수명 주기가 다시 실행됩니다. 래스터 및 디코딩 작업이 발생할 수 있지만 여기에 묘사되지 않았습니다.
- 컴포지터 프레임이 Viz로 전송됩니다.
- Viz는 foo.com 렌더링 프로세스, bar.com 렌더링 프로세스 및 브라우저 UI를 위한 컴포지터 프레임을 집계합니다.
- Viz가 추첨 일정을 잡습니다.
- Viz는 집계된 컴포지터 프레임을 화면에 그립니다.
탭 3에서 웹페이지를 스크롤하는 방법은 다음과 같습니다.
- 일련의
input
이벤트 (마우스, 터치 또는 키보드)가 브라우저 프로세스에 수신됩니다. - 각 이벤트는 baz.com의 렌더링 프로세스 컴포지터 스레드로 라우팅됩니다.
- 컴포지터는 기본 스레드가 이벤트에 관해 알아야 하는지 여부를 결정합니다.
- 필요한 경우 이벤트가 기본 스레드로 전송됩니다.
- 기본 스레드에서
input
이벤트 리스너를 실행합니다. (pointerdown
,touchstar
,pointermove
,touchmove
,wheel
) 리스너가 이벤트에서preventDefault
를 호출하는지 확인합니다. - 기본 스레드는
preventDefault
가 컴포지터에 호출되었는지 여부를 반환합니다. - 그렇지 않으면 입력 이벤트가 브라우저 프로세스로 다시 전송됩니다.
- 브라우저 프로세스에서 이 이벤트를 다른 최근 이벤트와 결합하여 스크롤 동작으로 변환합니다.
- 스크롤 동작은 baz.com의 렌더링 프로세스 컴포지터 스레드로 다시 한번 전송됩니다.
- 스크롤이 여기에 적용되고 bar.com의 컴포지터 스레드가 적용됩니다.
컴포지터 이벤트 루프에서 애니메이션을 틱합니다.
그런 다음 속성 트리에서 스크롤 오프셋을 변경하고 컴포지터 수명 주기를 다시 실행합니다.
또한
scroll
이벤트를 시작하도록 기본 스레드에 지시합니다 (여기에 설명되지 않음). - 컴포지터 프레임이 Viz로 전송됩니다.
- Viz는 foo.com 렌더링 프로세스를 위한 컴포지터 프레임을 집계합니다. bar.com 렌더링 프로세스, 브라우저 UI입니다.
- Viz가 추첨 일정을 잡습니다.
- Viz는 집계된 컴포지터 프레임을 화면에 그립니다.
iframe의 하이퍼링크에서 click
이벤트를 라우팅하려면 탭 1에서 iframe #2로 이동합니다.
input
이벤트 (마우스, 터치 또는 키보드)가 브라우저 프로세스에 발생합니다. 대략적인 히트 테스트를 실행합니다. 을 사용하여 bar.com iframe 렌더링 프로세스에서 클릭을 수신해야 하며 이를 거기로 전송합니다.- bar.com의 컴포지터 스레드가
click
이벤트를 기본 스레드로 라우팅합니다. bar.com에 대한 요청이며 이를 처리할 렌더링 이벤트 루프 작업을 예약합니다. - bar.com의 기본 스레드를 위한 입력 이벤트 프로세서가 테스트를 통해
iframe의 DOM 요소가 클릭되고 스크립트가 관찰할 수 있도록
click
이벤트를 실행합니다.preventDefault
가 들리지 않으면 하이퍼링크로 이동합니다. - 하이퍼링크의 도착 페이지가 로드되면 새 상태가 렌더링되고 '렌더링된 DOM'과 유사한 단계를 예로 들 수 있습니다 (이후의 변경사항은 여기에 설명되지 않습니다.)
요점
렌더링 작동 방식을 기억하고 내부화하는 데 많은 시간이 걸릴 수 있습니다.
가장 중요한 점은 렌더링 파이프라인에서 세부 사항에 대한 세심한 주의가 필요합니다. 독립적인 구성요소로 분할할 수 있습니다 이러한 구성요소는 동일한 신경망을 사용하여 프로세스 및 스레드를 사용하여 확장 가능한 성능을 그리고 확장성 기회에 대해 알아보겠습니다
각 구성요소는 애플리케이션의 성능과 기능을 있습니다.
주요 데이터 구조에 관해 자세히 알아보려면 이는 코드 구성요소만큼이나 렌더링에 중요합니다.
삽화: 우나 크라베츠