[javascript] 자바스크립트 동작 원리

Mandy·2022년 8월 16일
0

본 게시물은 아래 링크의 강좌 및 게시글을 참조하여 작성되었습니다.
출처 :
https://www.youtube.com/watch?v=v67LloZ1ieI
https://joshua1988.github.io/web-development/translation/javascript/how-js-works-inside-engine/
https://ingg.dev/js-work/

자바스크립트 강좌를 들으면서 자바스크립트의 실행, 동작 원리에 대해 자세히 알아가면 좋다는 이야기를 듣게되었습니다.




그런데, 자바스크립트의 동작 원리라 하는것이 정확히 무엇을 의미하는것인지 감이 오지 않았습니다.

동작 원리? 동기? 비동기?


우선 자바스크립트의 동작 원리라고 일컬어지는것은 자바스크립트 엔진과 브라우저가 자바스크립트 코드를 실행해주는 것이기 때문에 브라우저의 동작 원리라고 생각하면 될 것 같습니다!

웹 브라우저 동작 원리


위의 그림처럼 웹 브라우저 내부가 이루어져 있습니다.

이중에서 우리가 주목해야 할 부분은
Call Stack => 편의상 스택이라고 부르겠습니다.
Web API =>편의상 대기실로 부르겠습니다.
Task Queue =>편의상 큐로 부르겠습니다.
이 세 부분입니다!

먼저, 간단한 자바스크립트 코드를 작성한 후 그것을 브라우저에서 실행한다고 가정해보겠습니다!

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

1.

간단한 코드이기 때문에 스택에 입력한 순서대로 쌓인 후 그 역순으로 실행되어 스택에서 사라집니다.

자바스크립트는 기본적으로 작업을 싱글스레드로 처리합니다. 즉, 단 하나의 호출 스택을 사용하며 호출 스택에 쌓인 함수나 코드를 위에서부터 그림과 같이 아래로 차례차례 실행되어 스택에서는 제거됩니다.

작업을 차례대로 실행하므로 하나의 작업이 끝날 때까지 또 다른 작업을 실행하지 않습니다.

그렇기 때문에 자바스크립트는 한 번에 여러개를 동시에 처리하는 병렬처리를 할 수 없는 구조입니다!



그런데, 여기서 아래 코드를 위의 두 코드 사이에 추가하여 실행하면 독특한 방식으로 처리되는일이 발생합니다.

setTimeout(function(){console.log(3+3)},1000);

setTimeout() 함수는 만료된 후 함수나 지정한 코드 조각을 실행하는 타이머를 설정하는 함수로, 코드상에 1000으로 입력된 부분은 주어진 함수를 실행하기 전에 기다릴 밀리초 단위의 시간입니다.
또한 이 함수는 비동기 함수로서 함수 스택의 다른 함수 호출을 막지 않습니다.




아까와 같은 방식으로 스택안에 호출될 함수들이 쌓이고 순서대로 실행하여 스택에서 제거됩니다.


그런데 스택에서 console.log(2+2)를 실행한 후 일반 함수들과 달리 setTimeout() 함수가 대기실에 가야하는 함수인 것을 알고 대기실로 보냅니다.
대기실로 보내는 것들에는 대기실에 적혀있는 것처럼 AJAX 요청코드, 이벤트리스너, setTimeout 등이 있습니다.


호출 스택에 쌓인 함수나 코드를 위에서부터 그림과 같이 아래로 차례차례 실행하고 스택에서는 제거되어 대기실에는 여전히 setTimeout 함수가 남게됩니다.


대기실에 있던 setTimeout 함수는 바로 스택으로 들어가는것이 아니라, 큐에 들어간 후 스택이 비어있을때만 스택으로 들어가 실행하게 됩니다.
이런 방식으로 브라우저는 자바스크립트 코드를 실행해주고 있는것입니다!

쉽게 풀어 설명했으니 이번에는 자세히 알아보도록 하겠습니다.

출처 : https://ingg.dev/js-work/

6번 그림에서 스택이 setTimeout 함수를 대기실로 보내는것은 setTimeout 함수가 자바스크립트 엔진 내에서 처리되지 않고 Web API가 처리하기 때문입니다.
엄밀히 말하면 대기실로 보낸다는 표현은 Web API로 함수를 전달하고 setTimeout 작업을 요청하는 것입니다. 그림상에서는 callback으로 되어있으나, 제가 예시로 든 케이스인 console.log(3+3) 함수가 될 것입니다.

출처 : https://ingg.dev/js-work/

Web API는 setTimeout 작업을 실행하고 1초(예시에서의 딜레이 설정 시간) 후 Task Queue로 함수를 보냅니다.

출처 : https://ingg.dev/js-work/

Event Loop는 Call Stack이 비어있으면 Task Queue에서 함수를 하나씩 꺼내 Call Stack에 넣고 실행합니다.

만약 Call Stack에 함수들이 너무 많이 차있으면 타임아웃 딜레이 시간 후에 정확히 실행되지 않을 수도 있습니다. Event Loop는 Call Stack이 비어있을 때만 Task Queue의 함수를 Call Stack으로 가져오기 때문입니다. 그렇기에 setTimeout() 함수를 실행하더라도 딜레이 시간이 정확하지 않을 수도 있습니다.




그렇다면, 이런 경우가 발생한다면 어떻까요?

아무튼 엄청 오래걸리는 작업이 스택에 들어와서 실행중에 있습니다.

그런데 이 와중에 버튼을 클릭하여 모달창을 띄우거나(이벤트리스너) AJAX 요청 후 코드실행, setTimeout 작업을 요청하면 해당 작업들은 실행되지 않습니다.
앞서 말했다시피 큐에 들어간 함수들은 스택이 비어있을때만 스택으로 들어갈 수 있기 때문입니다!

이런 상황이 지속되면 브라우저 프리징 현상이 발생하게 되어 위와 같은 결과가 나타납니다.
하지만 매번 짧게 끝나는 작업만 스택에 들어가는 것은 아닐것이기에 연산량이 많은 코드를 실행하면서도 위와 같은 현상이 나타나지 않게 한다면 좋을것입니다.



그 방법에 대해서는 다음 포스팅에 이어서 작성하도록 하겠습니다!
자바스크립트의 동작 원리를 알아보며 어느정도 이해가 된 것같습니다. 원리를 이해하고 나니 코드를 작성할때도 이러한 점들을 고려할 수 있을것 같습니다!

profile
즐코 행코 하세용

0개의 댓글