[JavaScript] 이벤트 루프

Wynter_j·2022년 9월 20일
0

JavaScript

목록 보기
1/1
post-thumbnail
post-custom-banner

안녕하세요. 정지현 입니다 :)
오늘은 간단하게 이벤트 루프에 대해 이해한 것들을 정리해볼게요.

서론 (배경지식)

✅ 자바스크립트의 특징

자바스크립트는 싱글 쓰레드 기반이며
논 블로킹 방식의 비동기적인 동시성 언어이다.

싱글 스레드 언어는 동시에 하나의 작업만을 처리할 수 있어요.
즉, 브라우저에 내장된 자바스크립트 엔진은 한 번에 한 개의 테스크만 처리합니다.

하지만! 실제로 웹페이지가 실행되는 것만 보아도 많은 작업이 동시에 처리되고 있는 것처럼 보이는데요. 예를 들어 웹브라우저가 사용자의 인풋을 처리함과 동시에 여러개의 HTTP 요청을 처리하기도 하는 것처럼 말이죠. 또, 우리는 setTimeout() 함수로 특정 시간을 기다림과 동시에 다른 코드를 동작시키는 작업들도 할 수 있습니다.

분명 자바스크립트는 싱글 스레드인데 어떻게 동시성을 지원하는걸까요 ?
(동시성: 여러 작업이 마치 동시에 일어나는 것처럼 보이는 것)

위의 질문에 해답이 바로, Event Loop 입니다.

이벤트 루프

자바스크립트는 이벤트 루프 기반의 비동기 방식으로 동시성을 지원한다.

✅ 용어 정리 (JS의 Memory Heap & Call Stack)

Memory Heap - 참조 타입(객체 등) 데이터들이 저장되는 공간입니다. 변수나 상수들에 사용되는 메모리를 저장하는 영역 입니다.

Call Stack - Primary Type(원시 타입) 데이터들이 저장되는 공간입니다. 실행 콘텍스트를 통해 현재 어떤 함수가 동작하고 있는지, 그 함수 내에서 어떤 함수가 동작하는지, 다음에는 어떤 함수가 호출되어야 하는지 등을 제어합니다.

✅ Web API (Application Programming interface)

이벤트 루프를 이해하기 전에 web API에 대해 알고 가야 합니다.

브라우저는 JS엔진이 제공하지 못하는 기능들을 Web API로 제공합니다. (예를 들어, setTimeout은 JS엔진인 V8에 내장되어 있지 않아요.)
사실 우리는 Web API의 도움을 항상 받고 있습니다. DOM, Ajax, setTimeout(), Event Handler 등과 같이 웹 브라우저에서 제공하는 기능들이 바로 Web API 입니다.

JS엔진 Call Stack에서 실행된 비동기 함수는 Web API를 호출하고, Web API는 콜백함수를 Callback Queue에 집어 넣습니다.

순서대로 다시 정리해보면,

  1. JS 엔진의 Call Stack에서 실행된 비동기 함수가 비동기 작업을 요청
  2. 해당 비동기 함수는 Web API를 호출
  3. Web API는 브라우저에게 해당 비동기 작업에 대한 정보와 콜백 함수를 넘김
  4. 브라우저는 이러한 요청들을 별도에 쓰레드에 위임

이렇게 정리할 수 있을 것 같습니다.

✅ 이벤트 루프 왜 중요할까?

이벤트 루프는 메인 스레드의 동작을 관리합니다.

브라우저 동작의 대부분이 메인 스레드에서 싱글 스레드로 실행이 됩니다.
싱글 스레드에서 하나의 작업을 하고 있다면 다른 작업은 지연시키기 때문에 하나의 작업이 굉장히 길어진다면 다른 작업은 실행될 수 없겠죠?

그러므로 싱글 스레드의 작업 관리는 매우 중요합니다. 이러한 작업 관리를 해주는 게 이벤트 루프 입니다.

✅ 이벤트 루프 동작 원리

이제 간단한 코드 예제를 보며 이벤트 루프의 동작 순서를 이해해볼게요.

function response() {
  return setTimeout(() => {
    return "Hi!"
	}, 1000))
}

response()
  1. response 함수가 실행되고( = JS콜스택에 추가되고) setTimeout을 반환합니다.

    이 때 setTimeout은 Web API가 제공하기 때문에 메인 쓰레드를 막지 않고 작업을 딜레이 시킬 수 있어요.

  2. setTimeout 함수의 콜백 함수인 화살표 함수가 Web API에 저장됩니다.

  3. Web API에서는 두 번째 인자인 1000ms 만큼 기다리는 타이머가 실행됩니다

    그 동안 JS의 call Stack은 setTimeout 함수와 response 함수를 pop 합니다. (그럼 콜스택이 비어있는 상태가 되겠죠?)

  4. 콜백 함수는 콜스택에 바로 저장되지 않고 큐로 이동합니다.

    모든 비동기 API들은 작업이 완료되면 콜백 함수를 태스크 큐에 추가 합니다.

    여기서 잠깐! MDN에서 0의 지연 시간에 대해 이렇게 설명하고 있어요.
    " setTimeOut 지연시간을 0 으로 지정하는 것이 콜백을 0밀리초 후에 호출한다는 뜻이 아니다. 0의 지연시간을 지정하고 호출하더라도 콜백 함수는 즉시 실행되지 않는다. 즉, 실제 실행 시점은 큐에서 대기 중인 작업의 수에 따라 다르다. setTimeout에 특정 지연 시간을 지정하더라도, 큐에서 대기 중인 모든 메시지의 처리는 기다려야 한다. "

    즉, 우리의 예시에서도 1000ms가 지났다고 함수가 바로 실행되는 것이 아니라 1000ms 후에 큐로 이동한다는 것이죠. 실제 실행 시점은 큐에서 대기중인 작업의 수에 달려있는 겁니다.

  5. 드디어 이벤트 루프가 작업을 수행합니다.
    콜스택이 비어 있을 때 ( = 이전에 실행된 함수가 모두 값을 리턴했고 스택에서 pop 되었을 때) 콜스택에 큐의 첫 번째 아이템이 추가됩니다.

    예제 코드의 콜백 함수가 콜스택에 추가되고, 호출(invoke)되고 , 값을 반환한 뒤 비로소 스택에서 pop 됩니다.

실제로 시뮬레이션 해 볼 수 있는 좋은 사이트가 있네요.
직접 실행하며 예측 해보는 연습을 해보면 좋을 것 같습니다.
http://latentflip.com/loupe


정리

예제로 다룬 setTimeout 뿐만 아니라 다른 비동기 함수들이나 Node.js의 IO 관련 함수등 모든 비동기 방식의 API들은 이벤트 루프를 통해 콜백 함수를 실행시킵니다.
그렇기 때문에 이벤트 루프에 대해서 꼭 이해하고 있어야겠죠 ?

오늘은 이벤트 루프의 기본적인 동작 원리만 살펴보았습니다.
다음에 더 심화로 공부해볼 것은 Promise와 이벤트 루프 , 큐의 우선순위 입니다 🙌

! 해당 주제 함께 공부한 신디 덕분에 수월하게 했어요 🙂

Ref.

저는 능력 부족으로 예제를 이미지 파일로 첨부하였는데요. 해당 사이트에서 동일한 예제를 gif로 확인하실 수 있습니다.
https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif

MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

Video
https://vimeo.com/96425312

ETC
https://meetup.toast.com/posts/89
https://tecoble.techcourse.co.kr/post/2021-08-28-event-loop/

post-custom-banner

0개의 댓글