Execution Context

woolee의 기록보관소·2022년 11월 24일
0

FE개념정리

목록 보기
15/35

실행 컨텍스트란?

Execution Context(흔히 실행 컨텍스트)는 현재 실행 중인 코드와 이를 실행하는 데 도움이 되는 모든 것을 의미한다. JS엔진이 코드를 실행하기 위해서는 코드에 대한 각종 정보가 필요하다.

  • 즉, 코드가 어떤 범위에서 어떤 변수들로, 함수가 있다면 그 함수가 어떻게 어떤 인자로 동작하는지 등등 해당 코드와 관련된 각종 정보들(변수, 함수, scope, this, arguments 등)

실행 컨텍스트의 종류는 세 가지가 있다.

  1. GEC(Global Execution Context) : 전역 컨텍스트. global object를 생성하며 단 1개만 정의된다. 어플리케이션이 실행되면 call stack에 가장 먼저 추가되어 가장 늦게 삭제된다.

  2. FEC(Functional Execution Context) : 함수 컨텍스트. 함수가 실행될 때마다 실행되는 컨텍스트이다. 함수가 실행되면 call stack에 쌓이고, 함수가 종료되면 제거된다.

  3. eval메서드(Eval Context) : 권장하지 않는 컨텍스트.

언제 어떻게 동작하는가?

JS 엔진은 실행 컨텍스트를 관리하기 위한 목적으로 Call Stack(호출스택)을 가지고 있다. JS는 단일 스레드이므로 런타임에 단 하나의 call stack을 갖고 있다.
물론 다중 스레드를 구현할 수 있다

어플리케이션이 실행되면 자동으로 GEC가 가장 먼저 call stack에 쌓인다. 그리고 함수를 실행하면 call stack에 차례대로 쌓인다. ES6+에서부터는 block을 생성해도 call stack에 쌓인다.

call stack은 최대 공간이 한정되어 있으며 이를 초과하면 에러가 발생한다(Stak Overflow).

실행 컨텍스트를 구성하는 것들은?

[1] 컨텍스트가 실행되면 현재 컨텍스트의 각종 정보들이 담긴 environment가 필요하다. 정보들을 알아야 코드를 실행하니까.

이러한 정보가 담긴 Environment는 크게 Lexical Environment와 Variable Environment로 구분할 수 있다. 하지만 사실 Variable Environment는 Lexical Environment을 상속한다. 그러므로 Variable Environment와 Lexical Environment 모두 Lexical Environment라고 말할 수 있다.

사용 가능한 수많은 Lexical Environments이 존재하지만, 그중에서 실행 중인 것만 Execution Context에 의해 관리된다.

자바스크립트에서, Lexical Environment란 코드가 물리적으로 작성되는 곳을 말한다. 아래 코드예제에서 변수 name은 함수 sayName() 내부에 lexically하게 존재한다.

function sayName() {
  let name = 'someName';
  console.log('The name is, ', name);
 }

Variable Environment에는 현재 컨텍스트의 식별자(변수)들에 대한 정보, 외부 환경 정보 등이 담긴다. Variable Environment는 선언 시점의 Lexical Environment을 스냅샷을 의미한다. 그래서 위에서 Variable Environment이 Lexical Environment을 상속한다고 설명한 것이다.

Variable Environment에는 var로 선언된 변수, 선언형 함수가 메모리에 mapping되며 초기값으로 undefined가 할당된다.

Lexical Environment은 현재 컨텍스트의 식별자(변수)들이 실시간으로 변경되는 정보, 외부 환경 정보들이 담긴다. 즉, Variable Environment이 초기값이라면, Lexical Environment은 업데이트값이다.

let, const로 선언된 변수가 메모리에 mapping된다.

[2] 실행 컨텍스트가 어디를 바라보고 있는지가 결정되어야 한다.

