-자바스크립트의 동작 원리에 대해 살펴본다.
-단일스레드인 자바스크립트가 비동기 방식으로 작동하는 원리를 살펴본다.
*개인 공부 목적으로 포스팅한 것이기 때문에 틀린부분이 있거나 취약한 부분이 있습니다. 지적해주셔도 좋고 여러 블로그에서 잘 정리 해두었으니 다양하게 참고해보시면 좋을 것 같습니다.
자바스크립트 런타임 환경, 기본 동작 원리
자바스크립트 런타임이란 자바스크립트 코드가 돌아가는 환경을 말한다. 이 런타임을 구성하고 있는 요소들은 인터프리터 V8 엔진, WEB API, 이벤트루프, 콜백큐 등이 있다. 하나하나 개념을 간단하게 살펴보면 다음과 같다.
- V8 : 크롬 브라우저의 일부인 엔진이다. 자바스크립트 코드는 V8 엔진을 통해 코드가 해석되고 돌아간다. 대표적으로 자바스크립트 엔진이 V8인 것이지 익스플로러나 다른 브라우저에서도 각자의 엔진이 있어서 자바스크립트 코드를 해석할 수 있다. 대표적으로 익스플로러는 '차크라'라는 엔진을 사용한다. 그리고 V8 엔진은 메모리힙, 스택큐로 구성되어 있는데 이 것은 뒤에 다룬다.
- WEB APIs : 자바스크립트 엔진에서 지원하지 않는 setTimeOut, Ajax 등의 메소드를 지원하며 비동기 방식에서 주로 사용된다.
- 이벤트루프, 콜백큐 : 자바스크립트를 비동기 방식으로 작동하기 위한 구성요소로 뒤에서 설명한다.
자바스크립트는 싱글스레드 기반의 언어다. 그러므로 작업시 하나의 콜스택이 한 번에 하나의 작업을 처리한다. 다음과 같은 예시 코드를 보자.
function test1(){
console.log("test1");
}
function test2(){
test1();
console.log("test2");
}
test2();
//결과
//test1
//test2
위의 코드는 콘솔에 test1,test2 순서로 나온다. 싱글스레드 동기방식으로 호출 순서대로 처리한 것이다. 아래 그림과 같은 흐름으로 콜스택에 쌓이며 호출된다.
근데 자바스크립트는 어떻게 싱글스레드인데 비동기 방식으로 작업을 처리하는 것일까? 특히 ajax 작업과 같이 있는 코드가 가끔 원하는 순서대로 동작하지 않을 때가 있다. 또는 setTimeOut 호출이 원하는 순서대로 안 될때도 있다. 이는 자바스크립트의 비동기 방식을 이해해야 하며, 비동기 방식을 가능하게 해주는 콜백큐(Callback Queue), 이벤트 루프(Event Loop) 등을 이해해야 한다.
자바스크립트 비동기 방식 원리, 콜백큐와 이벤트 루프
큰 개요부터 요약해서 말하자면 싱글스레드 기반의 자바스크립트를 비동기 방식으로 동작하게 만들어 주는데에는 자바스크립트 런타임의 이벤트 루프, 콜백큐가 필요하다. 비동기 요청은 콜백큐와 이벤트 루프가 추가적으로 담당하는 구조라고 보면 된다.
콜백큐는 비동기 요청시 넘어오는 콜백함수를 담는 큐(Queue)를 말한다. 이벤트 루프는 콜스택과 콜백큐를 계속 감시(?)하면서 스택큐가 비었을 때, 큐에 있는 콜백함수를 스택큐로 밀어 넣는 역할을 한다.
간단하게 설명이 가능할지 모르겠지만 최대한 간단하게 다음과 같은 코드를 순서대로 설명해보려고 한다.
function first(){
console.log("first");
}
function second(){
console.log("second");
}
function third(){
console.log("third");
}
first();
setTimeout(second,0);
third();
//결과
//first
//third
//second
setTimeout에 0초를 인자로 주었기 때문에 first->second->third 순서로 출력될 것 같지만 first->third->second로 출력된다. 동작 방식은 다음과 같다.
- first()가 호출되면서 콜스택에 쌓인다.
- console.log("first")를 출력하고 first()가 제거된다.
- setTimeout이 호출되면서 스택큐에 쌓인다.
- setTimeout은 자바스크립트 엔진이 아닌 WEB APIs에서 처리하는 함수이기 때문에 setTimeout 콜백 요청이 WEB APIs로 넘어가고 스택큐의 setTimeout은 제거된다.
- setTimeout의 인자에 따라 타이머API가 작동되고, 타이머가 끝나면 콜백함수로 넘어온 함수를 콜백큐에 넘긴다.
- 콜스택에는 third()가 쌓인다.
- third()의 console.log("third")가 출력되고 third()가 제거된다.
- 콜스택에는 남아 있는 함수가 없다. 이벤트루프는 콜스택이 빈 것을 확인하고 콜백큐의 콜백함수(second)를 불러서 콜스택으로 넘긴다.
- second가 콜스택에 쌓이고 console.log("second")가 출력된 후 second가 제거되며 종료된다.
비동기 흐름을 그려내는 것이 상당히 부담스러워서 게으르지만 동작하는 과정을 그림으로 표현한 블로그를 찾아봤다. 아직 제대로 읽어보진 않았는데, 동작하는 이미지로 잘 표현한 블로그가 있어서 아래에 참고 링크를 건다.
https://beomy.github.io/tech/javascript/javascript-runtime/
'개발자 일지 > JavaScript' 카테고리의 다른 글
[자바스크립트,JavaScript]함수선언식, 함수표현식 (0) | 2021.11.13 |
---|---|
[기타]웹 브라우저 동작 방식, DOM에 관하여 (0) | 2021.10.05 |
[제이쿼리]$('a,b')와 $('a','b')의 차이점 (0) | 2021.02.23 |