티스토리 뷰

 

  이번 주제는 우리가 작성한 코드 혹은 서버에 요청한 코드가 어떻게 화면에 표시되는지에 대해 알아보겠습니다.

 

 

 사용자가 볼 수 있는 화면을 구성하기 위해 브라우저는 HTML, CSS, Javascript로 작성된 텍스트 문서를 파싱하여 브라우저에 렌더링을 합니다. 벌써부터 낯선 단어가 두 개나 등장했습니다. 하나씩 차근차근 알아보도록 할게요.

 

 

 먼저, 파싱(구문 분석)은 프로그래밍 언어의 문법에 맞게 작성된 텍스트 문서를 읽어 들여 실행하기 위해 텍스트 문서의 문자열을 토큰으로 분해하고 토큰에 문법적 의미와 구조를 반영하여 트리 구조의 자료 구조인 파스 트리를 생성하는 일련의 과정을 말합니다. 여기서 토큰은 문법적인 의미를 가지며, 문법적으로 나눌 수 없는 코드의 기본 요소를 의미합니다. 쉽게 설명해서 파싱은 코드를 분석하여 이해하기 좋은 구조로 만드는 것입니다.

 

 

 다음으로 렌더링은 HTML, CSS, 자바스크립트로 작성된 문서를 파싱하여 브라우저에 시각적으로 출력하는 것을 말합니다.

 

 

 

 

1. 브라우저의 렌더링 과정

 

브라우저의 렌더링 과정

 

 

브라우저는 다음과 같은 과정을 거쳐 렌더링을 수행합니다.

 

  1. 브라우저는 HTML, CSS, 자바스크립트, 이미지, 폰트 파일 등 렌더링에 필요한 리소스를 요청하고 서버로부터 응답을 받는다.

  2. 브라우저의 렌더링 엔진은 서버로부터 응답된 HTML과 CSS를 파싱하여 DOM과 CSSOM을 생성하고 이들을 결합하여 렌더 트리를 생성한다.

  3. 브라우저의 자바스크립트 엔진은 서버로부터 응답된 자바스크립트를 파싱하고 실행한다. 이때 자바스크립트는 DOM API를 통해 DOM이나 CSSOM을 변경할 수 있다. 변경된 DOM과 CSSOM은 다시 렌더 트리로 결합된다.

  4. 렌더 트리를 기반으로 HTML 요소의 레이아웃(위치와 크기)을 계산하고 브라우저 화면에 HTML 요소를 페인팅 한다.

 

 

 

 

2. HTML 코드 따라가며 렌더링 이해하기

 

 HTML 코드를 따라가며 단계별로 자세히 살펴보도록 하겠습니다.

 

2-1. DOM 생성

 

 

 

 브라우저의 렌더링 엔진은 클라이언트가 서버로부터 요청한 HTML에서부터 순차적으로 파싱하여 DOM을 생성해 나갑니다. 여기서 DOM은 HTML 문서를 파싱한 결과물입니다. (DOM에 대한 설명은 yung-developer.tistory.com/74에서 확인할 수 있습니다.) HTML 문서를 순차적으로 파싱하면서 다음과 같은 DOM 트리를 생성합니다.

 

 

DOM & BOM 이해하기

1. DOM은 왜 필요할까?  웹 사이트는 크게 세가지의 요소로 구성됩니다.  먼저, HTML은 웹 페이지의 제목, 이미지, 표 등을 정의하고 그 구조와 의미를 부여하는 정적 언어로 웹의 전체적인 구조를

yung-developer.tistory.com

 

HTML 파싱과 DOM 트리 생성

 

 

 

DOM 트리

 

 

 

2-2. CSSOM 생성

 

 

 

 렌더링 엔진은 DOM을 생성해 나가다가 CSS를 로드하는 link 태그나 style 태그를 만나면 DOM 생성을 일시 중단합니다. 그리고 CSS 역시 HTML과 동일한 파싱과정을 거쳐 CSSOM(CSS Object Model)을 생성합니다. CSSOM은 스타일을 구성하는 트리 구조를 가진 객체 모델입니다. 이후 CSS 파싱을 완료하면 HTML 파싱이 중단된 지점부터 다시 HTML을 파싱하기 시작하여 DOM 생성을 재개합니다. CSSOM 역시 CSS의 상속을 반영하여 생성됩니다.

 

 

 

CSS 파싱과 CSSOM 트리 생성

 

 

 

CSSOM 트리

 

 

 

