본문 바로가기
Web/HTML, CSS

웹 브라우저의 렌더링 과정, 원리

by 가나닩 2024. 4. 23.

HTML와 CSS, Javascript로 개발을 완료한 뒤 웹페이지에 표시를 시키기 위해서는 웹 브라우저의 렌더링 과정이 필요하다.

React 등의 프레임워크로 개발된 프로젝트도 HTML, CSS, Javascript로 변환되어 브라우저에서 실행된다.

 

웹 브라우저는 렌더링 엔진을 통해 HTML 파일을 렌더링한다. 

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

※ 웹 브라우저마다 렌더링 엔진이 다르며 전체 렌더링 과정에 조금씩 차이가 있다. 아래 그림은 렌더링 과정을 간소화하여 표현했으며 실제 렌더링은 코드, 네트워크, 최적화, 기타 환경의 차이등의 이유로 훨씬 복잡하고 유기적으로 작동한다.

간소화한 웹브라우저의 렌더링 과정

  1. 문서 다운로드 : 사용자가 요청한 웹페이지에 해당하는 문서를 서버에서 가져온다.
  2. HTML 파싱 및 DOM트리 생성 : 가져온 문서인 HTML을 파싱하고 DOM트리를 성한다.
    2-1. CSS 파싱 및 CSSOM트리 생성 : HTML문서에서 <style>태그 혹은 css파일을 발견하면 CSSOM트리를 생성하기 시작한다.
    2-2. Javascript 실행 : HTML문서에서 <script>태그를 만나면 Javascript 코드를 실행한다.
  3. 렌더 트리 생성 : 완성된 DOM트리와 CSSOM트리를 이용해 렌더 트리를 생성한다.
  4. 레이아웃 : 렌더 트리 노드들의 위치와 크기 등을 계산한다. (레이아웃)
  5. 페인트 : 계산된 위치와 크기를 기반으로 하여 색칠, 그림자등의 효과를 추가하여 렌더링한다. (페인트)

 

2. 각 과정에 대한 설명

2-1. 문서 다운로드

사용자가 URL을 입력하면 브라우저는 해당 서버에 HTTP 요청을 보낸다. 서버는 요청된 리소스(HTML 문서)를 포함한 HTTP 응답을 반환한다. 이때 다운로드 받은 리소스는 웹브라우저의 렌더링엔진에서 입력으로 사용된다.

CSS파일, JS파일과 img태그에 링크된 이미지 파일 등은 이때 다운로드되지 않는다. 이후 과정인 HTML 파싱 단계에서 해당 파일이 링크되어 있는것을 발견하면 그때 추가적으로 다운로드를 진행하게 된다.

 

2-2. HTML 파싱 및 DOM트리 생성

HTML 파일은 웹브라우저의 렌더링엔진에 의해 파싱된다.

HTML 파싱 과정

  • Bytes -> Characters : HTML 파일은 네트워크를 통해 전송될때 바이트 형태로 인코딩 되어 전송된다. 렌더링엔진은 인코딩된 HTML파일을 받게되는데 이 내용을 캐릭터 형태로 변환한다. 우리에게 익숙한 HTML문서의 모습이다.
  • Characters -> Tokens : HTML파일은 토큰으로 변환된다. <div>, <a> 등의 다양한 태그와 콘텐츠(태그 내부 내용), 주석 등을 역할에 따라 구문 단위로 분해하는 과정이다.
  • Tokens -> Nodes : 각 토큰들은 다시 노드로 변환된다. DOM 트리를 성하기 위해 요소 노드, 텍스트 노드 등으로 구분하게 된다. 이 노드들은 각각 의미를 가지고 있지만 관계가 표현되어있지 않은 상태이다.
  • Nodes -> DOM : 변환된 노드들은 서로의 관계성에 따라 연결되며 연결된 노드들의 구조를 DOM 트리라고 부른다.

이 과정에서 HTML 문서내에 있는 <link>태그 <script>태그 <style>태그 등으로 css와 js코드를 발견하게 된다.

이때 렌더링엔진은 상황에 맞춰 css와 js코드를 처리한다.

 

2-2-1. CSS 파싱 및 CSSOM트리 생성

CSS는 주로 HTML문서에 세가지 형태로 담긴다.

  1. <link> 태그를 통해 css문서를 첨부. 서버에 있는 css파일을 첨부하거나 웹에있는 css파일을 첨부하기도 한다.
    (비동기 처리, 렌더링 차단 혹은 FOUC 가능성)
  2. <style> 태그를 통해 작성된 css코드
    (동기 처리, 파싱속도에 영향, FOUC 방지)
  3. 인라인 방식으로 태그안에 작성된 style 속성
    (즉시 적용, FOUC 방지, 필요한 경우에만 사용)
더보기
  1. <link> 태그 : 외부에서 css파일을 다운로드받는다. HTML 파싱과 별개로 리소스 다운로드를 진행하므로 파싱속도에 영향을 주지않는다는 장점이 있다.
    하지만 css파일이 크거나 네트워크가 느릴경우 HTML 파싱이 먼저 완료될 수 있다. 이때 브라우저는 초기 속도 저하를 막기위해 이 내용을 먼저 렌더링 할 수 있다. 이후 css가 적용되면 화면 레이아웃이 갑자기 바뀌게 되는데 이를 FOUC(Flash of Unstyled Content)라고 한다. (IE에서 주로 발생) 이는 preload 등으로 해결할 수 있다.
  2. <style> 태그 : HTML 문서 내에 작성된 내용이므로 HTML 파싱 과정에서 바로 CSSOM 트리 생성에 사용된다. HTML 파싱 과정에 바로 해석되는 CSS 코드이므로 FOUC 현상을 방지할 수 있다.
    하지만 HTML 내부에 직접 작성된 내용이므로 HTML 파싱속도에 영향을 준다.
  3. 인라인 style : FOUC 현상이 방지되며 태그에 직접 작성되어있으므로 즉시 해당요소의 CSSOM에 반영된다.
    HTML 태그에 직접 작성된 내용이므로 동적 스타일 변경에 유리할 수 있지만 추후 해당문서의 스타일 변경이 힘들 수 있다. 일반적으로는 스타일 관리를 위해 CSS파일을 따로 작성하는것이 권장된다.

