[JS] 실행 컨텍스트 - 실행 컨텍스트란?

이승혜·2021년 9월 2일
0

JS/JQUERY

목록 보기
3/10
post-thumbnail

이 글은 📕코어 자바스크립트 책을 바탕으로 정리한 글입니다.

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

자바크립트는 어떤 실행 컨텍스트가 활성화되는 시점에 선언된 변수를 위로 끌어올리고(hoisting), 외부 환경 정보를 구성하고, this 값을 설정하는 등의 동작을 수행하는데, 이로 인해 다른 언어에서는 발견할 수 없는 특이한 현상들이 발생한다.

🗄 실행 컨텍스트란?

실행 컨텍스트를 살펴보기 앞서, 스택(stack)큐(queue)의 개념을 살펴보자

스택


스택은 출입구가 하나뿐인 깊은 우물 같은 데이터 구조이다.
비어있는 스택에 순서대로 a,b,c,d,e를 저장했다면, 꺼낼때는 e,d,c,b,a 순서로 꺼낼 수 밖에 없다.
많은 프로그래밍 언어들은 스택이 넘칠 때 에러를 던진다.

let eternalLoop = function () {
  return eternalLoop();
};

eternalLoop();

예를 들어 데이터를 100개만 저장할 수 있는 우물에 100개 이상의 데이터를 넣으려고 한다면 넘치게 된다.
재귀 함수와 같이 함수 안의 함수를 계속 호출하여 스택이 쌓이게 되면 스택이 넘치게 되는데 이 때,

다음과 같은 오류를 던져준다.


한편 큐는 양쪽이 모두 열려있는 파이프를 떠올리면 된다.
종류에 따라 양쪽 모두 입력과 출력이 가능한 큐도 있지만, 보통은 한쪽은 입력만, 다른 한쪽은 출력만을 담당하는 구조를 말한다.
이 경우 비어있는 큐에 순서대로 a,b,c,d를 저장했다면 꺼낼 때도 a,b,c,d의 순서로 꺼낼 수 밖에 없다.

실행 컨텍스트

앞서 실행 컨텍스트를 실행할 코드에 제공할 환경 정보들을 모아놓은 객체라고 했다. 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 콜 스택(call stack)에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장한다.
여기서 '동일한 환경', 즉 하나의 실행 컨텍스트를 구성할 수 있는 방법으로 전역공간, eval() 함수, 함수 등이 있다.
우리가 흔히 실행 컨텍스트를 구성하는 방법은 함수를 실행하는 것이다.

eval(string) 함수?

console.log(eval('2 + 2'));
// expected output: 4

실행 컨텍스트 예제

예제를 통해 실행 컨텍스트를 구성하는 방법을 살펴보자

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

이 때, inner()안의 console.log(a)의 결과가 undefined가 나오는 이유는 var의 hoisting 속성 때문이다. 나중에 자세히 살펴보도록 하자

다음과 같이 처음 자바스크립트 코드를 실행하는 순간(1) 전역 컨텍스트가 콜 스택에 담긴다.
전역 컨텍스트라는 개념은 일반적인 실행 컨텍스트와 특별히 다를 것이 없다.
최상단의 공간은 코드 내부에서 별도의 실행 명령이 없어도 브라우저에서 자동으로 실행하므로, 자바스크립트 파일이 열리는 순간 전역 컨텍스트가 활성화된다고 이해하면 된다

콜 스택에는 전역 컨텍스트 외에 다른 덩어리가 없으므로, 전역 컨텍스트와 관련된 코드들을 순차적으로 진행하다가 (3)에서 outer 함수를 호출하면 자바스크립트 엔진은 outer에 대한 환경 정보를 수집해서 outer 실행 컨텍스트를 생성한 후 콜 스택에 담는다.
콜 스택의 맨 위에 outer 실행 컨텍스트가 놓인 상태가 됐으므로 전역 컨텍스트와 관련된 코드의 실행을 일시중단하고 대신 outer실행 컨텍스트와 관련된 코드, 즉 outer함수 내부의 코드들을 순차로 실행한다.
다시 (2)에서 inner 함수의 실행 컨텍스트가 콜 스택의 가장 위에 담기면 outer 컨텍스트와 관련된 코드의 실행을 중단하고 inner 함수 내부의 코드를 순서대로 진행한다.

inner 함수 내부에서 a 변수에 3을 할당하고 나면 inner 함수의 실행이 종료되면서 inner 실행 컨텍스트가 콜 스택에서 제거된다.
그러면 아래에 있던 outer 컨텍스트가 콜 스택의 맨위에 존재하게 되므고 중단했던 (2)의 다음 줄부터 이어서 실행한다. a 변수의 값을 출력하고 나면 outer 함수의 실행이 종료되어 outer 실행 컨텍스트가 콜 스택에서 제거되고, 콜 스택에는 전역 컨텍스트만 남아있게 된다.
그런 다음 a 변수의 값을 출력하고 나면 전역 공간에 더는 실행할 코드가 남아있지 않아 전역 컨텍스트도 제거되고, 콜 스택에는 아무것도 남지 않은 상태도 종료된다.

이렇게 어떤 실행 컨텍스트가 활성화될 때 자바스크립트 엔진은 해당 컨텍스트에 관련된 코드들을 실행하는 데필요한 환경 정보들을 수집해서 실행 컨텍스트 객체에 저장한다.
이 객체는 자바스크립트 엔진이 활용할 목적으로 생성할 뿐 개발자가 코드를 통해 확인할 수는 없다.
여기에 담기는 정보들은 다음과 같다

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

위 내용들은 다음 페이지에서 다뤄보자

profile
더 높이

0개의 댓글