[Javascript] JS는 어떻게 동작할까?

Dongjun Ahn·2022년 7월 11일
0

Javascript?

웹페이지에 생동감을 불어넣기 위해 만들어진 프로그래밍 언어
자바스크립트로 작성한 프로그램을 스크립트라고 부름 이러한 스크립트는 웹페이지의 HTML안에 작성될 수 있는데, 웹페이지를 불러올 때 스크립트가 자동으로 실행됨.

Javascript Engine V8

V8 엔진은 구글이 주도하여 C++로 작성된 고성능의 ECMAScript와 & Web Assembly 엔진이다. 즉 JS와 WASM을 실행할수 있는 환경!!
대표적으로 Chrome, Node.js에서 사용

V8이 수행하는 일

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

Memory Heap

데이터를 임시 저장하는 곳으로, 함수나 변수, 함수를 실행할 때 사용하는 값들을 저장한다.

Call Stack

코드가 실행되면 코드의 내부의 실행 순서를 기록해 놓고, 하나씩 순차적으로 진행할 수 있도록 도와준다.
자바스크립트는 한 번에 한 가지 일 밖에 처리할 수 없는 싱글 쓰레드 언어. (Call stack이 하나)


function multiplyNumber(num1, num2) {
	return num1 * num2;
}

function printSquare(x) {
	let n = multiplyNumber(x, x);
	console.log(n);
}

printSquare(5);

위 함수를 실행하면 아래와 같은 Call Stack 이 생성된다.

만약에 Call Stack에 들어간 코드 중 일부가 시간이 오래 걸린다면 어떻게 될까?

노랑색으로 칠해진 코드가 시간이 오래걸리게 된다면 당연히 다음에 호출되어야 코드는 실행에 시간이 걸릴 수 밖에 없다. 이와 같은 상황이 다른 코드를 실행하지 못하게 되어 block이 된 상태이다.
이 때 효과적으로 event를 관리하기 위해 필요한 것이 바로 Web APICallback Queue, Event Loop이다.

런타임

자바스크립트 엔진 밖에서도 자바스크립트에 관여하는 요소들이 있다.
Web API, Task Queue, Event Loop등이다. 런타임은 특정 언어로 만든 프로그램들을 실행할 수 있는 환경이다. Node.js나 크롬등의 브라우저들은 자바스크립트가 구동되는 환경이기 때문에, 이를 자바스크립트 런타임이라고 한다.

Web Api

Web API는 브라우저에서 제공되는 API이다. 자바스크립트 엔진에서 정의되지 않았던 setTimeout이나 HTTP 요청(ajax) 메소드, DOM 이벤트 등의 메소드를 지원한다.

Callback Queue(Task Queue)

이벤트 발생 후 호출되어야 할 콜백 함수들이 기다리는 공간. 이벤트 루프가 정한 순서대로 줄을 서 있으므로 콜백 큐(Callback Queue) 라고도 한다.

Event Loop

Event Loop는 Call Stack과 Callback Queue의 상태를 체크하여, Call Stack이 빈 상태가 되면, Callback Queue의 첫번째 콜백을 Call Stack으로 밀어넣는다.
이러한 반복적인 행동을 틱(tick) 이라 부른다.

console.log('시작!');
setTimeout(function timeout(){
	console.log('1초가 지났습니다');
});
console.log('끝!');

---------------------

시작! 
끝!
1초가 지났습니다
  1. 처음 코드를 실행하면 console.log(‘시작’)코드가 call stack에 들어가게 되고 실행된다.
  2. Call Stack에 setTimeout 함수가 들어간다.
  3. setTimeout 함수가 비동기 함수이기 때문에 Call Stack 에서 바로 실행되지 않고, web API로 콜백 함수 timeout()이 들어 간다.
  4. 다음 코드인 console.log('끝!');을 실행한다. 아직 1초가 지나지 않아 timeout() 함수는 여전히 web API에 있다.
  5. 1초가 지나 callback Queue에 timeout()함수가 들어 옵니다.
  6. event loop가 Call Stack이 비어있는지 확인하고, timeout() 함수를 call Stack으로 보낸다.
  7. timeout 함수 안에 있던 console.log(‘1초가 지났습니다’) 코드가 호출된다.
  8. 모든 함수가 호출되고 Call Stack이 비워진다.

결과적으로 event loop는 Call Stack 비어있는지를 주기적으로 확인하여 Callback Queue에서 Callback function을 가져와 Call Stack에서 Javascript 코드가 실행될 수 있도록 돕는 역할을 한다.

Memory Heap and Call Stack Throw

Stack trace

스택 트레이스란 기본적으로 예외가 발생했을 때 Call Stack의 상태

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

만약 이 코드를 크롬에서 실행하면(이 파일이 foo.js라는 파일에 들어 있다고 했을 때) 다음과 같은 스택트레이스가 생성된다.

Stack Overflow

Call Stack이 최대 크기에 다다랐을 때 나타난다. 보통 재귀함수를 잘못 실행 시에 발생한다.(콜 스택의 최대치는 브라우저마다 다르다)

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


무한정 스택에 정보를 쌓을 수 없기 때문에 브라우저는
Maximum call stack size exceeded 오류를 뱉어낸다.

동시성(Concurrency)

호출 스택에 처리 시간이 어마어마하게 오래 걸리는 함수가 있으면 호출 스택에서 해당 함수가 실행되는 동안 브라우저는 아무 작업도 못하고 대기 상태가 된다. 이 말뜻은 브라우저는 페이지를 그리지도 못하고, 어느 코드도 실행을 못하게 되어, 말 그대로 그냥 가만히 있게되어 문제가 된다.
브라우저가 호출 스택의 정말 많은 작업들을 처리하다 보면 화면이 아마 오랫동안 응답하지 않게 되어 대부분의 브라우저가 아래와 같은 에러를 띄우면서 페이지를 종료할 건지 물어본다.

이렇게 렌더링에 방해받지않고 브라우저의 응답도 끊지 않으면서 연산량이 많은 코드를 실행할 수 있는 방법은 비동기 콜백 이다.

Garbage Collector(GC)

콜스택과 메모리 힙을 배우면서 각각의 공간은 무제한이 아니고 한정적임을 알 수 있다.
공간이 무한정 하다면야 크게 효율성에 대해서 고려하지 않을 수도 있지만, 콜스택과 메모리 힙은 언제나 한정적이기 때문에 이를 효율적으로 관리할 필요가 있다.

자바스크립트는 이 공간을 효율적으로 관리하기 위해서, 더 이상 효용가치가 없다고 판단되는 변수, 함수 등을 함수 실행 종료 후 메모리 힙에서 제거하는 동작을 수행한다.
필요한 데이터만 메모리 힙에 저장함으로써 메모리를 더욱 여유롭게 관리한다. 따라서 자바스크립트는 Garbage Collected Language라고 말할 수 있으며, 이러한 역할을 수행해주는 도구를 Garbage Collector라고 한다.

Reference

https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf?gi=3ee6e5715c10

profile
Front-end Developer

0개의 댓글