[JS]Event Loop

Yoon Ki Hyuk·2022년 7월 20일
0

JavaScript

목록 보기
4/6

최근 자바스크립트와 CS 공부를 더 해야겠다는 마음이 들어서 자바스크립트의 중요한 내용인 Event Loop에 대해 정리 해보려한다.

이벤트루프를 이해하려면 먼저 자바스크립트가 싱글스레드 언어이고 이것이 무엇을 의미하는지 이해해야 한다고 생각한다. 그렇다면 스레드가 무엇이고 어떤 용어들을 알고가야하는지 알아보자

스레드(Thread)

프로세스 내에서 실제로 작업을 수행하는 주체를 의미
모든 프로세스는 한개이상의 스레드를 가지고 있으며 스레드가 하나면 싱글스레드 그 이상이면 멀티스레드라 칭한다.

프로세스(Thread)

프로세스란 단순히 실행중인 프로그램이라 말할수 있다.
사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행중인 것을 말한다.

그렇다면 자바스크립트 에서 이벤트루프가 어떤역할을 하는걸까?

이벤트 루프(Event Loop)

자바스크립트는 싱글스레드 언어 이기때문에 한번에 하나씩 작업을 처리한다

하지만 자바스크립트 기반 웹 들을 보면 마치 멀티스레드 인 것 처럼 동작한다 왜 그럴까?

그것은 자바스크립트가 비동기로 동작하기 때문인데 정확히 말하면 비동기 처럼 동작하는 것이다 자바스크립트 언어 자체가 비동기를 제공하는 것이 아니라 브라우저가 지원하는 Web APIs(DOM / AJAX / setTimeout 등), Callback Queue, Event Loop 그리고 Node.js(libuv 라이브러리 에서 Event Loop를 지원)에서 제공한다 그렇다면 각 용어에 대해 알아보고 오늘의 주제인 Event Loop가 어떻게 동작하는지 알아보자

Memory Heap

우리가 선언한 변수, 함수, 메모리등이 할당 되는 곳

Call Stack

자바스크립트 안에서 실행되는 모든 함수의 호출을 기록하고 추적하는 곳(자료구조 중 Stack의 형태) 자바스크립트는 단 하나의 Call Stack을 가지고 있음(싱글스레드)

Callback Queue(Task Queue)

Web APIs에서 제공하는 비동기 동작들의 콜백함수들이 할당 되는 곳(자료구조 중 Queue의 형태)

Event Loop

자바스크립트가 비동기 방식으로 동시성을 지원하기위해 사용하는 끊임없이 돌아가는 루프

메인스레드는 이벤트루프에 의해 관리된다
-> 싱글스레드에서 하나의 작업이 너무 오래 실행 되면 안된다
또한 여러 작업중 어떤 작업을 우선으로 실행할지 결정하는 것 도 중요하며 작업간 전환을 빠르게 하여 마치 동시에 동작하는 것 처럼 동작해야 한다 이것을 가능 하게 해주는 것이 Event Loop 이다

Event Loop의 동작

  • 코드가 실행되고 코드들이 Call Stack 에 쌓인다
  • Call Stack 에 쌓인 코드들을 실행하고 비워진다
  • 이러한 과정중 비동기 작업을 만나면 Web APIs를 호출한다
  • Web APIs는 비동기 콜백함수들 을 Callback Queue(Task Queue) 에 밀어 넣는다
  • 이때 Call Stack 이 비게되면 Event Loop는 Callback Queue(Task Queue)를 확인하여 Call Stack으로 밀어넣는다

    Event Loop는 이렇게 끊임없이 Call Stack과 Callback Queue(Task Queue)가 비었는지 확인하고 처리할 Task가 없다면 동작하지 않는다 이러한 반복적인 동작을 틱(Tick)이라 한다

지금까지 Event Loop가 뭐하는 친구이고 어떻게 동작하는지 알아봤다 하지만 이게 끝이 아니다 모든 비동기 작업을 Callback Queue(Task Queue)에서 처리하지 않는다 Micro Queue 와 rAF 라는 친구도 있는데 같이 알아보자

Microtask Queue

자바스크립트의 비동기 작업중에는 Promise가 있다 Promise는 자바스크립트에서 비동기 작업만을 위해 만들어진 class인데 이 promise의 Callback 함수들이 Microtask Queue에 담긴다
여기서 중요한 점은 Microtask Queue가 Callback Queue 보다 먼저 처리 된다는 점이다 Event Loop가 Callback Queue 보다 Microtask Queue를 먼저 확인한다는 것 이다. 이해하기 편하게 예시를 살펴보자

console.log('one');

setTimeout(function() {
  console.log('timeout')
}, 0);

Promise.resolve()
  .then(() => console.log('first promise'))
  .then(() => console.log('second promise'))

console.log('two')

과연 콘솔에는 어떤 순서대로 출력될까?

'one'
'two'
'first promise'
'second promise'
'timeout'

순으로 출력될 것이다 예시를 통해 위에 설명했듯 Call Stack -> Micro Queue -> Callback Queue 순으로 출력된 것을 알수 있다

여기서 짚고 넘어가야 할점은 Promise Callback 이 담겨있는 Microtask Queue는 모든 Callback이 처리되기 전까지 계속 동작한다는 것이다 따라서 Promise 콜백을 무한히 돌리는 코드를 작성하고 실행하면 브라우저가 멈춘다 하지만 Callback Queue는 다르다 Callback Queue는 담겨있는 Callback들을 하나씩 처리한다 여기서 하나씩 이란 담겨있는 Callback을 실행하고 Event Loop를 놓아주어 다른 작업을 할수있게 해준다는 뜻 이다. 실제로 setTimeout()을 무한히 돌리는 코드를 작성하고 실행시켜도 브라우저는 멈추지 않는다.

rAF(requestAnimationFrame()) 와 setTimeout()

rAF는 애니메이션 관련 브라우저에서 제공하는 Api다 주로 애니메이션 효과를 구현할때 사용하는데 왠 애니메이션 효과랑 Event Loop 와 관련이 있나 할수 있는데 Event Loop가 관리하고 setTimeout()과 관련이 있기때문에 알아야 한다.

rAF와 setTimeout()의 차이점은 1fps당 호출이 보장되냐 안되냐의 차이인데 이말은 setTimeout()을 특정 시간마다 호출되게 만들어도 setTimeout()은 Callback Queue 에 담기기 때문에 싱글 스레드의 특성상 개발자가 지정한 시간에 호출이 안될수도 있다는 의미이다
즉 setTimeout()에 지정한 시간은 Callback Queue에 담기게되는 시간을 보장하는 것 이지 호출을 보장하는 것 이 아니다

rAF에 보다 자세한내용은 다음에 포스팅 할 예정이다

profile
개발은 낭만이다

0개의 댓글