How Browsers Work

Addie L.·2020년 6월 7일
2
post-thumbnail

요청한 uri주소로 웹 브라우저가 표시될때까지의 과정

브라우저의 주요 기능

브라우저의 주된 기능은 사용자가 선택한 자원을 서버에 요청하고 응답된 결과를 브라우저에 표시하는 것입니다. 이때 브라우저는 HTML파일을 해석해 표시하는데, 웹 표준화 기구인 W3C에서 정한 HTML과 CSS 명세에 따라 표시하게 됩니다. 사용자가 자원을 요청하는 주소는 uri입니다.

브라우저와 관련된 용어

그렇다면 브라우저와 관련된 용어를 정리해보겠습니다.

naver에서 uri라는 검색어로 검색을 하게 되면 이 자원을 서버에 요청하고 응답 결과를 표시해주기 위해 이러한 url을 쓰게 됩니다. hosting은 홈페이지를 구성하는 파일 즉, html css js파일들이 인터넷에 한상 연결되어있고 이 구성파일들이 절대 꺼지지 않는 호스트 컴퓨터, 웹서버에 저장되어있다가 사용자의 요청이 오면 언제든 응답하는 것을 말합니다.

IP란 인터넷으로 통신하는 각 device에 부여된 고유한 값으로 인터넷에 연결된 모든 컴퓨터는 이 값을 사용해 서로를 찾고 통신합니다. Domain이란 문자로 된 고유주소로, 이 url의 경우 naver.com까지를 말합니다. DNS란 Domain name system을 말하는데, 사람이 읽을 수 있는 도메인의 이름을 머신이 읽을 수 있는 IP주소로 변환하는것을 말합니다. 이때 이름에 대한 요청을 IP주소로 변환해 그 사용자를 어떤 서버에 연결할 것인가를 제어하게 되는 데 이 요청을 query라고 부릅니다. 즉, 이 경우 uri라는 검색어를 가진 결과만 보여주게끔 제어하는 부분입니다.

브라우저의 기본 구조

사용자 인터페이스란 요청한 페이지를 보여주는 창을 제외한 나머지 모든 부분을 말합니다. 즉, 뒤로가기버튼, 검색창, 북마크 등의 요소들입니다.

브라우저 엔진이란 이러한 사용자 인터페이스와 렌더링 엔진사이의 동작을 제어하는 엔진입니다. 브라우저 엔진은 웹 표준화 기구인 W3C에서 정의한 HTML과 CSS 표준 명세에 따라 파일을 해석하고 브라우저에 표시합니다.

렌더링 엔진이란, 요청한 콘텐츠를 표시해주는 역할을 담당하는데, 대부분 HTML을 요청하면 HTML 문서를 파싱하고, 내부에서 DOM노드로 변환한다음 CSS파일과 스타일 요소를 함께 파싱해 렌더 트리를 생성합니다. 렌더 트리 생성 후에 각 노드가 화면에 표시되도록 배치를 시작하고 UI backend 레이어를 이용해 배치된 노드들이 그려집니다.

이러한 렌더링 엔진은 통신, 자바스크립트 해석기, UI백엔드로 다시 구성됩니다.

통신은 HTTP요청과같은 네트워크 호출에 사용되고 각 플랫폼 하부에서 실행됩니다. 자바스크립트 해석기는 자바스크립트 코드를 해석하고 실행합니다. UI백엔드는 콤보박스나 창 같은 기본적인 장치를 그리는 역할로 플랫폼에서 명시하지않은 일반적인 인터페이스입니다.

마지막으로, 자료 저장소는 자료를 저장하는 계층으로써 쿠키 저장 같이 모든 종류의 자원을 하드 디스크에 저장합니다.

렌더링 엔진

앞서 말했듯 렌더링 엔진은 요청받은 내용을 브라우저 화면에 표시하는 역할을 담당합니다.

그림과 같이 4가지 과정을 거쳐 UI백엔드에 노드를 배치시키고 배치된 노드들이 그려지게 되는데,

렌더트리를 배치하고 그리는 과정은 좀 더 나은 사용자 경험을 위해 가능하면 빠르게 화면을 표시하려고 모든 HTML이 파싱될때까지 기다리지않고 계속 통신을 하면서 전송된 내용에 대한 배치와 그리기 과정을 시작하게 됩니다. 첫번째로 DOM트리를 구축하기 위해 HTML파싱을 하고, 이때 콘텐츠 트리 내부에서 태그를 DOM 노드로 변환합니다. 그 다음 CSS파일과 스타일요소를 함께 파싱해 스타일 정보와 HTML표시 규칙을 포함한 렌더트리라고 부르는 또 다른 트리를 생성하게 됩니다. 이때 랜더트리는 랜더러를 활용해 CSS명세에 따라 노드의 CSS박스에 부합하는 사각형을 표시하게 되고, 자신과 자식요소를 어떻게 배치하고 그려내야하는지 알고 있는 렌더러는 너비, 높이, 위치와 같은 기하학적 정보를 포함하고 있어 정해진 순서대로 화면에 표시되게 됩니다. 이렇게 랜더 트리 생성이 끝나면 배치가 시작되는 데 이것은 각각의 노드가 화면 안에서 정확한 위치에 표시되는 것을 의미합니다. 그다음 UI 백엔드에서 랜더 트리의 각 노드를 가로지르며 형상을 만들어내게 됩니다. 이것을 랜더 트리 그리기 과정이라고 합니다.

