[Javascript] 이벤트루프에 관해서,,,

최은지·2022년 3월 28일
1
post-thumbnail

여러 블로그를 참고하여 정리해본 글 입니다.

이벤트 루프란?

우리가 JavaScript를 학습 시, Node.js의 이벤트 루프에 대해 접하게 된다.
주로 이를 접하는 시기는 비동기 처리를 공부하는 중 일 것이다.
이벤트 루프를 검색하면 각기 다른 내용이 설명되어 있는 경우가 많아서, 순차적으로 정리해보려 한다.

Javascript는 메인 스레드싱글 스레드 이기에 하나의 작업만을 처리할 수 있다.
때문에, setTimeOut, I/O와 같은 시간이 오래 걸리는 작업은 기다리지 않고 비동기 방식으로 처리 한다.

Node.js의 공식문서에는 아래와 설명한다.

이벤트 루프는 가능하다면 언제나 시스템 커널에 작업을 떠넘겨서 Node.js가 논 블로킹 I/O 작업을 수행하도록 해줍니다.
출처 - https://nodejs.org/ko/docs/guides/event-loop-timers-and-nexttick/

Blocking과 Non-Blocking이 궁금하다면? 아래를 참고해 주세요!
참고 - https://medium.com/@rpf5573/nodejs-blocking-vs-non-blocking-8f92f2b522a7

위에서 메인스레드가 싱글 스레드라고 설명했는데, 다른 스레드가 존재한다는 것일까??
살펴보자!!

우선, 인터넷에 가장 많이 설명 되어있는 방식이다.

  • 1 - setTimeout ( WebAPI) 가 호출되면, call stack에 쌓인다.
  • 2 - setTimeout의 콜백 run은 백그라운드에서 수행된다.
  • 3 - 백그라운드에서 설정된 시간이 지나면, callback queue콜백 함수가 이동한다.
    • 구글링 시, callback queue, task queue, job queue, event queue 등 다양한 용어들이 나온다.
    • microtask queue에 관한 내용은 조금 이따 다룰 예정이다. 큰 흐름을 이야기 하고 있기에 callback queue로 칭하려 한다.
    • (확실하진 않지만, 검색을 하다보면 task queue는 event queue와 같은 의미로 쓰이고 있고, microtask queue는 microtask queue와 같은 의미로 쓰이고 있다.)
    • 출처 - https://cbw1030.tistory.com/351
  • 4 - call stack이 비워지면, callback queue의 콜백을 call stack으로 보낸다.
  • Loupe에서 해당 동작 방식을 눈으로 확인할 수 있다.
  • 영상 설명 도 참고하면 좋다.

이 내용을 이해했다면, microtask queue라는 개념을 추가해서 이해할 수 있다.

위에서 callback queue 에는 task queuemicrotask queue가 포함되어 있다고 언급했었다.
microtask queuetask queue보다 높은 우선순위를 갖는다.

출처 - https://velog.io/@xortm854/Javascript%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%8C%EC%95%84%EA%B0%88%EA%B9%8C-2%ED%8E%B8-Event-Loop%EB%9E%80

위의 그림 처럼 queue가 한개가 아니라는 것을 알 수 있는데, microtask queue에 있는 내용이 먼저 수행된다. microtask queue의 모든 task를 처리하고 task queue의 내용을 처리한다.

  • Task Queue
    • setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O 등
  • Microtask Queue
    • process.nextTick, Promise, Object.observe, MutationObserver

=> Promise의 콜백이 setTimeout의 콜백보다 먼저 수행된다.

  • 여기 링크!!!!!!!! 에서 동작 방식을 자세히 확인 할 수 있다.
  • 처음의 내용에서 queue가 한개가 아니라는 점, queue 마다 우선 순위가 다르다는 점이 추가되었다.

위의 내용에서 내용을 더 추가하면?

libuv에 대해 알아봐야 한다.

  • libuv란 C++로 작성된, Node.js가 사용하는 비동기 I/O 라이브러리이다.
  • javascript는 싱글 스레드이며, 이벤트 루프 동작도 싱글 스레드가 처리한다.
  • 하지만 libuv에 여러개의 thread pool이 존재하며, CPU Intensive한 작업들을 수행할 시에 libuv의 스레드가 처리를 하게 된다.
    ex) crypto

참고 - https://medium.com/@rpf5573/nodejs-nodejs%EB%8A%94-single-thread%EA%B0%80-%EC%95%84%EB%8B%88%EB%8B%A4-f02b0278c390
참고 - https://medium.com/@rpf5573/nodejs-event-loop-part-1-big-picture-7ed38f830f67

출처 - Node.js 공식 문서

이런 식으로 동작한다.
아까랑 다르게 생긴 루프를 확인할 수 있다.
위 검정색 그림의 phase들은 queue를 가지고 있으며, 해당 queue에는 특정 이벤트 들의 콜백을 넣고 CPU가 할당 될때 실행된다.
여기!!에서 각 단계에서 수행하는 자세한 내용을 확인할 수 있다.


출처 - https://medium.com/@rpf5573/nodejs-event-loop-part-1-big-picture-7ed38f830f67

task queue에 콜백을 넣는다고 했었고, microtask queuetask queue보다 우선 순위를 갖는다고 언급했었다.
그리고, 아키텍쳐에 각 phase 전 실행되는 microtask queuenext tick queue가 보인다.
next tick queue & micro task queuephase 전에 수행되는 것이다.

이해한 바로는,

  • 위에서 언급된 call stacklibuv가 아닌, V8 엔진에 존재한다. 이벤트 루프는 libuv가 수행한다.
  • task queue로 알고 있던 내용 -> 여러 개의 phase들이 존재하며, 내부엔 queue가 있고, 단계마다 콜백을 처리한다.
  • 각 phase가 실행 되기 전 next tick queue & micro task queue가 수행된 후, phase의 queue 의 콜백을 처리한다. 참고 - next tick
  • 이벤트 루프가 도는 것은 single thread가 처리하는 것이 맞지만, CPU Intensive 한 작업을 처리하는 thread poollibuv 에 추가로 존재한다.
  • 위에서 언급하지는 않았지만, I/O 관련 처리는 thread pool, 그리고 OS에서도 처리한다.

참고 링크들
https://meetup.toast.com/posts/89
https://blog.bitsrc.io/nodejs-event-loop-system-a-hands-on-approach-part-1-ec5dddf6d7c4
http://docs.libuv.org/en/v1.x/design.html
https://sjh836.tistory.com/149
https://www.youtube.com/watch?v=QyUFheng6J0
https://ko.javascript.info/event-loop
https://resilient-923.tistory.com/308
https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
https://www.korecmblog.com/node-js-event-loop/
https://www.zeolearn.com/magazine/understanding-the-javascript-event-loop
https://medium.com/zigbang/nodejs-event-loop%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B0-16e9290f2b30
https://bigpel66.oopy.io/library/etc/nodejs/1

profile
배고파

0개의 댓글