인터넷 기본 지식

#5. 웹 브라우저는 어떻게 작동하는가?

흰제비갈매기 2024. 5. 31. 21:00

브라우저란?

웹 브라우저는 동기(Synchronous)적으로 (HTML + CSS), Javascript 언어를 해석하여 내용을 화면에 보여주는 응용 소프트웨어이다.

웹 브라우저가 웹 서버에 필요한 자원(웹 페이지)를 요청하면 서버는 응답하고 웹 브라우저는 이를 해석한 후 사용자(Client)에게 보여준다.
보통 자원은 HTML문서지만, PDF, 이미지 등 다양한 형태일 수 있다.

브라우저의 구조

1. 사용자 인터페이스(UserInterface)

사용자가 접근할 수 있는 영역. URI를 입력할 수 있는 주소 표시줄, 이전/다음 버튼, 북마크 메뉴, 새로 고침 버튼, 현재 문서의 로드를 중단할 수 있는 정지 버튼, 홈 버튼 등 요청한 페이지를 보여주는 창 등의 모든 부분

2. 브라우저 엔진

사용자 인터페이스와 렌더링 엔진 사이에서 중개자 역할을 한다.
사용자 인터페이스의 주소 입력창에 github.com 을 입력했다고 하자. 그 다음에는 브라우저 엔진이 작동하게 된다.
만약 자료 저장소(Data Storage)에 데이터가 없다면 입력받은 URI 값을 렌더링 엔진에 전달해준다.

  • 웹 브라우저마다 전용 브라우저 엔진을 사용한다.
    1. Gecko: 파이어 폭스
    2. Webkit: 사파리
    3. Blink: 크롬, 오페라
    4. Trident: 마이크로소프트
-moz-border-radius: 1em; // 파이어폭스 브라우저에 적용
-ms-border-radius: 2em; // 익스플로어에 적용, 보통 생략
-o-border-radius: 3em; // 오페라에 적용
-webkit-border-radius: 4em; // 구글, 사파리 브라우저에 적용

3. 자료 저장소(Data Storage)

자료 저장소를 거치지 않고 URI를 입력할 때마다 서버로 가서 데이터를 받아오면, 불필요한 메서드 통신이 발생한다.
따라서 자료 저장소로부터 자주 다운로드 받는 데이터를 저장해두고, 사용할 때마다 서버로부터 데이터를 요청(통신)할 필요 없이 바로 받아올 수 있다. 캐싱이라고도 한다.

4. 통신

서버에게 HTTP 요청을 하고, 서버로부터 응답받은 데이터(HTML, CSS, JS)를 렌더링 엔진에 전달해준다.

5. 자바스크립트 해석기

자료 저장소 또는 통신 단계를 거쳐 데이터를 응답 받은 렌더링 엔진은 javascript 해석기를 통해 javascript를 파싱하게 된다.
Chrome에서는 V8이라는 javascript 엔진을 사용한다. 이것을 통해 javascript를 파싱하게 되는 것이다.

6. UI 백엔드

select, input 등 기본적인 위젯을 그리는 인터페이스이다.

7. 렌더링 엔진

렌더링 엔진은 요청받은 내용을 브라우저 화면에 표시해주는 역할을 한다. 브라우저마다 사용되는 렌더링 엔진이 각각 다르기에 모든 브라우저가 동일한 소스를 화면에 동일하게 그려주지 아니한다. 또한 엔진마다 읽을 수 있는 코드의 버전도 다르기에 크로스 브라우징(cross browsing) 이슈가 발생한다.

크로스 브라우징(cross browsing): 웹 페이지 제작 시 모든 브라우저에서 깨지지 않고 의도한 대로 올바르게 나오게 하는 작업을 말한다. 

렌더링 엔진의 동작 과정

 

'HTML 파싱 단계'와 '렌더 트리 구축, 배치, 페인팅' 단계는 병렬적으로 일어난다. 즉 DOM 트리가 완성이 되는 순간 바로바로 렌더 트리가 구축이 되고 그려지게 된다. 따라서 사용자는 DOM 트리가 완벽하게 구축될 때까지 기다릴 필요 없이 렌더 트리가 그려짐으로 인해서 브라우저가 렌더링 될 때 위에서부터 조금씩 표시되는 것이다.

단계 설명
HTML 파싱 1. 렌더링 엔진은 HTML 문서의 구문 분석(파싱) 2. 파싱된 요소를 '콘텐츠 트리'라는 트리의 'DOM 노드'로 변환 3. 외부 CSS 파일, 스타일 요소도 같이 파싱 4. 스타일 정보, HTML 표시 규칙, javascript 파싱 결과물은 '렌더 트리'를 만드는데 사용된다.
렌더 트리 생성 HTML, CSS를 파싱해서 만들어진 '렌더 트리'에는 색상, 면적과 같은 시각적 속성을 포함하며, 이것을 정해진 순서대로 렌더링 한다.
렌더 트리 배치(레이아웃) DOM node는 배치 정보를 갖고 있다. 화면에 정해진 순서대로 배치하는 '레이아웃 단계'를 거치게 된다. 생성 과정이 끝났을 때 이루어지며 노드가 화면에 정확한 위치에 표시되는 것을 의미한다.
렌더 트리 페인팅 node 배치가 끝나면 UI 백엔드에서 렌더 트리의 각 node들을 순회하고, 페인팅 작업을 하여 그리기를 완료하게 된다.

