Node.js - Event Loop (이벤트 루프)

Patrick·2021년 6월 23일
1

Node.js

목록 보기
3/3
post-thumbnail

처음 Javascript를 공부하게 되면 var, let, const 부터 시작해서 문자열, 객체, 클래스, 화살표함수 등을 배우기 시작하는 경우가 많은 것 같다.
나의 경우 또한 그랬다.
우선은 코드를 쳐보면서 내 눈 앞에서 무언가가 만들어지는 것이 신기했고, 그런 것들을 재미있게 느꼈기 때문에 시작으로는 나쁘지 않다고 생각한다.

하지만 이제 조금 Javascript의 맛을 봤다면, 발을 조금 담궈봤다고 한다면 Event Loop(이벤트 루프)에 대해서 알아볼 차례라고 생각한다.
흔하게 들을 수 있는 말로, "이벤트 루프를 모른다면 Javascript를 안다고 말하면 안 된다!" 라고 한다.
그런만큼 이벤트 루프에 대해서도 미리 알아두는 것이 좋다.
우선 이것이 이벤트 루프의 전체적인 모양부터 보자

Javascript는 크게 메모리 힙(Memory Heap)과 콜 스택(Call stack)으로 이루어져 있다.
여기서 메모리 힙(Memory Heap)은 메모리 할당이 일어나는 곳이며, 힙(Heap)이라는 것은 구조화 되지 않은 넓은 메모리 영역을 말한다.
변수나 함수 등 객체들이 담기게 된다.

콜 스택(Call stack)은 호출 스택 이라고도 불리는데 Javascript는 인터프리터 언어(Interpreter Language)이므로 한줄 씩 실행이 되는데, 이 때 실행 될 코드의 한 줄 단위로 콜 스택이 할당이 된다.
stack이라는 말에서 알 수 있듯이 벽돌을 쌓듯 위로 쌓이는 형태인데, 동기적인 코드일 때는 맨 아래에서부터 채워져서 위로 쌓이고, 위에서부터 아래로 차례대로 실행된다.

동기적인 코드의 예를 들어보자!

function first() {
	second();
  	console.log('First')
}

function second() {
	third();
  	console.log('Second')
}

function third() {
	console.log('third')
}

first();
third();

이런 코드가 있다면 어떤 순서로 나올까?
이런 예시는 유명해서 아는 분들도 많겠지만 답은 아래와 같다

third
Second
First
third

그 이유가 무엇일까?
동기적인 것은 다른 것 다 필요없이 Call stack에 쌓이는 것만 보면 되는데, 가장 먼저 anonymous로 시작 된다.

== This is Call Stack Section ==
	console.log('Third')
	third()
	second()
	first()
	anonymous
================================

이렇게 anonymous부터 위로 계속해서 쌓이고, 실행은 위에서부터 시작된다.
즉, console.log('Third')가 실행되면서 third()가 call stack에서 빠져나가고, 그 다음 second()로 가서 second()안의 third()가 끝났으니 console.log('second')를 실행하게 되고, 이후 first()로 가서 first() 안의 second()가 끝났으니 console.log('first')가 실행되게 된다.
그리고 다음 함수인 third가 실행되면서 마지막으로 console.log('third')가 실행되는 것이다.

Web APIs는 비동기 처리를 담당하는 곳이라고 할 수 있다.
위의 사진에서 볼 수 있는 것 처럼 setTimeout과 같은 비동기 처리를 하게 되며, 브라우저 상에서는 Web APIs라고 하고, Node에서는 백그라운드(Background)라고 말한다.

콜백 큐(Callback Queue)는 Task Queue(혹은 Event Queue)와 Microtask Queue(혹은 Job Queue)그리고 Animation Frames로 이루어져 있다.
여러가지 이름이 있지만 알아둬야 하는 이유는 누군가 설명 할 때 이게 무엇인지는 알아먹어야하지 않을까 해서이다...

이들은 우선순위가 나뉘는데 Microtask Queue > Aniamation Frames > Task Queue 순서로 진행된다.
비동기 처리 한 것을 가지고 있다가 이벤트루프가 계속 돌면서 call stack을 확인하게 되고, stack이 비었을 때 콜스택으로 보내어 실행시키게 된다.

말이 길어서 헷갈린다면 간단하게 비동기 코드의 이동을 보자!
call stack -> Web APIs -> Callback Queue -> Call stack -> console
이런 식으로 이동을 하게 된다.

setTimeout의 예를 들어보자!

console.log('start')

setTimeout(function() {
	console.log('3초 후 실행');
}, 3000)

console.log('end')

이 또한 너무 유명한 예라서 답은 아마 다들 알것이라고 생각한다.
답은 아래와 같다

시작
끝
중간

자, 이제 어떻게 작동하는지 알아보자!
우선 call stack에는 anonymous가 무조건 가장 먼저 들어간다고 보면 된다.
그리고 console.log('start')가 call stack에 들어갔다가 바로 console로 찍히게 된다.
그리고 비동기 함수인 setTimeout(익명함수'중간', 3초)이 call stack에 들어갔다가 실행되면서 browser의 경우 Web APIs, Node의 경우 백그라운드로 넘어가게 된다.
그리고 Web APIs에서는 3초를 돌리고 있을 것이며 이 때, console.log('end')가 call stack에 들어왔다가 console에 바로 찍히게 되며, anonymous가 실행되면서 call stack을 빠져나온다.
마지막으로 Web APIs에서 setTimeout이 3초가 지나면, setTimeout의 콜백함수 즉, 여기서의 익명함수가 callback Queue로 넘어간다.
이벤트루프(Event Loop)는 계속 체크를 하면서 Call stack이 비어있는지 확인을 하고 비어있는 것이 확인이 된다면 callback Queue의 익명함수를 call stack으로 보내주게 된다.
이것이 바로 이벤트루프의 역할이다.
이 때, 익명함수 안을 봤더니 '3초 후 실행' 이라는 console.log가 있다.

== This is Call Stack Section ==
	console.log('3초 후 실행')
	익명함수
================================

그러면 이런 식으로 쌓이게 되고, console.log가 더 위에 있으니 순서대로 위에 있는 "3초 후 실행"이 먼저 console에 찍히게 되고, 익명함수가 종료가 되면서 해당 코드의 프로그램 동작이 마무리가 된다.

profile
예술을 사랑하는 개발자

0개의 댓글