브라우저
브라우저는 우리가 컴퓨터를 사용하면서 가장 많이 사용하는 소프트웨어일 것입니다.
크롬, 파이어폭스, 엣지등등과 같은 소프트웨어들이 우리가 흔히 사용하는 브라우저죠.
브라우저의 주요 기능
브라우저의 주요 기능은 사용자가 원하는 자원을 서버에 요청하고
그리고 받은 자원을 브라우저에 띄우는 것입니다.
브라우저의 인터페이스는 소프트웨어들마다 조금씩 다 비슷하게 되어있는데
오랜 기간을 거쳐 제일 적합한 인터페이스로 정형화 됐다고 생각하시면 됩니다.
즐겨찾기(북마크), 뒤로가기, 앞으로가기, 새로고침, 주소표시줄 등등과 같은 기능을 제공하죠
브라우저 구조
브라우저가 어떻게 동작하는지 구글에 검색하면
아래의 사진이 정말 많이 나옵니다. 그만큼 중요하고, 대부분의 브라우저들이 비슷하게 동작한다는 것으로 보입니다.
사용자 인터페이스
주소 표시줄, 이전/다음 버튼, 북마크 메뉴 등. 요청한 페이지를 보여주는 창을 제외한 나머지 모든 부분이다.
브라우저 엔진
사용자 인터페이스와 렌더링 엔진 사이의 동작을 제어.
자료 저장소
이 부분은 자료를 저장하는 계층이다. 쿠키를 저장하는 것과 같이 모든 종류의 자원을 하드 디스크에 저장할 필요가 있다. HTML5 명세에는 브라우저가 지원하는 '웹 데이터 베이스'가 정의되어 있다.
렌더링 엔진 ⭐
요청한 콘텐츠를 표시. 예를 들어 HTML을 요청하면 HTML과 CSS를 파싱하여 화면에 표시함.
통신
HTTP 요청과 같은 네트워크 호출에 사용됨. 이것은 플랫폼 독립적인 인터페이스이고 각 플랫폼 하부에서 실행됨.
자바스크립트 해석기 ⭐
자바스크립트 코드를 해석하고 실행.
UI 백엔드
콤보 박스와 창 같은 기본적인 장치를 그림. 플랫폼에서 명시하지 않은 일반적인 인터페이스로서, OS 사용자 인터페이스 체계를 사용.
서버로부터 자원을 받아 그 자원을 바탕으로 렌더링하는 렌더링 엔진
그리고 웹 개발자가 개발한 자바스크립트를 해석하는 자바스크립트 해석기
이 둘을 중요시하게 여기는 것 같았다.
렌더링 엔진
이 글에서 다루는 브라우저인 파이어폭스와 크롬, 사파리는 두 종류의 렌더링 엔진으로 제작되었다. 파이어폭스는 모질라에서 직접 만든 게코(Gecko) 엔진을 사용하고 사파리와 크롬은 웹킷(Webkit) 엔진을 사용합니다.
렌더링 엔진은 통신(HTTP)으로부터 요청한 문서의 내용을 얻는 것으로 시작하는데 문서의 내용은 보통 8KB 단위로 전송됩니다.
렌더링 엔진의 큰 동작 과정은 아래와 같습니다.
렌더링 엔진은 HTML 문서를 파싱하고 "콘텐츠 트리" 내부에서 태그를 DOM 노드로 변환한다. 그 다음 외부 CSS 파일과 함께 포함된 스타일 요소도 파싱한다. 스타일 정보와 HTML 표시 규칙은 "렌더 트리"라고 부르는 또 다른 트리를 생성한다.
우선 HTML 문서를 파싱한다, HTML 문서를 읽고 분석하는 겁니다.
그리고 태그들을 DOM 노드로 변환한다는 것의 의미는 다음과 같습니다.
HTML은 그냥 문서일 뿐입니다. 그 문서를 분석해서 객체로 만들고, 그 객체들에게 의미를 부여해서
분석가능한 것으로 만들겠다는 겁니다. 그리고 계층이 있는 Tree 구조로 만드는 것이죠.
의미가 없는 문서를 분석하고 각각의 태그에 의미를 부여해 계층화(트리화)를 시키는 작업입니다.
렌더 트리는 색상 또는 면적과 같은 시각적 속성이 있는 사각형을 포함하고 있는데 정해진 순서대로 화면에 표시된다. 렌더 트리 생성이 끝나면 배치가 시작되는데 이것은 각 노드가 화면의 정확한 위치에 표시되는 것을 의미한다. 다음은 UI 백엔드에서 렌더 트리의 각 노드를 가로지르며 형상을 만들어 내는 그리기 과정이다.
위의 작업들에서 트리를 만들고 나면 배치, 즉 화면에 노드들이 배치가 된다는 뜻입니다. 이 단계는 아직 그려지는 단계는 아닙니다.
배치가 완료되면 UI 백엔드에서 만들어진 렌더트리를 가로지르며(순차적으로) 그리기 과정을 수행합니다.
일련의 과정들이 점진적으로 진행된다는 것을 아는 것이 중요하다. 렌더링 엔진은 좀 더 나은 사용자 경험을 위해 가능하면 빠르게 내용을 표시하는데 모든 HTML을 파싱할 때까지 기다리지 않고 배치와 그리기 과정을 시작한다. 네트워크로부터 나머지 내용이 전송되기를 기다리는 동시에 받은 내용의 일부를 먼저 화면에 표시하는 것이다.
네트워크로부터 나머지 내용이 전송되기를 기다리는 동시에 받은 내용의 일부를 먼저 화면에 표시하는 것이다.
자바스크립트의 비동기와 비슷하다는 느낌을 받았습니다.
처리한 요청을 기다리지 않고 다른 작업을 수행하도록 하는 것이죠.
렌더링 엔진중에 대표적인 웹킷의 동작 과정의 사진을 볼 수 있었습니다.
처음에 봤을 때는 조금 어지러웠지만,
이해를 하며 읽으면 조금 잘 읽혔습니다.
HTML을 읽어 들입니다. 그리고 번역기, 파서를 통해서 그냥 HTML 문서였던 것을
DOM 이라는 객체 모델로 트리라는 구조를 만들어냅니다.
웹은 파싱과 실행이 동시에 수행되는 동기화(synchronous) 모델이다. 제작자는 파서가 < script > 태그를 만나면 즉시 파싱하고 실행하기를 기대한다. 스크립트가 실행되는 동안 문서의 파싱은 중단된다. 스크립트가 외부에 있는 경우 우선 네트워크로부터 자원을 가져와야 하는데 이 또한 실시간으로 처리되고 자원을 받을 때까지 파싱은 중단된다. 이 모델은 수 년간 지속됐고 HTML4와 HTML5의 명세에도 정의되어 있다. 제작자는 스크립트를 "지연(defer)"으로 표시할 수 있는데 지연으로 표시하게 되면 문서 파싱은 중단되지 않고 문서 파싱이 완료된 이후에 스크립트가 실행된다. HTML5는 스크립트를 비동기(asynchronous)로 처리하는 속성을 추가했기 때문에 별도의 맥락에 의해 파싱되고 실행된다.
HTML 파서는 HTML을 순차적으로 읽습니다.
읽다가 <script> 태그를 만나면 HTML 파서는 하던일을 멈추고
스크립트를 실행합니다. 그리고 스크립트 실행이 전부 끝나고 나면 다시 HTML 파서를 진행합니다.
우리가 스크립트 태그를 <body> 태그의 제일 아래에 넣는 이유가 위와 같습니다.
자바스크립트에서 DOM 조작을 했을 때 없는 요소로 판단되는 것을 막는 것이죠.
그리고 예측 파서라는 것이 파이어폭스와 웹킷에 존재합니다.
웹킷과 파이어폭스는 예측 파싱과 같은 최적화를 지원한다. 스크립트를 실행하는 동안 다른 스레드는 네트워크로부터 다른 자원을 찾아 내려받고 문서의 나머지 부분을 파싱한다. 이런 방법은 자원을 병렬로 연결하여 받을 수 있고 전체적인 속도를 개선한다. 참고로 예측 파서는 DOM 트리를 수정하지 않고 메인 파서의 일로 넘긴다. 예측 파서는 외부 스크립트, 외부 스타일 시트와 외부 이미지와 같이 참조된 외부 자원을 파싱할 뿐이다.
즉, 스크립트를 만나서 스크립트를 실행하는 중에는 HTML 파서가 작동하지 않지만
웹킷과 파이어폭스는 DOM에 영향을 주지 않는 일에 대해서 병렬적으로 처리를 한다고 합니다.
성능을 향상시킨 것이죠.
그럼 스타일 시트 파싱은 어떻게 진행할까요? 네이버 D2에선 아래와 같이 언급했습니다.
한편 스타일 시트는 다른 모델을 사용한다. 이론적으로 스타일 시트는 DOM 트리를 변경하지 않기 때문에 문서 파싱을 기다리거나 중단할 이유가 없다. 그러나 스크립트가 문서를 파싱하는 동안 스타일 정보를 요청하는 경우라면 문제가 된다. 스타일이 파싱되지 않은 상태라면 스크립트는 잘못된 결과를 내놓기 때문에 많은 문제를 야기한다. 이런 문제는 흔치 않은 것처럼 보이지만 매우 빈번하게 발생한다. 파이어폭스는 아직 로드 중이거나 파싱 중인 스타일 시트가 있는 경우 모든 스크립트의 실행을 중단한다. 한편 웹킷은 로드되지 않은 스타일 시트 가운데 문제가 될만한 속성이 있을 때에만 스크립트를 중단한다.
그러니까 스타일 시트는 DOM 트리를 일반적으로 변경하지 않아서 문서 파싱을 기다리지 않는다고 합니다.
근데 스크립트에서 스타일 정보를 요청하는 것은 꽤 자주 일어납니다. 그래서 렌더링 엔진마다 이에 대한 해답을 다르게 구현해놨는데
파이어폭스는 스타일 시트가 파싱중이면 스크립트 실행을 그냥 중단합니다. 하지만 웹킷은 유동적으로 문제가 될만한 속성이 있을 때만 스크립트를 중단합니다.
아래의 사진에서 전체적인 과정을 한눈에 볼 수 있었습니다. (크롬의 웹킷 기준입니다.)
- HTML을 읽는다
- HTML을 파싱한다.
- HTML 파싱 도중 스타일시트를 만나면 HTML 파싱을 멈추지 않고 스타일시트 로드와 파싱, CSSOM Tree를 생성한다.
- HTML 파싱 도중 스크립트 태그를 만나면 HTML 파싱을 멈추고 스크립트 로드, 파싱, 트리를 만드는 작업을 진행한다.
- 스크립트 파싱 도중 스타일 시트 파싱을 보통은 멈추지 않지만, 스크립트에 스타일정보를 요청하는 일이 빈번하기 때문에 파이어폭스는 스크립트 파싱 도중 스타일 시트 파싱을 멈추고, 웹킷은 스타일정보가 필요할 때만 멈춘다.
- 파이어폭스나 웹킷은 스크립트 파싱도중 HTML 파싱을 멈추는 것이 비효율적이라고 생각했는지, DOM에 영향이 가지 않는 선에서 외부 문서 파싱을 병렬적으로 진행한다.
- 이렇게 HTML과 CSS을 로드, 파싱, 그리고 트리를 생성까지 했다면 렌더 트리를 생성한다.
- 렌더 트리를 이용해 노드들을 화면에 배치한다.
- 배치한 것을 사용자 화면에 그린다.
참고
'개발지식' 카테고리의 다른 글
[개발지식] Webpack과 Babel은 왜 쓰이는 건지 알고 계신가요? (0) | 2022.01.26 |
---|---|
[개발지식] 브라우저 저장소, 각각에 대해서 자세히 알고 계신가요? (0) | 2022.01.21 |
[개발지식] Client Side Rendering & Server Side Rendering 차이점에 대해서 아시나요? (0) | 2022.01.19 |
[개발지식] 웹 서버와 웹 애플리케이션 서버의 차이, 정확히 알고 계신가요? (0) | 2022.01.11 |
[개발지식] CORS, 잘 알고 계신가요? (0) | 2022.01.08 |