Published on

실행 컨텍스트

Authors
  • avatar
    Name
    Na Hyunwoo
    Twitter

실행 컨텍스트란 ?

실행 컨텍스트란 코드가 실행되기 위해 필요한 환경입니다.

자바스크립트에서 실행 컨텍스트를 만들 수 있는 방법은 다음과 같습니다.

  • 전역 코드
  • Eval 코드
  • 함수 코드
  • 블록문 (ES6 이후)

실행 컨텍스트는 스택 구조를 가집니다. 실행되는 순서대로 콜 스택에 쌓였다가, 가장 위에 쌓여있는 컨텍스트와 관련있는 코드를 실행하는 식으로 동일한 환경과 순서를 보장합니다.

코드를 통해 살펴보겠습니다.

let x = 'x'

function foo() {
  let y = 'y'

  function bar() {
    let z = 'z'
    console.log(x + y + z)
  }
  bar()
}

foo()

위의 코드를 실행하면, 아래 그림과 같이 실행 컨텍스트가 쌓이고 소멸합니다.

execution-context-call-stack
  1. 처음 자바스크립트 코드를 실행하는 순간 전역 컨텍스트가 콜 스택에 담깁니다. 전역 컨텍스트는 애플리케이션이 종료될 때까지 유지됩니다.
  2. foo() 함수가 호출되면, 자바스크립트는 foo()함수에 대한 정보를 수집해서 새로운 실행 컨텍스트를 생성한 후, 전역 컨텍스트 위에 쌓습니다.
  3. foo()함수 실행도중 내부 함수 bar()를 만나면, 자바스크립트는 bar()함수의 실행 컨텍스트를 생성합니다. 이 실행 컨텍스트는 스택의 최상단에 쌓입니다.
  4. 최상단에 쌓인 bar() 함수가 실행을 종료하면 bar() 함수에 의해 만들어진 실행 컨텍스트는 콜 스택에서 제거됩니다.
  5. foo()함수가 실행을 종료하면 foo() 함수에 의해 만들어진 실행 컨텍스트는 콜 스택에서 제거됩니다.

실행 컨텍스트의 구성

실행 컨텍스트는 다음과 같은 구성을 하고 있습니다.

execution-context-composition

실행 컨텍스트를 생성할 때, Variable Environment에 정보를 먼저 담은 후 이를 그대로 복사해서 Lexical Environment를 만들고 이후에 Lexical Environment를 주로 활용하게 됩니다.

Variable Environment

  • 현재 컨텍스트 내의 식별자들에 대한 정보외부 환경 정보선언 시점의 스냅샷으로 저장됩니다. 실행중에도 변경사항이 반영되지 않으며 초기 상태를 유지합니다.
  • Environment Record와 Outer Environment Reference로 이루어져 있습니다.

Lexical Environment

  • Variable Environment와 동일하지만 변경 사항이 실시간으로 반영됩니다.
  • Environment Record와 Outer Environment Reference로 이루어져 있습니다.

ThisBinding

  • this 식별자가 바라보고 있는 대상 객체입니다.

Variable Environment와 Lexical Environment는 식별자를 정의하는데 사용하는 객체입니다. 일반적으로 함수의 Lexical Environment는 해당 함수가 가지는 자신의 로컬 스코프 범위를 말합니다.

Variable Environment와 Lexical Environment는 Environment Record와 Outer Environment Reference로 이루어져 있습니다.

execution-context-lexical

Environment Record

컨텍스트와 관련된 코드의 식별자 정보들이 저장됩니다. 호이스팅이 일어난 변수와 함수등의 식별자 정보가 이곳에 저장됩니다.

Outer Environment Reference

호출된 함수가 선언될 당시의 Lexical Environment를 참조하는 포인터로 스코프 체인을 가능하게 합니다.

Outer Environment Reference

Outer Environment Reference는 현재 호출된 함수가 선언되는 시점에서의 Lexical Environment를 참조하는 포인터입니다. 여기서 기억해야할 점은 함수가 선언되는 시점에서의 Lexical Environment입니다.

execution-context-scope-chaining

각 함수의 Outer Environment Reference는 변수의 유효 범위를 검색할 때 가장 가까운 요소부터 바깥으로 찾아나가는데, 이것을 스코프 체인이라고 합니다.

const outerWrap = function () {
  let a = 1

  const outer = function () {
    let b = 2

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

    inner()
    console.log(a) // outer의 LexicalEnvironment에는 a가 없지만 스코프 체인을 통해 값에 접근한다.
  }

  outer()
}

outerWrap()

console.dir(inner)를 통해 inner 함수의 계층 정보를 열어보면 [[scopes]] 프로퍼티에서 상위 스코프 정보를 확인할 수 있습니다.

execution-context-scopes

참고로 전역 컨텍스트에서의 Outer Environment Reference는 null입니다.

ThisBinding

실행 컨텍스트의 thisBinding에는 this로 지정된 객체가 저장됩니다. 자바스크립트에서 this는 굉장히 광범위하기 때문에 따로 포스팅으로 다루겠습니다.

정리

자바스크립트에서 실행 컨텍스트코드를 실행하기 위해 필요한 정보들을 가진 범위를 객체 형태로 나타낸 것입니다.

실행 컨텍스트를 구성하는 Lexical Environment식별자를 정의하는데 사용하는 객체입니다.

Lexical Environment는 식별자들에 대한 정보를 담은 Environment Record와 상위 Lexical Environment를 참조해 스코프 체인을 가능하게 하는 Outer Environment Reference로 구성되어 있습니다.

부록

식별자

  • 자바스크립트에서 이름을 붙일 때 사용하는 단어
  • 변수명, 함수명, 속성명, 메서드명
let hyunwoo = 3 // 여기서 식별자는 hyunwoo 이다.

스코프

  • 식별자에 대한 유효범위
  • 전역 스코프, 지역 스코프가 있다.

Environment Record

Environment Record에는 현재 컨텍스트와 관련된 식별자 정보들이 저장됩니다.

Environment Record는 현재 실행될 컨텍스트의 대상 코드 내에 어떤 식별자들이 있는지 만을 먼저 수집하기 때문에, 식별자만 끌어올리고 할당 과정은 원래 자리에 남겨둡니다. 호이스팅이 일어난 변수와 함수들은 이 Environment Record에 저장되는 것입니다.

execution-context-environment-record

Declarative Environment Record

  • 스코프 내에서 식별자들의 바인딩을 관리합니다.
  • Function Environment Record
    • 화살표 함수가 아닐경우 thist, super에 대한 정보를 담고 있습니다.
  • Module Environment Record

Object Environment Record

Global Environment Record

레퍼런스

자바스크립트 함수(3) - Lexical Environment : NHN Cloud Meetup

식별자 찾기 모험

자바스크립트의 실행 컨텍스트 (execution context)

[10분 테코톡] 💙 하루의 실행 컨텍스트