1. DOM(Document Object Model), CSSOM(CSS Object Model) 생성 -> Parsing

  • HTML을 파싱하여 DOM 노드를 만든다. 이 DOM 노드들을 병합하여 DOM 트리를 만든다.
  • CSS를 파싱하여, CSSOM(CSS Object Model) 트리를 만들게 된다.

브라우저는 렌더링 할 문서를 HTML과 CSS로 나눠서 읽는데 각각 HTML Parser, CSS Parser가 담당한다. 이후 이들은 각각 Object Model을 만든다.

HTML 파싱과 DOM 생성 과정

  1. 서버는 브라우저로부터 요청받은 HTML 파일을 읽은 후 메모리에 저장, 그리고 메모리에 저장된 바이트(1101010101010...)를 응답한다.
  2. 브라우저는 응답받은 바이트 형태의 문서를 meta태그의 charset 속성에 지정된 인코딩 방식(UTF-8)에 따라 문자열로 반환
  3. 문자열로 변환된 HTML문서를 이번에는 문법적 의미를 갖는 코드의 최소 단위인 토큰(token)으로 분해한다.
  4. 토큰들의 내용에 따라 객체로 변환하여 각 노드들을 생성한다.(문서 노드, 요소 노드. 속성 노드, 텍스트 노드)
  5. HTML은 요소 간의 부자 관계인 중첩 관계를 갖는데, 이를 반영하여 모든 노드들을 트리 구조로 구성하여 DOM을 만든다.
CSS파싱과 CSSOM 생성 과정

렌더링 엔진은 HTML 문서를 한줄 한줄 순차적으로 파싱하여 DOM을 생성. 이때 CSS를 로드하는 link태그, 혹은 style태그를 만나면 DOM 생성을 중지한 후 CSS파싱의 결과물인 CSSOM을 생성하는 과정을 진행

<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8"> // 여기까지 해석 후, 
  <link rel="stylesheet" href="style.css"> //link를 만나면 DOM생성을 중지하고 CSS파일을 서버에 요청한 후 응답받아 CSS파싱을 시작한다. 
  ...

css파싱 과정은 바이트 > 문자 > 토큰 > 노드 > CSSOM 생성 순으로 HTML의 파싱과정과 동일하다.

자바스크립트 파싱 과정

렌더링 엔진은 HTML 문서를 한 줄씩 순차적으로 파싱하다가 자바스크립트 파일을 로드하는 script 태그를 만나면 DOM 생성을 일시 중단한다.


script 태그의 src에 정의된 자바스크립트 파일을 서버에 요청하여 응답받으면 자바스크립트 코드를 파싱하기 위해 자바스크립트 엔진에게 제어권을 넘긴다.


자바스크립트 파싱이 끝나면 렌더링 엔진으로 다시 제어권을 넘기고 DOM 생성을 이어나간다.


만약 생성되지 않은 DOM을 조작한다면 에러가 발생할 수 있다. 따라서 body 요소 아래에 자바스크립트를 위치시키거나 DOM 생성이 완료된 시점에 자바스크립트가 실행되도록 한다.

  1. 자바스크립트 코드를 토크나이저가 어휘 분석하여 문법적 의미를 갖는 코드의 최소 단위인 토큰들로 분해하는데 이것을 토큰나이징이라 한다.
  2. parser가 토큰들을 구문분석하여 AST(Abstract Syntax Tree: 추상 구문 트리)로 파싱한다.
  3. 바이트 코드 생성기가 AST를 바이트코드로 변환한다.
  4. 인터프리터에 의해 바이트코드를 실행한다.

2. 렌더 트리 구축(Attachment)

CSSOM 트리와 DOM 트리를 결합하여, 표시해야 할 순서로 내용을 그려낼 수 있도록 하기 위해 렌더 트리를 형성한다. 이 과정을 Attachment라고 한다.


렌더 트리는 화면에 표시되는 각 노드의 위치를 계산하여 레이아웃에 사용되고 픽셀을 화면에 그리는 페인트 과정에도 사용된다.

렌더 트리의 생성을 위해 브라우저는 다음과 같은 작업을 한다.

  1. DOM 트리의 루트부터 노드 각각을 모두 탐색한다.
    • 이 때 화면에 표시되지 않는 일부 노드들(script, meta 태그 등...)은 렌더 트리에서 제외된다.
    • CSS 속성 중 'display:none' 같이 화면에서 숨겨지는 속성도 렌더 트리에서 반영되지 않는다.
  2. 화면에 표시되는 각 노드에 대해 적절하게 일치하는 CSSOM 규칙을 찾아 적용한다.
  3. 화면에 표시되는 노드를 콘텐츠 및 계산된 스타일과 함께 렌더트리로 생성된다.

3. 렌더 트리 배치(Layout of Reflow)

렌더 트리가 생성되고, 기기의 뷰포트 내에서 렌더 트리의 노드가 정확한 위치와 크기를 계산한다.
이때 모든 상대적인 값이 픽셀값으로 변환된다. CSS에 상대적인 값 %, rem, vh으로 할당된 값들은 절대적인 값인 px 단위로 변환된다.
이러한 배치 과정을 Layout 또는 Reflow라고 한다.

4. 렌더 트리 그리기(Paint)

렌더 트리의 각 노드를 화면의 실제 픽셀로 나타날 때 Painting메서드가 호출된다. Painting 과정 후 브라우저 화면에 UI가 나타나게 된다.