2025. 03. 06 블로그 A/S 프로젝트🚧 로 업데이트한 글입니다.
1. 브라우저 렌더링 과정
사용자가 브라우저를 통해 웹사이트에 접속하고, 브라우저가 리소스를 다운받으면서 시작된다. (HTML, CSS, JS 등)
- Parsing: 렌더링 엔진이 HTML을 파싱해 DOM 트리를 만듦
- Style: 렌더링 엔진이 CSS를 파싱해 CSSOM 트리를 만듦. 다양한 상대적인 값들이 px로 치환되어 계산.
- DOM 트리 + CSSOM 트리 = Render 트리 구축.
- Layout: 각 요소의 배치 결정
- Paint: 구축된 Render 트리를 화면에 어떻게 그릴 지 결정하는 페인트 레코드 생성 (이때 그리는건 아니다)
- Layerize: Paint 결과물을 사용해서 특정한 레이어들로 쪼갬
- Commit: Layerize 결과물을 Composite Thread로 복사 (이때 화면에 그리는 것도 아니다, 합성 쓰레드에서 작업이 완료되어야 함!!)
- Composite: Render 트리에 존재하는 레이어들을 합치는 과정
- Display: 렌더링 ~~
2. Layer
여기서 말하는 레이어란, 포토샵의 레이어처럼 페인팅 영역을 나누는 것. 기본적으로 같은 좌표공간상에서는 같은 레이어를 가진다.
2-1. Paint Layer (CPU)
- 페인트 레이어가 생성되는 조건
root element
- 명시적인
position
속성값을 가지고 있는 경우 - 투명도가 1 미만인 경우
filter
,mask
,transform
을 가진 경우
2-2. Graphics Layer (GPU)
- GPU 활용 변환 + 병렬처리 특화 로 빠르게 변환 가능
- 기존 레이어에서 새롭게 분리되어 주변 레이어 영향 없이 해당 레이어만 빠르게 렌더링 가능
- 그래픽 레이어가 생성되는 조건
video
나canvas
태그를 사용하는 경우3d, 2d transform
속성이 존재하는 경우- 하드웨어 가속이 된 2D canvas 요소인 경우
transition
oranimation
속성 +opacity
,transform
,filter
속성 적용backdrop-filter
will-change
- 그러면 무조건 좋을까?
- 레이어를 초기 구성하는 작업은 CPU(메인쓰레드)가 진행
- 레이어에 원래 비트맵 정보를 복사하기 때문에 메모리가 2배로 필요
2-3. 직접 확인해볼까?
루트 요소와, 명시적으로 position을 주어서 설정한 요소들이 레이어로 발견되었다!
3. JS는 언제 반영될까?
- HTML 파싱 과정에서 script 태그를 만나면,
- DOM 생성을 중단, JS 리소스를 요청,
- JS 코드를 받아와 파싱한다. (JS 엔진)
- JS 코드에 따라 DOM/CSSOM을 동적으로 변경한다.
따라서 <body>
아래에 <script>
태그가 위치하면, DOM 생성 완료 이후에 조작이 가능하다. 즉 <script>
태그를 최하단에 위치시키는 것이 렌더링 최적화에 유리하다.
4. 리플로우와 리페인트
4-1. Reflow
- 리플로우란
- 웹 인터랙션 발생 ➡️ 렌더링 과정의 Layout을 다시 수행
- 리플로우는 언제 발생할까?
width
,height
,padding
,margin
,positon
,border
등 레이아웃에 영향을 주는 모든 속성이 바뀔 때- 브라우저 사이즈가 바뀔 때
- JS에서 DOM 관련 메서드를 실행하거나, DOM의 속성에 접근할 때
- display: none ↔️ display: block
- 리플로우가 발생한다면, 부모, 자식, 형제 요소에도 영향을 주기 때문에 비용이 큰 작업이다!
4-2. Repaint
- 리페인팅이란?
- 웹 인터랙션 발생 ➡️ 렌더링 과정의 Paint를 다시 수행
- 리페인팅은 언제 발생할까?
color
,background
,boder-radius
등 스타일 속성이 변경되었을 때- 리플로우가 발생했을 때
- visibility: hidden ↔️ visibility: visible
4-3. Reflow와 Repaint 줄이기
여러 최적화 방법들이 있지만, 리액트를 사용하면서 쉽게 적용해 볼 만한 세가지 방법을 소개한다.
(1) transform 속성 사용하기
이 코드, 괜찮을까...?
당연히 괜찮지 않았다. 마우스가 이동할 때마다 포지션이 변경되는데, top과 left가 계속해서 변경되면서 리플로우를 유발하고 있다..
이렇게 변경해 보면 어떨까?
레이아웃과 페인트가 사라진 것을 볼 수 있다..!
앞에서 알아봤던 것처럼, 그래픽 레이어가 생성되면서 메인 쓰레드가 아닌 컴포지트 쓰레드에서 처리되었다.
리플로우와 리페인트가 일어나지 않게 된 것이다.
이렇게 요소의 위치를 계속해서 바꿔주는 코드가 있다면, top, left 대신 transform 속성을 활용해 보자.
(2) 인라인 스타일 자제하기
이 코드는 괜찮을까?
앞에서 JS 코드는 DOM/CSSOM을 동적으로 변경할 수 있다고 했다. 즉 리플로우를 발생시킨다! 브라우저가 배치 처리로 한방에 적용하지만, 보장되지는 않는다고 한다..
이 코드를 open, close 두가지 클래스로 나누어서 클래스만 갈아끼운다면? 리플로우 & 리페인팅이 한번씩만 발생함이 보장된다.
(3) 애니메이션이 있는 노드의 position을 fixed 또는 absolute로 분리하기
애니메이션이 있는 노드가 다른 노드의 리플로우를 유발하지 않도록 분리해버리자.
'TIL > Web' 카테고리의 다른 글
[240205] 이미지 최적화 (1) | 2024.02.05 |
---|---|
[240203] CSR, SSG, SSR (0) | 2024.02.03 |
[240112] 스크린리더 UX 개선하기 (1) | 2024.01.13 |
[240111] 웹 표준, 웹 접근성 (0) | 2024.01.11 |