카테고리 없음

브라우저의 구조와 v8

Ahyeon, Jung 2024. 9. 29. 03:23

 최근 모바일 찍먹하면서 느끼는건,, 브라우저가 천사라는 점이다. 모바일은 처음에 프로젝트 시작하는 것부터 중간에 하나하나 코드 수정하는 것까지 다 빌드해서 진도를 나갈 수가 없다. 코드 수정하는 순간 노트북 멈출까봐 무섭다. 최종적으로 빌드할 때만 마음 졸이면 되는 웹이 그립다..! 앱등이들의 핍박도 이겨낸 갤럭시 + 윈도우지만 심각하게 맥북으로 갈아탈까 고민중이다.. 어쨌든 기다리는 이유라도 알고 싶지만 그럴려면 일단 웹부터 알아야 한다.

 


브라우저의 기본 구조

브라우저 엔진

네트워크 모듈

HTML, CSS, JavaScript 파일을 서버에서 받아온다.

렌더링 엔진

브라우저는 렌더링 엔진을 활용하여 HTML 문서를 파싱하고 DOM(Document Object Model) 트리를 생성한다. DOM은 웹 페이지의 구조를 보여주며 각 요소를 객체로 표현한다. 그리고 HTML 내의 CSS 파일을 파싱하여 CSSOM(CSS Object Model)을 생성한다. CSSSOM은 스타일 규칙을 기반으로 한 객체 구조로, DOM과 함께 페이지의 스타일을 결정한다. DOM과 CSSOM이 생성되면, 브라우저는 이를 바탕으로 렌더 트리를 생성한다. 이 렌더 트리를 기반으로 페이지의 요소들이 어떻게 배치될지 계산하는 레이아웃 단계가 일어나고 최종적으로 브라우저는 화면에 요소를 그리는 작업을 수행한다. 

자바스크립트 엔진

자바스크립트 코드나 라이브러리를 요청하면, 자바스크립트 엔진이 이를 해석하고 실행한다. 자바스크립트는 DOM과 CSSOM에 접근할 수 있으며, 이를 통해 웹 페이지의 콘텐츠와 스타일을 동적으로 변경할 수 있다.

 

자바스크립트 엔진 안에는 파서, 컴파일러, 콜 스택, 힙, 가비지 컬렉터, 실행 컨텍스트, 환경 레코드 등이 있다.

이벤트 루프

이벤트 루프는 콜스택을 지켜보다가 비어있을때 Web API 환경에서 대기 중인 비동기 함수 처리 결과들이 있으면 콜 스택에 집어넣는 역할을 한다. 이를 통해 자바스크립트의 비동기 작업을 관리하고 실행 순서를 조절할 수 있다. 

 

Web API 환경

클라이언트가  HTTP 요청을 보내면 JavaScript 엔진은 이 요청을 Web API 환경으로 전달한다. Web API 환경은 HTTP 요청을 처리하고 서버의 응답이 오면, 사용자 인터페이스를 업데이트하거나 추가 작업을 수행한다. 클라이언트로부터 비동기 요청을 받으면, 요청을 큐에 추가하여 나중에 처리하여 클라이언트의 대기 시간을 줄인다.

매크로태스크 큐

setTimeout(콜백함수, 300) 호출을 하면, WebAPI 환경에 300초 후 콜백함수를 실행하도록 예약된다. 이 시간 동안 자바스크립트 엔진은 다른 코드를 실행할 수 있다. 그리고 300초가 만료되면, 콜백 함수는 대기 상태로 되어 매크로태스크 큐에 들어간다. 이벤트 루프가 콜 스택이 비어있을 때 콜 스택에 추가하여 콜백 함수를 실행한다.

마이크로 태스크 큐

Promise 객체의 경우, 객체 내부에서 비동기작업이 있으면 WebAPI 환경으로 들어와 처리되며, 객체는 Pending 상태로 변경된다. 작업이 완료되면 resolve 혹은 reject가 호출되어 fulfilled 상태 혹은 rejected 상태로 변경되어 마이크로 태스크 큐에 추가된다.


v8의 작동방식

v8은 주로 사용되는 자바스크립트 엔진이다. 기존의 여러 자바스크립트 엔진이 웹 특성상 인터프리터 언어로 한줄 씩 번역을 했었다. v8은 JIT (Just In Time) 컴파일러를 사용하여 성능을 높였다.

 

Parser

자바스크립트 코드를 Paser를 통해 코드를 토큰으로 분해한다. 이 과정에서 문법 오류를 검사하고, 코드 구조를 이해한다.

AST 생성

분해된 토큰을 바탕으로 AST Tree(Abstract Syntax Tree)를 생성한다. 이 트리는 코드의 구조적 표현으로, 코드의 의미를 반영한다.

Bytecode 생성

AST는 인터프리터에게 전달되어 Bytecode로 변환된다. 바이트코드는 기계어에 가까운 형태로, 더 빠른 실행이 가능하게 한다.

Bytecode 실행

Bytecode를 생성하고 실행한다. Bytecode가 실행될 때 Profiler는 프로파일링 데이터를 수집하여 최적화될 수 있는 부분을 분석한다.

최적화

프로파일러는 분석 결과를 JIT 컴파일러에게 전달하고, 필요한 부분을 기계어로 최적화한다.

코드 교체

최적화한 코드가 수행할 차례가 오면, Bytecode 대신 컴파일러가 변환한 최적화된 코드가 대체하여 실행된다.


Node.js의 기본 구조

v8의 빠른 성능 덕분에 JavaScript는 브라우저에서만 사용되던 언어에서 서버 측 개발로 범위가 확장되었다. Node.js는 v8 엔진을 기반으로 하여 빠른 성능을 가지고, 네이티브 모듈을 통해 파일 시스템 접근, 네트워크 요청 처리, HTTP 서버 구축이 가능해졌다.

V8

서버 환경 역시 V8에서 실행된다.

libuv

Node.js는 libuv 라이브러리를 사용하여 비동기 I/O 및 이벤트 루프를 관리한다. 작업 종류에 따라 OS커널 혹은 스레드 풀에 전달한다. libuv의 스레드풀이 멀티 스레드로 이루어져 있기 때문에, Node.js는 완전한 싱글 스레드가 아니라고 볼수 있다.

 

libuv | Cross-platform asynchronous I/O

Asynchronous I/O made simple. libuv is a multi-platform support library with a focus on asynchronous I/O. Show me the code!

libuv.org


[Web] 🤔 V8 엔진이 대체 뭐야? (velog.io)

[NodeJS] node.js 개념, 작동방식, 특징, 구조

Node.js 동작원리 (Single thread, Event-driven, Non-Blocking I/O, Event loop) | by vincent | Medium