렌더링 엔진이 HTML을 파싱하다다 js 코드를 만나면,
토크나이징, 렉싱, 파싱을 한 후 실행하게 된다.
1. 토크나이징(Tokenizing)
소스코드를 작고 관리 가능한 토큰으로 나누는 텍스트 전처리 작업으로 렉싱과 파싱 과정에서 이를 쉽게 다루기 위한 단계
토큰이란?
코드의 최소 단위로 변수와 연산자, 키워드, 구분자 등으로 구분한다.
2. 렉싱(Lexing)
생성된 토큰에 의미를 할당하는 단계
예를 들면, 아래와 같은 코드는 렉싱을 하면 각각 다른 의미가 할당된다.
let a = 5;
Token | 의미 |
let | 키워드 |
a | 식별자 |
= | 할당 연산자 |
5 | 숫자 상수 |
; | 구분자 |
3. 파싱(Parsing)
목적에 맞춰 추상 구문 트리(Abstract Syntax Tree)를 구성하는 단계
AST(Abstract Syntax Tree) 구조란?
노드, 루트 노드, 자식 노드로 이루어진 코드의 계층적인 구조를 표현하는 트리이다. JS 엔진이 이 트리를 통해 코드의 구조를 이해하게 된다.
❓여기서 드는 궁금증❓
위 예시 코드와 같은 문자열을 AST 구조로 어떻게 변환하는가?
바로, Babel이라는 트렌스파일러 도구를 이용한다.
바벨은 최신 자바스크립트 문법(ES6 이상)으로 작성 된 코드를 이전 버전의 자바스크립트 문법으로 변환시켜 구형 브라우저에서도 동작을 하게 하는(크로스 브라우징) 도구이다. 바벨도 일종의 컴파일 과정을 거치고 소스코드를 파싱해서 AST를 생성한다.
그래서 Babel은 컴파일러로 불릴 때도 있고, 트렌스파일러라고 불릴 때도 있다.
- 컴파일러: 소스코드를 한 번에 기계어로 번역
- 트렌스파일러: 소스코드의 input과 output이 비슷한 레벨의 언어일때 사용.
ex) es6 → es5 또는 c++ → c
4. 실행(execution)
자바스크립트를 실행하기 위해서는 자바스크립트 엔진이 필요하다.
JS 엔진에는 크게 메모리 힙(Memory Heap)과 콜 스택(Call Stack)이 있다.
Memory Heap:
변수나 함수를 저장하는 보관소
Call Stack:
실행할 함수를 쌓아두는 자료구조
(밑에서부터 쌓기 때문에 특정 함수를 실행하게 되면, 해당 함수는 콜 스택의 가장 상단에 위치한다.)
실행 시, 어떤 일이 일어나는지 쉽게 설명하자면,
1. 변수와 함수를 Memory Heap에 저장을 하고,
2. Call Stack은 메인 함수부터 실행하며 작업들을 밑에서부터 하나씩 쌓는다. 이때 Memory Heap에서 작업 수행에 필요한 것들을 찾아서 작업을 수행한다.
그러나 JS 엔진은 단 하나의 Call Stack만 가질 수 있다.
즉, 한 번에 한 가지만 실행 가능하다는 것이다.
이를 싱글스레드라고 하는데, 단점은 실행할 일이 많아도 앞에 일이 완료될 때까지 다음 할 일을 하지 못한다는 것이다.
그래서 우리는 비동기 작업을 한다. 비동기 작업을 위해 추가로 Web API, Callback Queue와 Event Loop가 있다.
이들이 어떻게 상호작용하며 작동하는 지, 전체적인 흐름은 아래 GIF로 확인해보자.
- JS 엔진이 비동기 함수가 호출를 만나면 함수를 WEB API로 보냄
- 작업이 완료되면 해당 작업의 콜백 함수가 Callback Queue(micro/macro)로 들어감
- Event Loop가 Call Stack이 비어있음을 감지하면, Callback Queue에서 대기하고 있는 콜백함수를 Call Stack으로 이동시켜서 실행
Web API
브라우저가 제공하며 인터페이스로 비동기 작업(이벤트 리스너, 타이머, http 요청 등)을 처리한다.
- 자바스크립트 엔진의 외부에서 실행되고 작업 완료 후 콜백함수가 Callback Queue에 추가됨
- 각 API마다 스레드가 할당되어 있음 → 모여서 멀티스레드 역할을 함
- 즉, 자바스크립트 엔진은 싱글 스레드이지만, 브라우저가 멀티스레드이므로 비동기가 가능함.
더보기기능:
- 브라우저에 로드된 문서를 조작함
- 웹 페이지의 일부를 업데이트 함
- 그래픽 요소들을 웹 페이지에 그림
- 오디오, 비디오 작업을 웹 페이지에서 가능하게 함
- 클라이언트 측 저장소를 사용할 수 있게 함
Callback Queue
완료된 비동기 작업들의 콜백들이 대기하는 큐
- 이벤트 루프가 처리하기까지 대기하는 콜백 함수들이 담겨짐
- 종류:
- Micro Task Queue: promise, async/await()와 같은 비동기 작업 → 우선순위 더 높음
- Macro Task Queue: setTimeout(), setInterval(), I/O과 같은 비동기 작업
Event Loop
call stack과 queue를 지속적으로 확인하며, call stack이 비어있을 때 event loop는 콜백을 callback queue에서 가져와서 call stack에 넣음
📌결론
자바스크립트는 싱글 스레드 방식으로 동작하기 때문에, 멀티 스레드와 비동기로 동작하도록 해주는 것은 자바스크립트 엔진이 아닌 브라우저이다. 결국, 자바스크립트 엔진 스스로는 비동기로 동작할 수 없기 때문에 이를 위해 추가적으로 Web API, Callback Queue, Event Loop의 힘을 빌려 동작한다.
'자바스크립트' 카테고리의 다른 글
[JavaScript] 자바스크립트 비동기 프로그래밍 [#1 동기 vs 비동기] (0) | 2024.09.18 |
---|