이 글은 ASAC 06기를 수강하며 강의 자료 참고 및 추가 자료 수집을 통해 작성된 글입니다.
Javascript Runtime
자바스크립트 엔진을 기반으로 자바스크립트 언어로 된 모든 코드를 실행할 수 있게 한 뒤, 필요한 API들을 조합한다.
- 엔진 = 언어를 구동
자바스크립트 엔진은 웹 서버와 웹 브라우저에서 모두 사용될 수 있다.
자바스크립트 엔진의 종류는 많지만, 대표적인 엔진으로는 구글의 v8 엔진이 있다.
자바스크립트 엔진의 용도는 사용하는 API에 의해 결정된다.
- 웹 브라우저 (프론트엔드)
=> 자바스크립트 엔진(V8) + Web APIs - 웹 서버 (백엔드)
=> 자바스크립트 엔진(V8) + Node APIs + LIBUV- LIBUV = 비동기 I/O 라이브러리
Javascript 엔진 구성
구글 V8 기반의 Javascript 엔진 구성은 다음과 같다.
- 싱글 스레드
자바스크립트 엔진 자체는 싱글 스레드이다.
2. Stack + Heap
- (Call) Stack
- 함수 실행 순서대로 스택에 적재 및 수행
- 함수 실행에 필요한 모든 것
- Heap
- 개발자가 선언 및 할당한 변수 및 함수 저장
- 여러 변수 및 함수 담는 바구니. 객체는 힙에 할당됨
1. 웹 브라우저 비동기 처리
- 엔진(V8) + Web APIs
자바스크립트 엔진이 싱글 스레드임에도 멀티 스레드처럼 동작할 수 있는 이유는, Web API와 이벤트 루프 때문이다.
웹 브라우저에서 Web API를 통한 비동기 작업을 지원하기 때문에 멀티 스레드처럼 동작시킬 수 있다. 브라우저 내부에서 이벤트 루프와 태스크(콜백) 큐를 가지고 있다. 그리고 자바스크립트 엔진 내부의 메모리 힙과, 콜 스택을 사용해 작업을 처리한다.
Web API를 사용하여 커널(하드웨어)를 직접적으로 조작하고 활용할 수 있다.
setTimeout(() => console.log('Done'), 2000);
위는 setTimeout Web API를 사용하는 코드이다.(일종의 타이머 역할을 수행한다.) 첫번째 파라미터로는 콜백 함수가, 두번째 파라미터로는 적용할 시간(ms 단위)가 주어진다.
주의
자바스크립트 브라우저 런타임의 처리 방식은 실제로는 멀티 스레드가 아니다. 자바스크립트 엔진은 실제로는 싱글 스레드로 동작하고, 이벤트 루프 에 의해서 여러 이벤트들을 순차적(논블로킹) 처리하여 멀티 스레드처럼 보일 뿐이다. 그렇기 때문에 Timeout을 여러 번 실행하는 경우에 delay가 발생한다. => 즉, 시간과 관련된 Web API를 사용하는 경우 부정확성이 존재할 수밖에 없다.
위 그림은 자바스크립트 엔진을 사용하여 웹 브라우저의 비동기 처리를 하는 자바스크립트 시스템이다.
- Call Stack + Memory Heap : 작업장
- 엔진에 내장되어 있다. Task들을 올려서 처리하는 용도로 사용된다.
- 초기에는 동기 작업들을 순차적으로(논블로킹) 수행하고, 동기 작업이 모두 완료되면 비동기 작업(콜백함수)들을 수행한다.
- Web APIs : 비동기 일감 모음
- 웹과 관련한 다양한 작업들에 대한 Web API가 존재한다.
ex) DOM 조작, 지리 정보, Timeout ... etc
비동기적(Asynchronous)으로 동작한다.
- 웹과 관련한 다양한 작업들에 대한 Web API가 존재한다.
- Event Loop : 문지기
- Task Queue(MicroTask Queue가 있는 경우, MicroTask Queue도 포함)의 Task를 관리한다. 자바스크립트 엔진이 싱글 스레드임에도, 비동기 작업을 통하여 멀티 스레드처럼 동작할 수 있도록 해준다.
- Task(Callback) Queue : 대기실
- 동기 작업이 끝난 후에 실행할 콜백 함수(비동기 작업)를 적재한다.
- 콜스택이 비워지면, 이벤트 루프에 의해서 Task Queue의 가장 오래된 작업(콜백함수)가 콜스택으로 올려지고 실행된다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Event_loop
https://dev.to/lovepreetsingh/multithreading-event-loops-vs-thread-pools-and-more-48di
Web Worker API
웹 브라우저의 자바스크립트 런타임에서 자바스크립트 엔진은 싱글 스레드로, Web API들은 비동기로 동작하여 실제로는 멀티 스레드가 아님에도 멀티 스레드처럼 동작시킬 수가 있었다.
Web Worker API 를 사용하면 실제로 멀티 스레드를 활용하여 개발이 가능하다.
각각의 Web Worker들은 독립적인 메세지 큐, 이벤트 루프, 메모리 공간을 가진다.
사용 예시
한 웹 페이지에서 이미지를 수백개 가져오는 AJAX 콜이 발생한다면, Web Worker API를 사용하여 멀티 스레드로 처리한다.
https://medium.com/@rajeev.rehansh/web-workers-and-multithreading-621856d91b57
2. 웹 서버 비동기 처리
- 엔진(V8) + Node APIs + Libuv(비동기 I/O 라이브러리)
Libuv 는 Node.js에서 비동기 작업을 처리하기 위해 C언어로 개발된 비동기 I/O 라이브러리이다. 네트워크, 파일 시스템 등의 논블로킹 비동기 I/O 연산을 지원하며, OS에 관계없이 하나의 플랫폼을 제공한다. 자바스크립트 브라우저 런타임에서 브라우저의 역할과 비슷한 역할을 한다. (전통적인 I/O 함수들을 사용하는 경우 블로킹이 발생하거나, 비동기적으로 처리되지 않기 때문에 기다려야하는 문제점이 있었다.)
Libuv는 내부에 이벤트 큐, 이벤트 루프와 Worker Threads라는 스레드풀을 가지고 있다.
이벤트 루프는 Libuv 내부에 하나만 존재하며, Worker Thread로 Task를 할당하여 멀티 스레드로 동작시킨다.
위 그림은 자바스크립트 엔진을 사용하여 웹 서버의 비동기 처리를 하는 Node.js 시스템이다.
- Node APIs : 비동기 일감 모음
- I/O Task
ex) 파일, 폴더 관리, TCP/UDP transaction, 압축, 암호화 작업
- I/O Task
- Event Queue : 대기실
- 동기 작업이 끝난 후 실행할 콜백 함수(비동기 작업)를 적재한다.
- Worker Threads의 작업들이 끝나면, Event Loop에 의해서 Worker Threads로 할당된다.
- Event Loop : 문지기
- Worker Threads로 작업들을 할당한다.
- Worker Threads : 작업장
- 기본적으로 스레드풀에는 4개의 Worker Thread가 존재한다.
- 최대 스레드 수 이하로 작업이 존재하는 경우, 작업들은 동시에 실행될 수 있지만, 작업 수가 스레드 수를 넘어가면 이미 실행되는 작업이 끝나야 실행될 수 있기 때문에 즉시 실행할 수 없다.
https://www.geeksforgeeks.org/libuv-in-node-js/
https://medium.com/@viralthaker27/how-well-do-you-understand-nodes-event-loop-and-threadpool-ad1d62af66fd
'ASAC' 카테고리의 다른 글
[ASAC 06] Javascript 프레임워크 동작원리(2) - Bundling & Code Splitting (0) | 2024.08.27 |
---|---|
[ASAC 06] Javascript 프레임워크 동작원리(1) - Javascript Transpiler (2) | 2024.08.27 |
[ASAC 06] 프론트엔드 변천사(Vanilla JS, jQuery, React.js) (1) | 2024.08.27 |
[ASAC 06] 렌더링, 렌더링 패턴(SSR, CSR, SSG, ISR, Hydration) (0) | 2024.08.27 |
[ASAC 06] WS와 WAS (0) | 2024.08.27 |