[딥다이브 스터디] 브라우저 렌더링 과정

dana·2022년 5월 30일
3

CS

목록 보기
11/11

구글의 V8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임 환경인 Node.js의 등장
-> 자바스크립트는 웹 브라우저가 아닌 서버에서도 동작하는 범용 개발 언어

대부분의 프로그래밍 언어는 운영체제, 가상 머신 위에서 동작
<-> 웹 애플리케이션의 클라이언트 사이드 자바스크립트는 브라우저에서 HTML, CSS와 함께 실행
-> 브라우저 환경을 고려할 때 더 효율적인 클라이언트 사이드 자바스크립트 프로그래밍이 가능

파싱
프로그래밍 언어의 문법에 맞게 작성된 텍스트 문서를 읽어 들여 실행하기 위해 텍스트 문서의 문자열을 토큰으로 분해하고 문법적 의미와 구조를 반영해 트리 구조의 자료구조인 파스 트리를 생성하는 일련의 과정

렌더링
렌더링은 HTML, CSS, 자바스크립트로 작성된 문서를 파싱해 브라우저에 시각적으로 출력하는 것을 의미

브라우저의 렌더링 과정

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

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

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

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

38.1 요청과 응답

브라우저의 핵심 기능 : 필요한 리소스를 서버에 요청하고 서버로부터 응답 받아 브라우저에 시각적으로 렌더링하는 것

서버에 요청하기 위해 브라우저는 주소창을 제공

브라우저의 주소창에 URL을 입력
-> URL의 호스트 이름이 DNS를 통해 IP 주소로 변환
-> 해당 IP 주소를 갖는 서버에게 요청을 전송

예시

주소창에 https://velog.io 입력시, https://(스킴), velog.io(호스트)로 이루어진 루트 요청이 서버로 전송.
루트 요청에는 명확한 리소스를 요청하는 내용이 없지만, 일반적으로 index.html을 응답하도록 기본 설정.
만약 index.html 이 아닌 다른 파일을 요청하는 경우, path에 작성해 해당 폴더를 요청.

브라우저의 주소창을 통해 서버에게 정적 파일만 요청할 수 있는 것이 아니라, 자바스크립트를 통해 동적으로 서버에 정적/동적 데이터 요청 가능

38.2 HTTP 1.1 과 HTTP 2.0

HTTP 1.1

커넥션 하나당 하나의 요청과 응답만 처리
= 여러개의 요청과 응답을 한번에 전송할 수 없음
-> 요청할 리소스의 개수에 비례해 응답 시간이 증가

HTTP 2.0

여러 리소스의 동시 전송이 가능
-> HTTP/1.1에 비해 페이지 로드 속도가 약 50% 정도 빠름

38.3 HTML 파싱과 DOM 생성

브라우저의 요청에 의해 서버가 응답한 HTML 문서는 문자열로 이루어진 순수한 텍스트
-> 응답받은 HTML 문서를 파싱해 브라우저가 이해할 수 있는 자료구조인 DOM을 생성

진행 과정

  1. 서버에 존재하던 HTML 파일이 브라우저의 요청에 의해 응답.
    • 서버는 브라우저가 요청한 HTML 파일을 읽어 들여 메모리에 저장한 다음 메모리에 저장된 바이트를 인터넷을 경유해 응답.
  2. 브라우저는 서버가 응답한 HTML 문서를 바이트(2진수) 형태로 응답
    • 응답된 바이트 형태의 HTML 문서는 meta 태그의 charset 어트리뷰트에 의해 지정된 인코딩 방식을 기준으로 문자열로 변환
    • meta 태그의 charset 어트리뷰트 : 응답 헤더에 담겨 응답
  3. 문자열로 변환된 HTML 문서를 읽어 들여 문법적 의미를 갖는 코드의 최소 단위인 토큰들로 분해
  4. 각 토큰들을 객체로 변환해 노드를 생성.
    • 토큰의 내용에 따라 문서 노드/ 요소 노드 / 어트리뷰트 노드 / 텍스트 노트 생성
  5. HTML 문서는 HTML 요소들의 집합으로 구성되며, 중첩 관계를 가짐.
    • 중첩 관계를 반영해 모든 노드를 트리 자료구조(DOM)로 구성

DOM은 HTML 문서를 파싱한 결과물

38.4 CSS 파싱과 CSSOM 생성

렌더링 엔진이 한 줄씩 순차적으로 DOM을 생성하다가 link태그나 style 태그를 만나면 DOM 생성을 일시 중단

서버에 css 파일 요청 후, 바이트 - 문자 - 토큰 - 노드 - CSSOM을 거치며 해석해 CSSOM을 생성
CSSOM은 CSS의 상속을 반영해 생성되기 때문에, 상위에 지정한 스타일이 하위 요소에 전달 됨.

