코딩/Javascript

자바스크립트 작동 원리 Execution Context 설명

드리프트 2022. 4. 5. 22:17
728x170

자바스크립트 Execution Context, Synchronous Single Thread  Language

 

 

 

안녕하세요?

 

오늘은 자바스크립트를 처음 배울 때 한 번쯤은 배우고 지나가면 큰 도움이 될만한 기초 개념을 알아볼 예정인데요.

 

바로 자바스크립트가 작동하는 방식, 작동 원리에 대해 간단히 알아보겠습니다.

 

 

 

자바스크립트를 가장 잘 표현한 영어 문구는 위와 같이 "동기식 싱글 스레드 언어(Synchronous Single-Threaded Language)"가 아닐까 싶은데요.

 

동기식이란 현재의 명령어가 실행 완료가 다돼야 다음 행으로 이동한다는 뜻이며, 동기식이란 말은 특정 순서에 의해 한번에 하나의 명령어만 수행한다는 뜻입니다.

 

지금은 자바스크립트로 비동기식 프로그래밍이 유명한데 무슨 말씀이냐고 하실 수 있는데요.

 

자바스크립트 비동기식, 멀티 쓰레드 관련해서는 다음 시간에 따로 설명할 예정이며,

 

오늘은 자바스크립트가 처음 개발되었을 때의 그 시점 기준으로 자바스크립트의 작동 원리에 대해 알아볼 생각입니다.

 

일단, 동기식, 싱글 스레드라는 점을 명심하고 다음으로 넘어가 보겠습니다.

 

 

자바스크립트의 작동원리에 대해 알려면 위 문구처럼 "실행 콘텍스트(Execution Context)"를 알아야 합니다.

 

자바스크립트의 모든 것은 바로 Execution Context안에 싸여 있다고 말할 수 있으며, 약간은 추상적인 콘셉트로 들릴지 모르겠지만 자바스크립트 모든 코드가 실행되는 주위 모든 환경의 정보를 전부 가지고 있는 커다란 컨테이너? 또는 박스?라고 볼 수 있습니다.

 

Execution Context는 두 가지 단계(Phase)를 가지는데요.

 

하나는 Memory Allocation Phase, 다른 하나는 Code Execution Phase입니다.

 

즉, 메모리 할당 단계와 코드 실행 단계를 가진다고 보시면 됩니다.

 

1. 메모리 할당 단계에서는 자바스크립트의 모든 함수와 변수가 Execution Context의 메모리 컴포넌트 안에 키 밸류(Key-Value) 타입으로 저장되는 단계입니다.

 

이 단계에서는 자바스크립트는 함수 블록 전체를 메모리 블록에 카피하고, 변수일 경우는 placeholder 즉, 변수의 자리를 undefined 타입으로 할당하게 됩니다.

 

2. 코드 실행 단계에서는 그냥 코드 컴포넌트 안에서 한 줄 한 줄 순차적으로 코드가 실행될 뿐입니다.

 

 

 

위 그림을 보시면 쉽게 도식화해서 이해할 수 있을 겁니다.

 

메모리 컴포넌트는 보통 변수 환경(Variable Environment)라고 불리며, 코드 컴포넌트는 실행 스레드(Thread of Execution)이라고 불립니다.

 

그러면, 위에서 개념적으로 설명된 Execution Context를 실제 예를 들어 설명해 보겠습니다.

 

1: var number = 2;
2: function Square (n) {
3:     var res = n * n;
4:     return res;
5: }
6: var newNumber = Square(3);

 

위와 같은 자바스크립트 코드가 실행될 때 Execution Context가 어떻게 구성되는지 하나 하나 따져 보도록 하겠습니다.

 

참고로 위 코드에 행 번호를 추가했습니다.

 

위의 코드를 실행하면 자바스크립트는 Global Execution Context(전역 실행 콘텍스트)를 생성하는데요.

 

그러고 나서 두 가지 단계 중 첫 번째 단계인 메모리 할당 단계가 실행되게 됩니다.

 

메모리 할당 단계는 코드의 처음부터 끝가지 쭉 훑어서 변수와 함수 선언을 찾습니다.

 

그러고 나서 찾은 변수와 함수 선언을 메모리 컴포넌트에 순차적으로 저장하게 됩니다.

 

그래서 위의 코드 1행인 var  number = 2; 란 코드에 의해 number라는 변수가  다음 그림과 같이 Execution Context의 메모리 컴포넌트에 number : undefined라는 키-밸류 타입으로 저장되게 됩니다.

 

자바스크립트의 모든 변수는 메모리 할당 단계에서는 undefined이라는 값을 가지게 됩니다.

 

자, 메모리 할당단계에서 모든 코드의 변수, 함수를 훑어본다고 했었죠.

 

두 번째로 보이는 게 바로 Square 이란 함수입니다.

 

메모리 할당 단계에서는 자바스크립트가 함수를 만나면 위와 같이 메모리 컴포넌트에 함수 이름을 Key 값으로 하고 Value 값으로는 함수 코드 전체를 저장하게 됩니다.

 

함수는 undefined로 할당되지 않고 function..... 형식으로 할당됩니다.

 

