[JavaScript] 이벤트 루프? 그게 뭔데,,, 그거 어떻게 하는건데,,,⭐️

jiveloper·2025년 3월 17일
0

JavaScript

목록 보기
1/1
post-thumbnail

안녕하세요~ 😎👋 오늘은 자바스크립트의 동작 원리에 대해 포스팅 하려고 합니다!
자바스크립트 포스팅은 처음 써보는 것 같네요.

그동안 자바스크립트에 대한 깊은 이해도 없이 무작정 개발만 해왔다는게 많이 느껴지고 있는 요즘입니다. 연차가 쌓이면서 이제 웬만한 기능 구현은 할 줄 알지만, 여전히 근본적인 이해가 부족한 제 모습에 모순을 느끼고 있습니다. 이런 괴리감 있는 제 모습을 n년 전부터 느끼긴 했지만 이제야 괴리감 좁히기를 시도해보려 합니다...

뭐... 그래도... 원래는 공부의 필요성만 느끼고 공부하지 않았는데, 이제는 모르는 게 느껴지면 몸소 반응해 공부하는 걸 보니 마음 가짐은 확실히 성장한 것 같네요.

.
.
.

서론을 거의 뭐 일기처럼 주저리 주저리 써내려갔는데... 😅😅


일기는 이쯤에서 멈추고...!

제가 이번에 공부한 자바스크립트의 동작 원리에 대해 포스팅하며, 저도 같이 복기해보려 합니다. 😤 ‼️


자 그럼 시작...! (엄근진)



스레드

자바스크립트는 싱글 스레드로 동작하는 언어입니다.
싱글 스레드 이전에 스레드가 무엇일까요? 스레드에 대해 간단하게 짚고 넘어가겠습니다!

스레드: 프로세스 안에서 실제로 실행되는 작업의 흐름
프로세스: 하나의 앱이나 프로그램이 실행되는 단위
ex) 크롬 웹 브라우저(=프로세스)를 틀어 한 탭에선 유튜브 뮤직으로 음악 듣기(=스레드1)와 다른 탭에선 구글링 하기(=스레드2)


멀티 스레드

위의 예시처럼 크롬 웹 브라우저에서는 한 탭에선 음악을 틀을 수 있고, 동시에 다른 탭에선 음악을 들으며 구글링이 가능합니다. 이는 각 탭이 별도의 스레드로 동작하기 때문입니다. 이렇게 하나의 프로세스 안에서 여러 스레드가 동시에 실행되는 환경멀티 스레드라고 합니다.
멀티 스레드를 적극 활용하는 언어에는 Java, C++, C#, Kotlin, Swift, Objective-C 등이 있습니다.

(오늘은 자바스크립트에 대해 알아보는 시간이니, 멀티 스레드는 이쯤에서 멈추고 싱글 스레드로 바로 넘어가봅시다!)

싱글 스레드

싱글 스레드하나의 프로세스 내에서 하나의 스레드만 실행되는 환경입니다. 즉, 이 경우 프로세스는 한 번에 하나의 작업만 수행할 수 있습니다.
싱글 스레드를 적극 활용하는 언어에는 JavaScript, Python, Ruby, PHP 등이 있습니다.

😎 : 자바스크립트는 기본적으로 싱글 스레드로 동작하지만, 여러 작업을 동시에 처리하는 것처럼 실행할 수 있습니다.

자바스크립트에서 여러 작업을 동시에 처리하도록 하는 것이 이벤트 루프비동기 프로그래밍 덕분인데...

비동기 프로그래밍 방식을 이해하기 위해선 먼저 동기/비동기 프로그래밍 방식의 차이부터 알 필요가 있습니다.



동기 프로그래밍

아래의 코드가 있습니다. 실행하면 어떤 결과가 나올까요?

console.log(1)
console.log(2)
console.log(3)

1 -> 2 -> 3 이렇게 위에서부터 아래로 순차적으로 출력됩니다.

1
2
3

console.log(1)이 출력될 때까지 console.log(2)는 기다리고, console.log(2)가 출력될 때까지 console.log(3)도 기다립니다.

이렇게 작업이 하나씩 순차적으로 진행되며, 이전 작업이 끝난 후에 다음 작업이 시작되는 방식을 동기 프로그래밍(Synchronous Programming)이라고 합니다.

자바스크립트는 기본적으로 동기 프로그래밍 방식으로 동작합니다.



비동기 프로그래밍

그렇다면, 아래 코드는 실행하면 어떤 결과가 나올까요?

console.log(1)
setTimeout(() => console.log(2), 0)
console.log(3)

두둥-! 아래와 같이 출력됩니다.

1
3
2

setTimeout이 0초인데도 console.log(2)보다 console.log(3)이 먼저 실행된 걸 볼 수 있습니다.

이렇게 즉시 수행할 수 있는 작업은 먼저 실행하고, 시간이 오래 걸리는 작업은 나중에 처리하는 방식을 비동기 프로그래밍(Asynchronous Programming)이라고 합니다.

