자바스크립트는 어떻게 비동기처리를 할 수 있나요?
면접에 저 질문이 나왔다. 공부를 더 해봐야 할 것 같다 하고 시원하게 답했다. 진짜 하나도 모르겠어서 포기가 빨랐다 (자랑이다..🙄)
그래서 다시 정리를 해보았다.
우선, 자바스크립트는 싱글 쓰레드 프로그래밍 언어이다.(CallStack이 1개)
즉, 한번에 하나의 작업만을 수행할 수 있음을 의미한다. 다른 작업이 중간에 끼어들수 도 없고, 기존에 수행하던 작업이 끝나야 다음 작업을 수행할 수 있다.
code : 이 프로세스가 어떻게 실행되어야 하는지에 대한 코드
Stack : 코드와 이 프로세스 안에서 함수들이 어떤 순서로 실행되어야 하는지, 이 함수가 끝나면 어디로 다시 돌아가야 되는지에 대한 정보를 가지고 있다.
Heap: 오브젝트를 생성하거나 데이터를 만들 떄 그 데이터들이 저장되는 공간, 동적으로 할당된 변수들이 저장된다.
Data : 전역변수(global) 나 스태틱 변수들이 할당되어 저장된다.
: 한 프로세스 안에서 여러개가 동작가능
⇒ 한 프로레스가 동시다발적으로 작업을 수행할 수 있도록 일한다.
ex) 🎧음악 들으면서, 🎨사진 편집하고, 👭카톡도 하고!
그러니까, 쓰레드는 자기들만의 수행해야 되는 함수의 호출을 기억해야 하기 때문에 쓰레드마다 스택이 할당되어져 있다.
⇒ 각 자 일의 흐름을 기억해주는 스택이 필요하겠지? ㅇㅇ
하지만,
이 프로세스 안에서 동작하는 쓰레드들은 결국은 한 프로그램을 위해서 일해야 되므로 프로세스에 지정된 코드와 데이터, 힙들을 공통적으로 접근해서 공통적으로 업데이트가 가능하다.
그러나!! 멀티쓰레딩을 잘못하면 공통적으로 업데이트하면서 순서가 맞지 않거나 하면 발생 할 수 있는 문제가 있다.
: 런타임이란 프로그래밍 언어가 구동되는 환경을 말한다.
자바스크립트 런타임은 JavaScript Engine, WebAPI, Render, MicroQueue, Task Queue, EventLoop으로 구성되어 있다.
: 자바스크립트 엔진은 Call Stack과 Memory Heap으로 구성되어 있다. 그 중 가장 유명한 것이 구글의 V8엔진이다.
하여, 더욱 구체적으로 데이터는 쓰레드 A가 하고, 이 일은 쓰레드 B가 하자고 지정하거나 몇개의 쓰레드가 동시에 동작하게 할 수 있도록도 지정 가능하다.
ex) 쓰레드A는 노래재생하고, 쓰레드B는 사진다운받아줘, 쓰레드C는 메일보내자
하여, JAVA처럼 구체적인 멀티쓰레드 동작들이 불가하다.😥
즉, 한번에 하나의 작업만을 수행 할 수 있다.(CallStack이 1개)
⇒ 기존의 수행하던 작업이 끝나야 다음 작업을 수행할 수 있다.
: 함수들이 호출하는 순서를 기억했다가 함수가 끝나면 원래 있던 자리로 돌아가기 위해 쓰이는 자료구조 중 하나이다. 모든 프로세스와 쓰레드 안에는 각각 저마다의 콜스택이 들어가 있다.
why? 정해진 일을 수행하려면 어디서 왔고, 어디로 다시 돌아가야 하는 정보를 무엇인가는 기억하고 있어야 하므로!
📍LIFO : Last In First Out
: Stack이 실행되는 순서는 가장 나중에 들어온 함수가 가장 먼저 나간다.
IN : push(main) → push(first) → push(second)
Out : pop(second) → pop(first)→ pop(main)⇒ empty!
: Web API는 브라우저에서 제공하는 API로 DOM,Ajax, TimeOut등 이 있다.
콜스택에서 실행된 비동기 함수는 WebAPI를 호출하고, WebAPI는 콜백함수를 Task Queue에 넣는다.
: WebAPI로부터 들어온 콜백함수들이 CallStack으로 가기 전에 기다리고 있는 곳이다.
📍FIFO (First IN First Out)
:Queue는 Stack과 달리 가장 먼저 들어온 콜백함수가 가장 먼저 나간다.
📌 그리고 한 번에 하나의 콜백함수만 콜스택으로 보내고 다시 이벤트루프가 돌아간다.
: 이벤트루프가 CallStack과 TaskQueue의 상태를 체크하여, 콜스택이 비어 자바스크립트엔진이 일이 없을때, Task Queue로부터 첫 번째 콜백을 Call Stack으로 밀어넣는다.
자바스크립트는 싱글 스레드 프로그래밍 언어라 한번에 하나의 작업만 수행한다. 하지만 Web API, TaskQueue, EvnetLoop 덕분에 멀티 스레드처럼 실행하는듯 보여진다.