실행 컨텍스트

</>·2022년 3월 4일
4
post-thumbnail

목표

  • 23장의 내용을 최대한 이해하고 정리하기

23. 실행 컨텍스트(execution context)


23-1. 실행 컨텍스트를 왜 알아야 할까?

  • 실행 컨텍스트를 이해하면 다음과 같은 방식을 이해할 수 있다.
    • 자바스크립트가 스코프를 기반으로 식별자와 바인딩된 값을 관리하는 방식
    • 호이스팅이 발생하는 이유
    • 클로저의 동작 방식
    • 태스크 큐(task queue)와 함께 동작하는 이벤트 핸들러, 비동기 처리 방식

23-2. 소스코드의 타입

  • 실행 컨텍스트를 이해하기 전에 알아두어야 할 것이 있다.
  • ECMAScript 사양은 소스 코드를 4가지 타입으로 구분한다.
    1. 전역 코드
    2. 함수 코드
    3. eval 코드
    4. 모듈 코드
  • 소스 코드를 4가지 타입으로 구분하는 이유는 타입에 따라 실행 컨텍스트를 생성하는 과정과 관리 내용이 다르기 때문이다.

23-2-1. 전역 코드

  • 전역 코드는 전역 변수를 관리하기 위해 최상위 스코프인 전역 스코프를 생성해야 한다.
  • 그리고 전역 변수와 전역 함수를 전역 객체 프로퍼티와 메서드로 바인딩하고 참조하기 위해 전역 객체와 연결한다.
  • 전역 코드가 평가되면 전역 실행 컨텍스트가 생성된다.

23-2-2. 함수 코드

  • 함수 코드는 지역 스코프를 생성하고 지역 변수, 매개 변수, arguments 객체를 관리한다.
  • 그리고 생성한 지역 스코프를 전역 스코프에서 시작하는 스코프 체인의 일원으로 연결해야 한다.
  • 함수 코드가 평가되면 함수 실행 컨텍스트가 생성된다.

23-2-3. eval 코드

  • eval 코드는 strict mode에서 자신만의 독자적은 스코프를 생성한다.
  • eval 코드가 평가되면 eval 실행 컨텍스트가 생성된다.

23-2-4. 모듈 코드

  • 모듈 코드는 모듈별로 독립적인 모듈 스코프를 생성한다.
  • 모듈 코드가 평가되면 모듈 실행 컨텍스트가 생성된다.



23-3. 소스코드의 평가와 실행

  • 자바스크립트 엔진은 소스코드를 2개의 과정으로 나누어 처리한다.
    1. 소스코드의 평가
    2. 소스코드의 실행

23-3-1. 소스코드의 평가

  • 평가 과정에서는 실행 컨텍스트를 생성 하고 변수, 함수 등의 선언문만 먼저 실행하여 생성된 변수나 함수 식별자를 키로 렉시컬 환경의 환경 레코드(실행 컨텍스트가 관리하는 스코프)에 등록한다.

23-3-2. 소스코드의 실행

  • 평가 과정이 끝나면 선언문을 제외한 소스코드가 순차적으로 실행(런타임)된다.
  • 소스코드 실행에 필요한 정보(변수나 함수의 참조 등)는 실행 컨텍스트가 관리하는 스코프에서 검색해서 취득한다.


23-3-3. 예제

  • 변수를 선언해 값을 할당하는 소스코드를 예로들면,
var x;
x = 1;
  • 자바스크립트는 평가와 실행 2개의 과정으로 나누어 처리한다.
  • 평가 과정에서는 변수 선언문인 var x; 를 먼저 실행하고 실행 컨텍스트가 관리하는 스코프에 등록해 undefined로 초기화한다.

  • 평가 과정이 끝나면 런타임이 실행되고 x = 1;이 실행된다. 이 때, 변수에 값을 할당하려면 변수 x가 이미 선언되었는지 확인해야 하므로 실행 컨텍스트가 관리하는 스코프를 참조해 선언되었다면 실행 컨텍스트에 등록하여 관리한다.


23-4. 실행 컨텍스트의 역할

const x = 1;
const y = 2;

function foo(a) {
  const x = 10;
  const y = 20;
  
  console.log(a + x + y);
}

foo(30);

console.log(x + y);

// 결과
60
3

23-4-1. 전역 코드 평가

  • 전역 코드를 실행하기 전 선언문만 먼저 실행하는 평가 과정을 거친다.
  • 따라서, 변수 선언문과 함수 선언문이 먼저 실행되고, 그 결과 생성된 전역 변수와 전역 함수가 실행 컨텍스트가 관리하는 전역 스코프에 등록된다.
  • 위 코드에서는 변수 x와 y, 함수 foo 가 먼저 실행되고 전역 스코프에 등록된다.

23-4-2. 전역 코드 실행

  • 전역 코드 평가 과정이 끝나면 런타임이 시작된다. 이 때, 전역 변수에 값이 할당되고 함수가 호출된다.
  • 함수가 호출되면 순차적으로 실행되던 전역 코드의 실행을 일시 중단하고 함수 내부로 진입한다.
  • 위 코드에서는 전역 변수 x와 y에 값이 할당되고 foo 함수 내부로 진입한다.

