Ryu.log

[ NodeJS 03 ] 호출 스택과 이벤트루프 본문

Prev-content

[ NodeJS 03 ] 호출 스택과 이벤트루프

류뚝딱 2018. 7. 10. 23:07



내가 Node를 배우는이유는 실제 서버로 동작시키기 위함이다.

실제서버는 사용자의 요청에 응답을 위해서 항상 실행 되어 있어야 한다.

1장과 2장에서 예제로 작성된 코드만으로는, Node가 어떻게 서버로서 동작하는가에 대한것을 알아보기 힘들었다.


이번에는 Node가 어떻게 서버로서 동작하는가를 알아보자!


노드에는 핵심적인 개념 세가지가 있다


  • 이벤트 기반
  • 논블로킹 I/O
  • 싱글 쓰레드

먼저 세가지를 이해하기 전에 이벤트기반, 논블로킹 I/O, 싱글쓰레드를 이해하기 위해서는 이벤트루프 알아야한다


이벤트 루프 JavaScript 코드가 쭉 있을때 이코드가 어떤순서로 실행되는지 이해하는 것을 말한다.


01. 호출 스택(콜 스택)

아래 JavaScript 코드를 보고 이코드의 실행순서를 한번 알아보자.

function first() {
  second();
  console.log('첫번째');
}
function second() {
  third();
  console.log('두번째');
}
function third() {
  console.log('세번째');
}
first();

위 코드의 결과는 세번째, 두번째, 첫번째 가 콘솔로 찍힐 것이다.

왜 그런 것일까?


이코드를 잘 보면

first, second, third함수를 선언한 뒤 12번 라인에서 first()함수를 실행한다.

first()함수가 실행되면 2번 라인에서 바로 second()함수를 실행한다.

second()함수로 이동한 뒤 6번 라인에서 third()함수를 실행한다.

third()함수가 실행되서는 console.log('세번째')가 찍히고 third()함수는 끝이난다.

third()함수가 끝났기때문에 second()함수는 곧장 7번째 라인을 실행하여 console.log('두번째')를 찍는다.

그뒤에 second()함수가 종료된다. 종료가 된 뒤에는 first()함수에서 second()함수가 종료됬기때문에

console.log('첫번째')가 찍히게 된다.


함수가 종료되기 전 다른함수를 실행하면 JavaScript는 실행된 함수가 종료 될때까지 다음 실행을 멈추고 대기한다.

이러한 이유로 세번째, 두번째, 첫번째가 console로 찍히는 것이다. 


위 코드를 이미지로 표현하면 아래와 같은 이미지로 표현될 수 있다.

이미지에 적혀있는 번호순서대로 자세히보면 

먼저들어온 함수블럭 부터 쌓이기 시작하고, 나갈때는 마지막에 들어온 함수블럭 부터 빠져나가게 된다.

이것을 자료 구조의 일종인 스택 이라 하며, 함수들이 호출이되서 쌓이는 것을 스택이 쌓인다라 표현하고,

이러한 스택을 호출스택(콜스택)이라 말한다.



02. 테스크 큐

아래 코드도 실행순서를 한번 생각해보자.
function run() {
  console.log('3초 후 실행');
}
console.log('시작');
setTimeout(run, 3000);
console.log('끝');

위 코드가 실행되면 console시작, 끝, 3초 후 실행 이렇게 찍힌다. 왜그런 것일까? 

여기서 이벤트 루프개념이 들어간다.


run 함수를 선언한 뒤 4번 라인 에서 console.log('시작')을 실행한다.

곧장 5번 라인에서 setTimeout(run, 3000)함수가 실행되지만, setTimeout(run, 3000)은 테스크 큐라는 자료구조의 일종으로 들어간다.

그 뒤에 6번 라인 console.log('끝')을 실행한 후, 다음 실행할 코드가 없을 때, 3초 뒤에 테스크 큐로 넘어간 run()함수를 실행한다.

호출 스택에 있떤 모든 스택이 끝난 뒤 JavaScript테스크 큐라는 백그라운드로 이동하여 다음 실행할 코드를 찾는다

setTimeout함수가 호출되고 3초타이머를 보냈기에, 3초뒤에 테스크 큐에 있던 setTimeout함수가 실행된다.


여기서 중요한 것은,

호출 스택은 들어온 것은 먼저 들어온것이 나중에나가지만

테스크 큐에 들어온 것은 먼저 들어온것이 먼저나간다.

테스크 큐까지 있는 것도 다 나가게 되면 프로그램이 할것이 더이상 없게되어 끝나게 된다.


이러한 것들을 이벤트 루프라 하며, 이것을 이해해야만


  • 이벤트 기반
  • 논블로킹 I/O
  • 싱글 쓰레드

이 세가지를 이해할 수 있다.


그렇다면 테스크 큐로는 언제 들어가게 되는 것일까. 간단하게 리스트로 아래의 것들이 있다.

  • setTimeout, setInterval
  • setImmediate,
  • Promise, resolve, reject (async, awaait)


목록의 함수를 실행했을때 코드는 테스크 큐로 들어가게 되고 

먼저 들어온 것이 먼저 나가는 형식으로 코드들을 실행한다.


이렇게 이벤트 루프를 이용하면 함수의 호출의 실행순서를 인위적으로 조작이 가능해지며

이것이 Node에서의 JavaScript 코딩의 핵심이다.


Comments