HTML, CSS, JavaScript 등 개발자가 작성한 문서가 브라우저에서 출력되는 과정을 의미합니다.
요청받은 HTML, CSS, JavaScript의 파일을 브라우저가 화면에 표시할 수 있도록 픽셀단위로 변환하는 것을 의미합니다.
브라우저마다 렌더링을 수행하는 렌더링 엔진을 가지고 있습니다.
렌더링 엔진이 브라우저마다 다르기 때문에, 같은 소스일지라도 브라우저마다 다르게 그려집니다.
이것을 크로스 브라우징이라고도 합니다.
브라우저 | 렌더링 엔진 |
---|---|
Edge | EdgeHTML, Blink |
Chrome | Webkit, Blink |
Safari | Webkit |
FireFox | Gecko |
아래 그림은 Webkit의 렌더링 동작 과정입니다.
1. 변환(Conversion) : HTML의 바이트를 인코딩에 따라 개별 문자로 변환합니다.
2. 토큰화(Tokenizing) : 문자열을 W3C 표준에 지정된 고유 토큰(<html>
,<body>
)으로 변환합니다.
3. 렉싱(Lexing) : 토큰을 해당 속성 및 규칙을 정의한 객체로 변환합니다.
4. DOM 생성 : HTML은 상-하위 관계로 정의할 수 있으며, 렉싱 과정에서 변환된 객체들을 서로 연결하여 트리 구조로 변환합니다.
DOM 트리를 생성하는 과정과 동일한 과정으로 CSSOM 트리를 생성합니다.
렌더링 트리를 생성하려면 브라우저에서 3가지 작업을 수행합니다.
1. DOM 트리의 루트에서 시작하여 화면에 표시되는 노드 각각을 탐색합니다.
- 화면에 표시되지 않는 일부 노드(script, meta 태그 등)은 렌더 트리에 반영되지 않습니다.
- CSS에 의해 화면에 숨겨지는 노드들은 렌더 트리에 반영되지 않습니다.
(display : none은 포함되지 않지만 visibility : hidden은 포함됨)
2. 화면에 표시되는 각 노드에 대해 적절하게 일치하는 CSSOM 규칙을 찾아 적용합니다.
3. 화면에 표시되는 노드를 콘텐츠 및 계산된 스타일과 함께 내보냅니다.
브라우저의 크기나 스타일이 변경이 될 때 리플로우와 리페인트가 발생합니다.
요소 추가, 제거, 요소의 크기 및 위치 변경, 텍스트의 글꼴 크기 및 줄 높이 변경과 같이 웹 페이지의 레이아웃이 변경될 때 발생합니다.
리플로우는 브라우저가 영향을 받는 모든 요소의 레이아웃과 페이지의 다른 요소와의 관계를 다시 계산해야 하기 때문에 작업 속도가 느려질 수 있습니다.
그래서 리플로우를 과하게 사용한다면 브라우저 성능을 저하시키게 됩니다.
position, width, height, margin, padding, border, border-width, font-size, font-weight, line-height, text-align, overflow
요소 모양의 변경 사항을 반영하기 위해 화면의 픽셀을 업데이트 하는 프로세스 입니다.
웹 페이지에서 요소의 색상, 배경, 또는 불투명도 변경과 같이 웹 페이지의 스타일이 변경될 때 발생합니다.
리페인트는 브라우저 요소의 레이아웃을 다시 계산할 필요가 없기 때문에 리플로우보다는 비교적 빠릅니다. 하지만 리페인트도 과하게 사용한다면 브라우저 성능을 저하시킬 수 있습니다.
background, color, text-decoration, border-style, border-radius
리플로우는 레이아웃을 변경시킬 때 발생하고, 리페인트는 단순 요소의 스타일을 변경시킬 때 발생합니다. 리플로우가 발생되면 리플로우와 리페인트가 같이 수행하지만, 리페인트는 리페인트만 수행합니다.
- 클래스에 따른 스타일 변화 시 최대한 DOM 구조 상 끝단 노드에 클래스 사용하기
=> 클래스 변화 시 리플로우는 일어나지만 전체를 감싸는 wrappper에 변화를 주느냐, 일부만 변화를 주느냐는 큰 차이가 있습니다.- 인라인 스타일 최대한 쓰지 않기
=> 인라인이 들어가면 리플로우가 수차례 발생합니다.- 애니메이션이 들어간 요소의 position은
absolute
와fixed
로 하자
=> 다른 요소 레이아웃에 영향을 끼치지 않으므로 해당 애니메이션 요소만 리페인트 발생한다.- 퀄리티와 퍼포먼스 사이에서 타협
- 테이블 레이아웃을 피하자
=> 작은 변화에도 테이블 전체 노드에 리플로우가 발생합니다.- JS를 통해 스타일 변화는 한번에 처리하기
- CSS 하위 선택자는 필요한 만큼만 사용하기
=> 해당 클래스가 유일한 상태에서 CSS 하위 선택자를 여러 단계를 걸쳐 선택하는 이유는 코드 가독성이나 유지보수 측면에서 중요하기 때문에 그렇게 할 수도 있지만 이러한 방식은 퍼포먼스에 상당한 영향을 미치게 됩니다. 최소한의 CSS 하위 선택자를 쓰는 대신 주석처리를 하는 것이 훨씬 효과적이라고 볼 수 있습니다.- script 태그는 body 요소 마지막에 위치하기
=> 브라우저는 동기적으로 HTML, CSS, Javascript를 처리합니다.
HTML 요소들이 script 태그의 위치에 따라 블로킹이 발생하여 DOM의 생성이 지연될 수 있습니다.
또한 DOM이 완성되지 않은 상태에서 자바스크립트가 DOM을 조작한다면 에러가 발생할 수 있습니다.
https://beomy.github.io/tech/browser/critical-rendering-path/
https://developer.mozilla.org/ko/docs/Web/Performance/Critical_rendering_path
브라우저의 렌더링 과정
https://choar816.tistory.com/192
https://beomy.github.io/tech/browser/browser-rendering/
https://basemenks.tistory.com/292
https://tecoble.techcourse.co.kr/post/2021-10-24-browser-rendering/
https://ajdkfl6445.gitbook.io/study/web/browser-rendering
https://lists.w3.org/Archives/Public/public-html-ig-ko/2011Sep/att-0031/Reflow_____________________________Tip.pdf