각각의 Execution Context는 Environment Record를 포함한다. 자바스크립트 엔진이 코드를 실행하면, 변수와 함수명이 Environment Record에 추가되며, 이를 자바스크립트에서는 Binding이라고 한다.

Binding은 Execution Context에서 identifiers(변수, 함수명)을 this 키워드와 연결하는 데 도움을 준다.

Binding에 대해 더 자세히 알고 싶다면

컨텍스트의 생성-실행 과정

1. Creation Phase

JS 엔진이 함수를 호출했지만 실행이 시작되지 않은 단계를 말한다. Lexical Environment와 Variable Environment의 정의가 이루어진다.

2. Execution Phase

전역 변수에 값을 할당하면서 코드를 실행하는 단계를 말한다.
코드를 읽어나가면서 Environment Record에 저장된 정보들을 수정, 할당 등의 작업을 거치며 어플리케이션을 실행한다. 즉, JS 엔진은 코드를 실행하기 전에 생성단계를 거치면서 이미 정보들을 알고 있는 상태에서 코드를 읽어나간다.

이때 호이스팅 문제는 이렇게 생성단계와 실행단계가 분리되면서 발생하는 걸 말한다. var로 선언된 변수의 경우 생성단계에서 이미 메모리에 매핑되고, 값도 undefined로 할당된다. 반면 let, const는 똑같이 메모리에 매핑되지만 값이 할당되지 않는다.

Scope Chain

outer environment reference는 현재 호출된 함수가 선언될 당시의 Lexical Environment을 참조한다. 식별자의 유효 범위를 안에서 바깥으로 차례대로 탐색하면서 식별자를 찾아나선다.

let title = 'PADO';

function second() { // second 선언 시점 
  console.log('두번째'); // 두번째
  console.log(b); // (error)
} // (3)
function first() { // first 선언 시점 
  let b = 3;
  second(); // (2)
  console.log(title); // PADO
  console.log(name); // undefined (not error)
}

first(); // (1)
var name = 'bibi';

/** 출력 순서 
 * 두번째
 * PADO
 * undefined
 */

생성 단계를 먼저 거쳐서 Lexical Environment와 Variable Environment를 정의한다. 그리고 실행되기를 기다린다.

(1) first 함수가 실행되는 순간 함수 실행 컨텍스트가 되고
call stack에 있는 전역 컨텍스트 위에 first 함수 실행 컨텍스트가 쌓인다. 이때 scope chain이 발생한다. first 함수는 전역 컨텍스트에 접근할 수 있다.

이때 var로 선언된 name 변수는 설령 first 함수가 실행되는 시점보다 뒤에 있지만 var의 경우 생성단계에 undefined로 변수 할당을 같이 해버리므로 오류가 나지 않고 undefined를 반환한다.

(2) 그리고 곧 바로 second 함수가 실행된다. 그러므로 first 함수 실행 컨텍스트 위에 second 함수 실행 컨텍스트가 쌓인다. 이때도 scope chain이 발생한다.

(3) call stack은 LIFO이므로 second 함수 실행 컨텍스트가 종료되고 나면 나머지 first 함수 실행 컨텍스트를 수행한다.

그럼 b는 왜 에러가 나는 걸까?
아래예제 코드를 살펴보면, second 함수 선언 시점에 Lexical Environment에 변수 b가 수집된다. 반면 위 코드는 second 함수 선언 시점에 b가 수집되지 않으므로 에러를 내뱉는 것이다.

let a = 1;
function first() {
  let b = 2;
  function second() {
    let c = 3;
    console.log(a+b+c);
  }
  second();
}
first();

디버깅을 진행하면 더욱 자세하게 scope, call stack 동작 과정을 살펴볼 수 있다.

참고

The JavaScript this Keyword + 5 Key Binding Rules Explained for JS Beginners

[JS]Execution Context와 Call Stack

자바스크립트 실행 컨텍스트

profile
https://medium.com/@wooleejaan

0개의 댓글