렌더링 엔진은 두가지 종류가 있는데, 파이어폭스는 모질라에서 직접 만든 게코 엔진을 사용하고 사파리와 크롬은 웹킷 엔진을 사용합니다. 다른 종류의 엔진이지만 하는 일과 흐름은 똑같습니다.

제일 먼저 DOM노드와 시각정보를 연결하는 과정이 필요하고 그 다음 생성된 요소들을 렌더 트리를 그려내 시각적으로 하고 이 요소들을 화면 내에 정확한 위치에 표시하게 됩니다.

게코는 시각적으로 처리되는 렌더 트리를 형상 트리라고 부르고 각 요소를 형상이라고합니다. 웹킷은 랜더 객체로 구성되어있는 렌더트리라는 용어를 사용합니다. 이러한 요소를 배치하게 될때 웹킷은 배치라는 용어를 사용하지만 게코는 리플로라고 부릅니다. 어태치먼트(attachment)"는 웹킷이 렌더 트리를 생성하기 위해 DOM 노드와 시각 정보를 연결하는 과정입니다. 게코는 HTML과 DOM트리사이에 콘텐츠 싱크라고 부르는 과정을 두는데 이는 DOM요소를 생성하는 공정입니다.

이제부터는 DOM tree가 구축되기까지의 과정을 자세히 살펴보겠습니다.

DOM은 HTML 마크업과 1:1관계를 맺습니다. 한 태그당 하나의 DOM 구성요소가 생깁니다.

랜더러란 표시해야할 순서에 따라 올바른 순서로 내용을 그려내는 역할을 담당하는 구성요소로, 게코 엔진에서는 형상이라고 부르고 웹킷엔진에서는 렌더러 혹은 랜더 객체라는 용어를 사용합니다. 자신과 자식요소를 어떻게 배치하고 그려내야하는 지 알고있는데, 돔 트리에 부합하긴하지만 1:1관계를 맺지는 않습니다. 밑의 코드를 예시로 들어보면, html과 body태그에 대한 돔 트리가 먼저 생성이 되고 그 다음 p와 div태그, 그리고 p태그에 해당하는 text, div태그 안에 있는 img tag순으로 생성되게됩니다.

 <html>
  <body>
   <p>Hello World</p>
   <div><img src="example.png" /></div>
  </body>
</html>  

이 과정이 webkit의 경우에서 동작하게된다면, 모든 Dom node에서 동기적으로 작동하는 attachment메서드로 렌더 트리 루트를 구성하고, 배치 메서드로 크기와 위치정보같은 기하학적 정보를 계산해 배치를 시작하게 됩니다. attachment란 즉 스타일을 결정하고 렌더러를 만드는 과정입니다. DOM트리에 노드를 추가할때마다 동기적으로 새 노드의 attach메소드를 호출하게 됩니다. 이때 html과 body태그를 처리함으로써 렌더 트리 루트를 구성하게 됩니다. 이 루트 랜더 객체는 문서가 가리키는 랜더 객체가 되고 트리의 나머지 부분은 계속 DOM 노드를 추가함으로써 구축됩니다.

이렇게 랜더러가 생성되어 트리에 추가되면 크기와 위치정보를 계산하는것이 배치입니다. 배치는 프레임 계층에서 일부 혹은 전부를 통해 반복되게되고 각렌더러에 필요한 크기와 위치정보를 계산합니다. 모든 렌더러는 배치 메서드를 가지는데, 각 랜더러는 배치해야할 자식의 배치 메서드를 불러와 배치를 시작하게 됩니다.

이런 과정을 거쳐, html 파서에 의해 html을 파싱해 DOM트리가 그려지게 되는데 파싱이란 즉 브라우저가 코드를 이해하고 사용가능한 구조로 변환하는 과정입니다. 보통 이러한 파싱의 결과는 문서구조를 나타내는 노드 트리가 되고 이것을 파싱 트리혹은 문법트리라고 합니다.

html파서는 여기서 html 마크업을 파싱 트리로 변환하는 역할을 담당합니다.

DOM요소와 속성 노드의 트리로써 파싱의 결과물이 나오는데, 이 파서 트리는 최종 결과물은 아닙니다.

파싱은 컴파일러처럼 보통 문서를 다른 양식으로 변환하는데 DOM은 HTML문서의 객체 표현이고, 자바스크립트같이 외부를 향하는 HTML 요소들의 연결지점이됩니다. 그래서 DOM트리의 최상위 객체는 문서입니다. 파싱 트리는 이러한 DOM노드들을 포함하게 되는데 이 뜻은 접점 중 하나를 실행하는 요소를 구성한다는 뜻으로 브라우저에서 내부의 다른 속성들을 이용해 이렇게 구축된 트리를 구체적으로 실행하게됩니다. 여기까지 HTML파서에 의한 파싱을 거쳐 DOM트리가 어떻게 구축되는지 자세한 예시를 들어 설명해봤습니다.

0개의 댓글