JavaScript 기본 동작 원리
01. 자바스크립트는 싱글 쓰레드 언어
자바스크립트는 싱글 쓰레드 언어
이다. 자바스크립트는 하나의 Call Stack
만을 가지고있기 때문에 Stack에 쌓이는 순서대로 한번에 하나의 명령만 수행한다. Stack이 하나뿐이므로 여러 동작이 같은 Stack에 쌓이고, 하나의 동작이 끝나고 pop이 되어야만 다음 동작을 수행한다.
이는 언뜻 자바스크립트에서는 오로지 동기(Synchronous)
처리만 가능하고 비동기(Asynchronous)
처리는 불가능한것으로 보인다. 이렇게되면 시간이 오래 걸리는 작업을 만나게 되면, 그 뒤의 작업들이 Block 되므로 정상적인 어플리케이션의 구현이 불가능하다.
그러나 사실 자바스크립트는 비동기 처리가 가능하다. 자바스크립트를 실행하는 브라우저(JS Engine)가 Wep API
라는것을 제공하기 때문이다.
02. Web API
만약 자바스크립트가 setTiemout
, EventListener
, Ajax
등의 코드를 만나게 되면 바로 Stack에 쌓이는것이 아니라, Web API라는 곳으로 옮겨진다. 그리고 이 Web API에서 코드들을 수행하고, 처리가 끝나면 이를 Callback Queue
라고 하는 곳으로 이동시키며, Callback Stack이 비어있으면, Event Loop
가 이 Queue에서 함수를 하나씩 꺼내어 Stack에 넣고 실행시킨다.
이 때 Event Loop가 Stack이 비어있는지 주기적으로 확인하는것을 tick
이라고 한다. Queue는 선입 선출 (First-In-First-Out)의 구조를 가지기 때문에, 별도의 처리를 하지 않을 경우 기본적으로 작업이 끝나는 순서대로 Queue에서 꺼내 사용하게 된다.
즉 동작 순서는 다음과 같다.
- Call Stack에 Ajax, EventListener등의 함수가 들어온다
- 해당 함수를 Web API로 이동시켜서 작업을 수행한다.
- 작업이 완료되면 Callback Queue로 이동시킨다.
- EventLoop이 Stack이 비어있는지 확인하고(tick), 비어있다면 Stack으로 보낸다.
- Call Stack은 이렇게 들어온 함수를 수행한다.
이러한 동작방식이 setTimeout등의 코드가 정확한 delay 이후 실행되지 않는이유가 된다. 3초동안 작업을 수행하였어도, Stack이 비어있지 않다면 EventLoop가 Call Stack으로 보내지 않기 때문이다. 때문에 기본적으로 Stack에 쌓이는 함수에는 너무 오래걸리는 코드, 예를 들어 수많은 중첩 반복문 등을 작성하면 안된다. 이 Stack이 오랫동안 비어있지 않게 되기 때문에 웹 브라우저가 프리징이 일어날 수 있다.
console.log('1');
setTimeout(function() {
console.log("2");
},0);
console.log("3");
참고로 위 코드같이 setTimeout에 delay할 시간을 0으로 주어도, setTimeout 함수는 무조건 바로 Web API로 옮기기 때문에 위 코드는 "1" -> "3" -> "2" 순서로 로그가 찍히는것을 확인할 수 있다.
+) 흔히 비동기작업을 할때 사용하는 Promise
선언자체는 바로 Web API로 이동시키는것이 아니다.
const p = new Promise((resolve, reject) => {
console.log('1');
setTimeout(() => {
console.log('2');
resolve('3');
});
});
console.log('4')
p.then((resut) => {
console.log('result', result);
});
위 코드의 출력 결과는 다음과 같다.
1
4
2
3
Web API로 이동하는 함수는 then
함수이며 이는 promise의 resolve
혹은 에러의 경우 reject
가 호출되어야 Queue로 이동한다.
03. 결론
자바스크립트는 싱글 스레드만을 지원하므로 기본적으론 동기적으로 동작한다. 그러나 브라우저의 JS Engine은 비동기로 처리해야 하는 작업을 만나게되면, 이 동작은 Web API 라는 별도의 공간에서 실행시키고, Queue로 이동시킨 다음 차례대로 Stack으로 올려보내 함수를 실행함으로써 비동기적인 처리도 할 수 있게 된다.
Referenece
'WEB' 카테고리의 다른 글
[React] useState의 동작원리에 관하여 (0) | 2022.12.28 |
---|---|
next-sitemap을 사용하여 동적 생성 페이지 sitemap 생성하기 (0) | 2022.12.19 |
DOM(Document Object Model) (0) | 2022.06.27 |
CSS em & rem (0) | 2022.06.26 |
CORS(Cross-Origin Resource Sharing) 기본 (0) | 2022.06.24 |