자바 스크립트 는 어떻게 작동 하는가 - jaba seukeulibteu neun eotteohge jagdong haneunga

자바스크립트는 여전히 가장 인기있는 언어로 자리매김하고 있고

자바 스크립트 는 어떻게 작동 하는가 - jaba seukeulibteu neun eotteohge jagdong haneunga

자바스크립트는 나에게 첫 언어이고
그렇기에 현재까지 자바스크립트를 기반으로 모든 프로젝트를 진행하였다.

그렇지만 자바스크립트 내부에서 어떻게 동작하는지 고민 해본 적이 있었던가...?

1편에서는 자바스크립트 엔진과 런타임, 콜스택으로 설명!

자바스크립트 엔진(V8)

V8이란 ?

: C++로 작성된 구글의 오픈소스, ECMAScript, WEbAssembly엔진 -> 즉 JS와 WASM을 실행할 수 있는 환경

V8이 수행하는 일

: JS, WASM 코드 컴파일, 실행
: 콜스택 처리(함수 실행)
: 메모리 할당
: 가비지 컬렉션

V8의 실행 과정

자바 스크립트 는 어떻게 작동 하는가 - jaba seukeulibteu neun eotteohge jagdong haneunga

V8엔진 구성

자바 스크립트 는 어떻게 작동 하는가 - jaba seukeulibteu neun eotteohge jagdong haneunga

메모리힙(Memory Heap): 메모리할당이 이루어지는 곳
콜스택(Call Stack): 코드가 실행되면서 스택 프레임이 쌓이는 곳

런타임

브라우저에는 거의 모든 자바스크립트 개발자가 사용하는 API가 존재

자바 스크립트 는 어떻게 작동 하는가 - jaba seukeulibteu neun eotteohge jagdong haneunga

콜스택

자바스크립트는 싱글 쓰레드(single-threaded) 프로그래밍 언어이다. 다시 말하면 콜스택이 하나라는 뜻. 따라서 한 번에 하나의 일만 할 수 있다.

자바스크립트는 어떻게 작동하는가: 엔진, 런타임, 콜스택 개관

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

이 글은 원저자의 허락을 받아 How JavaScript works을 번역한 것입니다.

자바스크립트의 인기는 점점 커지고 있어서 프론트엔드, 백엔드, 하이브리드앱, 임베디드 디바이스 등 다양한 곳에서 사용되고 있습니다.

이번 글은 자바스크립트의 구동 원리를 다루는 시리즈의 첫 번째로서, 자바스크립트가 어떻게 구성되어 있고 구성 요소들이 서로 어떻게 맞물려 돌아가는지를 알아봅니다. 이를 이해함으로써 더 좋은 코드와 앱을 작성할 수 있다고 생각합니다.

깃헛 통계에 나타난 것처럼 자바스크립트는 깃헙에서 활동적인 리포지토리 및 토탈 푸시 부분에서 최고를 기록하고 있습니다. 통계의 다른 부분에서도 크게 뒤쳐저있지 않습니다.

깃헙 언어통계에 대한 최신 정보를 확인하려면 여기를 참고하십시오

프로젝트가 자바스크립트에 많이 의존적인 경우 개발자들은 자바스크립트 및 그 생태계가 지원하는 모든 것을 이용할 수 있어야 합니다. 멋진 소프트웨어를 개발하기 위해서는 내부 동작에 대해 더 잘 이해해야 합니다.

하지만 자바스크립트를 매일 이용하면서도 그 내부는 어떻게 돌아가는지 모르는 개발자들 많이 있습니다.

개관

많은 사람들이 V8엔진에 대해 개념적인 이야기는 들어보았을 것입니다. 또한 자바스크립트가 단일 쓰레드(single-threaded)이고 콜백 큐(callback queue)를 이용한다는 사실도 압니다.

이번 글에서 우리는 이러한 개념을 좀 더 자세히 들여다 보고 자바스크립트가 실제로 어떻게 작동하는지 알아보겠습니다. 이렇게 세밀한 부분을 알게되면 자바스크립트의 API를 이용해 블록킹이 없는, 더 나은 앱을 작성할 수 있게 될 것입니다.

자바스크립트 경험이 상대적으로 적은 개발자라면 이 글은 자바스트립트가 다른 언어와 비교해 ‘왜 이렇게 이상한지’ 이해하는데 도움이 될 것입니다.

또한 경험 있는 개발자라면 매일 같이 이용하는 자바스크립트의 런타임에 대한 새로운 안목을 줄 수 있을 것입니다.

자바스크립트 엔진

자바스크립트 엔진 중 유명한 것이 구글의 V8엔진입니다. V8엔진은 크롬과 노드js에서 사용됩니다. V8엔진을 간단히 표시한 모습은 이렇습니다.

V8엔진은 크게 두 부분으로 구성됩니다.

  • 메모리힙(Memory Heap): 메모리할당이 이루어지는 곳입니다
  • 콜스택(Call Stack): 코드가 실행되면서 스택 프레임이 쌓이는 곳입니다

런타임

브라우저에는 거의 모든 자바스크립트 개발자가 사용하는 API가 있습니다(예를 들면 setTimeout과 같은 것들). 하지만 이들은 엔진이 제공하는 것이 아닙니다.

