Rego의 블로그

브라우저 렌더링 본문

Front-end

브라우저 렌더링

RegularPark 2023. 4. 17. 23:25

반드시 잊어버릴 나를 잘 알기에 기록하는 글 #1


브라우저 렌더링이란?

브라우저 렌더링은 브라우저(Chrome, Edge, Safari 등)가 HTML, CSS, JS로 작성된 문서를 파싱하여 브라우저에 시각적으로 출력하는 것을 말합니다. 파싱(Parsing)이란, 프로그래밍 문법에 맞게 작성된 텍스트를 읽어 들여 실행하기 위해 텍스트 문서의 문자열을 토큰으로 분해하고, 토큰에 문법적 의미와 구조를 반영하여 파스 트리를 생성하는 과정을 말합니다.

브라우저는 아래의 과정을 거쳐 렌더링을 수행합니다.

  1. 브라우저는 HTML, CSS, JS 등 렌더링에 필요한 리소스를 요청하고 서버로부터 응답을 받는다.
  2. 브라우저의 렌더링 엔진은 서버로부터 응답된 HTML과 CSS를 파싱하여 DOM과 CSSOM을 생성하고 이들을 결합하여 렌더 트리를 생성한다.
  3. 브라우저의 자바스크립트 엔진은 자바스크립트를 파싱하여 AST(Abstract Syntax Tree)를 생성하고 바이트코드로 변환하여 실행한다, 이때 자바스크립트는 DOM API를 통해 DOM이나 CSSOM을 변경할 수 있다. 변경된 DOM과 CSSOM은 다시 렌더 트리로 결합된다.
  4. 렌더 트리를 기반으로 HTML 요소의 레이아웃(위치와 크기)을 계산하고 브라우저 화면에 HTML 요소를 페인팅한다.

렌더링 과정을 단계별로 자세히 알아보겠습니다.

요청과 응답

예를 들어 브라우저의 주소창에 https://velog.io/을 입력하고 엔터 키를 입력하면 velog.io 서버로 루트 요청이 전송됩니다. 루트 요청이란 /, 스킴(scheme)과 호스트만으로 구성된 URI에 의한 요청을 말합니다. 일반적으로 서버는 루트 요청에 대해 암묵적으로 index.html을 응답하도록 기본 설정되어 있습니다.
따라서 서버는 루트 요청에 대해 서버의 루트 폴더의 index.html을 클라이언트(브라우저)로 응답합니다. 이때 index.html뿐 아니라 CSS, JS, 이미지, 폰트 파일들도 응답됩니다. 이는 렌더링 엔진이 HTML을 파싱하는 도중에 외부 리소스를 로드하는 태그를 만나면 HTML 파싱을 일시 중단하고 해당 리소스 파일을 서버로 요청하기 때문입니다.

HTML 파싱과 DOM 생성

브라우저의 렌더링 엔진은 응답받은 HTML 문서를 파싱하여 브라우저가 이해할 수 있는 자료구조인 DOM을 생성합니다.

  1. 서버와 브라우저는 바이트 형태로 요청과 응답을 주고 받는다.
  2. 브라우저는 바이트 형태의 응답을 문자열로 변환하는 과정을 거친다.
  3. 문자열로 변환된 HTML 문서를 문법적 의미를 갖는 코드의 최소 단위인 토큰들로 분해한다.
  4. 토큰들을 객체로 변환하여 노드들을 생성한다. 노드는 DOM 구성의 기본 요소가 된다.
  5. HTML 요소는 중첩 관계를 갖는다. HTML 요소의 콘텐츠 영역 에는 텍스트뿐만 아니라 다른 HTML 요소도 포함될 수 있다는 말이다. 이때 중첩 관계에 의해 부자 관계가 형성되는데, 이를 반영하여 모든 노드들을 트리 자료구조로 구성한다. 이 트리 자료구조를 DOM이라고 한다.

CSS 파싱과 CSSOM 생성

렌더링 엔진은 HTML을 한 줄씩 파싱합니다. 그러다가 CSS를 로드하는 link/style 태그를 만나면 DOM 생성을 일시 중지하고 CSS 파일을 서버에 요청합니다. 그리고 HTML과 동일하게 CSS를 파싱하여 CSSOM을 생성하는 과정을 거칩니다. CSS 파싱을 완료하면 HTML 파싱이 중단된 지점부터 다시 HTML을 파싱하기 시작하여 DOM 생성을 재개합니다.

렌더 트리 생성

렌더링 엔진은 DOM과 CSSOM를 생성하고, 렌더링을 위해 렌더 트리로 결합합니다.

완성된 렌더 트리는 각 HTML 요소의 레이아웃(위치와 크기)을 계산하는 데 사용되며 브라우저 화면에 픽셀을 렌더링하는 페인팅 처리에 입력됩니다. 여기까지의 과정으로 사용자는 화면에 렌더링된 결과물을 확인할 수 있습니다.

그러나 지금까지 설명한 렌더링 과정은 반복되어 실행될 수 있습니다. 다음과 같은 경우 반복해서 레이아웃 계산과 페인팅이 재차 실행됩니다.

  • 자바스크립트에 의한 노드 추가 또는 삭제

  • 브라우저 창의 리사이징에 의한 뷰포트 크기 변경

  • HTML 요소의 레이아웃(위치, 크기)에 변경을 발생시키는 width/height, margin, padding, border, display, position, top/right/bottom/left 등의 스타일 변경


위 경우들이 브라우저의 리렌더링을 발생하게 하는 요인들인데요, 리렌더링은 비용이 많이 드는, 성능에 악영향을 끼칩니다. 이 과정을 리플로우, 리페인트라고도 합니다.

리플로우와 리페인트

리플로우는 레이아웃 계산을 다시 하는 현상입니다. 노드 추가/삭제, 요소의 크기/위치 변경, 윈도우 리사이징 등 레이아웃에 영향을 주는 변경이 발생하면 실행됩니다. 리페인트는 재결합된 렌더 트리를 기반으로 다시 페인트하는 것을 의미합니다.

리플로우와 리페인트에 관한 자세한 내용은 다음 글에서 기술하겠습니다.


작성 동기(넋두리)

우아한테크코스 레벨1을 마치며, 레벨을 진행하는 동안 학습한 것에 대한 인터뷰(이하 레벨 인터뷰)를 진행했습니다. 얕디 얕은 학습 상태를 메타인지할 수 있는 귀중한 시간이었어요.😭 인터뷰 중 리플로우에 대한 꼬리 질문으로 브라우저 렌더링의 과정에 대한 질문이 있었습니다. 리플로우를 설명한다면 당연하게도 선행학습이 되어있어야 할 브라우저 렌더링에 대해서 제대로 설명할 수가 없더라구요...😇
이러한 작금의 사태를 타개하고자 앞으로도 부족한 학습 상태의 보충분을 기록하고자 합니다. 이 글에 넘버링이 된 이유이기도 하구요. 어렵겠지만 제발 꾸준히 작성하길 다짐해봅니다...

reference

- 모던 자바스크립트 Deep Dive, 이웅모 지음
- https://tecoble.techcourse.co.kr/post/2021-10-24-browser-rendering/
- https://d2.naver.com/helloworld/59361

'Front-end' 카테고리의 다른 글

[TypeScript]상표 기법  (0) 2023.09.17
[JavaScript]프로토타입(Prototype)  (0) 2023.09.12
Webpack을 통한 build  (0) 2023.07.30