Browser

Browser, reflow/repaint

song 2022. 7. 27. 11:33

브라우저 기본 구조

  1. User Interface: 주소 표시줄, 뒤로가기, 앞으로가기, 북마크 등 page를 제외한 browser의 모든 부분
  2. Browser Engine: User Interface와 Rendering engine 사이의 동작을 제어
  3. Rendering Engine: 요청한 contents를 화면에 표시하는 기능을 담당 (HTML, CSS 등을 파싱하여 표시)
  4. Networking: HTTP 요청 등의 network 통신 기능을 담당
  5. Javascript Interpreter: js code 파싱 및 실행을 담당
  6. UI Backend: checkbox, button 등 기본 element의 UI를 담당. OS의 UI method에 의존한다. (windows, max 버튼 다름)
  7. Data Storage: cookie, webDB, local/session storage 등 browser가 관리하는 data 저장소

 

브라우저 동작 과정

  1. 브라우저는 network 통신으로 요청한 문서(HTML, CSS, javascript, image 등)를 얻는다.
  2. 문서를 파싱한다.
    1. HTML을 파싱하여 DOM tree를 생성한다. ("무엇을" 그릴지 결정한다.)
    2. CSS를 파싱하여 CSSOM tree를 생성한다. ("어떻게" 그릴지 결정한다.)
  3. 생성한 DOM tree와 CSSOM tree를 결합하여 Render tree를 생성한다.
  4. Render tree를 기반으로 HTML 요소의 layout(화면상의 위치와 크기)을 계산하고, painting한다.

 

DOM tree

DOM은 document object model이다. 이것은 HTML 문서의 객체 표현이고 markup과 1:1의 관계이며 browser가 이해할 수 있는 형태의 자료구조이다.

 문자열로 이루어진 HTML file의 string을 파싱해 문법적 의미를 갖는 최소 단위의 토큰으로 분해하고, 이 토큰들을 객체로 변환하여 노드(DOM)를 생성한다. 이 노드들의 계층적 연결관계가 DOM tree가 된다.

 

CSSOM tree

HTML문서를 파싱하다가 css를 로드하는 link나, style tag를 만나면 DOM 생성을 일시 중지하고 css file을 서버로부터 요청하여 얻어온 뒤 HTML의 파싱과 같은 과정을 거쳐 CSSOM tree를 생성한다. 이후 DOM tree 생성을 재개한다.

 

Render tree

DOM tree를 생성하는 동안 Render tree도 생성된다. 각 DOM이 생성된 뒤에 attach라는 method를 호출함으로써 style요소를 입혀 render tree의 element를 구성한다. render tree는 문서의 시각적인 구성요소로써 올바른 순서로 내용(layout)을 그려낼 수 있게 하기 위함이다. (firefox는 이 각각의 요소를 frame이라고 부르고 webkit(chrome)은 renderer(render object)라고 부른다.) 

 "시각적" 구성요소만을 포함하기 때문에 DOM tree와 1:1 대응되지 않는다. 예를 들어 <head>, <script> 등의 tag는 화면에 표시되지 않기에 render tree에 반영되지 않고, display:none style이 있는 DOM 역시 화면에 표시되지 않기에 render tree에 반영되지 않는다. 반면에 visibility: hidden은 화면에 영역을 차지하지만(layout에 영향을 준다) 보이지 않는 것 뿐이기 때문에 render tree에 반영된다.

 

Layout(=flow)

Layout 단계에서는 render tree의 목적에 맞게 각 renderer의 화면상에서 표시되어야 할 구체적인 위치와 크기를 계산해낸다.

 

Paint

Layout 단계에서 위치 및 크기가 정해지면 해당하는 pixel을 칠하는 과정을 거치게 된다. (renderer의 paint() method 호출)

 

Javascript

Js는 rendering engine이 아닌 javascript engine이 처리한다. HTML을 파싱하다가 (css와 마찬가지로) script tag 등을 만나면 파싱을 중단하고 js code를 실행하기 위해 js engine으로 제어권한을 넘긴다. js engine은 js file을 로드하고 파싱하여 실행한다. 실행이 완료되면 다시 HTML 파서로 제어권을 넘기고  DOM tree 생성을 재개한다.

 

Reflow, Repaint

화면구성이 완료된 이후에 동적인 변화에 의해 화면이 변경되어야할 경우 layout(flow), paint 과정이 다시 실행된다. 브라우저는 최소한의 대응을 하도록 설계되어 있으며 만약 특정 엘리먼트의 color만 변경된다면 repaint만 발생할 것이고, 엘리먼트의 포지션이 변경되는 경우에는 reflow와 repaint가 동시에 발생한다.

 

Repaint

엘리먼트의 스킨에 변화가 발생하지만 layout에는 영향을 미치지 않을 때 발생된다. (visibility, outline, background-color 등)

 

Reflow

문서 내 노드들의 layout, position을 다시 계산해 뿌려주므로 repaint보다 더 무거운 프로세스이다. 특정 엘리먼트에 대한 reflow가 발생하면 해당 엘리먼트 뿐만 아니라 그에 영향을 받는 자식, 부모/조상 역시 layout 계산이 진행된다. (많은 경우 전체 page에 대해 일어난다고 함)