2-3. 렌더 트리 생성

 

 

 

 DOM과 CSSOM 생성이 끝나면 이 둘을 합쳐 렌더 트리를 구성합니다. 렌더 트리는 렌더링을 위한 트리 구조이기 때문에 렌더링에 포함되지 않는 노드들(meta 태그, script 태그, CSS에 의한 미표시 (display: none)) 등은 제외하고 구성됩니다.

 

 

 

렌더 트리 생성

 

 

렌더 트리

 

 

 

2-4. 자바스크립트 파싱과 실행

 

 

 

 CSS 파싱 과정과 마찬가지로 렌더링 엔진은 HTML을 한 줄씩 순차적으로 파싱하며 DOM을 생성해 나가다가 script 태그를 만나면 DOM 생성을 일시 중단합니다. 브라우저는 자바스크립트 코드를 실행하기 위해 렌더링 엔진에서 자바스크립트 엔진으로 제어권을 넘깁니다. 이후 자바스크립트 파싱과 실행이 종료되면 렌더링 엔진으로 다시 제어권을 넘겨 HTML 파싱이 중단된 지점부터 다시 DOM을 생성합니다. 만약 자바스크립트 코드에 의해 DOM이나 CSSOM을 변경하는 DOM API가 사용된 경우 DOM과 CSSOM은 다시 렌더 트리로 결합되고 변경된 렌더 트리를 기반으로 레이아웃과 페인트 과정을 거쳐 브라우저의 화면에 렌더링 합니다. 이를 리플로우, 리페인트라 합니다.

 

 

자바스크립트 실행 과정

 

 

 

 

 

3. CSS 태그와 Script 태그의 위치

 

 앞에서 살펴본 CSS의 경우에서 알 수 있듯이 브라우저는 동기적으로, 즉 위에서 아래 방향으로 순차적으로 HTML, CSS, Javascript를 파싱하고 실행합니다. 이 말은 script 태그의 위치에 따라 HTML 파싱이 중단되어 DOM 생성이 지연될 수 있다는 것을 의미합니다. 따라서 script 태그의 위치는 중요한 의미를 갖습니다. 다시한번 코드를 살펴보면 css 관련 태그의 경우에는 상단에 script 태그는 하단에 위치한 것을 확인할 수 있습니다. 그렇다면 이것은 일종의 암묵적인 규칙일까요?

 

 

 사실 이러한 데는 그만한 이유가 있습니다.

 

 

 먼저 CSS 태그를 상단에 위치시키는 이유는 사용자에게 우리가 원하는 화면을 빠르게 보여주기 위함입니다. CSSOM이 구성되어야 브라우저가 렌더링을 하기 때문에 CSSOM 트리를 빠르게 구성할수록 사용자가 흰 화면을 보는 시간이 줄어들게 됩니다. 또한 외부 스타일 시트를 다운받아 사용하는 경우가 많기 때문에 스타일 시트를 최대한 빠르게 다운받기 위해 CSS 태그를 상단에 위치시킵니다.

 

 

 다음으로 script 태그를 하단에 위치시키는 이유는 먼저 HTML 파서가 script 태그를 만나면 파싱을 멈추고 스크립트를 읽기 때문에 웹페이지의 로딩이 그만큼 늦춰질 수 있습니다. 따라서 웹 페이지의 로딩을 빠르게 하기 위해 하단에 위치시킵니다. 또다른 중요한 이유는 미처 생성되지 않은 DOM 노드를 읽거나 조작하는 것이 불가능하기 때문에 예상치 못한 오류가 발생할 수 있기 때문에 이를 예방하기 위해서 하단에 위치 시킵니다.

 

 

 

 

 

 위의 코드처럼 script 태그를 중간에 삽입하게 되면 DOM 트리가 생성되기 전에 DOM 요소를 조회하게 됩니다. 그러나 DOM에 id가 greeting인 요소는 아직 생성되지 않았기 때문에 다음과 같이 정상적으로 조회하지 못함을 알 수 있습니다.

 

실행결과 1

 

 

 반면 script 태그를 body 태그 밑에 위치시키면 DOM 요소를 생성한 후 조회를 하기 때문에 정상적으로 조회가 가능한 것을 확인할 수 있습니다.

 

 

 

실행결과 2

 

 

 따라서 이러한 문제를 회피하기 위해서는 script 코드를 body 하단에 위치시키는 것이 좋습니다.

 

 

 

 

 

