이벤트 기반 모델에서는 이벤트 루프
라는 개념이 등장한다.
여러 이벤트가 동시 발생했을 때 어떤 순서로 콜백함수를 호출할지를 이벤트 루프가 판단한다.
Node는 javascript 코드를 맨 위부터 한줄씩 실행하는데, 함수 호출 부분을 발견했다면 호출한 함수를 호출 스택에 넣는다.
function first(){
second();
console.log("첫번째");
}
function second(){
third();
console.log("두번째");
}
function third(){
console.log("세번째");
}
first();
다음과 같은 함수를 호출한다면,
실행결과는 이렇게 나온다!
호출순서는 first -> second -> third 순으로 호출 되지만,
실행은 호출된 순서와 반대로 실행이 되기 때문이다.
(여기서 main 함수는 전역 컨텍스트를 의미하며, 함수가 호출 되었을때 생성되는 환경이다)
이렇게 실행 된 후 함수 실행이 완료되면 호출 스택에서 차례로(third ->..) 지워진다.
최종으로 main 함수까지 실행이 완료되면, 호출 스택은 비어있게 된다.
이번에는 특정 밀리초 이후 코드를 실행하는 setTimeOut을 사용했다.
function run(){
console.log("3초후 실행");
}
console.log("실행");
setTimeout(run,3000);
console.log("끝");
다음과 같이 코드를 작성하면,
다음과 같은 결과가 나온다.(시작과 끝이 먼저 출력되고, 3초뒤 '3초 후 실행'이 나온다.)
여기서 SetTimeOut 함수의 콜백인 run이 호출 스택에 언제 들어가는지 파악하기 위해서는,
이벤트루프
, 태스크큐
, 백그라운드
에 대해 이해해야 한다.
이벤트루프 : 이벤트 발생 시 호출할 콜백함수를 관리하고, 콜백함수의 실행순서를 결정
테스트 큐 : 이벤트 발생 후 호출되어야 할 콜백 함수들이 기다리는 공간
백그라운드 : 타이머나 I/O 작업 콜백 또는 이벤트 리스너들이 대기하는 공간
다음은 위의 코드가 실행되는 내부 환경을 묘사한 그림이다.
먼저 전역함수인 main 함수가 들어가고 그 뒤 setTimeOut이 호출 스택에 들어간다.
여기서 실행은 반대의 순서로 진행된다.
먼저, SetTimeOut이 실행되면 타이머와 함께 run 콜백을 백그라운드로 보내고, 그 후 main 함수가 호출 스택에서 빠진다. 마지막으로 백그라운드에서 3초를 세고 run 함수를 테스크 큐로 보낸다.
그 후 호출스택이 비어있는 상황이 되면, 테스트 큐에서 함수를 하나씩 가져와 호출 스택에 넣고 실행한다.
호출 스택으로 올려진 run은 실행되고, 실행 완료 후 호출 스택에서 비워지게 된다.
이벤트 루프는 태스크 큐에 콜백 함수가 들어올때까지 계속 대기한다..
여기서, 만약 호출 스택에 함수가 너무 많으면 3초 뒤에도 run 함수가 실행되지 않을 수 있다.
(SetTimeOut의 시간이 정확하지 않을 수 있음)