파싱 완료 후, 기존에 작업중이던 HTML 파싱이 중단된 지점으로 돌아가 다시 시작

38.5 렌터 트리 생성

렌더링 엔진이 서버로 부터 받은 HTML과 CSS를 파싱해 각각 DOM, CSSOM을 생성하고, 이는 렌더링을 위해 렌더 트리로 결합

렌더 트리는 렌더링을 위한 트리 형태의 자료 구조
= 화면에 렌터링되지 않는 노드들은 포함되지 않음

  • meta tag
  • script
  • display : none

렌더 트리는 레이아웃을 계산하는데 사용되며, 페인팅 처리에 입력 됨.

브라우저 렌더링 과정은 반복해서 실행될 수 있음.

레이아웃 계산과 페인팅이 재차 실행되는 경우

  1. 자바스크립트에 의한 노드 추가, 삭제
  2. 브라우저 창의 리사이징에 의한 뷰포트 크기 변경
  3. HTML 요소의 레이아웃에 변경을 발생시키는 width/height, margin, padding, border, display, position, top/right/bottom/left 등 스타일 변경

레이아웃 계산과 페인팅은 비용이 많이 드는 작업
= 성능에 악영향
-> 가급적 리렌더링이 발생하지 않도록 주의

38.6 자바스크립트 파싱과 실행

자바스크립트 코드에서 DOM API를 사용해 이미 생성된 DOM을 동적으로 조작 가능

CSS 렌더링과정과 비슷하게 script 태그를 만나면 서버에서 파일을 받아 자바스크립트 엔진에 제어권을 넘김
자바스크립트 엔진은 CPU가 이해할 수 있는 저수준의 언어로 변환 및 실행하는 역할을 함
다양한 종류가 있으며, 모든 자바스크립트 엔진은 ECMAScript 준수

자바스크립트 엔진은 AST(추상적 구문 트리)를 생성해 이를 기반으로 인터프리터가 실행할 수 있는 중간 코드(바이트 코드)를 생성 및 실행

토크나이징
단순한 문자열인 자바스크립트 코드를 어휘 분석해 문법적 의미를 갖는 최소 단위인 토큰들로 분해

파싱
토큰들의 집합을 구문 분석해 AST를 생성
AST 사용시, 트랜스파일러를 구현할 수 있음.

바이트코드 생성과 실행
파싱의 결과물로서 생성된 AST는 인터프리터가 실행할 수 있는 바이트코드로 변환되고 인터프리터에 의해 실행
코드의 사용 빈도가 적어지면 디옵티마이징되기도 함.

38.7 리플로우와 리페인트

DOM API에 의해 변경되는 경우, 다시 렌더 트리가 결합되는 과정을 거치면서 변경된 렌터트리를 기반으로 레이아웃과 페인트 과정을 거쳐 브라우저의 화면에 다시 렌더링

리플로우

레이아웃 계산을 다시 하는 것

  • 노드 추가/삭제
  • 요소의 크기/위치 변경
  • 윈도우 리사이징

리페인팅

렌더트리를 기반으로 다시 페인트 하는 것.

리플로우와 리페인팅이 순차적으로 동시에 실행되는 것 ❌
레이아웃에 영향이 없는 경우 리페인팅만 실행되기도 함.

38.8 자바스크립트 파싱에 의한 HTML 파싱 중단

렌더링 엔진과 자바스크립트 엔진은 직렬적으로 파싱 수행
동기적으로 실행되기 때문에, HTML이 블로킹되어 실행이 지연될 수 있음.
그렇기 때문에 가장 아래에 자바스크립트를 위치시키는 것을 권장

  • DOM이 완성되지 않은 상태에서 자바스크립트가 DOM을 조작하면 에러 발생 가능
  • 자바스크립트 로딩/파싱/실행으로 인해 HTML요소들의 렌더링에 지장받는 일이 발생하지 않아 페이지 로딩 시간이 단축

38.9 script 태그의 async/defer 어트리뷰트

자바스크립트 파싱에 의한 DOM 생성이 중단되는 문제를 근본적으로 해결하기 위해 등장

외부 자바스크립트 파일을 불러오는 경우에만 사용 가능
인라인 자바스크립트로는 사용 불가

<script async src="extern.js"/> 
<script defer src="extern.js"/> 

HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행
-> 자바스크립트의 실행 시점의 차이 존재

async

파일 로드가 동시에 진행되며, 자바스크립트 파일 로드가 끝남과 동시에 실행. 이 때 HTML 파싱 중단

여러개의 script 태그에 async를 지정하면, 태그의 순서와 상관없이 먼저 로드가 완료된 순서부터 실행
-> 순서 보장 ❌

defer

자바스크립트의 파싱과 실행은 HTML파싱이 완료된 직후 (DOMContentLoaded 이벤트 발생)

profile
PRE-FE에서 PRO-FE로🚀🪐!

0개의 댓글