본문으로 바로가기
반응형

1) 브라우저

주요 기능

  • URI를 입력할 수 있는 주소 표시 줄
  • 이전 버튼과 다음 버튼
  • 북마크
  • 새로 고침 버튼과 현재 문서의 로드를 중단할 수 있는 정지 버튼
  • 홈 버튼

기본 구조

  1. 사용자 인터페이스

    • 주소 표시줄, 이전/다음 버튼, 북마크 메뉴 등.
    • 요청한 페이지를 보여주는 창을 제외한 나머지 모든 부분이다.
  2. 브라우저 엔진

    • 사용자 인터페이스와 렌더링 엔진 사이의 동작을 제어.
  3. 렌더링 엔진

    • 요청한 콘텐츠를 표시. 예를 들어 HTML을 요청하면 HTML과 CSS를 파싱하여 화면에 표시함.
  4. 통신

    • HTTP 요청과 같은 네트워크 호출에 사용됨.
    • 플랫폼 독립적인 인터페이스이고, 각 플랫폼 하부에서 실행됨.
  5. UI 백엔드

    • 콤보 박스와 창 같은 기본적인 장치를 그림. (콤보박스 : 드롭다운 목록과 텍스트 상자와 조합한 것)
  6. 자바스크립트 해석기

    • 자바스크립트 코드를 해석하고 실행.
  7. 자료 저장소

    • 이 부분은 자료를 저장하는 계층이다.
    • 쿠키를 저장하는 것과 같이 모든 종류의 자원을 하드 디스크에 저장할 필요가 있다.
    • HTML5 명세에는 브라우저가 지원하는 ‘웹 데이터 베이스’가 정의되어 있다.


2) 렌더링 엔진

  • 요청 받은 내용을 브라우저 화면에 표시한다.
  • HTML  XML 문서와 이미지를 표시할 수 있다.

XML
XML이란 문자 기반의 마크업 언어, HTML처럼 데이터를 보여주는 목적이 아닌, 데이터를 저장하고 전달할 목적으로 만들어졌음. XML태그는 HTML태그처럼 미리 정의되어 있지 안혹, 사용자가 직접 정의할 수 있다.

2-1. 렌더링 엔진들

파이어복스, 크롬, 사파리는 두 종류의 렌더링 엔진으로 제작되어있다.

  • 파이어폭스 : 게코엔진
  • 사파리 : 웹킷
  • 크롬 : 블링크
    (크로미움 프로젝트 공식 블로그는 웹킷에서 블링크로 넘어간 이유를 “웹킷이 여러 아키텍처를 지원하면서 웹킷과 크로미움 프로젝트의 복잡성이 증가했고, 이에 따라 집단 혁신 속도가 저하되었기 때문”이라고 밝혔다. 출처)

Comparison of browser engines

2-2. 동작 과정

렌더링 엔진은

1. [HTML 파싱](#html_parse) (for DOM트리 구축) 2. [렌더 트리 **구축**](#setting) 3. [렌더 트리 **배치**](#layout) 4. [렌더 트리 **그리기**](#draw)

  • 일련의 과정들이 동기적으로 진행되지 않는다. HTML을 파싱할 때까지 기다리지 않고 렌더 트리 배치와 그리기 과정을 시작한다.
  • 렌더링 엔진에 따라서 동작과정이 약간 다르다.

3-2-1. 웹킷

  • 렌더트리 (렌더객체로 구성)
  • 렌더객체
  • 배치(layout)라는 용어를 사용
  • attachment : 웹킷이 렌더 트리를 생성하기 위해 DOM 노드와 시각 정보를 연결하는 과정.

3-2-2. 게코

- 형상트리(frame tree) : 시각적으로 처리되는 렌더 트리 - 형상(frame) : 형상 - 배치라는 뜻으로 리플로(`reflow`)라는 용어를 사용 - 콘텐츠 싱크 (content sink) : DOM 요소를 생성하는 공정

 

3) 자바스크립트 엔진

자바스크립트는 싱글 스레드 언어로 한번에 하나의 태스크만 처리할 수 있다. 구글에서 개발한 V8를 비롯해 대부분의 자바스크립트 엔진은 크게 세 영역으로 나뉜다.

  • Call Stack
  • Task Queue(Evnet Queue)
  • Heap

1. Call Stack

호출 스택은 자바스크립트 프로그램에서 우리가 어디에 있는지 기록하는 데이터 구조이다. 함수를 실행하면 함수에 대한 기록을 스택 제일 위에 추가한다(push). 함수의 결과값을 반환하면 스택에서 제거된다. (pop!)

function foo(b){
	var a = 5;
  	return a * b + 10 
}
function bar(x) {
var y = 3;
  return foo(x*y);
}