그렇다면 이것들은 어디에 구현되어 있을까요?

사실은 생각 보다 약간 더 복잡합니다.

자바스크립트의 엔진이 중요하긴 하지만 엔진만으로 모든 것이 이루어지는 것은 아닙니다. 브라우저가 제공하는 웹 API라는 것도 있어서 DOM, AJAX, setTimeout등이 여기에 포함됩니다.

또한 저 유명한 이벤트루프콜백큐도 자기 역할을 하고 있습니다.

콜스택

자바스크립트는 싱글 쓰레드(single-threaded) 프로그래밍 언어입니다. 다시 말하면 콜스택이 하나라는 뜻입니다. 따라서 한 번에 하나의 일만 할 수 있습니다.

콜스택은 기본적으로 우리가 프로그램의 어디에 있는지를 기록하는 자료 구조입니다. 우리가 함수 안으로 들어가는 순간 해당 함수를 이 스택의 제일 위에 놓게됩니다. 이 함수에서 돌아오면 스택의 가장 윗 부분의 것이 제거됩니다. 스택이 할 수 있는 일은 이것 뿐입니다.

예를 들어 보겠습니다. 다음 코드를 살펴봅시다.

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

엔진이 이 코드의 수행을 시작할 때 콜 스택은 비어있는 상태입니다. 이후의 단계는 이렇게 됩니다.

콜스택의 각각은 스택프레임(Stack Frame)이라고 부릅니다.

또한 이것이 예외가 발생했을 때 스택트레이스가 만들어지는 방식입니다. 스택 트레이스란 기본적으로 예외가 발생했을 때 콜스택의 상태입니다. 다시 코드를 살펴 보겠습니다.

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 함수를 호출하는 것부터 시작합니다. 하지만 이 함수는 재귀적이어서 별 다른 종료 조건 없이 자기 자신을 계속해서 호출합니다. 따라서 이러한 실행의 모든 단계에서 동일한 함수가 콜 스택에 반복해서 추가됩니다. 이를테면 이런 그림입니다.

하지만 어느 순간이 되면 콜 스택의 수가 실재 콜 스택의 크기를 넘게 되고 브라우저는 무언가 조취를 취해야겠다고 결정하게 됩니다. 그러면 브라우저가 에러를 던지는데 바로 아래와 같은 모습입니다.

단일 쓰레드를 기반으로 코딩을 하는 것은 어찌보면 참 쉬울 수 있습니다. 예를 들어 데드락(deadlocks)과 같이 멀티쓰레드 기반 환경에서 대처해야 하는 상황을 신경쓰지 않아도 되기 때문입니다.

하지만 단일 쓰레드는 제한점도 많습니다. 자바스크립트는 콜스택이 하나입니다. 그러면 특정 코드 실행이 늦어지면 어떤 일이 벌어질까요?

동시성과 이벤트 루프

만약 콜스택 내에 수행시간이 긴 함수가 있으면 어떤 일이 벌어질까요? 예를 들어 브라우저의 자바스크립트로 복잡한 이미지를 변형을 해야 한다고 생각해보겠습니다.

‘왜 이게 문제이지?’ 라고 물을지도 모르겠습니다. 콜스택에 수행할 함수가 있으면 브라우저는 사실 아무것도 할 수 없다는 게 문제입니다. 바로 ‘블록킹'되는 것입니다. 브라우저는 렌더링을 할 수도 없고 다른 코드를 수행할 수도 없고 그야말로 끼어 있는 상황이 되는 것입니다. 이는 부드러운 UI가 표현 되기를 원하는 경우 문제가 될 수 있습니다.

문제는 또 있습니다. 브라우저는 콜스택 내의 많은 작업을 수행하면서 꽤 긴 시간 동안 응답이 없을 수 있습니다. 그러면 대부분의 브라우저에서 에러를 일으키고 사용자에게 해당 페이지를 닫을지 물어보기도 합니다.

이런 것이 최고의 사용자 경험이라고 할 수는 없겠습니다.

그러면 UI를 막지 않고 브라우저가 응답없음 상태에 빠지게 하지 않으면서도 무거운 코드를 수행하려면 어떻게 해야 할까요? 바로 해결책은 비동기 콜백(asynchronous callbacks)입니다.

이에 대해 파트2 “Inside the V8 engine + 5 tips on how to write optimized code”에서 더 자세히 설명하겠습니다.

그때까지 만약 자바스크랩트 앱에서 일어나는 문제를 재현해내거나 이해하는데 어려움을 겪는 경우 세션스택을 살펴봐주시기 바랍니다. 세션스택은 웹 앱 내의 모든 것을 기록합니다. 모든 DOM 변화와 사용자 상호작용, 자바스크랩트 예외, 스택 트레이스 실패한 네트워크 요청, 디버그 메세지 등이 기록됩니다.

세션스택을 이용하면 웹앱 내의 문제를 비디오 처럼 재생해볼 수도 있고 사용자에게 일어나는 모든 것들을 들여다볼 수 있습니다.

무료로 시험 사용해 볼 수 있는 무료 플랜도 있습니다.