브라우저 동작과정 최종정리
프론트엔드 개발관련 공부내용을 기록하는 포스트 입니다.
1. 개요
브라우저 동작과정
에 대해서 그동안 공부해왔던 모든 것들을 최종적으로 정리해본다.
렌더링`
해당 포스팅은 네이버 D2 블로그 관련 내용을 토대로 정리하였습니다.
2. 브라우저 동작과정
브라우저
의 주요 기능은 웹 상에서 사용자가 선택한 자원을 서버에 요청하고 브라우저에 표시하는 것이다.
2-1. 브라우저의 기본 구조
-
사용자 인터페이스 : 우리가 브라우저에서 볼수 있는
주소표시줄, 버튼
등 사용자가 컨트롤 할 수 있는 부분 -
브라우저 엔진 :
사용자 인터페이스
와렌더링 엔진
사이 동작을 제어 -
렌더링 엔진
- 사용자가 요청한
URI
를브라우저 엔진
으로부터 받아서버에 요청
한다. - 서버로 URI 요청하여
응답받은 데이터
(HTML
,CSS
,JavaScript
) 를 받아서파싱 후 렌더링
한다.(Chrome webkit)
- 사용자가 요청한
-
통신 :
렌더링 엔진
으로부터HTTP 요청
등을 받아서네트워크 처리
후 응답을 전달 - 자바스크립트 해석기 : JavaScript 를 파싱한다(chrome V8)
-
자료 저장소 :
쿠키
등의 자료를컴퓨터 하드디스크
에저장
한다. (HTML5
부터Web Database
에 저장가능) - UI 백엔드 : render tree 를 Browser 에 그리는 역할을 담당
위와 같은 역할을 하는 브라우저의 각 기능별로 자세히 알아본다.
2-2. Rendering 과정
브라우저
의 렌더링 엔진은 구글이 사용하는 웹킷(Webkit)
을 기준으로 담는다.
위 과정을 Critical Rendering Path
로 불리운다.
-
HTML
마크업을 처리하고DOM 트리
를 만든다.- HTML 파싱
-
CSS
마크업을 처리하고CSSOM 트리
를 만든다.- Stylesheet 파싱
-
DOM
및CSSOM
을 결합하여렌더 트리
를 만든다.- 스타일 계산
-
렌더 트리
에서레이아웃
을 실행하여 각 노드를기하학적 형태
를 계산한다. -
개별 노드
를 화면에 그린다(Paint).- Paint
- Raster
- Composit Layer
위 프로세스의 전체
혹은 일부
를 거쳐 화면이 그려지게 되며 이에 따라 성능
이 다르게 나올 수 밖에 없다.
DOM 트리 생성
DOM 트리
생성은 아래와 같은 과정으로 진행된다.
Bytes > Characters > Tokens > Nodes > DOM
-
변환(Bytes -> Characters)
- 브라우저가
HTML
의 원시Byte
를디스크
혹은네트워크
에서 읽어와서, 해당 파일에 지정된인코딩
에 따라 개별 문자로 변환
- 브라우저가
-
토큰화(Character -> Tokens)
- 브라우저가 문자열을 고유 토큰으로 변환하며, 각 토큰은 특별한 의미와 고유한 규칙을 가진다.
- 토큰화는
파싱
을 통해 진행된다.
-
렉싱(Tokens -> Nodes)
-
구문 분석기
가노드
를 파싱 트리에 추가하기 위해어휘 분석기
즉, 토큰화된 토큰을 요청하여노드 객체
로 변환
-
-
DOM 생성(Nodes -> DOM)
- 마지막으로
HTML
마크업이 상위 / 하위 관계가 포함된트리
로 생성
- 마지막으로
DOM 트리 구축을 위한 HTML 파싱
문서 파싱은 브라우저
가 코드를 이해하고 사용할 수 있는 구조로 변환
하는 것을 의미한다.
파싱은 어휘 분석(어휘 분석기)
과 구문 분석(파서)
두가지로 구분할 수 있다.
어휘 분석
은 자료를 토큰
으로 분해하는 역할을 진행한다.
토큰
은 구문의 단어
를 의미한다 생각하면 될 것이며, 유효한 토큰으로 분해하면서 어휘 분석기는 공백
과 줄 바꿈
같은 의미 없는 문자를 제거한다.
이후 구문 분석
을 진행하는데 이는 어휘 분석기
로부터 변환된 새로운 유효한 토큰
을 받아 구문 규칙
과 일치하는지 확인한다.
이후 규칙에 맞는다면 토큰
에 해당하는 노드
가 파싱 트리에 추가되고, 맞지 않으면 토큰
을 내부적으로 저장 후 어휘 분석기
에게 일치하는 규칙이 발견될까지 요청한다.
규칙이 없는 경우는 예외 처리
를 진행하며 문제가 없으면 다음 토큰
을 요청한다.
이러한 파싱
을 통해 마크업
들을 분석하여 DOM
트리로 변환하게 된다.
이후 CSS
정보 또한 파싱을 통해 CSSOM 트리
로 변환이 된다.
이 과정에서 <script>
태그를 만나게 되면 파싱
은 일시적으로 중단을 하고 우선적으로 스크립트
를 파싱한 후에 다시 진행이된다.
이러한 부분으로 인해 발생하는 문제점과 지연(defer), 비동기(async)
를 통해서 해결하는 방법은 별도의 포스팅으로 남긴다.
CSSOM 트리 구축
수신된 CSS
규칙을 브라우저가 이해하고 처리할 수 있는 형식으로 변환하기 위해 DOM 트리
생성과 동일하게 CSSOM 트리
를 생성한다.
렌더트리 구축
DOM 트리
가 구축되는 동안 브라우저
는 렌더 트리
를 구축한다.
이는 표시해야 할 순서
와 문서의 시각적인 구성 요소
로써 올바른 순서로 내용을 그려낼 수 있도록 하기 위한 목적
을 가진다.
웹킷
에서는 이 구성요소를 렌더러(renderer)
또는 렌더 객체(render object)
라는 용어를 사용한다.
웹킷
의 렌더러
의 기본 클레스는 아래와 같다.
class RenderObject { virtual
void layout(); virtual
void paint(PaintInfo); virtual
void rect repaintRect();
Node * node; //the DOM node
RenderStyle * style; // the computed style
RenderLayer * containgLayer; //the containing z-index layer
}
각각의 렌더러
는 CSS2
명세에따라 CSS
박스에 부합하는 사각형을 표시하며, 너비
, 높이
그리고 위치
와 같은 기하학적 정보를 포함한다.
즉, 렌더러
는 화면에 전체적인 구조를 잡는다고 생각하면 될 것이다.
이러한 렌더러
를 만드는 과정을 어태치먼트(attachment)
라 부른다.
모든 DOM 노드
에는 attach
메서드가 있으며, DOM 트리
에 노드가 추가되면 새 노드의 attach
메서드를 호출한다.
결과적으로 정리를 해본다면 이렇다.
렌더 트리
를 구축하기 위해 html, body
태그 를 처리하면서 렌더 트리 루트
를 구성하고 이후 파서가 DOM 트리
를 구축하면서 DOM 노드
가 추가되면 동기적
으로 attach
메서드를 호출해서 렌더 트리
의 나머지 부분을 구축하는 방식인것이다.
이후 최적화된 과정
즉, 규칙
에 따라서 렌더 트리
를 구축하는 과정에서 DOM 노드
에 스타일 시트
정보를 규칙에 따라 적용하여 DOM
의 시각적 요소와 스타일
요소가 규칙에 따라 정의된 트리
를 만들어 낸다.
즉, 정리하면 아래와 같다.
1. CSSOM 의 트리 정보와 DOM 트리의 정보를 활용해서 렌더링엔진이 렌더트리생성
2. 렌더 트리는 화면에 표시되어야할 모든 콘텐츠와 스타일을 가지고 있는 트리
3. 만들어지는 과정은 DOM 트리의 최상단 노드인 루트노드(document 노드)부터 각 노드를 순회하면서
각 노드에 맞는 CSSOM 안의 노드를 찾아서 규칙을 적용하여 만든다.
4. meta, display:none 과 같은 부분은 렌더 트리에 포함되지 않는다.
DOM트리와 렌더트리의 관계
렌더러
는 모든 DOM 트리 요소
와 1:1
대응은 아니며, head
요소 및 display
속성이 none
값이 할당된 요소와 같은 비시각적 DOM 요소
는 렌더 트리
에 추가되지 않는다.
예를들면, ` select``의 경우 ` 표시영역, 드롭다운 목록, 버튼
표시를 위한 3개의 렌더러
가 해당 DOM 트리
노드에 대응 될 것이다.
Layout(배치) 과정
렌더러
가 생성되면 attach
과정을 통해 DOM
요소에 스타일 정보를 입힌 렌더 트리
가 생성된다.
결과적으로 생성된 렌더 트리
는 노드 와 노드
의 스타일
만 계산되어 있다.
하지만, 앞서말한 렌더러
가 생성되어 트리
에 추가될때 크기나 위치정보에 대한 계산은 없었는데 이 배치과정
에서 이를 계산하게되며 배치
또는 리플로
라고 한다.
배치
는 <html>
요소에 해당하는 최상위 렌더러
에서 시작되어 각 노드를 반복하며 각 렌더러
에 필요한 크기
와 위치 정보
를 계사한다.
페이지에서 각 객체의 정확한 크기
와 위치
를 파악하기 위해 브라우저는 렌더 트리
루트에서부터 렌더 트리
를 탐색하며 각 노드의 Box Type
을 확인한다.
Type
이 Block
이면 세로, Inline
이면 가로로 Box
위치를 계산한다.
- 더티 비트 체제
초기 생성 외 소소한 변경
때문에 전체를 다시 배치하지 않기 위해 브라우저
는 더티 비트
체제를 사용한다.
렌더러
는 다시 배치할 필요가 있는 변경 요소
또는 추가된 것과 그 자식을 더티
라고 표시한다.
더티 플레그에는 dirty
와 children are Dirty
두가지 플레그가 존재하며, 후자의 경우 자식 중 재배치할 필요가 있는 경우에 사용된다.
- 전역 배치와 점증 배치
배치
에는 전역 배치
와 점증 배치
가 존재한다.
전역 배치
는 모든 렌더러
에 영향을 줄 수 있는 경우 실행된다.
1. 글꼴 크키 변경
2. 화면 크기 변경
점증 배치
는 렌더러
가 더티
일때 비동기적으로 일어난다.
전역 배치
는 보통 동기적
으로 실행된다.
반면, 점증 배치
의 경우 웹킷
은 점증 배치
를 실행하는 타이머
를 두고 트리
를 탐색하여 더티 렌더러
를 배치하게 된다.
배치
가 크기 변경
또는 렌더러 위치 변화
로 인해 실행되는 경우 렌더러
는 크기를 다시 계산하지 않고 캐시
로부터 가져온다.
전체적인 과정은 아래와 같다.
1. 부모 렌더러가 자신의 너비를 결정.
2. 부모가 자식을 검토.
2-1. 자식 렌더러를 배치(자식의 x와 y를 설정)
2-2. (부모와 자식이 더티하거나 전역 배치 상태이거나 또는 다른 이유로 필요하다면 자식 배치를 호출하여 자식의 높이를 계산한다.
3. 부모는 자식의 누적된 높이와 여백, 패딩을 사용하여 자신의 높이를 설정한다. 이 값은
부모 렌더러의 부모가 사용하게 된다.
4. 더티 비트 플래그를 제거한다.
이때 너비
가 고정된 경우 값은 캐시
에 저장된다.
그리기(Paint) 과정
Layout(배치)
과정을 거쳐 화면에 UI
를 표현하기 위한 계산식이 끝나면 Paint
과정이 시작된다.
Layout
과정에서 Render Layer
가 2개이상 생성되면 각각의 Layer
를 Painting
한 뒤 하나의 이미지로 Composite
하는 과정을 거쳐 브라우저에 표현한다.
-
Paint
-
Paint
는Render 트리
를픽셀
로 변환하는 프로세스이다. - 텍스트, 색, 이미지, 경계 및 그림자 등 요소의 모든 시각적 부분을 그리는 작업을 포함
- 흔히
painting
또는rasterizing
이라고 하며 실제로픽셀
을 채우는 작업은rasterize
라고 하며,paint
는 그릴 호출 목록을 생성한다.
-
-
Composite
- 사용된
HTML
이나CSS
속성에 따라 여러개의Layer
가 생성된 경우, 생성된Layer
들을 합성하여 한장의비트맵
dmfh aksemsms rhkwjd
- 사용된
그리기 상세 과정
Layout(배치)
과정이 끝나게 되면 화면에 내용을 표시
하기 위해 렌더 트리
가 탐색
이 되고 렌더러
의 paint
메서드가 호출된다.
그리기 또한 배치
와 마찬가지로 전역, 점증
방식으로 수행된다.
점증 그리기
에서 일부 렌더러
는 전체 트리에 영향을 주지 않는 방식으로 변경된다.
Paint
순서는 아래와 같은 순으로 진행된다.
1. 배경 색
2. 배경 이미지
3. 테두리
4. 자식
5. 아웃라인
만약에 RePainting
이 실행이 실행된다면 그 전에 웹킷
은 기존의 정보를 비트맵
에 저장하고 변경된 정보와 비교하여 차이가 있는 부분
만 다시 그린다.
동적 변경
초기에 렌더링
과정을 통해 화면에 노출되고 JS
의 인터렉션
등으로 인해 시각적인 화면
의 변경이 발생할 경우 아래와 같은 프로세스
를 타게 된다.
- JS / CSS > 스타일 > 레이아웃 > 페인트 > 합성
레이아웃 너비, 높이, 왼쪽 또는 상단 위치 등 요소의 기하학적 형태에 영향을 주는 ‘layout’ 속성을 변경하면 브라우저가 다른 모든 요소를 확인하고 페이지에 대해 ‘리플로우’를 수행해야 합니다. 영향을 받은 영역이 있으면 다시 페인트해야 하고 최종적으로 페인트한 요소는 다시 합성해야 합니다.
- JS / CSS > 스타일 > 페인트 > 합성
페이지의 레이아웃에 영향을 주지 않는 배경 이미지, 텍스트 색상 또는 그림자 등의 ‘paint only’ 속성을 변경하면, 브라우저가 레이아웃을 건너뛰되 페인트 작업은 여전히 수행합니다.
- JS / CSS > 스타일 > 합성
레이아웃과 페인트가 필요 없는 속성을 변경하면 브라우저가 합성 단계로 건너뜁니다. 이 최종 버전은 앱의 수명 주기에서 애니메이션이나 스크롤처럼 많은 부담을 주는 시점에 가장 이상적이고 비용이 가장 적게 드는 버전입니다.
결과적으로 브라우저
는 변경에 대해 가능한 최소한의 동작
으로 반응하기 때문에 요소
의 색깔
이 바뀌면 해당 요소
만 리페인팅
이 발생한다.
요소
의 위치
가 바뀌면 요소
와 자식
그리고 형제
의 리페인팅
과 재배치
가 발생한다.
DOM 노드
가 추가되게 되면 재배치(ReFlow)
와 리페인팅(RePainting)
이 모두 발생하며, html
요소의 글꼴 크기
를 변경하는 것과 같은 큰 변경은 캐시
를 무효화 하고 트리 전체
의 배치
와 리페인팅
이 발생한다.