4. 렌더링 성능 최적화

 

 최근 우리가 흔히 접할 수 있는 큰 규모의 웹 어플리케이션, 예를 들어 인스타그램이나 유튜브를 생각해봅시다. 우리가 특정한 행동을 할 때마다, 수많은 데이터가 로딩되고 새로운 내용이 화면에 등장하게 됩니다. 이렇게 새로 표현 돼야하는 요소의 개수가 많아 진다면 조금씩 느려지는 성능이슈가 발생하게 됩니다. 이 때문에 일부는 ‘요즘 자바스크립트 엔진은 매우 빠른 반면, DOM은 느리다’라고 말합니다. 하지만 이는 정확한 말은 아닙니다.

 

 

 사실 DOM 자체는 빠릅니다. DOM 자체를 읽고 쓸 때의 성능은 자바스크립트 객체를 처리할 때의 성능과 비교하여 다르지 않습니다. 단 앞서 살펴본 것처럼 DOM에 변화가 생기면, CSS를 다시 연산하고 레이아웃을 구성하고, 페이지를 리페인트 합니다. 이 과정에서 많은 시간이 지체됩니다. 따라서 DOM 조작을 최소화하여 리플로우와 리페인트 되는 시간을 줄이는 것은 웹 페이지의 성능과 매우 밀접한 연관이 있습니다.

 

 

따라서 이러한 문제를 개선하기 위해 등장한 virtual DOM에 대해 간략히 알아보겠습니다.

 

 

 

 

 

5. Virtual DOM

 

 

 

 최근 React와 Vue 등에서 많이 쓰이는 virtual DOM은 어떤 식으로 이 문제를 해결할까요? Virtual DOM은 이전 DOM과 가상 DOM에 있는 내용을 비교하여 바뀐 부분만 실제 DOM에 적용합니다. 따라서 결과적으로 브라우저는 불필요한 렌더링 횟수를 줄이고 한 번만 렌더링 할 수 있습니다. 이를 통해 브라우저는 리플로우와 리페인트에 소요되는 시간을 줄여 성능을 개선할 수 있습니다.

 

 

실제로 리액트에서 데이터가 변하여 웹 브라우저에 실제 DOM을 업데이트할 때는 다음 세 가지 절차를 밟습니다.

 

  1. 데이터를 업데이트하면 전체 UI를 Virtual DOM에 리렌더링한다.

  2. 이전 Virtual DOM에 있던 내용과 현재 내용을 비교한다.

  3. 바뀐 부분만 실제 DOM에 적용한다.

 

 

 

 

 

6. 마무리

 브라우저의 렌더링 과정을 이해하는 것은 웹을 학습하는데 많은 도움을 줍니다. 특히, 자바스크립트로 DOM을 조작할 때, 왜 DOM이 변경되는 것을 최소화 해야하는지 이해할 수 있습니다. 특히, 프론트엔드 개발자라면 브라우저의 성능을 최적화 시키기 위해 렌더링 과정을 이해하고 있어야 어떤 지점에서 최적화를 할 수 있을지 고민할 수 있습니다.

 

이상으로 브라우저의 렌더링 과정에 대한 설명을 마치겠습니다.

감사합니다 :)

 

 

 

 

참고

웹 페이지

https://d2.naver.com/helloworld/59361

https://poiemaweb.com/js-dom

 

DOM | PoiemaWeb

브라우저는 웹 문서(HTML, XML, SVG)를 로드한 후, 파싱하여 DOM(문서 객체 모델. Document Object Model)을 생성한다. 파일로 만들어져 있는 웹 문서를 브라우저에 렌더링하기 위해서는 웹 문서를 브라우저

poiemaweb.com

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model?hl=ko

 

객체 모델 생성  |  Web Fundamentals  |  Google Developers

브라우저가 DOM 및 CSSOM 트리를 구성하는 방법을 학습하십시오.

developers.google.com

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css?hl=ko

 

렌더링 차단 CSS  |  Web  |  Google Developers

기본적으로, CSS는 렌더링 차단 리소스로 취급됩니다. CSS가 렌더링을 차단하지 않도록 방지하는 방법에 대해 알아보세요.

developers.google.com

 

 

도서

  • 모던 자바스크립트 deep dive (이웅모 지음)

  • 리액트를 다루는 기술 (김민준 지음)

'웹 개발 > ' 카테고리의 다른 글

댓글 모듈 iframe 개발기  (0) 2021.08.22
Custom DOM Library 만들기  (1) 2021.04.05
eventListener의 Garbage Colletion에 대한 고찰  (0) 2021.03.28
HTMLCollection과 NodeList 차이 이해하기  (2) 2021.03.07
DOM & BOM 이해하기  (0) 2021.02.21