-
브라우저 작동 방식을 알아보자개발 2022. 11. 18. 23:53
컴퓨터를 사용하는 사람 중 대다수는 지금도 브라우저를 사용하고 있을 것이다.
거의 모든 서비스가 웹을 통해 이뤄지고, 웹 서비스에 접근하려면 웹브라우저를 이용하기 때문이다.
그런데 웹 브라우저의 UI가 각 웹 브라우저마다 조금씩 다른 것과
그 어느 것도 자동으로 마법처럼 일어나는 것은 없다는 점을 고려하면
웹 브라우저도 결국은 개발자가 만든 프로그램이라는 것을 알 수 있다.
웹 브라우저는 어떤 프로그램일까?
웹 브라우저는 사용자가 요청한 정보를 서버에서 받아서 보여주는 역할을 한다.
한 줄로 정의하자면 HTML, CSS, JS를 바탕으로 화면을 그려내는 역할을 하는 프로그램이다.
웹 브라우저는 무엇으로 구성되어 있을까?
- 사용자 인터페이스는 주소 표시줄, 새로고침, 이전, 다음 버튼 등 요청한 페이지를 보여주는 부분 이외의 모든 부분이다.
- 브라우저 엔진은 사용자 인터페이스와 렌더링 엔진 사이에서 중개하는 역할을 한다.
- 렌더링 엔진은 브라우저의 핵심이라고 볼 수 있는, 요청한 내용을 보여주는 역할을 한다.
- 네트워크 레이어는 HTTP요청 등 네트워크 호출을 할 때 이용된다.
- 자바스크립트 인터프리터는 스크립트 언어인 자바스크립트 코드를 해석하고 실행한다.
- UI 백엔드는 브라우저가 동작하고 있는 운영체제의 사용자 인터페이스를 사용하여 기본적인 위젯을 그리는데 사용된다.
- 자료 저장소는 쿠키, 로컬 스토리지, 세션 스토리지 등의 자료를 저장하는데 사용된다.
브라우저의 핵심인 렌더링 엔진의 동작 과정에 대해 알아보자
렌더링 엔진은 사용자가 요청한 내용을 아래와 같은 순서에 따라 화면에 표시해준다.
- HTML문서를 파싱하여 DOM 트리를 생성한다.
파싱은 브라우저가 코드를 이해하고 사용할 수 있도록 하는 과정이고,
파싱을 통해 보통 문서 구조를 나타내는 노드 트리가 생성된다.
HTML은 유연한 문법을 가지고 있기 때문에
파싱 중에 에러가 발생해도 최대한 에러를 브라우저 자체적으로 복구하고,
파싱 중에 <script>나 <link>등의 외부 태그를 만나면 파싱이 중단되고 외부 태그의 해석이 실행된다.
만약 defer 속성을 설정하면 파싱을 멈추지 않은채 스크립트를 다운로드할 수 있고, 파싱 이후에 스크립트가 실행된다.
그리고 DOM 트리는 JS로 상호작용할 수 있는 HTML요소로 이뤄진 트리이고, HTML 마크업과 1:1관계를 갖는다.
이 때 DOM 트리의 최상위 객체는 document이다. - HTML문서를 파싱하는 중에 링크된 CSS 파싱을 통해 CSSOM 트리를 생성한다.
CSS는 문맥 자유 문법을 따르기 때문에 정의된 CSS 명세를 바탕으로 파싱을 하게 된다.
문맥 자유 문법은 정규 파서로 파싱을 할 수 있는, 정해진 용어와 구문 규칙에 따라야하는 문법을 말한다.
CSS 파일이 스타일 시트 객체로 파싱되고, 각 객체는 CSS 규칙을 포함한다. - DOM 트리가 구축되는 동안 DOM트리와 CSSOM트리를 바탕으로 조합하여 화면에 나타나는 요소들을 결정하는 렌더 트리가 생성된다.
렌더 트리의 각 요소는 너비, 높이, 위치 등의 기하학적 정보를 포함하고 있고,
자신과 자식 요소를 어떻게 배치하고 그려야 하는지 알고 있기 때문에
렌더 트리를 통해 올바른 순서로 내용을 표현할 수 있게 된다.
렌더 트리의 요소는 시각적으로 표현되는 요소들이기 때문에 head 요소 등 비시각적 DOM요소는 렌더 트리에 포함되지 않는다.
또한 display 속성 값이 hidden인 요소는 렌더 트리에 나타나지만 none인 요소는 렌더 트리에 나타나지 않는다.
스타일 속성 선언이 여러 번 나타나는 경우에는 cascade 순서에 따라 적용이 되고,
사용자 중요 선언 (user important declarations), 저작자 중요 선언 (author important declarations), 저작자 일반 선언 (author normal declarations), 사용자 일반 선언 (user normal declarations), 브라우저 선언 (browser declarations) 순으로 우선순위가 낮아진다.
같은 순서 내에서 동일한 속성이 선언된 경우는 특정성에 의해 정렬된다.
특정성은 선택자에 id개수에 100을 곱한 값에 클래스(.test), pseudo-classes(:hover), 속성([href]) 의 개수들에 10을 곱한 값에 요소나 pseudo-element(:before) 의 개수를 더한 값으로 결정된다.
이 때 인라인 스타일은 특정성이 1000이고, !important를 쓰지 않는 이상 인라인 스타일이 가장 우선시 된다. - 레이아웃 또는 리플로우 과정을 통해 노드들의 크기와 위치, 레이어 순서 등을 바탕으로 각 노드가 화면에 표현된다.
렌더 트리가 생성되어 렌더 트리의 요소들이 추가될 때는 크기와 위치 정보를 가지고 있지 않은데,
각 요소의 크기와 위치, 레이어 순서 등을 배치하는 과정에서 계산한다.
수정을 효율적으로 하기 위해 브라우저는 더티 비트 시스템을 이용한다.
다시 배치해야되는 변경된 요소, 추가된 요소와 그 자식을 '더티'로 표시한다.
만약 글꼴 크기, 화면 크기 등 렌더 트리에 영향을 주는 변경이 있는 경우 렌더 트리 전체에서 배치가 발생하는 전역 배치가 발생하지만,
레이아웃 과정에서 렌더 트리를 탐색하다가 '더티'한 렌더러를 만나면 비동기로 일괄적으로 작업을 하게 되고,
이 방식을 이용하면 특정 부분만 다시 계산하여 연산 횟수와 범위를 줄일 수 있게 된다. - 페인팅 과정에서는 화면에 배치된 요소들에 색을 입히고, 레이어의 위치를 결정하여 실제로 그린다.
렌더 트리의 구성 요소인 렌더러의 paint 메서드가 호출되어 그려진다.
CSS 페인팅 순서는 배경 색, 배경 이미지, 테두리, 자식, 아웃라인 순이다.
각 노드의 박스들은 박스의 유형(inline, block, inline-block, none, hidden 등), 박스 크기, 박스 position, 이외의 정보들을 바탕으로 배치된다.
요소가 겹쳐진 경우에는 z-index가 낮은 것부터 먼저 페인팅되고, 앞쪽에 위치한 요소는 겹치는 요소를 가리게 그려진다.
편리하게 사용하는 웹 브라우저의 내부 동작 원리가 간단하지는 않다.
파싱 과정 하나만으로도 많은 알고리즘이 필요할 것이다.
최적화 등을 하기 위해서는 브라우저 동작 원리를 제대로 파악해야하기 때문에
브라우저의 동작 원리를 이해를 하고 개발을 하는 것이 중요할 것 같다.
'개발' 카테고리의 다른 글
Heroku로 spring boot 프로젝트 배포하기 (2) 2022.10.14 [인텔리제이 팁] wildcard * import를 막고 싶을 때 (0) 2022.09.25 화면 가르기 (0) 2022.09.02 시장의 판도를 바꾸는 Apple silicon M1 (0) 2022.08.11 백업용 조립컴을 만들어보자! (0) 2022.08.10