[Javascript] 실행 컨텍스트

HJ·2022년 4월 26일
0

Interview prep

목록 보기
9/12

실행 컨텍스트(execution context)

  • 자바스크립트는 실행 컨텍스트가 활성화되는 시점에 선언된 변수를 상단으로 끌어 올리고 (호이스팅), 외부 환경 정보를 구성하고, this 값을 설정하는 등의 동작을 수행하는데 이 과정에서 다른 언어에선 볼 수 없는 현상들이 발생합니다.

    실행 컨텍스트 는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체로, 동적 언어로서의 자바스크립트 성격에 대해 가장 잘 파악할 수 있는 개념입니다.

  • 자바스크립트는 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 콜 스택에 넣었다가 가장 위에 있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장합니다.

  • 하나의 실행 컨텍스트를 구성할 수 있는 방법으로 전역공간, eval(), 함수 등이 있는데 개발자가 흔히 실행 컨텍스트를 구성하는 방법은 함수를 실행하는 방법 뿐입니다.

실행 컨텍스트 더 알아보기

예제 코드

var a = 1;

function outer() {
  function inner() {
    console.info(a); // undefined
    var a = 3;
  }
  
  inner();
  console.info(a); // 1
}

outer();
console.info(a); // 1

상단의 코드를 참고하여 콜 스택에 실행 컨텍스트가 어떤 순서로 쌓이고, 어떤 순서로 코드 실행에 관여하는지는 하단의 그림을 통해 자세히 알아보겠습니다.

  1. 제일 먼저 자바스크립트 코드가 실행되면 전역 컨텍스트가 콜 스택에 담깁니다.
  2. 전역 컨텍스트와 관련된 코드들을 순차로 진행하다가 outer() 라인에서 자바스크립트 엔진은 outer 에 대한 환경 정보를 수집해서 outer 실행 컨텍스트를 생성한 후 콜 스택에 담습니다.
  3. 전역 컨텍스트와 관련된 코드 실행을 일시 중단하고 outer 실행 컨텍스트와 관련된 코드를 실행합니다. (즉 outer 함수 내부 코드)
  4. inner() 라인에서 inner 함수의 실행 컨텍스트가 outer 때와 동일하게 콜스택에 담기게 되고, 자바스크립트는 inner 함수 내부 코드를 진행합니다.
  5. 이어서 내부 함수가 종료되면, inner 는 콜스택에서 제거되고, 순차적으로 outer, 전역 컨텍스트가 제거되게 됩니다.

이렇게 어떤 실행 컨텍스트가 활성화될 때 자바스크립트 엔진은 해당 컨텍스트에 관련된 코드들을 실행하는 데 필요한 환경 정보들을 수집해서 실행 컨텍스트 객체에 저장합니다. 이 객체는 자바스크립트 엔진이 활용할 목적으로 생성되므로 개발자가 코드를 통한 확인은 불가능합니다. 이 객체는 아래와 같은 정보들을 담고 있습니다.

  • VariableEnvironment
    현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보 (선언 시점의 LexicalEnvironment 의 스냅샷이며, 변경 사항은 반영되지 않음)
  • LexicalEnvironment
    처음엔 VariableEnvironment 와 같지만 변경 사항이 실시간으로 반영됨
  • ThisBinding
    this 식별자가 바라봐야 할 대상 객체

VariableEnvironment (변수 환경)

  • 실행 컨텍스트를 생성할 때 VariableEnvironment 에 정보를 먼저 담은 다음, 이를 복사해서 LexicalEnvironment 를 만들고 이후엔 LexicalEnvironment 를 주로 활용하게 됩니다.
  • VariableEnvironment 와 LexicalEnvironment 의 내부는 environmentRecord 와 outerEnvironmentReference 로 구성되어 있습니다.

LexicalEnvironment (사전적 환경)

  • environmentRecord & 호이스팅

environmentRecord 에는 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장됩니다.
식별자에는 컨텍스트를 구성하는 함수에 지정된 매개변수 식별자, 선언한 함수가 있을 경우 그 함수 자체, var 로 선언된 변수의 식별자 등이 해당됩니다.
컨텍스트 내부 전체를 처음부터 끝까지 훑으며 순서대로 수집합니다.

