1.
[ Q. 브라우저 렌더링 과정 간단하게 설명 ]
- 준혁: HTML과 CSS를 파싱하여 DOMTree와 CSSOM Tree를 생성
- 이 둘을 합쳐 RenderTree 생성
- RenderTree를 바탕으로 화면에 배치하고 그린다.
꼬리질문
- 왜 브라우저 렌더링 과정을 알아야하나요? (배워서 좋은 점)
- 렌더링 과정을 잘 컨트롤하지 않으면 성능상 이슈가 있을 수 있고, 사용자 경험에 중요한 영향을 미치기 때문
- 결국은 프론트엔드는 화면을 출력하는 것을 담당 → 기본 메커니즘의 이해 필요
- 프론트엔드에서 가장 핵심
- 리액트 등장 이유
- 양방향에서 단방향으로 바꾼 것이 핵심
- reconcilation → deep dive → 바닐라로 구현? 팀으로 함께 +
상윤
- 왜 인라인스타일을 지양해야하나요?
- fact / 의견 구분하기
fact
: html파서, css파서 병렬적 진행, html 파싱 중 인라인스타일 만나면 Css파서에게 해당 처리 넘겨주게 됨. 이 과정에서 리플로우 발생- 의견 첨가 방식으로 (reflow → reflow가 왜 발생하는지에 대한 합리적인 추론 필요)
- <link ref=”stylesheet”> 비동기 파싱일 경우 의미 없는게 아닌가?
(Web) 일반적으로 CSS <link>
태그를 <head></head>
태그 사이에 위치시키고, JS <script>
태그를 <body>
태그가 끝나기 직전에 위치시키는 이유가 무엇인가요?
[한 줄]
브라우저 렌더링과정을 고려했을 때 화면을 빠르게 보여주기 위해서라고 생각합니다.
[script]
script 태그가 body의 마지막 부분에 있는 것은, <head>부분에 존재할 경우 html 파싱이 끝나기 전 script가 실행이 되어 html파싱이 멈추고, 그에 따라 존재하지 않는 DOM요소에 접근하게되어 오류가 발생할 수 있습니다.
따라서 html파싱 중 자바스크립트 파일이 반드시 필요하지 않다면 html파싱 이후에 스크립트가 실행되도록 하여, 오류발생을 막고 빠르게 화면을 보여줄 수 있습니다.
[css]
한편 css 태그의 경우 스크립트와 다르게 html 파싱과정을 멈추게 하지 않고, 별도의 css파서가 스타일을 관리하기 때문에 헤드에 위치하도록 합니다.
또 script 가 실행될 때, 스타일이 파싱되지 않는 경우 의도치 않은 화면을 보여줄 수 있기 때문에 보통 body태그에 있는 스크립트에 앞서 실행되도록 합니다.
자료 아카이빙
인수
HTML파싱 → DOM Tree → CSSOM → RenderTree → Layout → Paint
DOM 구축
in 렌더러 프로세스- HTML 파싱 (메인스레드)
- 리소스 로딩( 프리로드 스캐너)
- img, link, script 와 값는 네트워크 필요한 태그들 미리 읽어서 브라우저 프로세스의 네트워크 스레드로 요청 보내놓음
- script 태그는, 문서의 DOM구조를 바꿀 수 있기 때문에, HTML 파싱작업을 일시중지 시킨다.
- index.html을 받았을 때 렌더링
- 1) HTML파일을 파싱한다
- 2) HTML 파싱하여 DOM Tree 생성
- 3) 파싱 중 CSS 링크 만나면 CSS 파일 요청하여 받아온다.
- 4) CSS파일을 읽어서 CSSOM을 만든다.
- 5) DOM Tree와 CSSObjectModel을 합쳐서 RenderTree를 만든다.
- 6) RenderTree의 노드들이 화면에 위치할 지 계산하는 Layout과정
- 실제 그리기 위한 위치를 가짐 ( x, y, 박스영역)
- 7) 최종적으로 실제 픽셀에 대하여 Paint 한다.
- 요소의 크기, 모양, 위치를 알지만 순서는 ?
- 레이아웃 트리를 순회하며, 페인트 순서를 정한다.
- 모든 레이아웃 정보들을 실제 화면의 픽셀로 변환하는 작업
- Reflow, Repaint 무엇이고, 언제발생?
- reflow는 액션이나 이벤트발생으로 DOM요소의 크기나 위치등이 변경되었을 경우, 연관된 상위하위 노드들의 위치와 크기를 재계산한다.
- repaint는 레이아웃에 영향을 주지 않는 color, backgroundclor등의 스타일 속성이 변경되었을 경우 발생
From GitHub (링크)
1. 브라우저 렌더링 과정을 흐름에 따라 설명해주세요.
HTML파싱(DOM Tree 구성)
,CSS 파싱(CSSOM Tree 구성)
,RenderTree(attachment)
,Layout(reflow)
,Paint
- 브라우저는 HTML, CSS, 자바스크립트, 이미지, 폰트 파일 등 렌더링에 필요한 리소스를 요청하고 서버로부터 응답을 받습니다.
- 브라우저의 렌더링 엔진은 서버로부터 응답된 HTML과 CSS를 파싱하여 DOM과 CSSOM을 생성하고 이들을 결합하여 렌더 트리를 생성합니다.
- 파싱 과정 : 바이트 -> 문자 -> 토큰 -> 노드 -> DOM/CSSOM
- 브라우저의 자바스크립트 엔진은 서버로부터 응답된 자바스크립트를 파싱하여 AST를 생성하고 바이트코드로 변환하여 실행합니다. 이 때 자바스크립트는 DOM API를 통해 DOM이나 CSSOM으로 변경할 수 있습니다. 변경된 DOM과 CSSOM은 다시 렌더 트리로 결합됩니다.
- 렌더 트리를 기반으로 HTML 요소의 레이아웃(위치와 크기)을 계산하고 브라우저 화면에 HTML 요소를 페인팅 합니다.
2. Reflow와 Repaint는 무엇이고, 언제 발생하나요?
DOM과 CSSOM이 변경되는 경우에 변경된 DOM과 CSSOM은 다시 렌더 트리로 결합되고 변경된 렌더 트리를 기반으로 레이아웃과 페인트 과정을 거쳐 브라우저 화면에 다시 렌더링 되는데 이를 리플로우, 리페인트라고 합니다.
리플로우 레이아웃 계산을 다시 하는 것을 말하며, 노드 추가/삭제, 요소의 크기/위치 변경 등 레이아웃에 영향을 주는 변경이 발생한 경우에 한하여 실행됩니다.
input에 값을 변경하는 것도 리플로우, 리페인트가 발생하는지?
리페인트 재결합된 렌더 트리를 기반으로 다시 페인트를 하는 것을 말합니다.
다만, 리플로우와 리페인트가 반드시 순차적으로 실행되는 것은 아니며 레이아웃에 영향이 없는 변경은 리플로우 없이 리페인트만 실행됩니다. 렌더링 최적화를 위해서는 Reflow 연산을 줄이거나 Repaint만 일어날 수 있도록 브라우저 성능 최적화를 고민해보는 것이 좋습니다.
2-1. reflow, repaint를 줄일 수 있는 방법은 무엇이 있을까요?
reflow 최적화 방법
- reflow, repaint를 일으키는 스타일 사용 줄이기
- 인라인 스타일 지양하기 : 인라인 스타일은 HTML이 파싱 될 때 레이아웃에 영향을 주어 추가적인 Reflow를 발생시킨다.
virtual DOM
사용하기 : 뷰의 변화를 먼저 virtual DOM에 전달해 줌으로서 브라우저내에서 발생하는 양을 줄이면서 성능이 개선됩니다.
- 사용하지 않는 노드에는
display: none;
을 사용하기 =>visibility: invisible
은 layout의 공간을 차지하기 때문에 Reflow의 대상이 된다.
3. script 태그를 body 가장 하단에 삽입하는 이유는 무엇일까요?
DOM 조작
,로딩 시간
브라우저는 순차적으로 HTML, CSS, 자바스크립트를 파싱하고 실행하는데 이것은 script 태그 위치에 따라 HTML 파싱이 블로킹되어 DOM 생성이 지연될 수 있다는 것을 의미합니다. DOM이 완성되지 않은 상태에서 자바스크립트가 DOM을 조작하면 에러가 발생할 수 있고, 자바스크립트 로딩/파싱/실행으로 인해 HTML 요소들의 렌더링에 지장받는 일이 발생하지 않아 페이지 로딩 시간이 단축되기 때문에 body 요소의 가장 아래에 script 태그를 위치하는 것이 좋습니다.
4. script 태그의 async
, defer
어트리뷰트에 대해서 설명해주세요
자바스크립트 파싱에 의한 DOM 생성이 중단되는 문제를 근본적으로 해결하기 위해서 async와 defer 어트리뷰트가 생겼습니다. 이 두 어트리뷰트는 src 어트리뷰트를 통해 외부 자바스크립트 파일을 로드하는 경우에만 사용할 수 있습니다. 모두 HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행됩니다. 하지만 자바스크립트 실행 시점에 차이가 있습니다.
async 어트리뷰트 HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행된다. 단, 자바스크립트의 파싱과 실행은 자바스크립트 파일의 로드가 완료된 이후 진행되며, 이때 HTML 파싱이 중단된다. 여기서 여러 개의 script 태그에 async 어트리뷰트를 지정하면 script 태그의 순서와는 상관 없이 로드가 완료된 자바스크립트부터 먼저 실행되므로 순서가 보장되지 않는다.
defer 어트리뷰트 HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행된다. 단, 자바스크립트의 파싱과 실행은 HTML 파싱이 완료된 직후, 즉 DOM 생성이 완료된 직후에 진행된다. 따라서 DOM 생성이 완료된 이후 실행되어야 할 자바스크립트에 유용하다.
5. virtual DOM
을 사용하는 것이 항상 옳을까요?
Virtual Dom은 실제 DOM의 작업량을 실질적으로 줄여주는 것은 맞지만 많은 컴포넌트를 조작하게 된다면 오버헤드가 생기기 마련이고 메모리에 존재하기 때문에 메모리의 사용이 늘어날 수 밖기 때문에 항상 옳은 것은 아니다.
참조
- 이웅모 저, ⌜모던 자바스크립트 Deep Dive⌟, 위키북스