Skip to content

자바스크립트 사용법 엔진, 런타임, 호출스택

Dia edited this page Apr 2, 2019 · 1 revision

자바스크립트는 많은 인기와 관심이 많아지면서 프론트엔드, 백엔드, 하이브리드앱, 임베디드 디바이스 등등 높은 레벨에 대한 활용을 지지하고 있다 더 좋은 코드를 작성하기 위해 좀 더 깊게 자바스크립트를 이해하기 위한 문서!

경쟁력을 유지하기 위해 성능이 우수해야 하는 SessionStack을 구축할 때 사용하는 몇 가지 규칙이 있다

GitHut에서도 보듯 자바스크립트는 Github 의 Active Repositories 와 Total Pushes에서 1위를 차지하고 있습다. 다른 범주에서도 크게 뒤떨어져 있지는 않죠.

(최신 GitHub 언어 순위)

프로젝트가 자바스크립트의 의존도가 높다면 좋은 소포트웨어를 만들기 위해 언어에 대해 깊이 이해를 해야하고 언어적 특성과 내부 구조를 정확하게 이해해야 한다. 많은 자바스크립트 개발자들이 매일 자바스크립트를 사용하고 있지만 실제로 기본적인 동작원리가 어떻게 일어나는지 알지 못하는 개발자가 많다고 한다


Overview

아마 모든 사람들이 V8엔진에 대해 들어보았고 대부분의 사람들이 자바스크립트는 싱글쓰레드 언어거나 콜백 큐를 사용하는걸 알고있다.

해당 포스트는 모든 개념을 살펴보고 자바스크립트가 어떻게 실행되는지 알아보도록 하고, 이 글을 다 읽고 나면 자바스크립트 내장 API를 효율적으로 사용하는 non-blocking 앱을 구현할 수 있을것이다.

만약 자바스크립트에 비교적 익숙하지 않다면 왜 다른 언어에 비해 이상한 언어인지 깨닫게 될 것 이다. 숙련된 자바스크립트 개발자라면 여러분이 매일 사용하는 자바스크립트 런타임 작동 방식에 대한 새로운 통찰력을 얻을 수 있을 것이다.


The JavaScript Engine

대표적인 예로 자바스크립트 엔진으로 구글의 V8엔진을 꼽는다. V8엔진은 크롬과 Node.js 내부에서 사용이 된다.

엔진은 다음 두 가지 주요 구성 요소로 구성된다.

Memory Heap - 메모리 할당이 이루어 지는 곳

Call Stack — 코드 실행에 따라 호출 스택이 쌓이는 곳


The Runtime

모든 자바스크립트 개발자가 setTimeout 같은 브라우저 내장 API를 사용하게 된다. 엔진에 의해 제공되지 않는다

그럼 도대체 어디서 오는걸까?

사실 좀 더 복잡하다.

자바스크립트 엔진 이외에도 관여해야할 것이 많다. DOM, AJAX, setTimeout과 같이 브라우저 내장 API를 Web API라고 한다. 그리고 event loop, callback queue도 있다


The Call Stack

자바스크립트는 싱글쓰레드 프로그래밍 언어이다. 호출스택이 하나이다. 따라서 한 작업에 하나만 처리할 수 있다. 호출스택은 프로그래밍에서 어디에 있는지 기록하는 자료구조이다. 함수를 실행하면 호출스택의 맨 위에 놓인다. 함수의 실행이 끝나면 호출스택에서 제거를 하는게 스택의 역할이다.

아래코드를 보자.

function multiply(x, y) {
    return x * y;
}
function printSquare(x) {
    var s = multiply(x, x);
    console.log(s);
}
printSquare(5);

엔진이 실행하는 시점에서 호출스택은 비워져있다. 나중에 코드가 실행이 되면서 호출스택은 아래와 같이 변하게 된다

호출스택의 단계를 Stack Frame이라 부른다.

예외케이스가 발생했을 때 나타나는 Stack Trace가 만들어지고 있는 방법이다. 즉, 예외가 발생했을 때 기본적으로 호출스택의 상태를 의미한다

