이벤트 루프란
이벤트 루프(Event loop)에 대해 설명해주세요 ⭐⭐⭐
Last updated
이벤트 루프(Event loop)에 대해 설명해주세요 ⭐⭐⭐
Last updated
콜 스택에 현재 실행 중인 실행 컨텍스트(함수)가 있는지, 태스크 큐에 대기 중인 함수(콜백 함수, 이벤트 핸들러 등)가 있는지 반복해서 확인한다.
만약 콜 스택이 비어 있고 태스크 큐에 대기 중인 함수가 있다면 이벤트 루프는 순차적(FIFO)으로 태스크 큐에 대기 중인 함수를 콜 스택으로 이동시킨다.
이때 콜 스택으로 이동한 함수는 실행된다. 즉, 태스크 큐에 일시 보관된 함수들은 비동기 처리 방식으로 동작한다.
JS 엔진 영역, LIFO
코드 실행에 따라 스택 프레임이 쌓이는 공간으로 함수가 호출되면 콜 스택에 하나씩 쌓이게 된다. LIFO 방식으로 실행되며 top에 있는 함수부터 실행하고 pop하여 하나씩 처리한다.
함수를 호출하면 함수 실행 컨텍스트가 순차적으로 콜 스택에 push되어 순차적으로 실행된다. JS 엔진은 단 하나의 콜 스택을 사용하기 때문에 최상위 실행 컨텍스트가 종료되어 콜 스택에서 제거되기 전까지는 다른 어떤 태스크도 실행되지 않는다.
-> JS 엔진은 단순히 태스크가 요청되면 콜 스택을 통해 요청된 작업을 순차적으로 pop하며 실행할 뿐이다.
브라우저 or Node.js 영역, FIFO
콜백 큐 혹은 이벤트 큐라고도 부른다. 비동기 함수의 콜백 함수, 이벤트 핸들러가 일시적으로 보관되는 영역으로 FIFO 방식으로 하나씩 처리한다.
콜 스택이 비게 되면 이벤트 루프에 의해 함수가 순차적으로 하나씩 콜 스택에 전달된다.
위 코드는 어떤 순서로 출력될까?
먼저 과정을 설명해보면
start가 출력된다. 출력하고나서 콜 스택은 비워져 있다.
addEventlistener 함수가 호출되어 실행 컨텍스트가 생성된다. 콜 스택에 push되어 현재 실행 중인 실행 컨텍스트가 된다.
등록했던 콜백은 태스크 큐에 enqueue한다.(브라우저의 역할) 콜 스택은 비워져 있다.
end가 출력된다. 출력하고나서 콜 스택은 비워져 있다.
사용자가 클릭을 했을 때 상황
JS 엔진의 입장에서 코드 실행입니다.
callback start를 출력한다. 출력하고나서 콜 스택은 비워져 있다.
setTimeout함수가 호출되어 실행 컨텍스트가 생성된다. 콜 스택에 push되어 현재 실행 중인 실행 컨텍스트가 된다. 콜백 함수를 호출 스케줄링하고 종료되어 콜 스택에서 팝된다.
1ms(4ms, 최소 지연 시간)가 지나고 콜백 함수가 태스크 큐에 enqueue되어 대기한다.(브라우저 역할)
이때 2번째 setTimeout 혹은 console.log는 JS엔진에 의해 병행 처리된다.
만약 1ms가 경과했어도 콜 스택이 비어 있지 않으면 태스크 큐에 있는 함수는 아직 대기 중이다.
콜 스택이 비었다는 것이 확인되면 1을 출력하고 다음 setTimeout도 2번 과정처럼 진행한다.
10ms가 지나고 콜백 함수가 태스크 큐에 enqueue되어 대기한다.
콜 스택이 비었다는 것이 확인되면 3을 출력하고 콜 스택에서 팝된다.
2번째 setTimeout함수가 호출되어 실행 컨텍스트가 생성된다. 콜 스택에 push되어 현재 실행 중인 실행 컨텍스트가 된다. 콜백 함수를 호출 스케줄링하고 종료되어 콜 스택에서 팝된다.
1000ms가 지나고 콜백 함수가 태스크 큐에 enqueue되어 대기한다.
콜 스택이 비었다는 것이 확인되면 2을 출력하고 콜 스택에서 팝된다.
callback end를 출력한다. 출력하고나서 콜 스택은 비워져 있다.
조금 더 심화 학습을 위해 주석을 풀고 생각해보세요!
setTimeout 함수의 함수 실행 컨텍스트가 생성되고 콜 스택에 push되어 현재 실행 중인 실행 컨텍스트가 된다. 브라우저의 Web API(호스트 객체)인 타이머 함수도 함수이므로 함수 실행 컨텍스트를 생성한다.
setTimeout 함수가 실행되면 콜백 함수를 호출 스케줄링하고 종료되어 콜 스택에서 팝된다. 이때 호출 스케줄링, 즉 타이머 설정과 타이머가 만료되면 콜백 함수를 태스크 큐에 enqueue하는 것은 브라우저의 역할이다.
브라우저는 타이머를 설정하고 타이머의 만료를 기다린다. 이후 타이머가 만료되면 콜백 함수가 태스크 큐에 푸시된다. 지연 시간이 4ms 이하인 경우 최소 지연 시간 4ms가 지정된다.
setTimeout 함수로 호출 스케줄링한 콜백 함수는 정확히 지연 시간 후에 호출된다는 보장은 없다. 지연 시간 이후에 콜백 함수가 태스크 큐에 push되어 대기하게 되지만 콜 스택이 비어야 호출되므로 약간의 시간차가 발생할 수 있기 때문이다.
이벤트루프에 의해 콜스택이 비어있음이 감지되고 태스크 큐에서 대기중인 콜백함수가 이벤트루프에 의해 콜스택에 push된다.
현재 실행 중인 실행 컨텍스트가 되고 함수가 종료되어 콜 스택에서 pop된다.
모던 자바스크립트 Deep Dive 42장 비동기 프로그래밍