이러한 비동기 프로그래밍을 가능하게 해주는 것이 바로 이벤트 루프(Event Loop) 입니다!
그렇다면, 이벤트 루프는 어떻게 이러한 과정을 처리할까요? 함께 알아봅시다! ✊🏻
(위 예시 풀이 대공개 예정 +_+)



이벤트 루프

(재차 강조)
⭐️ 자바스크립트는 싱글 스레드 기반으로 동작하기 때문에, 기본적으로 한 번에 하나의 작업만 실행할 수 있습니다. ⭐️

자바스크립트에서 작업이 실행되는 공간을 Call Stack이라고 하며, 이 곳에서는 한 번에 하나의 작업만 처리할 수 있습니다. setTimeout이나 fetch 같은 비동기 작업은 Call Stack 영역이 아닌 Web API 영역에서 처리됩니다. Web API 영역에서 작업을 실행한 결과는 Queue라는 대기열에 들어가게 됩니다.

이벤트 루프Call Stack이 비었을 때 Queue에 있는 작업을 Call Stack으로 이동시킵니다. 쉽게 말해, 이벤트 루프는 지금 실행할 수 있는 작업이 있는지 확인하고, 실행할 작업이 없으면 Queue에 대기 중인 작업을 실행하는 일련의 처리 과정을 뜻합니다.

흠 조금 어려운데...🤔
위 설명을 아까의 예시 코드와 함께 차근차근 알아보겠습니다. 🤩

console.log(1)
setTimeout(() => console.log(2), 0)
console.log(3)
  1. console.log(1)
    console.log(1)은 작업이 실행될 공간인 Call Stack 영역에 들어가게 됩니다.
    Call Stack에 작업이 들어오면 자바스크립트 엔진에 의해 해당 작업을 실행하게 됩니다.

  1. setTimeout(() => console.log(2), 0)
    Call Stack에 있던 1번 작업이 수행되었습니다.
    그리고 2번 작업이 Web API 영역으로 넘어갔습니다. 이 작업의 콜백은 0초 뒤 Queue로 이동할 예정입니다.
  1. console.log(3)
    Call Stack 영역이 비어있기 때문에, 3번 작업이 바로 Call Stack에 들어갑니다.
    이 과정에서 타이머가 끝나 2번 작업의 콜백이 Queue로 이동합니다.
    Call Stack 영역에 있던 console.log(3)을 수행 하면
    "딸깍‼️" 이벤트 루프에 의해 console.log(2)Call Stack 영역으로 이동하게 됩니다.
    마지막 작업인 console.log(3)까지 수행하게 되어 Call Stack 영역이 완죠니 비워졌습니다! +_+

이렇게 이벤트 루프의 전반적인 과정을 살펴보았습니다. (훗훗 내 자신 칭찬해 😎)



Task Queue < Microtask Queue

Web API에서 비동기 작업이 수행된 후, 모두 Queue의 영역으로 들어가게 되는데 Queue 영역 내 작업 중에서도 우선순위가 나뉘어집니다.

QueueTask QueueMicrotask Queue로 나눌 수 있습니다.

  • Task Queue : 일반적인 비동기 작업들이 들어가는 대기열
    ex) setTimeout, setInterval, 사용자 이벤트 등
  • Microtask Queue: 더 높은 우선순위를 가진 작업들이 들어가는 대기열
    ex) Promisethen, catch, finally 핸들러, MutationObserver

Microtask Queue는 Task Queue보다 우선적으로 처리됩니다.

예제

간단한 예제를 볼까요? 아래의 코드를 실행하면 어떻게 될까요?

console.log(1)

setTimeout(() => console.log(2), 0)

fetch('~').then(() => console.log(3))

두둥-! 아래와 같이 출력됩니다.

1
3
2

위 과정 또한 그림으로 같이 알아보겠습니다! ☺️

  1. console.log(1)
    console.log(1)은 작업이 실행될 공간인 Call Stack 영역에 들어가게 됩니다.
    Call Stack에 작업이 들어오면 자바스크립트 엔진에 의해 해당 작업을 실행하게 됩니다.
  1. setTimeout(() => console.log(2), 0)
    Call Stack에 있던 1번 작업이 수행되었습니다.
    그리고 2번 작업이 Web API 영역으로 넘어갔습니다. 이 작업의 콜백은 0초 뒤 Task Queue로 이동할 예정입니다.
  1. fetch('~').then(() => console.log(3))
    3번 작업이 Web API 영역으로 넘어갔습니다.
    이 과정에서 타이머가 끝나 2번 작업의 콜백이 Task Queue 영역으로 이동합니다.
    현재 Call Stack 영역이 비어있기 때문에, 실행할 작업을 Call Stack 영역에 넣어줘야 합니다. 실행할 작업들은 모두 Queue에 있고, 우선순위는 Microtask Queue가 더 높습니다. Microtask Queue 영역에 있는 console.log(3)이 바로 Call Stack 영역으로 이동할 예정입니다!
    "딸깍‼️" 이벤트 루프에 의해 console.log(3)Call Stack 영역으로 이동하였습니다.
    Call Stack에 있던 console.log(3)이 수행되었습니다.
    "딸깍‼️" 이벤트 루프에 의해 console.log(2)Call Stack 영역으로 이동하였습니다.
    마지막 작업인 console.log(2)까지 수행하게 되어 Call Stack 영역이 완죠니 비워졌습니다! +_+



