개발공부/자바스크립트

[JavaScript] 스터디 13일차_ 2강_실행컨텍스트와 콜스택

햄❤️ 2021. 7. 22. 17:58
728x90

실행컨텍스트(EC)는 자바스크립트 코드가 실행되는 환경을 의미한다.

크게 2가지 타입의 EC가 있다.

 

1) Global Execution context

 - 자바스크립트 엔진이 처음 코드를 실행할 때 Global Execution context 가 생성이 된다. 생성 과정에서 전역객체인 Window Object를 생성하고, this는 Window 객체를 가리킨다.

즉, 아무런 코드가 없어도 자바스크립트 엔진은 파일을 실행시키는 시점에서 Global Execution context를 생성한다.

 

2) Function Execution context 

 - 자바스크립트 엔진은 함수가 호출 될 때마다 호출된 함수를 위한 Execution Context를 생성한다. 모든 함수는 호출되는 시점에 자신만의 Execution Context를 가진다. 

 

 

자바스크립트 엔진은 처음 코드를 실행할 때 단 한번만 Global EC를 생성하고, 함수를 호출할 때 마다 함수의 EC를 생성한다. 

 

Call Stack

코드가 실행되면서 생성되는 EC를 저장하는 자료구조이다. JS엔진이 처음 파일을 실행할 때, Global EC를 생성하고, 이를 Call Stack에 추가한다. 그 후 엔진이 함수를 호출할 때 마다 함수의 EC를 생성해서 Call stack에 추가한다.

 스택의 구조는 입출구가 같아 먼저 들어간 것이 가장 마지막에 나오는 자료 구조(Last in, First out, LIFO)로, 가장 위에 있는 함수를 실행하고 함수가 종료되면 스택에서 제거한다. 그리고 그 다음 위에 있었던 함수로 이동한다. 

 

가령 아래와 같은 코드가 있다면, 콜스택은 어떤 순서로 함수를 실행할까?

function first(){
	console.log("first");
    second();
}

function second(){
	console.log("second");
}

first();

//first 출력
//second 출력

 

EC가 콜스택에서 어떻게 생성되고 사라지는지 그림으로 살펴보자. 

 

1) 제일 처음 자바스크립트 파일이 실행되면 Global EC를 생성하여 Call Stack에 추가

2) 엔진이 first 함수 호출 코드를 발견하고, first 함수의 EC를 생성하고 Call stack에 추가

3) first 함수 내부에서 console.log("fisrt")를 발견하고 이를 위한 EC를 생성하고 Call stack에 추가

4) console.log("first")가 종료되면(콘솔에 찍힌다) Call stack에서 제거

5) second 함수 호출 시, seconde EC를 생성하고 Call stack에 추가

 

 

6) second 함수 내부의 console.log("second") 함수를 발견하고 이를 위한 EC를 생성 후 Call stack에 추가

7) console.log("second") 가 종료되면(콘솔에 second가 찍힌다) Call stack에서 제거

8) Second 함수 종료 후 Call stack에서 제거

9) First 함수 종료 후 Call stack에서 제거

10) 모든 코드 실행이 끝나면 엔진은 Call stack 에서 Global EC를 제거 

 

EC가 생성되는 과정

EC의 생성 과정은 두 단계로 나뉜다. 

 

1) Creation phase (생성단계)

2) Execution phase (실행단계)  

 

자바스크립트 엔진에 의해 파일이 처음 실행되면, 위에서 본 것 처럼 Global EC가 생성되는데, 이 과정에서 Creation과 Excution 두 단계를 거친다.

아래 코드를 실행할 때, 생기는 Global EC의 생성단계, 실행단계를 살펴보자

var name = 'amy';
var age = 18;

function Hiamy() {
    return {
        name: name, 
        age: age
    }
}

Global creation 단계(생성단계)에서 JS 엔진은 아래와 같은 컨텍스트가 실행되기 위해 필요한 여러 정보를 담는 객체를 생성하는데, 이를 활성객체라고 부른다. 활성객체는 엔진 내부에서만 접근할 수 있고 사용자는 접근할 수 없다. 

 - Global Object를 생성하고,

 - this 객체를 생성한다

 - 변수와 함수를 위한 메모리를 준비한다.

 - 변수에는 undefined를 할당하고, 함수 선언문은 실제 메모리에 할당한다.

 

Global execution 단계(실행 단계)에서 JS 엔진은 코드를 한줄씩 실행하고 변수에 실제 값을 할당한다.

console.log(name)    // undefined
console.log(age)     // undefined
console.log(Hiamy) // f Hiamy(){...}

var name = 'amy';
var age = 18;

function Hiamy() {
    return {
        name: name, 
        age: age
    }
}

 

위의 경우, console.log가 실행되는 시점 Global 생성단계는 끝난 시점이며, var로 선언된 변수 age와 name은 undefined를 출력한다. 함수는 메모리에 있는 참조값을 가지고 와서 Hiamy() 함수를 출력한다.

여기서 생성단계로 인한 전역변수 var, 함수 선언문에 대한 hoisting이 발생한다.

environmentRecord에는 현재 컨텍스트와 관련된 식별자 정보 들이 저장되며, 코드가 순서대로 실행되는 것처럼 컨텍스트 내부 전체를 처음부터 끝까지 순서대로 훑어나가며 식별자들을 수집한다. 물론 수집만할 뿐이지 실행시키지는 않는다. 이 때문에 JS 엔진은 함수를 실행하거나 변수를 넣지는 않았지만 모든 곳의 식별자를 이미 알고 있다.

let, const의 경우 생성 단계에서는 어느 값도 가지고 있지 않는다. (var는 undefined로 set)

생성단계에서는 코드의 변수 및 함수 선언을 스캔하고, 변수 중 var는 처음에 정의되지 않는 상태로 설정되고, let과 const는 초기화 되지 않는 상태로 선언된다. 

 

함수 EC의 두 단계(생성, 실행)를 살펴보자.

 

생성단계에서 Function EC와 Global EC는 하나의 차이점만 존재한다.

Function EC는

 - arguments 객체를 생성한다.

 - 변수와 함수를 위한 메모리를 준비한다.

 - (var)변수에는 undefined를 할당하고, 함수 선언문은 실제 메모리에 할당한다.

 

코드를 통해 함수 EC의 생성, 실행단계를 확인해보자

var name = 'amy';
var age = 18;

function Hiamy(food) {
    var height = 166
    return {
        name: name, 
        age: age,
        favoriteFood: food,
    }
}

Hiamy("pizza");

 

자바스크립트 엔진이 Hiamy("pizza")라는 함수 호출 코드를 만나면 이 함수의 EC를 생성한다. 이때의 생성 단계, 실행단계는 아래와 같다. 

함수가 호출되면 생성단계에서 arguments와 this 객체를 생성하고, 내부 변수와 함수에 대해 호이스팅을 수행한다. 실행 단계에서는 코드를 한줄씩 실행하고 변수에 실제 값을 할당한다.

자바스크립트 엔진은 함수를 호출할 때, EC를 생성하고 Call stack에 추가한다. 함수가 종료되면 생성단계, 실행단계가 끝나면 자바스크립트 엔진이 Call stack에서 해당 함수를 제거한다. 

 

 

 


참고자료

https://medium.com/sjk5766/call-stack%EA%B3%BC-execution-context-%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90-3c877072db79

https://darrengwon.tistory.com/267

728x90