변수 정보를 수집하는 과정을 모두 마쳤어도 아직 실행 컨텍스트가 관여하는 코드들을 실행되기 전 상태이므로, 이는 즉 자바스크립트 엔진이 코드 실행 전 이미 해당 환경에 속한 코드의 변수명들을 모두 알고 있다는 뜻입니다.

위의 말은, 자바스크립트 엔진은 식별자들을 최상단으로 끌어올려 놓은 다음 실제 코드를 실행한다 라고 자바스크립트 엔진 동작 방식을 받아들여도 무방합니다. 이 개념이 호이스팅 입니다.

실제로 끌어 올리는건 아니지만, 자바스크립트 엔진이 끌어 올린 것으로 간주하는 것입니다.

  • OuterEnvironmentReference

OuterEnvironmentReference를 이해하기 위해서는 스코프(scope) 개념을 먼저 이해해야 한다.
스코프란 식별자에 대한 유효 범위를 말한다.
자바스크립트에는 전역 스코프(global scope)와 지역 스코프(local scope)가 있다.

var a = 1;
function scope() {  // 함수 스코프
  var b = 2;
  console.log(a);  // 1
  console.log(b);  // 2
}
console.log(a);  // 1
console.log(b);  // b is not defined

scope 함수 외부에서 선언한 변수 a는 함수 scope 안에서도 접근이 가능하다. 그러나 함수 안에서 선언한 변수 b는 오직 함수 안에서만 접근할 수 있다. 변수 a는 전역 스코프에, 변수 b는 지역 스코프에 있기 때문이다. 자바스크립트는 변수의 유효 범위를 검색할 때 안에서부터 바깥으로 찾아나가는데, 이것을 스코프 체인(scope chain)이라고 한다.
따라서 전역 스코프에 선언된 변수들은 어느 곳에서도 접근이 가능하다. 반면 지역 스코프는 선언된 함수의 내부에서만 접근이 가능하다.

OuterEnvironmentReference는 현재 호출된 함수가 선언되는 시점에서의 Lexical Environment를 참조하는 포인터이다. OuterEnvironmentReference는 연결리스트 형태를 띄며 ‘선언 시점의 LexicalEnvironment’를 계속 찾아 올라간다. '선언 시점의 LexicalEnvironment'라는건 결국 해당 함수가 속한 상위 스코프의 범위이다.
각 함수의 OuterEnvironmentReference는 오직 자신이 선언된 시점의 LexicalEnvironment만 참조하고 있기 때문에 가장 가까운 요소부터 위로 차례대로만 접근할 수 있다.

var outerWrap = function() {
  var a = 1;
  
  var outer = function() {
    var b = 2;
    
    var inner = function() {
      console.log(a, b); // inner의 LexicalEnvironment에는 a와 b가 없지만 스코프 체인을 통해 값에 접근한다.
      console.dir(inner);
    }
    
    inner();
    console.log(a); // outer의 LexicalEnvironment에는 a가 없지만 스코프 체인을 통해 값에 접근한다.
  }
  
  outer();
}

outerWrap();

중첩 구조가 많지만 각 함수들이 자신이 선언된 시점의 상위 LexicalEnvironment를 참조하고 있다는 것만 알면 어렵지 않다. 위의 코드에서 console.dir(inner)로 inner 함수의 계층 정보를 열어보면 [[scopes]] 프로퍼티에서 상위 스코프 정보를 확인할 수 있다.

0번째 스코프에는 함수 outer의 LexicalEnvironment에서 선언된 변수 b와 함수 inner가 있다. 한 단계 올라간 1번째 스코프에는 함수 outerWrap의 LexicalEnvironment에서 선언된 변수 a가 있다. 그 다음 단계로 올라가면 전역 컨텍스트가 노출된다. 이렇게 체인을 통해서 상위 스코프로 접근할 수 있음을 알 수 있다.

참고로, 전역 컨텍스트에서의 OuterEnvironmentReference는 null이다.

출처: https://velog.io/@ggong/자바스크립트의-실행-컨텍스트-execution-context
https://grepper.tistory.com/m/84

0개의 댓글