심화 예제

어떠셨는지요...🥹🥹
삘 받았을 때 더 전진해야하기 때문에 나름의 심화 예제(?)를 한번 같이 풀어보겠습니다!

아래의 코드를 실행하면 어떤 결과가 나올까요?

console.log(1)

setTimeout(() => {
  console.log(2)
}, 0)

Promise.resolve().then(() => {
  setTimeout(() => {
    console.log(3)
  }, 0)
  console.log(4)
  setTimeout(() => {
    console.log(5)
  }, 0)
})

console.log(6)

너무나도 복잡한데요,,, but 차근차근 하면 못할 것이 없습니다! 😤

렛츠고도리...!

  1. console.log(1)
    console.log(1)은 작업이 실행될 공간인 Call Stack 영역에 들어가게 됩니다.
    Call Stack에 작업이 들어오면 자바스크립트 엔진에 의해 해당 작업을 실행하게 됩니다.
  1. setTimeout(() => { console.log(2) }, 0)
    Call Stack에 있던 1번 작업이 수행되었습니다.
    그리고 2번 작업이 Web API 영역으로 넘어갔습니다. 이 작업의 콜백은 0초 뒤 Task Queue로 이동할 예정입니다.
    현재 Call Stack 영역이 비어있기 때문에, 실행할 작업을 Call Stack 영역에 넣어줘야 합니다. 처리하기 가장 빠른 console.log(6) 작업이 바로 Call Stack에 들어갑니다.
    이 과정에서 타이머가 끝나 2번 작업의 콜백이 Task Queue로 이동합니다.
  1. Promise.resolve().then(() => { setTimeout(() => { console.log(3) }, 0) console.log(4) setTimeout(() => { console.log(5) }, 0) })
    Call Stack에 있던 console.log(6) 작업이 수행되었습니다.
    그리고 3번 작업이 Web API 영역으로 넘어갔습니다. 이 작업의 콜백은 resolve 후, Microtask Queue로 이동할 예정입니다.
    resolve 후, Microtask Queue 영역에 있는 함수들은 각각 각자에 맞는 영역으로 찢어져야합니다...😭😭
    setTimeout(() => { console.log(3) }, 0), setTimeout(() => { console.log(5) }, 0)는 비동기 작업이므로 Web API로 이동하고, console.log(4)는 비어있는 Call Stack 영역으로 이동할 예정입니다.
    각자에 맞는 위치로 흩어졌습니다...!
    console.log(4)Call Stack 영역에 이동하였습니다.
    Web API에 있는 작업들은 먼저 작업 들어온 순서대로 작업하여 Task Queue로 이동할 예정입니다.
    Call Stack에 있던 console.log(4) 작업이 수행되었습니다.
    Web API에 있던 작업들도 순서대로 Task Queue에 이동하였습니다.
    "딸깍‼️" 이벤트 루프에 의해 console.log(2)Call Stack 영역으로 이동하였습니다.
    Call Stack에 있던 console.log(2)가 수행되었습니다.
    "딸깍‼️" 이벤트 루프에 의해 console.log(3)Call Stack 영역으로 이동하였습니다.
    Call Stack에 있던 console.log(3)이 수행되었습니다.
    "딸깍‼️" 이벤트 루프에 의해 console.log(5)Call Stack 영역으로 이동하였습니다.
    마지막 작업인 console.log(5)까지 수행하게 되어 Call Stack 영역이 완죠니 비워졌습니다! +_+
  1. console.log(6)
    (2번 과정에서 실행 완료)



마무리

끄흐흡...! 드디어 ... 잘 수 있다...!(?)

늘 블로그를 쓸 때마다 초보자에게 가르친다는 생각으로 엄청 자세히 쓰려고 노력하는데, 이번에도 제 최선을 다 한 것 같습니다... 🫠

다른 블로그들과 차별점을 두기 위해 글도 일부러 지루하지 않게 쓰려 하고, 그림 자료도 직접 ⭐️수제⭐️로 만들어가며 포스팅을 하느라 시간이 배로 걸리네요. 누군가 제 블로그를 통해 조금이라도 도움을 받았다면 너무 너무 만족할 것 같습니다...😭😭

앞으로도 저만의 특색 있는 블로그를 운영하기 위해 제 S.t.y.l.e.을 밀고 나가겠습니다.^^

그럼 다음 포스팅에서 만나요~👋👋


참고

https://www.youtube.com/watch?v=v67LloZ1ieI

https://velog.io/@gil0127/%EC%8B%B1%EA%B8%80%EC%8A%A4%EB%A0%88%EB%93%9CSingle-thread-vs-%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%93%9C-Multi-thread-t5gv4udj#%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9D%B4%EB%9E%80--thread-

profile
👩🏻‍💻 크로스플랫폼 앱 개발자입니다.

0개의 댓글

관련 채용 정보