티스토리 뷰
[번역] 자바스크립트는 어떻게 동작할까? - JS엔진, 런타임, 콜스택에 대한 개요
norux 2018. 4. 23. 19:53[번역] 자바스크립트는 어떻게 동작할까? - JS엔진, 런타임, 콜스택에 대한 개요
본 포스팅은 How JavaScript works: an overview of the engine, the runtime, and the call stack 의 글을 번역한 글입니다. How JavaScript 시리즈는 9편정도가 있으며, 지금도 나오고 있습니다. 최대한 모든 시리즈를 번역할 예정입니다.
많은 의역이 포함되어 있을 수 있습니다. :)
자바스크립트가 점점 더 인기있어지면서, 많은 팀들은 프론트엔드, 백엔드, 하이브리드, 임베디드와 그 이상의 많은 영역에서 자바스크립트를 사용하고 있습니다.
이 포스팅은 자바스크립트와, 자바스크립트가 어떻게 동작하는지에 대해 깊이 파보기 위한 목적으로, 시리즈의 첫 번째 글입니다. 자바스크립트의 블록을 생성하는 것과 어떻게 동작하는지를 보고나면, 여러분은 더 좋은 코드를 작성할 수 있을것입니다. 아, 포스팅에서는 SessionStack 을 이용할 것입니다. 세션스택은 경쟁력을 유지하기 위한 안정적이고 고성능의 가벼운 자바스크립트 어플리케이션입니다.
역자주: 이 사람은 세션스택의 공동 창업자겸 CEO입니다... 위 이야기는 자사제품의 막간 홍보라고 보시면 됩니다.
GitHub의 통계에서 보는 것 처럼 자바스크립트는 활성화된 레포지토리와 전체 GitHub 푸시 건수에서 1등에 위치하고 있습니다. 그 외 다른 카테고리들도 상위권에 위치하고 있습니다.
만약 프로젝트가 자바스크립트에 많은 의존성을 가지고 있다면, 어메이징한 소프트웨어를 만들기 위해서 개발자는 언어와 에코시스템이 제공하는 모든 것을 이용해야만 한다는 것을 의미합니다. 내부에서부터 아주 깊은 이해를 통해서 말이죠.
알다시피, 매일 자바스크립트를 사용하지만 핵심 내부에서 어떤 일이 일어나는지를 알고 있는 개발자들은 많이 없습니다.
개요
대부분 개념적으로 V8 엔진에 대해서는 들어본 적이 있을 것입니다. 그리고 대부분의 사람들은 자바스크립트가 싱글 쓰레드라고 알고 있거나 콜백큐를 사용한다고 알고 있습니다.
이 포스팅에서 이 개념들을 상세하게 알아보고, 자바스크립트가 실제로 실행되는 방법을 설명하겠습니다. 이 상세내용을 알게되면 여러분은 논블로킹non-blocking 어플리케이션을 좀 더 좋은 코드로 작성할 수 있을 것입니다.
만약 당신이 자바스크립트 초급자라면, 이 포스팅의 내용이 왜 자바스크립트가 다른 언어에 비해서 "이상하게" 느껴지는지 이해하는데 도움이 될 것입니다.
능숙한 자바스크립트 개발자라면, 바라건데 제가 당신이 매일 사용하는 자바스크립트 런타임이 실제로 어떻게 동작하는지에 대해서 약간은 신선한 인사이트를 드렸으면 좋겠습니다.
자바스크립트 엔진
구글의 V8엔진은 유명한 자바스크립트의 엔진입니다. V8엔진은 크롬과 Node.js에서 사용되고 있습니다. 다음은 엔진에 대해 굉장히 심플한 그림입니다.
엔진은 두 가지 컴포넌트로 구성됩니다.
- 메모리 힙: 메모리 할당이 일어나는 영역입니다.
- 콜 스택: 코드가 실행될 때, 스택 프레임이 생성되는 영역입니다.
런타임
거의 모든 자바스크립트 개발자에게 사용되는 setTimeout
과 같은 브라우저에 존재하는 API들이 있습니다. 하지만 이 API들은 엄밀히 말해 엔진이 제공하는 API는 아닙니다.
그럼 이런 API는 어디에 정의되어 있을까요?
실제로는 조금 복잡합니다.
즉, 우리는 엔진뿐만이 아닌 더 많은 것을 가지고 있습니다. 브라우저가 제공하는 Web API 라는 것이 있습니다. Web API에는 DOM, Ajax, setTimeout 같은 다양한 함수들이 정의되어 있습니다.
그리고, 또 유명한 이벤트 루프와 콜백 큐도 가지고 있습니다.
콜백 큐(Callback Queue)
자바스크립트는 싱글 쓰레드 프로그래밍 언어 입니다. 이 말은 하나의 콜 스택을 가진다는 의미입니다. 그러므로 동시에 한 개의 작업만 실행할 수 있습니다.
콜스택은 기본적으로 우리가 프로그램에서 어디에 있는지 기록하는 자료구조입니다. 만약 우리가 함수 내부로 진입(Function call)한다면, 스택에 함수를 쌓습니다. 그리고 함수로부터 빠져나온다면(return), 스택에서 함수를 빼냅니다. 이것이 스택이 하는 모든 일입니다.
다음의 코드 예제를 한 번 봅시다.
function multiply(x, y) {
return x * y;
}
function printSquare(x) {
var s = multiply(x, x);
console.log(s);
}
printSquare(5);
처음에 엔진이 코드를 실행하면, 콜 스택은 비어있습니다. 이후에 스탭 진행별로 콜 스택은 다음과 같이 변합니다.
콜스택에서 각 엔트리는 스택 프레임Stack Frame이라고 부릅니다.
그리고 다음 예제는 예외Exception이 던져졌을Throw 때, 스택 트레이스가 생성되는 방법에 관한 것입니다. 기본적으로는 예외가 발생할 때의 콜 스택 상태입니다.
function foo() {
throw new Error('SessionStack will help you resolve crashes :)');
}
function bar() {
foo();
}
function start() {
bar();
}
start();
이 코드가 작성된 foo.js 라는 파일을 크롬에서 실행하게 한다면, 다음과 같은 스택 트레이스가 생깁니다.
스택 날리기Blowing the stack - 이것은 최대 콜 스택 사이즈에 도달할 때 발생합니다. 이것을 쉽게 발생시키기 위해서 종료조건이 없는 재귀 함수를 사용하겠습니다. 다음의 예제코드를 봅시다.
function foo() {
foo();
}
foo();
엔진이 이 코드를 실행하면, foo
함수를 호출합니다. 이 함수는 종료조건 없이 끊임없이 스스로를 재귀 호출하게 됩니다. 각 실행의 스탭마다 같은 함수가 콜스택에 추가되게 되며, 곧 콜 스택의 최대 사이즈를 넘게 됩니다. 다음 그림처럼 말이죠.
콜 스택의 실제 사이즈를 초과하면서 브라우저는 다음과 같이 예외를 던지게 됩니다.
싱글 쓰레드에 코드를 실행하는 것은 데드락 같은 멀티 쓰레드 환경에서 발생할 수 있는 복잡한 시나리오를 다루지 않아도 되므로 꽤 쉬울 수 있습니다. 하지만 싱글 쓰레드는 제한적입니다. 자바스크립트는 싱글 콜스택을 가지고 있으므로, 어떤 작업이 느릴때 무슨 일이 일어날까요?
동시성과 이벤트 루프
콜스택에서 작업을 처리하기 위해 엄청난 시간이 걸리는 함수 호출을 가질 때, 무슨 일이 일어날까요? 한 번 상상해 봅시다. 여러분은 브러우저에서 자바스크립트로 복잡한 이미지 변환 작업의 수행을 원합니다.
아마 여러분은 그것이 왜 문제가 되냐고 질문할 수도 있습니다. 문제는 콜 스택에서 함수가 실행되는동안, 브라우저는 어떠한 작업도 수행할 수 없습니다. 블락되어 버립니다. 이 말은 브라우저가 랜더링도 할 수 없고, 다른 코드도 실행할 수 없고 그냥 멈춰있게 된다는 뜻입니다. 이것은 여러분이 만약 앱이 훌륭한 유동성 UI(Fluid UI)를 만들 것이라면 문제가 될것입니다.
이것이 유일한 문제점도 아닙니다. 여러분의 브라우저는 콜스택에 수많은 작업을 처리하기 시작할 것이며, 아마 긴 시간동안 반응이 멈춰버릴 것입니다. 그리고 대부분의 브라우저는 웹페이지를 종료시킬 것인지에 대한 에러를 발생시킵니다.
자, 이런 것이 좋은 유저 경험(UX)은 아닌건 아시겠죠?
그러면 무거운 코드는 어떻게 실행할까요? UI를 블로킹하거나 브라우저를 먹통으로 만들지 않고 실행할 수 있을까요? 해결책은 비동기 콜백입니다.
이것은 자바스크립트는 어떻게 동작할까? 2편(V8 엔진의 내부, 최적화 코드를 작성하는 5가지 이상의 방법)에서 자세히 설명하겠습니다.
역자주: 그리고 blah blah, SessionStack에 대한 홍보를 하십니다. ^_^; 열일하시는군요.
이 시리즈의 번역은 norux.me 에서 계속 됩니다~~~
참조
'Javascript&Typescript > Javascript' 카테고리의 다른 글
자바스크립트 ES6 방식의 모듈 로딩 방식 (import/export) (0) | 2018.01.31 |
---|
- Total
- Today
- Yesterday
- observable
- angular2
- 안시 컬러
- itoa
- 리눅스 터미널 색상
- 챗봇
- Rx.js
- ansi color
- C언어
- ECMA2015
- QT
- Zone.js
- terminal 색
- git proxy
- 스위프트
- ZONES
- 폰트 조정
- git 설정
- zone
- vim
- 우분투 16.04
- Angular
- lua table
- 안시 색상
- qemu linux arm
- JavaScript
- typeScript
- NgZone
- 타입스크립트
- Swift
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |