await/async - js의 동작원리

0

javascript는 비동기적으로 실행되는가?

js는 특정 코드의 실행이 끝나는걸 기다리지 않고 다음 코드를 실행한다.

console.log('1');

setTimeout(function() {
	console.log('2');
}, 2000);

console.log('3');

setTimeout을 기다리지 않고 console.log('3')이 먼저 실행되기 때문에.

위 코드는 1 -> 3 -> 2 순서로 콘솔에 찍힌다.

그렇다면 js는 비동기적 실행되는 언어이구나 라는 생각을 하게된다.

Javascript는 동기적으로 실행된다.

JavaScript (JS)는 기본적으로 동기적으로 실행되는 언어이다.

즉, 코드가 순차적으로 실행되며, 한 작업이 완료될 때까지 다음 작업이 실행되지 않는다.

Node.js 관련 글을 보다보면, "js는 싱글 스레드로 작동하기 때문에 대규모 프로젝트에는 어울리지 않는다"라는 글들을 종종 본다. 싱글 스레드라.. 싱글 스레드 운영체제 수업시간에 많이 들었던 단어이다.

싱글스레드는 하나의 프로세스에서 하나의 스레드를 실행하므로, 이는 Node.js 애플리케이션이 한 번에 하나의 작업만을 처리할 수 있다는 것을 의미한다.

싱글스레드는 프로세스 내의 작업을 순차적으로 실행한다. 하나의 작업이 다 끝나야 다음 작업을 실행한다.

엥? 그럼 위의 코드도 1->2->3 순서로 실행되어야 하는거 아닌가?

이를 이해하기 위해선 js의 작동원리에 대해 알아야 한다.

Javascript의 작동원리

이건 js 엔진의 그림이다. heap에는 변수가 저장되고, stack에는 함수가 호출되면 쌓인다.

함수가 호출되면 stack에 push되고, return이 일어나면 스택에서 pop이 된다.

console.log('1');
console.log('2');

function a(value_a) {
	return value_a;
}

function b(value_b){
	return value_b;
}

function sum() {
    console.log(a(2)+b(3));
    console.log('3');
}

sum();

위 코드는 console.log("1"); 이 stack에 들어가자마자 return되어 나오고,

console.log("2")가 그 다음으로 들어가 return되어 나온다.

그 다음 sum이 stack에 쌓이고, sum 안의 a()와 b()가 순서대로 스택에 쌓였다가 return되어 나온다.

그 다음 console.log('3')이 stack에 들어갔다가 return되며

sum이 코드의 끝에 도착했기 때문에 return되면서 스택에서 빠져나온다.


아니 그럼 맨 위 코드도 이렇게 실행되야 하는거 아닌가?

그럼 setTimeout은 왜 맨 마지막에 수행된걸까?

console.log("3")은 setTimeout이 스택에서 빠져나오기 전까지는 스택에 들어갈 수 없고,

싱글 스레드니까 setTimeout이 끝나기 전까지는 console.log('3')을 실행할 수 없는거 아닌가?

맞다, 하지만 이런식으로 모든 코드를 수행했다간 어느 한 코드의 실행시간이 매우 길다면, 코드가 실행을 마칠때 까지, 사용자는 화면에서 아무것도 볼 수 없을 것이다.

js는 어떻게 비동기적으로 코드를 수행할까?

우선 런타임이란 프로그래밍 언어가 구동 되는 환경을 말한다. js의 런타임으로는 대표적으로 웹 브라우져가 있다. setTimeout은 브라우져에서 제공하는 api이다.

setTimeOut같은 코드들은 호출되었을때 stack에 쌓였다가, web api로 이동한다.

console.log('1');

setTimeout(function() {
	console.log('2');
}, 2000)

console.log('3');

javascript동작 눈으로 확인하기
위의 링크를 타고 들어가서 이 코드가 실행되는 순서를 확인해보자.

먼저, console.log('1')이 스택에 쌓인다.

그 다음, setTimeout()이 스택에 쌓이고,

webApi로 이동하여 실행된다. 따라서 스택에는 없기 때문에 console.log('3')이 실행될 수 있다.

webApi에서 실행이 끝나면, stack으로 바로 오는게 아니라 callBack Queue(대기실)로 들어오게 된다.

그리고 stack이 비었다는게 확인되면, queue에서 stack으로 이동하여 console.log('2')가 스택에 쌓이고, 실행될 수 있게 되는 것이다. stack이 비기 전까지는 queue에서 stack으로 이동 할 수 없다.

console.log('1');

setTimeout(function() {
	console.log('2');
}, 0)

console.log('3');

따라서 이렇게 setTimeOut을 0으로 해도 스택이 비기 전까진 들어올 수 없기 때문에

이 코드도 똑같이 1 -> 3 -> 2 순으로 실행된다.

이를 통해서 js는 동기적으로 수행되지만, 비동기 적으로 수행하는 것처럼 보일 수 있는 것이다.

이와 마찬가지로 우리가 사용하는 nodejs도 js의 런타임 중 하나이다.

nodejs에선 이런 함수들이 webapi대신 c++ api를 통해 실행된다는 점에서 다를뿐이지, 동작원리는 같다.

profile
https://www.youtube.com/watch?v=__9qLP846JE

0개의 댓글