브라우저의 주요 기능은 사용자가 선택한 자원을 서버에 요청하고 브라우저에 표시하는 것이다.
여기서 자원이란? 보통 HTML 문서를 말한다. (+ PDF나 이미지 등 다른 형태도 O) → 자원의 주소는 URI(Uniform Resource Identifier)에 의해 정해짐
브라우저는 HTML과 CSS 명세에 따라 HTML 파일을 해석해서 표시한다. → 명세는 웹 표준화 기구인 W3C에서 정함
렌더링 엔진은 요청 받은 내용을 브라우저 화면에 표시하는 역할을 한다.
브라우저마다 사용하는 렌더링 엔진이 다름 → 크로스 브라우징 이슈가 발생하곤 한다.
파이어폭스 - 게코(Gecko)
사파리 - 웹킷(Webkit)
크롬 - 블링크(Blink)
(통신으로부터 요청한 문서의 내용을 얻는 것부터 시작한다.)
브라우저가 렌더링할 문서인 HTML과 CSS를 나눠서 읽는다. 이때 HTML과 CSS는 단순한 텍스트이므로 HTML Parser와 CSS Parser로 각각 연산과 관리가 가능한 Object Model을 만든다.
(여기서 렌더링 엔진은 더 나은 사용자 경험을 위해 가능한 빠르게 내용을 표시하게 만들어졌는데, 따라서 모든 HTML, CSS파싱이 끝나기도 전에 이후의 과정을 수행하여 미리 사용자에게 보여줄 수 있는 내용들을 출력한다.)
전 단계에서 DOM 트리와 CSSOM 트리가 생성되면, 이 둘을 연결하여 표시해야 할 순서로 내용을 그려낼 수 있도록 하기 위해 렌더 트리를 생성한다.
이는 순수한 요소들의 구조와 텍스트만 존재하는 DOM 트리와 달리 렌더 트리는 스타일 정보가 설정되어 있으며 실제 화면에 표현되는 노드들로만 구성된다.
display:none;
과 같은 속성이 설정된 노드는 제외된다.
렌더 트리가 생성되면 브라우저의 뷰포트 내에서 각 노드들의 정확한 위치와 크기를 계산한다. 이때 %, vh, vw와 같이 상대적인 위치, 크기 속성은 모두 실제 화면에 그려지는 px단위로 변환된다.
Layout 과정이 완료되면 요소들의 위치와 크기, 스타일 계산이 완료된 렌더 트리를 사용해 브라우저는 요소들을 실제 화면에 그리게 된다.
이때 처리해야 하는 스타일이 복잡할 수록 시간이 오래 걸린다.
(이는 script 태그에 어떠한 옵션도 쓰이지 않았을 경우에 해당한다. 만약 script 태그에 defer 옵션이 쓰였다면 html 파싱을 중단하지 않고 병렬적으로 js 파일을 받아온다. 그리고 html 파싱이 끝나면 fetch 해둔 js 파일을 실행한다.)
렌더링 과정을 모두 마친 후 최종적으로 브라우저에 페이지가 그려진다고 해서 렌더링 과정이 모두 끝난 것이 아니다. 특정 액션이나 이벤트에 따라 HTML 요소의 크기나 위치 등 레이아웃 수치가 수정되면 그에 영향을 받는 자식 노드나 부모 노드들을 포함하여 Layout 과정을 다시 수행하게 된다.(Reflow) 그리고 그 결과물을 다시 화면에 그려주는 Repaint 과정을 거친다.
reflow가 일어나면 실제 화면에 반영해주기위해 다시 painting이 일어난다.
그러나 항상 reflow가 발생해야 repaint되는 건 아니다. background-color, opacity처럼 레이아웃에 영향을 주지 않는 스타일 속성의 변경은 repaint만 일어난다.
reflow가 발생하는 속성보다 repaint만 발생하는 속성을 사용하는 것이 좋다.
🔔 reflow가 일어나는 대표적인 속성
position, width, height, left, top, right, bottom, margin, padding, border, border-width, clear, display, float, font-family, font-size, font-weight, line-height, min-height, overflow, text-align, vertical-align, white-space...
🔔 repaint가 일어나는 대표적인 속성
background, background-image, background-position, ackground-repeat, background-size, border-radius, border-style, box-shadow, color, line-style, outline, outline-color, outline-style, outline-width, text-decoration, visibilty...
애니메이션이나 레이아웃 변화가 많은 요소의 경우 position을 absolute나 fixed를 사용하면 영향을 받는 주변 노드들을 줄일 수 있다.
fixed는 주변에 영향을 주지 않아 repaint 비용만 들어서 효율적이다.
예를 들어 0.1초 마다 1px씩 이동하는 요소보다 0.3초마다 3px씩 이동하는 요소가 reflow 연산 비용이 3배 줄어든다고 볼 수 있다. 따라서 부드러운 효과를 조금 줄이면서 성능을 개선할 수 있다.
페인트 과정은 요소들이 어떻게 배치되었는가에 따라 작게 나누어 레이어별로 비트맵을 준비한다. 렌더링 이후 변화가 일어날 것 같은 요소에 will-change: 속성이름
을 해주면 그 요소는 레이어를 따로 준비해줘서 추후 발생할 변화에 대해 다른 노드에 줄 영향을 없앨 수 있다. (단, will-change를 남발하면 안된다.)
https://d2.naver.com/helloworld/59361
https://chanyeong.com/blog/post/43