23-4-3. 함수 코드 평가

  • 함수 내부로 진입하면 함수 내부의 문들을 실행하기 앞서 함수 평가 과정을 거치며 함수 코드를 실행하기 위한 준비를 한다.
  • 이 때, 매개변수와 지역 변수 선언문이 먼저 실행되고, 그 결과 생성된 매개변수와 지역 변수가 실행 컨텍스트가 관리하는 지역 스코프에 등록된다.
  • 또한, 함수 내부에서 지역 변수처럼 사용할 수 있는 arguments 객체가 생성되어 지역 스코프에 등록되고 this 바인딩도 결정된다.
  • 위 코드에서는 매개변수, 함수 내부 변수 x와 y가 지역 스코프에 등록된다.

23-4-4. 함수 코드 실행

  • 함수 코드 평가 과정이 끝나면 런타임이 시작된다. 이 때, 매개 변수와 지역 변수에 값이 할당된다.
  • 위 코드에서는 매개변수와 함수 내부 변수 x와 y에 값이 할당되고 console.log 메서드를 호출한다.
  • console.log 메서드를 호출할 때, 식별자인 console을 스코프 체인을 통해 검색한다.
  • 지역 스코프에서부터 상위 스코프인 전역 스코프를 연결해서 검색하는데 console 식별자는 스코프 체인에 등록되어 있는 것이 아닌 전역 객체의 프로퍼티로 존재한다.
  • 이는 전역 객체의 프로퍼티도 전역 변수처럼 검색이 가능하다는 것을 의미한다.
  • console 식별자를 찾으면 log 프로퍼티를 console 객체의 프로토타입 체인을 통해 검색한다.
  • 그 후, 인수로 전달된 표현식 a+x+y 가 평가되고 a, x, y 식별자는 스코프 체인을 통해 검색된다.
  • console.log 메서드의 실행이 종료되면 함수 코드 실행 과정이 종료되고 함수 호출 이전으로 되돌아가 전역 코드 실행을 계속한다.

23-4-5. 정리

  1. 선언에 의해 생성된 모든 식별자(변수, 함수, 클래스 등)를 스코프를 구분하여 등록하고 상태 변화(식별자에 바인딩된 값의 변화)를 지속적으로 관리할 수 있어야 한다.
  2. 스코프는 중첩 관계에 의해 스코프 체인을 형성해야 한다. 즉, 스코프 체인을 통해 상위 스코프로 이동하며 식별자를 검색할 수 있어야 한다.
  3. 현재 실행 중인 코드의 실행 순서를 변경할 수 있어야 하며 다시 되돌아갈 수도 있어야 한다.
  • 이 모든 것을 관리하는 것이 바로 실행 컨텍스트이다.
  • 실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다.
  • 식별자와 스코프는 실행 컨텍스트의 렉시컬 환경으로 관리하고 코드 실행 순서는 실행 컨텍스트 스택으로 관리한다.

23-5. 실행 컨텍스트 스택

const x = 1;

function foo () {
  const y = 2;
  function bar () {
    const z = 3;
    console.log(x + y + z);
  }
  bar();
}

foo();

// 결과
6
  • 위 예제는 전역 코드와 함수 코드로 이루어져 있다.
  • 자바스크립트 엔진은 먼저 전역 코드를 평가해 전역 실행 컨텍스트를 생성한다.
  • 그리고 함수가 호출되면 함수 코드를 평가하여 함수 실행 컨텍스트를 생성한다.
  • 이 때, 생성된 실행 컨텍스트는 스택 자료구조로 관리된다. 이를 실행 컨텍스트 스택이라 한다.


23-6. 렉시컬 환경

  • 렉시컬 환경(Lexical Environment)은 식별자와 식별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트이다.
  • 실행 컨텍스트 스택이 코드의 실행을 관리한다면 렉시컬 환경은 스코프와 식별자를 관리한다.
  • 렉시컬 환경은 키와 값을 갖는 객체 형태의 스코프(전역, 함수, 블록 스코프)를 생성하여 식별자를 키로 등록하고 식별자에 바인딩된 값을 관리한다.
  • 렉시컬 환경은 두 개의 컴포넌트로 구성된다.
    1. 환경 레코드(Environment Record)
    2. 외부 렉시컬 환경에 대한 참조(Outer Lexical Environment Reference)


23-6-1. 환경 레코드

  • 스코프에 포함된 식별자를 등록하고 등록된 식별자에 바인딩된 값을 관리하는 저장소이다.
  • 환경 레코드는 소스코드의 타입테 따라 관리하는 내용에 차이가 있다.

23-6-2. 외부 렉시컬 환경에 대한 참조

  • 외부 렉시컬 환경에 대한 참조는 현재 스코프의 상위 스코프를 가리킨다.
  • 이 참조를 통해 단방향 링크드 리스트인 스코프 체인을 구현한다.
profile
개발자가 되고 싶은 개발자

0개의 댓글