2022년 05월 01일 ~ 2022년 11월 20일까지 진행한 스터디를 바탕으로 로컬에 작성한 글을 Velog에 옮긴 내용입니다.
브라우저 렌더링
요청과 응답
- 브라우저 주소창에 Protocol(scheme), Domain(Host)를 통해서 서버로 요청을 보낼 수 있습니다.
- https: //naver.com이라고 작성하면 암묵적으로 https: //naver.com/index.html으로 서버에 전송합니다.
- 자신이 원하는 브라우저에 접근하기 위해서는 리소스(HTML, CSS, JavaScript, Font, Image 등)을 서버로 요청하여 응답을 받습니다.
- 응답 받은 리소스는 문자열로 전송 받습니다.
- 정확히는 지정된 바이트(2진수)로 전송 받아서 HTML의 meta tag를 파싱하면서 문자열로 변환합니다.
- 전달받은 문자열은 브라우저가 빠르게 해석할 수 있는 객체로 변환됩니다. ([정확한 동작은 DOM Tree 생성 과정에서 설명 예정](#DOM Tree 생성 과정))
- 위의 설명들은 정적으로 서버와 통신을 하는 내용으로 Ajax, REST API를 통해서 JavaScript로 동적으로 통신하여 원하는 데이터를 JSON 형식으로 받을 수 있습니다.
![image-20210318164554752](/Users/parkmoen/Library/Application Support/typora-user-images/image-20210318164554752.png)
DOM Tree 생성 과정
- HTML 파일을 서버로부터 응답 받습니다. (지정된 바이트로 전송받습니다.)
- 바이트 형태로 전송 받은 HTML 파일은 랜더린 엔진을 통해 meta 태그의 charset 어트리뷰에 지정된 인코딩 방식(UTF-8 등)으로 문자열로 변환됩니다.
- 문자열로 변환된 코드는 문법적으로 가장 작은 단위인 토큰으로 분해합니다.
- 분해한 토큰은 객체의 형태인 노드로 변환됩니다. 변환된 노드들은 DOM을 구성하는 기본 단위가 됩니다.
- HTML 요소들은 중첩관계를 유지하고 있으며(부모와 자식의 관계), 중첩관계를 노드로 표현한 자료구조가 DOM Tree입니다.
DOM Tree는 HTML 파일을 랜더링 엔진을 통해 해석한 객체들의 집합입니다.
렌더링 엔진: 서버로부터 요청받은 파일을 시각적으로 보여지는 픽셀단위로 해석하여 사용자에게 보여주는 엔진입니다.
CSSOM Tree 생성 과정
- 랜더링 엔진을 통해서 순서대로 위에서 밑으로 문자열을 해석하여 노드들을 생성합니다.
- 바이트 → 문자 → 토큰 → 노드 → CSSOM 순서로 생성
- 생성한 노드들의 집합인 CSSOM Tree를 생성합니다.
렌더링 엔진을 통해 HTML을 파싱하는 도중에 link 태그를 만나면 HTML 파싱을 중단하고 CSS 파일을 서버로부터 요청하고 응답 받은 CSS 파일을 렌더링 엔진이 파싱합니다. CSS 파일의 해석이 완료되어 CSSOM 생성이 완료되면 다시 HTML 파일을 해석하여 DOM을 생성합니다.
즉, 렌더링 엔진은 동기적으로 파일을 해석하기때문에 blocking현상이 발생합니다.
Render Tree 생성 및 Layout 계산
- DOM, CSSOM이 모두 만들어지면 화면에 렌더링 되는 부분으로만 이루어진 Render Tree가 만들어집니다.
- 화면에 보여지는 부분만을 모와서 자료구조로 만들어서 meta, script 등의 html 태그는 포함되지 않습니다.
- display: none 속성은 화면의 어떠한 공간도 차지하지 않기때문에 Render Tree에 포함되지 않습니다.
- visibility: invisible 속성은 화면에 보이지는 않지만 공간을 차지하기때문에 Render Tree에 포함됩니다.
- 완성된 Render Tree를 기반으로 HTML 요소의 레이아웃을 계산하여 화면을 렌더링하는 페이팅(Painting)처리를 진행합니다.
![image-20210319202301477](/Users/parkmoen/Library/Application Support/typora-user-images/image-20210319202301477.png)
지금까지 살펴본 브라우저의 렌더링 과정은 반복해서 실행될 수 있다. 예를 들어, 다음과 같은 경우 반복해서 레이아웃 계산과 페인팅이 재차 실행된다.
- 자바스크립트에 의한 노드 추가 또는 삭제
- 브라우저 창의 리사이징에 의한 뷰포트(viewport) 크기 변경
- HTML 요소의 레이아웃(위치, 크기)에 변경을 발생시키는 width/height, margin, padding, border, display, position, top/right/bottom/left 등의 스타일 변경
Reflow, Repaint
Reflow
Render Tree로 구성된 노드들을 HTML 요소의 위치 및 크기 등의 Layout을 계산합니다. DOM API로 위치, 크기를 수정하면 영향을 받은 DOM, CSSOM Tree는 다시 파싱을 통해 Render Tree를 만들어서 Layout 계산을 하는 행위입니다.
즉, Reflow는 Layout을 다시 계산하는 행동입니다.
reflow 영향을 주는 속성
width | height | padding | margin | border |
---|
top | bottom | left | right | position |
font-size | line-height | font-family | overflow | text-align |
display | float | font-weight | vertical-align | white-space |
Repaint
- RePaint는 Reflow가 발생하여 다시 Render Tree를 생성해서 Layout 작업 후 픽셀 단위로 화면에 랜더링하는 작업입니다.
- 위의 설명만 보면 Reflow가 발생해야지만 Repaint가 발생하는 것처럼 보이지만 Repaint만을 발생시키는 CSS 속성도 존재하기때문에 Reflow가 발생하지 않아도 Repint가 발생할 수 있습니다.
Repaint에 영향을 주는 속성
background | color | visibility | text-decoration | line-style |
---|
background-image | background-position | background-repeat | background-size | border-radius |
box-shadow | border-style | outline | outline-color | outline-style |
브라우저 최적화
위의 설명처럼 Reflow가 발생하지 않아도 Repint가 발생할 수 있습니다. 그 말은 Reflow가 발생하면 무조건적으로 Repaint가 발생한다는 의미입니다. 즉, 브라우저 최적화를 가장 간단하게 하는 방법은 Reflow가 최소한으로 발생하게 하는 방식을 채택할 수 있습니다.
Reflow 생성되는 과정
- 페이지 초기 랜더링 시.(최초 Layout 과정)
- 윈도우 리사이징 시
- HTML 요소 크기 변경 시
- HTML 요소 위치 변경 시
- 텍스트 변경(폰트) 시
- 원본 이미지 크기 변경 시
- DOM API를 통해 노드 추가 및 삭제 시
reflowr가 발생하는 속성 보기
Reflow 최적화하기
1. DOM API를 통해 Style. 변경 시 하나의 동작으로. 묶어서. 실행하기
- CSSStyleDeclaration.cssText 메서드를 사용하여 여러가지 Style 한번에 묶어서 변경하기
- Element.classList를 사용하여 지정한 class에 Style 적용하여 스타일 변경
간단한 작업에서도 0.10ms 정도의 차이가 나며, 프로젝트를 진행시 스타일 작업에 적절히 적용해서 Reflow를 줄이는 방식을 채택하면 좋습니다.
2. animation을 사용하는 노드는 position: fixed, absolute를 사용하기
- Javascript + CSS 조합으로 animation 적용 시 많은 프레임 계산으로 인한 브라우저 성능에 악영향을 줍니다.
- position: fixed, absolute 속성을 사용하여 전체 노드에서 animation 적용을 원하는 부분만을 따로 분리 시킬 수 있습니다.
- 전체 노드에서 animation 적용을 원하는 노드를 분리시키면 전체 노드는 Reflow가 발생하지 않고 animation을 적용한 노드에서만 Repaint를 진행합니다.
- position: fixed, absolute + transform: translate3D(x, y, z)를 사용하면 더욱 효과적인 Performance를 기대할 수 있습니다.
3. CSS 선택자 선택
- CSS 선택자를 통해 Style을 적용할때는 하위 선택자부터 선택해야 합니다.
- 만약 상위 선택자를 필요로 하면 최소한의 선택자를 선택해야 합니다.
- CSS 규칙은 오른쪽에서 왼쪽으로 이동합니다. 이 과정에서는 더 이상 일치하는 규칙이 없거나 잘못된 규칙이 나올 때 까지 계속됩니다. 그러므로 불필요한 선택자를 사용하는 것은 성능을 저하시킬 수 있습니다.
4. DOM API를 최소화 하여 Reflow 줄이기, 인라인 Style 방식 최소화 하기
- 위 부분은 타협점을 정하여 자신이 원하는 방식을 사용하면 됩니다.
참고 자료
Google 개발자 문서
poiemaweb
Reflow or Repaint(or ReDraw)과정 설명 및 최적화 방법
CSS 애니메이션 성능 개선 방법