들어가기
기본적인 문법과 API 사용법에 대해서 익히는 것도 중요하지만, 고급 개발자가 되기 위해선 자바스크립트 동작원리도 알아야 한다.
머릿말
자바스크립트의 동작원리 등 자바스크립트를 깊게 파보는 시리즈 물의 첫번째 글
구성방식
- 자바스크립트를 블락 단위로 구성하는 방법
- 그 블락이 어떻게 동작하는지
프로젝트에서 자바스크립트 의존성이 높아진다면, 개발자는 자바스크립트의 언어적 특성과 내부 구조를 정확하게 이해해야 한다.
자바스크립트 엔진
- 실제 자바스크립트 엔진은 단일 스택과 힙이 끝
- 나머지는 모두 이 JS 엔진을 실행시키는 환경에 포함되어 있다.
(환경 - 브라우저, Node.js 등등)
- 자바스크립트 엔진의 대표적인 예 : Google V8 엔진
- V8은 Chrome과 Node.js에서 사용한다.
엔진의 구조도를 간단히 나타낸 그림
- 엔진의 주요 두 구성요소
- Memory Heap : 객체가 할당되어 존재하는 곳
- Call Stack : 호출되는 함수가 저장되는 곳
런타임
- setTimeout과 같은 브라우저 내장 API를 자바스크립트 엔진에서 제공하지 ❌
- V8 엔진과 같은 자바스크립트 엔진을 제외한 나머지는 자바스크립 엔진을 구동하는 런타임 환경(브라우저, Node.js)이 제공해준다.
자바스크립트에 관여하는 다른 요소들 (V8 외부에 존재하는 요소들)
-
Web APIs : 브라우저에서 제공하는 API들
- ex)
setTimeout
, DOM
, Ajax
- Call Stack에서 실행된 비동기 함수는 Web API를 호출
→ Web API는 콜백함수를 Callback Queue에 밀어 넣는다.
(Web API는 직접 Call Stack에 접근할 수 없고, 오직 Task Queue에만 접근 가능)
-
Task Queue : 비동기적으로 실행된 콜백함수가 보관되는 영역
- Queue : 선입선출(FIFO)의 룰을 따르는 자료 구조
- ex)
setTimeout
에서 타이머 완료 후 실행되는 함수 (콜백 함수)
- ex)
addEventListener
에서 click 이벤트가 발생했을 때 실행되는 함수
-
Event Loop
- Call Stack과 Task Queue의 상태를 체크하여
→ Call Stack이 빈 상태가 되면
→ Task Queue의 첫번째 콜백을 Call Stack으로 밀어넣는다.
→ 이러한 반복적인 행동을 틱(tick)이라 부른다.
호출 스택(Call Stack)
- 호출 스택 : 우리가 프로그램 상에서 어디에 있는지를 기록하는 자료구조
- 자바스크립트는 기본적으로 싱글 쓰레드 기반 언어
- 호출 스택이 하나 (한 번에 한 작업만 처리 가능)
- 만약 함수를 실행하면, 해당 함수는 호출 스택의 가장 상단에 위치
- 함수의 실행이 끝나면, 호출 스택에서 제거
function multiply(x, y) {
return x * y;
}
function printSquare(x) {
var s = multiply(x, y);
console.log(s);
}
printSquare(5);
-
처음 엔진이 이 코드를 실행하는 시점에는 호출 스택이 비어있음.
-
코드가 실행되면 다음과 같이 변함.
-
호출 스택의 각 단계를 스택 프레임이라고 한다.
-
예외 발생 시 콘솔 로그 상에서 나타나는 스택 트레이스 = 에러 발생 시의 호출 스택의 단계
function foo() {
throw new Error('SessionStack will help you resolve crashes');
}
function bar() {
foo();
}
function start() {
bar();
}
start();
- 다음과 같이 에러 발생 시의 호출 스택의 단계가 나온다.
function foo() {
foo();
}
- 위의 코드를 실행시키면 호출 스택은 다음과 같이 되버린다.
- 그러다가 특정 시점에 함수 호출 횟수가 호출 스택의 최대 허용치를 넘게 되면 아래와 같은 에러를 발생시킨다.
결론
싱글 스레드 기반 코딩
- 멀티 스레드 환경에서 제기되는 복잡한 문제나 시나리오를 고민하지 않아도 됨 ⇒ 상당히 쉬움 (ex. 데드락)
- 코드를 실행하는 건 상당히 제약이 많음
⇒ 한 개의 호출 스택을 갖고 있어 자바스크립트의 실행이 느려질 수 있음
자바스크립트는...
- 단일 스레드 프로그래밍 언어라 한번에 하나씩 밖에 실행할 수 없다.
- 그러나 Web API, Task Queue, Event Loop 덕분에 멀티 스레드처럼 보여진다.
Queue의 종류
- Task Queue
Promise
가 공개되기 이전 비동기로 호출되는 대부분의 작업들을 임시 저장하는 큐
- Microtask Queue
Task Queue와 동일한 계층에 존재하며, Promise
비동기 호출작업들이 임시저장되는 큐
- Animation Frames
동시성 & 이벤트 루프
문제 상황
- 브라우저에서 자바스크립트로 매우 복잡한 이미지 프로세싱 작업을 하면
- 호출 스택에서 해당 함수가 실행되는 동안 브라우저
- 페이지를 그리지도 못하고, 어느 코드도 실행을 못한다.
- 브라우저가 호출 스택의 정말 많은 작업들을 처리하다보면
해결방법
- 이벤트 루프를 통한 동시성 확보
- 비동기 콜백
- 페이지 랜더링 동작을 방해하지 않고
- 브라우저의 응답도 끊지 않으면서
- 연산량이 많은 코드를 실행할 수 있음
참고자료