[JS] 이벤트 루프(Event Loop), 태스크 큐(Task Queue)

6
post-thumbnail

자바스크립트 엔진의 작동원리.. 이벤트 루프..태스크 큐.. 정말 익숙하고 무슨 개념인지 대략적으로는 알지만 누군가에게 설명하라하면 '이게 맞나?' 라고 느꼈던 것들을 정리해보고자 한다.😲

자바스크립트 엔진 : 싱글 스레드(Single thread)

브라우저에 내장된 자바스크립트 엔진은 한 번에 태스크(task) 1개만 처리하는 싱글스레드 방식으로 동작한다. 그런데 자바스크립트로 동작하는 브라우저를 보면 애니메이션 효과를 보여주며, 유저가 요청한 데이터도 가지고 온다. 어떻게 싱글 스레드로 여러 가지 일이 동시에 실행되는 것처럼 만드는 걸까? 이와 같이 싱글 스레드에서 여러 가지 일이 동시에 실행되는 것처럼 보이는 자바스크립트의 동시성(Concurrency)은 바로 이벤트 루프(Event Loop)를 통해 구현된다.

이벤트 루프(Event Loop), 태스크 큐(Task Queue)

자바스크립트 엔진 : 콜 스택, 메모리 힙

자바스크립트 엔진은 콜 스택(Call stack)과 메모리 힙(Memory Heap)으로 구성되어 있다.

1. 콜 스택
함수를 호출하면 함수 실행 컨텍스트가 순차적으로 콜 스택에 푸시되어 순차적으로 실행된다. 자바스크립트는 단 하나의 콜스택을 사용하기 때문에 실행 중인 실행 컨텍스트가 종료되어 콜 스택에서 제거되기 전까지는 다른 태스크는 실행시키지 않는다.

2.메모리 힙
객체가 저장되는 메모리 공간. 콜 스택의 요소인 실행 컨텍스트는 힙에 저장된 객체를 참조한다.

자바스크립트 엔진은 태스크가 요청되면 콜 스택을 통해 요청된 작업을 순차적으로 실행시킨다. 비동기 처리에서 자바스크립트 엔진이 담당한 소스코드 평가, 실행을 제외한 모든 처리는 자바스크립트를 구동하는 환경인 브라우저/Node.js가 한다.

  • 자바스크립트 엔진 : setTimeout 콜백 함수 평가/실행 담당
  • 브라우저/Node.js : 타이머 설정, 콜백 함수 등록(호출 스케줄링)

참고
👉* 실행 컨텍스트 : 식별자를 등록하고 관리하는 스코프, 코드 실행 순서를 관리한다. 모든 코드는 실행 컨텍스트를 통해 실행/관리된다.

💡실행 컨텍스트 동작 순서

  1. 전역 코드 평가 : 변수/함수 선언문을 먼저 실행시키고 전역 변수/전역함수를 전역 스코프에 등록 시킴
  2. 전역 코드 실행 : 런타임 시작되며 전역 코드가 순차 실행 ⇢ 전역 변수에 값 할당, 함수 호출을 함 ⇢ 함수가 호출되면 함수 내부로 들어감
  3. 함수 코드 평가 : 함수 내부에 있는 매개변수와 지역 변수 선언문 실행 ⇢ 매개변수, 지역 변수가 실행 컨텍스트가 관리하는 지역 스코프에 등록됨 ⇢ arugments 객체 생성 및 지역 스코프에 등록, this 바인딩 결정
  4. 함수 코드 실행 : 런타임 시작되며 함수 코드 순차 실행 ⇢ 매개변수, 지역 변수에 값 할당, 내부에 있는 매서드 등 실행

브라우저 환경 : 태스크 큐, 이벤트 루프

1.태스크 큐
setTimeout 이나 setInterval 같은 비동기 함수의 콜백 함수, 이벤트 핸들러가 일시적으로 보관되는 영역이다.

2.이벤트 루프
이벤트 루프는 콜 스택에 현재 실행 중인 실행 컨텍스트가 있는지, 태스크 큐에 대기중인 함수(콜백 함수, 이벤트 핸들러..)가 있는지 반복해서 확인한다. 콜스택이 비어 있고 태스크 큐에 대기중인 함수가 있다면 이벤트 루프는 순차적으로 태스크 큐에 대기 중인 함수를 콜스택으로 이동시킨다. 이때 콜 스택으로 이동한 함수는 실행된다.

이처럼 이벤트 루프는 스택이 비워지고 나서 태스크 큐에 있는 함수를 순차적으로 콜 스택으로 넣어주기 때문에, 아래와 같은 settimeout 0초 콜백 함수는 console.log Hi와 Daisy가 실행된 후 콜 스택이 비워졌을 때 태스크 큐로 이동되어 실행 된다.

이에 따라 아래 코드는 Hi ⇢ Daisy ⇢ Dami 순으로 콘솔창에 보여지게 된다.

console.log('Hi');
setTimeout(function cb(){
  console.log('Dami');
},0);
console.log('Daisy');

참고

0개의 댓글