본문 바로가기

Programming Language/Javascript

[Javascript] 자바스크립트 원리 & 이벤트 루프 동작(순회) 구조

이벤트 루프는 브라우저 동작을 제어하는 관리자 : 브라우저의 동작 타이밍을 제어하는 관리자

마치 순회(loop) 하는듯하여 이벤트 루프라 부르는 것이다

[ 자바스크립트 엔진 구동 환경]


자바스크립트를 실행하는 소프트웨어로는 우리가 잘 알고 있는 웹브라우저와 런타임인 Node.js 가 있다.

싱글 스레드인 자바스크립트 엔진이 어느 곳을 거쳐 비동기 작업을 수행하는지 우선 이 둘의 내부 구성도를 눈에 익혀보자.

[ 브라우저 내부 구성도 ]

구성 요소로는 Web APIs, Event Table, Callback Queue, Event Loop 등이 있다.

﹡ Call Stack : 자바스크립트 엔진이 코드 실행을 위해 사용하는 메모리 구조

﹡ Heap : 동적으로 생성된 자바스크립트 객체가 저장되는 공간

Web APIs: 브라우저에서 제공하는 API 모음으로, 비동기적으로 실행되는 작업들을 전담하여 처리한다. (AJAX 호출, 타이머 함수, DOM 조작 등)

Callback Queue : 비동기적 작업이 완료되면 실행되는 함수들이 대기하는 공간

﹡ Event Loop : 비동기 함수들을 적절한 시점에 실행시키는 관리자

﹡ Event Table: 특정 이벤트(timeout, click, mouse 등)가 발생했을 때 어떤 callback 함수가 호출되야 하는지를 알고 있는 자료구조 (위 그림에는 없음)

[ Web Apis 종류 ]

Web APIs는 타이머, 네트워크 요청, 파일 입출력, 이벤트 처리 등 브라우저에서 제공하는 다양한 API를 포괄하는 총칭이다. Web API는 브라우저(Chrome)에서 멀티 스레드로 구현되어 있다. 그래서 브라우저는 비동기 작업에 대해 메인 스레드를 차단하지 않고 다른 스레드를 사용하여 동시에 처리할수 있는 것이다.

예를 들어,setTimeout비동기 작업은 Web APIs의 한 종류인 Timer API 에서 타이머 스레드를 사용하여 타이머를 수행한다. 마찬가지로, XMLHttpReques , fetch와 같은 네트워크 관련 API는 네트워크 스레드를 사용하여 네트워크 요청과 응답을 처리된다.

Web APIs의 대표적인 종류로는 다음과 같다.

﹡ DOM : HTML 문서의 구조와 내용을 표현하고 조작할 수 있는 객체

﹡ XMLHttpRequest: 서버와 비동기적으로 데이터를 교환할 수 있는 객체. AJAX기술의 핵심.

﹡ Timer API: 일정한 시간 간격으로 함수를 실행하거나 지연시키는 메소드들을 제공

﹡ Console API : 개발자 도구에서 콘솔 기능을 제공

﹡ Canvas API: <canvas> 요소를 통해 그래픽을 그리거나 애니메이션을 만들 수 있는 메소드들을 제공

﹡ Geolocation API: 웹 브라우저에서 사용자의 현재 위치 정보를 얻을 수 있는 메소드들을 제공

[ Callback Queue 의 종류 ]


Web APIs가 여러 API들을 묶어 말하듯이, Callback Queue도 여러가지 종류의 Queue를 묶어 총칭하는 개념이다. Callback Queue에는 (macro)task queue와 microtask queue 두 가지 종류가 있다.

Task QueuesetIntervalfetchaddEventListener 와 같이 비동기로 처리되는 함수들의 콜백 함수가 들어가는 큐 (macrotask queue 는 보통 task queue 라고 부른다)

Microtask Queuepromise.thenprocess.nextTickMutationObserver 와 같이 우선적으로 비동기로 처리되는 함수들의 콜백 함수가 들어가는 큐 (처리 우선순위가 높음)

Callback Queue의 종류에 따라 이벤트 루프가 콜 스택으로 옮기는 순서가 달라진다. 일반적으로 microtask queue가 가장 우선순위가 높아 먼저 microtask queue를 처리하여 먼저 비우고 그라음 task queue의 콜백을 처리한다.

이벤트 루프를 배우기 전에 Promise.then 결과가 setTimeout보다 우선 된다는 것을 미리 배웠다면,

왜 프로미스가 먼저 처리되는지에 대한 이유가 이벤트 루프의 동작 원리와 관련이 있다는걸 알 수 있을 것이다.

→ Microtask Queue 인 promise.then 이 먼저 처리 되기 때문이다

또한 같은 queue 안에 적재되는 콜백이라도 어떠한 비동기 작업이냐에 따라 우선순위가 다른 태스크들이 있을 수 있다. 예를들어 Microtask Queue에 적재되는 Promise 와 Mutation ObserverVisit Website 콜백 중 Mutation Observer이 먼저 처리되는 식이다.

[ AnimationFrames Queue ]


브라우저의 큐는 콜백 큐 뿐만 아니라 브라우저 애니메이션 작업에 대한 처리를 담당하는 AnimationFrame Queue도 있다.

자바스크립트 애니메이션 동작을 제어하는 requestAnimationFrame 메소드를 통해 콜백을 등록하면, 이 큐에 적재되어 브라우저가 repaint 직전에 AnimationFrame Queue에 있는 작업들을 전부 처리한다.

따라서 자바스크립트 스타일 관련 코드들을 AnimationFrame Queue에 비동기로 처리하도록 구성하면 브라우저가 애니메이션의 타이밍을 관리하고, 적절한 프레임 속도를 유지하고, 다른 탭이나 창에 있을 때 애니메이션을 중지함으로써 브라우저의 애니메이션 동작의 성능과 품질을 향상시킬 수 있다.

  • repaint

    브라우저 렌더링 단계중 렌더 트리를 사용하여 실제로 화면에 픽셀을 출력 (객체가 실제 화면에 그려지는 것을 의미 )

[ 자바스크립트 이벤트 루프 동작 과정 ]


싱글 스레드인 자바스크립트 에서도 작업의 동시 처리를 지원할 수 있는 비결에는 이벤트 루프가 자바스크립트 엔진과 브라우저의 웹 API를 연결하여 비동기적인 일 처리를 가능케 하기 때문이다.

다만 모든 자바스크립트 코드를 비동기로 처리할 수 있는 것은 아니다.

자바스크립트에는 비동기로 동작하는 비동기 전용 함수가 있는데 대표적으로 setTimeout 나 fetchaddEventListener 가 있다.

이벤트 루프(Event Loop)는 이 비동기 함수 작업을 Web API에 옮기는 역할을 하고 작업이 완료되면 콜백을 큐(Queue)에 적재했다가 다시 자바스크립트 엔진에 적재해 수행시키는 일종의 '작업을 옮기는 역할' 만을 한다.

이벤트 루프는 Call Stack에 현재 실행 중인 작업이 있는지 그리고 Task Queue에 대기 중인 작업이 있는지 반복적으로 확인하는 일종의 무한 루프만을 돌고, 대기 작업이 있다면 작업을 옮겨주는 형태로 동작한다고 보면 된다.

// 이벤트 루프의 동작을 나타내는 가상의 코드
while(queue.waitForMessage()){ // 큐에 메시지가 있을 때까지 대기
  queue.processNextMessage(); // 가장 오래된 메시지를 큐에서 꺼내서 호출 스택으로 옮김
}


Uploaded by N2T