아래코드를 보자.

function foo() {
    throw new Error('SessionStack will help you resolve crashes :)');
}
function bar() {
    foo();
}
function start() {
    bar();
}
start();

위의 코드가 foo.js에 있다고 가정하고 크롬에서 실행이 된다면

호출스택이 최대크기가 되면 일어나면 “스택을 날려버린다.” 특히 광범위하게 테스트하지 않고 재귀법을 사용했을 때 쉽게 일어난다

아래코드를 보면

function foo() {
    foo();
}
foo();

엔진에서 위의 코드를 실행할때 foo()를 부르면서 시작한다. 하지만 그 함수는 재귀로 종료 없이 재호출을 하게 된다. 그래서 실행 단계마다 동일한 기능이 호출스택에 반복적으로 추가된다. 아래의 예시처럼!

그러나 어느 순간, 호출스택의 함수 호출 수가 호출스택의 실제 크기를 초과하고 브라우저가 오류를 발생시킴으로써 조치를 취하기로 결정한다. 아래와 같은 에러를 발생한다. (Stack overflow)

멀티쓰레드에서 발생하는 복잡한 시나리오에 대해 고민 하지 않아도 되기때문에 싱글쓰레드에서 코드를 실행하는 것은 쉬울 수 있다. 예를 들어 데드락이 있다 그러나, 싱글쓰레드에서 코드를 실행하는 것은 제약이 많다. 자바스크립트는 싱글 호출스택을 갖고 있기 때문이다. 그럼... 자바스크립트 실행이 느리면 어떻게 될까?


Concurrency(동시성) & the Event Loop (이벤트루프)

호출스택에서 엄청 많은 시간이 걸리는 함수 실행이 되면 처리하기 위해 얼마만큼의 시간을 소요할까? 예를들어 브라우저에서 자바스크립트로 복잡한 이미지 변환작업을 실행하려고 한다

'그게 뭐?'라는 생각을 할 수 있다. 호출스택에서 함수가 실행되는 동안 브라우저는 아무 작업도 하지 않고 대기 상태가 된다. 브라우저가 렌더링할 수 없고, 다른 코드를 실행할 수 없으면 그냥 가만히 있는 것을 의미한다. 만약 자연스러운 UI의 앱을 만들고 싶을 때엔 이 경우가 문제가 된다.

문제는 이것만이 아니다. 브라우저가 호출스택을 많은 작업 실행 했을 때 오랫동안 멈춰있을 것이다. 그리고 브라우저가 에러를 보내는데 페이지를 종료할 것 인지 물어볼 것이다.

자, 이 경우는 좋은 사용자 경험은 아니죠?

그렇다면 UI를 차단하지 않고 브라우저가 응답을 끊지 않으면서 여러가지 코드를 실행할 수 있을까? 그 해결책은 비동기식 콜백이다.

"실제로 Javascript가 작동하는 방법" Part2에서 자세하게 설명 된다: “Inside the V8 engine + 5 tips on how to write optimized code”.


문제를 재현하고 이해하기 어려울 때 SessionStack을 봐라. SessionStack은 모든 DOM의 변경사항, 사용자 상호 작용, Javascript 에외, Stack traces, 네트워크 실패시 Requests, 디버그에 대해 기록한다. SessionStack을 사용하면 웹 앱의 문제를 비디오로 재생하고 사용자에게 발생한 모든 것을 볼 수 있다. 무료다. Get started now. (이건 지워도 되지 않을까.. -디아왈)


출처: How JavaScript works: an overview of the engine, the runtime, and the call stack

느낀점

너무 다행히도 '재귀'라는 단어처럼 어려운 단어 외에는 문장 자체가 어려운 문장은 없어서 해석은 쉬웠던 것 같다. 좋은 내용이였지만, 좀 더 내용이 보강되었으면 좋겠다는 생각을 했다. 이 부분은 다른 스터디원들이 해석해준 내용을 보면 좀 더 보강이 될 것 같다.

Clone this wiki locally