1. What is JS?
Single-threaded, non-blocking , asynchronous, and concurrent language.
A) Call stack
: Javascript is single-threaded programming language, which means that it has a single call stack! 그렇다면, single-threaded는 무슨 의미일까? 단순히 한번에 하나
의 일만 처리할 수 있다라고 볼 수 있습니다. Call stack에 대한 시각화를 위해 간단한 예제를 작성해봤습니다.
function multiply (a, b) {
return a*b;
}
function square (x) {
return multiply(x, x);
}
function printSquare (x) {
result = square(x);
console.log(result);
}
printSquare(4);
multiply() |
square() |
printSquare() |
main() |
코드 실행결과 call stack에 쌓이는 순서는 위 그림과 같다. 다양한 경우가 존재하지만, synchronous callback이 stack에 쌓여 각각 순서를 기다린다고 가정해보자. 3개의 getSync를 동작시키면, 각 request가 완료될때까지 다른 getSync는 stack의 후순위에서 대기를 한다. 결과적으로 모든 Blocking 함수들이 완료되어야 stack은 비워진다. 이 과정은 매우 Time consuming process이며, 결과적으로 매우 느리다. 이러한 코드들이 Browser환경에서 실행되면, Browser는 이 모든 실행 과정이 종료될때까지, 아무것도 할 수 없는, 즉 Stuck to the process 상태가 됩니다. 이 문제를 해결하기 위해, Asynchronous callbacks가 존재한다.
B) Callback function
Callback function을 앞서 살펴본 Call stack을 통해 살펴보자.
conosole.log('hi');
setTimeout(() => {
console.log('there');
}, 5000);
console.log('JSConfEU');
console.log('JSConfEU') |
(5 seconds later)...setTimeout() |
main() |
순서대로, 'hi'가 출력되고, 'JSConfEU'가 출력되고, 마지막으로 5초뒤에 'there'가 출력됩니다. setTimeout의 경우, call stack에 쌓이지만, 즉시 실행되지 않고, stack에서 빠져나와 webAPI가 Timer를 통해 countdown을 하는동안 대기합니다. webAPI는 task가 끝남과 동시에 callback funtion을 task queue에 push 합니다. 이때, 비어있는 call stack에 task queue의 callback을 다시 push 해주는 것이 "Event Loop"입니다. 이렇게 'there'의 마지막 출력이 설명됩니다.
추가적으로, AJAX request 예제를 살펴보았습니다.
console.log('HI');
$.get('url', (data)=> {
console.log(data);
});
console.log('YS');
먼저, Main문이 실행되어, 'HI'가 출력됩니다. AJAX request javasript runtime에서 빠져나와 browser환경의 webAPI로 실행됩니다. 'YS'가 다음으로 출력되고, callback은 task queue로 들어가 event loop에 의해 비어있는 call stack에 다시 push됩니다.
2. Sync vs Async
Synchronous 코드와 Asynchronous 코드의 비교를 'forEach'를 통해 알아보자.
// Sync example
[1, 2, 3, 4].forEach((i) => {
console.log(i);
})
// Async example
const asyncForEach = (array, cb) => {
array.forEach(() => {
setTimeout(cb, 0);
})
}
asyncForEach([1,2,3,4], (i) => {
console.log(i);
])
강의에서, synchronous function의 예로 forEach method를 소개한다. callback fucntion이지만 synchronous로 실행됩니다. Sync 예제의 경우, blocking function이기 때문에 배열의 각 원소마다 함수가 실행되어 속도가 느립니다. Slow Synchronous 함수가 실행될때, Browser의 "render"는 block 됩니다. 반면에, 상대적으로 빠른 asynchronous callback의 실행은 중간 중간 render가 실행되어, browser가 callback에 fully stuck되는 일이 발생하지 않습니다 왜냐하면, "render"의 우선순위가 callback보다 높기 때문입니다.
* JSConf의 영상을 통해 정리한 내용입니다!
'웹 개발 > Node.js' 카테고리의 다른 글
[Node.js] #4 HTTP (0) | 2021.12.26 |
---|---|
[Node.js] #3 Promise 객체 사용과 Async 동작 (0) | 2021.12.12 |
[Node.js] #2 Event Loop이 무엇인가? (0) | 2021.11.19 |