그리고 마지막 변수가 남았죠. 바로 newNumber 변수입니다.

 

이 변수도 아까와 마찬가지로 undefined 값으로 저장되게 됩니다.

 

위의 그림이 Execution Context가 발생하고 나서 1단계인 메모리 할당 단계 후의 모양입니다.

 

이제 2단계인 코드 실행 단계입니다.

 

자바스크립트 동기식이며 순차적으로 한 개의 명령어만 실행한다고 처음에 말했었죠.

 

그래서 위의 코드 1행부터 실행하게 됩니다.

 

1행은 var number = 2;라는 코드인데요.

 

메모리는 할당됐으니까 1행의 오른쪽 부분인 = 2 부분이 실행되는데요.

 

바로 number에 2를 할당한다는 얘기입니다.

 

위 그림처럼 메모리 할당 단계에서 undefined로 저장되었던 number 항목이 2라는 숫자 값으로 할당되게 됩니다.

 

1: var number = 2;
2: function Square (n) {
3:     var res = n * n;
4:     return res;
5: }
6: var newNumber = Square(3);

이제 2번째 행으로 코드 실행이 넘어가게 되는데요.

 

2행부터 5행까지는 그냥 함수의 선언입니다.

 

함수의 선언 부분이라 실행되지 않고 그냥 지나가게 됩니다.

 

그래서 코드의 실행은 6행으로 넘어가게 되는데요.

 

6행의 왼쪽 부분은 메모리 할당 단계에서 newNumber : undefined 값으로 할당 저장되었고, 코드의 실행단계에서 보는 부분은 코드의 오른쪽 부분인 Square(3)이라는 명령어입니다.

 

Square라는 함수를 () 괄호를 쳐서 실행했고 파라미터로 3을 넣었습니다.

 

즉, 함수를 실행하고 파라미터로 3을 넣었다고 자바스크립트가 이해하게 됩니다.

 

코드 실행단계에서 함수의 실행 부분을 만나면 자바스크립트는 어떻게 작동할까요?

 

바로 코드 컴포넌트 안에서 또 다른 Execution Context를 생성하고 그 Execution Context 안에서 1단계인 메모리 할당 단계, 그리고 2단계로 코드 실행을 하게 됩니다.

 

즉, 맨 처음 생겼던 Execution Context를 광의의 범위라고 해서 Global Execution Context(글로벌 실행 콘텍스트)라고 부릅니다.

 

그리고 그 안에 또 생긴 Execution Context를 local이라고 부르겠죠.

 

그림으로 표현하면 다음과 같습니다.

 

 

코드 컴포넌트 안에 또 다른 Execution Context가 생겼고 이 Execution Context는 함수 Square에 관한 것으로 먼저 메모리 할당 단계에서는 Square의 파라미터인 n 이 undefined으로 할당됩니다.

 

그리고 Square 함수 안에 있는 또 다른 변수인 res가 또 undefined으로 할당되고요.

 

이제 안쪽에 있는 Execution Context의 코드 실행단계인데요.

 

글로벌 Execution Context에서 Square 함수를 실행할 때 넘겨준 파라미터(인수) number 값을 n으로 대체하게 됩니다.

 

그리고 Square 함수의 n * n 코드를 코드 실행단계에서 실행하게 되고 그 값을 res로 할당하게 됩니다.

그리고 Square 함수의 마지막인 return res; 코드를 만나게 되는데요.

 

자바스크립트는 return 코드가 오게 되면 현재 Execution Context를 끝내고(지우고) 현재의 Execution Context를 호출한 상위 Execution Context로 코드 실행 권한을 옮기게 됩니다.

 

그래서 최종적으로 return 코드가 실행되면 return res;라는 명령어로 res값이 리턴되어 newNumber 값으로 지정되게 됩니다.

 

그리고 Square 함수의 Execution Context는 삭제되게 되는 거죠.

 

 

이제 자바스크립트는 모든 일을 끝냈습니다.

 

만약에 또다시 Square 함수를 실행하는 코드가 나오면 자바스크립트는 또 다른 Execution Context를 코드 컴포넌트 안에 만들고 위에서 설명했던 대로 똑같이 작동한 다음 return 문을 만나면서 Execution Context가 삭제되고 다시 글로벌 Execution Context로 컨트롤 권한이 넘어가는 방식으로 진행되게 됩니다.

 

그래서 Execution Context가 또 다른 Execution Context를 호출하고 삭제하고 하는 방식이 Stack처럼 쌓인다 그래서 전문용어로 Call Stack이라고 부릅니다.

 

위 Call Stack 그림을 보시면 맨 아래에 있는 Global Execution Context가 맨 처음 실행 콘텍스트가 되고 위에 생긴 실행 콘텍스트는 발생된 역순으로 삭제되어 다시 최종적으로는 Global Execution Context만 남게 되는 형식입니다.

 

Call Stack은 다른 말로도 불리는 데요.

 

Execution Context Stack, Program Stack, Control Stack, Runtime Stack, Machine Stack이라고도 불립니다.

 

지금까지 설명한 Execution Context의 작동 원리가 바로 자바스크립트의 작동원리가 되는 겁니다.

 

 

그리드형