2-2-2. Javascript 실행

Javascript는 <script> 태그로 문서에 담긴다. CSS와의 큰 차이점은 Javascript 코드를 실행하는 동안에는 HTML 파싱과정이 중단된다는 것이다. 그 이유는 다음과 같다.

  1. Javascript의 DOM 조작
    JS는 DOM을 조작할 수 있다. 충돌 방지 등의 여러가지 이유로 JS해석엔진과 렌더링엔진은 직렬적으로 실행되는데 JS의 해석이 시작되면 렌더링엔진은 자연스럽게 파싱과정을 중단하게 된다.
  2. 스크립트 의존성 관리
    <script> 태그가 여러개 존재할경우 하단에 작성된 자바스크립트 코드가 상단에 작성된 자바스크립트 코드에 의존할 수 있다. 이를 관리하기위해 <script> 태그를 만나면 렌더링을 중단하고 자바스크립트를 실행하게된다.

이러한 이유로 파싱과정이 중단되면 페이지 로딩이 느려질 수 있고 아직 파싱되지않은 DOM요소를 Javascript에서 이용하려 한다면 오류가 발생하거나 개발자의 의도대로 작동하지 않을 수 있다.

이러한 문제를 해결하기위해 <body>태그 아래 최하단에 <script>태그를 두어 참조할 DOM요소의 파싱이 완료된후 Javascript가 실행되도록 할 수 있으며 HTML5부터 도입된 defer와 async를 사용해도 된다.

 

Javascript 실행까지 마무리하여 DOM과 CSSOM의 수정이 끝나면 렌더 트리를 생성할 준비가 완료된다.

 

2-3. 렌더 트리 생성

앞서 생성한 DOM 트리와 CSSOM 트리를 이용해 렌더 트리를 생성한다. HTML의 태그와 컨텐츠, CSS 속성이 하나의 트리에 모여 렌더링을 준비한다.

렌더 트리는 실제 화면에 표시되는 항목으로만 구성된다. 예를들어 CSS 속성에 display : none이 포함되어있어 보이지 않는 항목이거나 meta태그, script태그 처럼 사용자에게 보일 필요가 없는 부분은 렌더트리에 구성되지 않는다.

 

2-4. 레이아웃

생성된 렌더 트리를 토대로 레이아웃 과정을 거친다.

CSS 속성중 position, top 같은 위치태그나 width, height 같은 크기 태그 등을 기준으로 웹페이지에 표시할 자리들을 마련한다고 생각하면 된다.

em이나 rem, 혹은 vw, vh, % 같이 비율로 그 크기와 길이를 나타내는 요소들은 이 과정에서 px단위로 변경된다.

 

  • Stacking context (쌓임 맥락)

레이아웃 과정에서 position 값이나 z-index 값에 따라 어떤 요소가 더 앞에 있고 더 뒤에 있는지를 표현하기 위해 레이어 구조를 사용한다. postion, z-index 값이 없더라도 렌더 트리의 계층 구조와 더불어 여러가지 요소를 고려하여 모든 항목은 레이어로 구분되어 레이아웃을 구성하게 된다.

 

  • Box Model

레이아웃 과정에 생성할 요소들은 모두 Box Model 구조를 갖는다.

웹 브라우저 개발자 도구(F12)에서 확인이 가능하다.

 

앞서 설명한 크기, 위치 등의 값과 영향을 준 CSS 값을 확인할 수 있다.

2-5. 페인트

레이아웃 과정이 완료되면 각 요소가 위치할 자리를 모두 마련한 상태이다. 이 공간들에 색을 더하고 내용을 채우는 과정이 페인트 과정이다.

페인트 과정에서도 레이아웃 단계에 생성한 레이어 구조를 깨트리지 않고 그대로 내용을 채운다. 추후 레이아웃, 페인트 과정이 다시 필요한 리플로우, 리페인트 과정에서 내용을 수정할때 레이어 형태로 구성되어있어야 필요한 요소만 수정하기 편하기 때문이다.

 

2-6. Composite

레이아웃, 페인트 과정을 완료하고 나뉘어 있는 레이어를 모두 합쳐 하나의 화면으로 합성하는 과정이다. composite 과정이 완료되면 웹 브라우저는 렌더링 준비를 마친 상태이며 사용자에게 화면을 보여줄 수 있게 된다.

초기 렌더링이 완료된 이후에는 CSS와 DOM의 변경에 따라 레이아웃과 페인트 과정을 계속 반복하여 화면을 다시 그리게 되는데 이를 리플로우, 리페인트 과정이라고 한다.

'Web > HTML, CSS' 카테고리의 다른 글

CSS의 position 속성  (0) 2024.05.03
CSS의 Box Model, Margin과 Padding의 차이  (1) 2024.05.02
transition 사용하기  (0) 2024.04.13
(CSS) height와 width값이 auto일때 transition 사용하기  (0) 2024.01.25
Expo 설치  (0) 2022.07.10