들어가기전
이벤트루프에 대해 글을 처음쓴건 20년도인데, 21년도에 이 글을 보니 다시 정리할 필요가 있다는 생각이들었습니다. MDN 공식문서를 보면서 새롭게 보였던 부분이 있었습니다. 이벤트루프와 자바스크립트의 동시성 모델을 연관지어 설명한 부분입니다. 처음 이 개념을 공부할때는 이벤트루프만 이해하기 바빴는데 동시성 모델과 같이 이해하니, 이벤트루프가 자바스크립트의 언어적 특성과 깊은 연관이 있다는 점을 발견했습니다.
동시성을 지원하는 이벤트루프
자바스크립트의 동시성 모델과 이벤트루프의 연관성은 근본적으로 자바스크립트의 싱글스레드인 언어적 특성에서 비롯됩니다. 이는 한명의 일꾼으로 한번에 하나의 작업을 처리할 수 있다는걸 의미합니다. 하지만 프로그램이 복잡해지고 커지다보면 한명의 일꾼으로는 턱없이 부족합니다. API를 호출해서 데이터도 받아와야하고 setTimeout 함수처럼 의도적으로 delay를 주어야할 때도 있고 복합적인 상황들을 마주하게 됩니다. 이 때 만약 데이터를 받아올때 마다 페이지가 멈추면 어떨까요? 사용자 경험이 매우 좋지 못하고 유저가 페이지에서 이탈할 확률이 높아질 겁니다.
이러한 자바스크립트의 한계를 보완하기 위한 것이 자바스크립트의 '동시성 모델'이라는 생각이 들었습니다. 동시성의 의미는 여러가지 작업을 동시에 호출하는 것을 의미합니다. 예를 들어 API 데이터를 요청하고 데이터를 불러오는 동안 대기하는게 아니라, 요청만 해놓고 다음 작업을 계속해서 진행하는 것입니다. 이러한 동시성 모델의 기반이 되는게 이벤트루프입니다.
이벤트루프는 자바스크립트 런타임 환경의 구성요소이고, 이벤트루프가 정확하게 어떤 역할을 하는지 알기위해서는 자바스크립트 런타임 환경에 대한 이해가 필요합니다.
자바스크립트 런타임 환경과 동작원리
1) 자바스크립트 런타임 환경 구성
- JS 엔진
- Memory Heap: 변수나 함수의 메모리 할당을 하는 곳
- Call Stack: 함수 호출을 기록하는 곳
- Web APIs
- 브라우저에서 제공하는 API들입니다. DOM, AJAX, setTimeout과 같이 Web APIs에 해당되는 함수들이 호출되면 Call Stack에서 곧바로 Web APIs로 보내져 처리됩니다.
- Callback Queue
- 처리된 Web APIs들이 줄세워지는 곳이다.
- Event Loop
- Call Stack과 Callback Queue의 상태를 체크하여, Call Stack이 비면 이벤트루프는 Callback Queue에 줄세워진 콜백수들을 다시 Call Stack으로 전달한다.
2) 자바스크립트 런타임 실행 흐름
(1) 함수 호출 시, call stack에 함수가 쌓인다.
(2) Web APIs 함수가 호출될 경우에는 call stack에서 바로 실행하지 않고 Web APIs로 전달.
(3) Web APIs에서 처리*된 함수들은, 먼저 처리된 순서대로 callback Queue*에 줄을 선다.
(4) call stack에 쌓여있던 작업들이 모두 처리되고 비어지면, 이벤트루프는 Callback Queue에 대기중인 함수들을 call stack으로 이동시킨다.
*Queue : 선입선출의 자료구조.
*Web API에서 처리 : setTimeout함수가 2초라면 2초 후 콜백함수가 callback Queue로 이동
*Call stack 알아보기
Call stack이란?
Call stack이란 함수의 호출을 기록하는 스택 자료구조입니다.
* 스택: 스택이란 후입선출(Last In First Out, LIFO)을 기본으로하는 자료구조이다.
Call stack의 동작원리
Call stack은 push 와 pop 2가지 프로세스로 이루어집니다.
PUSH
1) main() (위 함수 전체를 감싼 함수)
2) printSquare(4)
3) square(n)
4) multiply (a, b)
POP
1) multiply (a, b) push
2) square(n)
3) printSquare(4)
4) main()
이처럼 함수의 호출이 stack에 아래부터 차례로 쌓이고, 위로부터 호출됩니다.
3) 자바스크립트 런타임 동작원리
[예시 코드]
console.log(1);
setTimeout(function sayHi () {
console.log(2);
}, 2000);
console.log(3);
// 1 -> 3 -> 2 순으로 출력된다.
[예시 코드 동작원리]
위 코드에서 동시성 모델을 포착할 수 있습니다. 1 - 3 - 2 순서로 출력합니다. setTimeout을 호출하고 2초를 기다리는 것이 아니라 다음 코드를 바로 실행합니다. 즉 setTimeout이 호출되면 바로 Web Apis로 보내 작업을 맡기고 다음 코드를 실행합니다. setTimeout은 Web Apis에서 2초를 기다렸다가 Callback Queue로 보내지고 Call Stack에 있는 작업들이 모두 실행되고 비면, 그 때 이벤트루프가 setTimeout을 Call Stack으로 보내고 실행됩니다.
동시성의 참의미
사실 동시성의 의미가 정말로 코드가 동시에 실행되는걸 의미하는 건 아닙니다. 자바스크립트의 동시성모델은 작업이 동시에 '호출' 될뿐 '실행'되는 건 아닙니다. 위 예시를 보면 setTimeout도 2초지나면 바로 실행되는게 아니라 다시 Call Stack에 돌아와서 실행되고 있습니다. 무조건 이 출입구를 거쳐야 실행될 수 있는데 이 출입문은 하나의 작업만 통과될 수 있습니다. 앞서 말했듯이 자바스크립트는 싱글스레드 언어입니다. 이는 작업을 실행하는 Call Stack이 하나라는 뜻입니다. 즉 자바스크립트에서 작업은 하나씩 실행될 수 있습니다. 아래 자바스크립트의 핵심 원리는 변하지 않습니다.
"one thread == one call stack == one thing at a time"
Ref
'프론트엔드 > Javascript' 카테고리의 다른 글
실행 컨텍스트 정리 (0) | 2020.10.23 |
---|---|
이벤트 버블링, 캡쳐링, 위임 (0) | 2020.10.21 |
비동기 처리하는 3가지 방법 (0) | 2020.10.19 |
싱글스레드 자바스크립트 (0) | 2020.10.16 |
Class vs Object vs Instance 정리 (0) | 2020.10.10 |