console.log(bar(6));
  1. 먼저 bar라는 함수를 호출했으니 bar에 해당하는 스택 프레임이 형성 되고, 그 안에는 y와 같은 local variable과 argument가 함께 생성된다.
  2. bar 함수는 foo 함수를 호출하고 있다. 아직 bar는 값을 반환하지 않은 상태이니 스택에서 pop 되지 않고 호출된 foo 함수가 Call Stack에 push 된다.
  3. foo 함수에서는 a* b + 10라는 값을 리턴하면서 함수의 역할을 마쳤으므로 stack에서 pop 된다.
  4. 다시 bar 함수로 돌아와서 foo 함수로 받은 값을 리턴하며 함수를 종료하고 스택에서 pop 된다.

자바스크립트는 단일 호출 스택을 사용한다. 이 말은 하나의 함수가 실행되고 있으면 이 함수의 실행이 끝날때까지 다른 태스크들은 수행될 수 없다는 뜻이다. 앞의 예 처럼 호출된 함수가 차례대로 쌓이고 값을 반환하면서 순서대로 pop 된다.

2. Heap

메모리 힙은 동적으로 만들어진 객체(인스턴스)가 메모리에 할당되는 곳이다.

이러한 단일 호출 스택의 문제점은 스택이 한번에 하나의 일만 처리할 수 있기 때문에 만약 그 함수가 복잡한 연산을 수행해야 한다고 하면 다른 함수가 실행되지 못하는 상황이 생긴다.

가장 쉬운 해결책은 비동기 콜백 을 사용하는 것이다. 우리 코드의 일부를 실행하고 나중에 실행될 콜백함수를 제공한다. 비동기 콜백은 즉시 호출 스택에 쌓이지 않고 Event Queue에서 기다렸다가 호출 스택이 비어있는 시점에 실행된다.

3. Event Queue

  • 자바스크립트의 런타임 환경의 이벤트 큐는 처리할 메세지 목록과 실행할 콜백 함수들의 리스트이다. 버튼 클릭 같은 이벤트나 DOM 이벤트, http 요청, setTimeout 같은 비동기 함수는 Web API를 호출하며 Web API는 콜백 함수를 콜백 큐에 밀어 넣는다.
  • 이벤트 큐는 대기하다가 스택이 텅!!!! 비는 시점에 이벤트 루프를 돌려 해당 콜백 함수를 스택에 넣는다. 이벤트 루프의 기본 역할은 큐와 스택 두 부분을 지켜보고 있다가 스택이 비는 시점에 콜백을 실행시켜 주는 것이다.
  • 웹 브라우저에서는 이벤트가 발생할 때마다 메세지가 추가되고 이벤트 리스너가 첨부된다. 콜백 함수의 호출은 호출 스택의 초기 프레임으로 사용되며 자바스크립트가 싱글 스레드 이므로 스택에 대한 모든 호출이 반환될 때까지 메세지 폴링 및 처리가 중지 된다. 동기식 함수 호출은 이와 반대로 새 호출 프레임을 스택에 추가한다.

이벤트 큐와 이벤트 루프의 동작을 잘 보여주는 setTimeout 예

setTimeout(function() {
  console.log("first");
}, 0);
	console.log("second");

// console >>
// second
// first
  • setTimeout에 0ms를 주었으니 바로 실행되는 것이 아니다. setTimeout은 호출 스택에서 실행된 후 Web API의 Timer API를 호출한다. Web API에 의해 setTimeout의 콜백함수는 이벤트 큐에 enqueue 된다. 즉 0초 뒤에 callback 함수를 실행해라! 가 아니라 0초 뒤에 callback 함수를 이벤트 큐에 넣어라~ 라는 의미이다.

  • console.log('second') 가 호출 스택에 쌓이고 second가 실행된 후 호출 스택이 비었을 때 first가 콘솔창에 나타나게 되는것이다.

    setTimeout의 delay를 0으로 주더라도 0초 보다 더 걸리는 이유는 콜 스택에서 모든 프레임이 실행될 때까지 기다려야하기 때문이다.

setTimeout은 자바스크립트 내부에서 제공하는 것이 아닌 외부에서 제공하는 Web API이다. 마찬가지로 어떤 버튼이 있다고 하고, 해당 버튼에 click 이벤트 리스너를 붙여놨다고 해보자. 버튼이 클릭되면 event Handler가 외부 API인 DOM API에 의해 이벤트 큐에 evnetHandler가 추가된 후, 호출 스택이 비었을 때 실행된다.

elem.addEventlistener('click', () => foo(value))

elem = document.querySelector('...');
elem.addEventlistener('click', foo()); //(1)
elem.addEventlistener('click', foo); // (2)
elem.addEventlistener('click', () => foo(value)); //(3) 

(1) 이렇게 핸들러를 바로 호출해버리면 이벤트 발생까지 기다리지 않고 바로 실행 됨
(2) click 될 때 event queue로 넘어가기 위해서 핸들러 이름만 적어줌, 잉 ? 근데 인자를 전달못함
(3) 편-안..이벤트 발생 때까지 기다렸다가 실행될 수 있고 인자를 전달 할 수 있음

 

 

 

 

출처: 

반응형

'IT > ' 카테고리의 다른 글

서버 사이드 렌더링(SSR), 클라이언트 사이드 렌더링(CSR)  (0) 2019.06.05