반응형

실행 컨텍스트 (Execution Context)


실행 컨텍스트란?
실행할 코드에 제공할 환경 정보들을 모아놓은 객체로서, JavaScript 의 동적언어의 성격을 가장 잘 나타내는 개념이다.
JavaScript 는 어떤 실행 컨텍스트가 활성화되는 시점에 선언된 변수를 위로 끌어올리고(호이스팅의 개념), 외부 환경 정보를 구성하고, this 값을 설정하는 등의 동작을 수행한다.

 
실행 컨텍스트라는 개념을 이해하는 것은 개발자의 성장으로서 가장 중요한 핵심이니 꼭 이해하고 넘어가도록 하자.
실행 컨텍스트를 이해하기 전 스택(stack)  과 큐(queue) 의 개념부터 살펴보자.

스택(stack) 은 출입구가 하나뿐인 깊은 우물같은 데이터 구조이다.
비어있는 스택에 순서대로 데이터 a, b, c, d 를 저장한 후 꺼낼 때에는 반대로 d, c, b, a 순서로 꺼낼 수 밖에 없다.
4개만 저장할 수 있는 우물에 4개 이상을 저장하면 넘치게되는 것을 overflow 라고 한다. (스택오버플로우라는 사이트가 생각난다)

큐(queue) 는 양쪽이  모두 열려있는 파이프이다.
비어있는 큐에 순서대로 데이터 a, b, c, d 를 저장했다면 꺼낼때에도 a, b, c, d 순서대로 꺼낼 수 밖에 없다.

 

 

앞서 언급했듯이, 실행 컨텍스트를 실행할 코드에 제공할 환경 정보들을 모아놓은 객체라고 했는데,
동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 콜 스택(Call Stack)에 쌓아올렸다가, 
가장 위에 쌓여있는 컨텍스트와 관련이 있는 코드들을 실행하는 방식으로 전체 코드의 환경과 순서를 보장한다.

동일한 환경이란 쉽게 설명하자면, 하나의 실행 컨텍스트를 구성할 수 있는 방법으로 전역공간, eval함수, 함수 등이 있다.
우리가 흔히 실행 컨텍스트를 구성하는 방법은 함수를 실행하는 것뿐이다.

예제 코드를 통해 확인해보자.

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

 


최상단의 공간은 코드 내부에서 별도의 실행 명령이 없이도 브라우저에서 자동실행하므로 JavaScript 파일이 열리는 순간 
전역 컨텍스트가 활성화된다고 이해하면 된다.

위 코드를 그림으로 이해해보자.


콜 스택에는 전역 컨텍스트 외에 다른 덩어리가 없으므로 전역 컨텍스트와 관련된 코드가 순차적으로 진행되다가
outer 함수를 호출하면 JavaScript 엔진은 outer 에 대한 환경정보를 수집하여 outer 실행 컨텍스트를 생성한 후 콜 스택에 담는다.
콜 스택의 맨 위에 outer 실행 컨텍스트가 놓인 상태가 되었으므로 전역 컨텍스트와 관련된 코드의 실행을 일시중단하고 outer 실행 컨텍스트와 관련된 코드들을 순차 실행한다.

순차적으로 진행한 후, 콜 스택에 아무것도 남지 않은 상태가 되면서 종료된다.

스택 구조를 생각해보면 한 실행 컨텍스트가 콜 스택의 맨 위에 쌓이는 순간 곧 현재 실행할 코드에 관여하게 되는 시점임을 알 수 있다.
어떤 실행 컨텍스트가 활성화될 때 JavaScript 엔진은 해당 컨텍스트에 관련된 코드들을 실행하는 데 필요한 환경 정보들을 수집하여 실행 컨텍스트에 저장한다.
이 객체는 JavaScript 엔진이 활용할 목적으로 생성할 뿐 개발자가 코드를 통해 확인할 수는 없다.
이 곳에 담기는 정보는 아래와 같다.

 

- VariableEnvironment : 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경정보. 선언 시점의 LexicalEnvironment 의 스냅샷으로 변경사항은 반영되지 않는다.

- LexicalEnvironment : 처음에는 VariableEnvironment 와 같지만 변경 사항이 실시간으로 반영된다.

- ThisBinding : this 식별자가 바라봐야할 대상 객체로, VariableEnvironment 와 LexicalEnvironment 내부에 environmentRecord 와 outer-EnvironmentReference 로 구성되어 있다.

 

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

 

호이스팅의 규칙
environmentRecord 에는 매개변수의 이름, 함수, 선언, 변수명 등이 저장된다.
이번에도 예제 코드를 살펴보자.

function a (x) {
    console.log(x);    // (1)
    var x;
    console.log(x);    // (2)
    var x = 2;    
    console.log(x);    // (3)
}
a(1);

 

호이스팅이 되지 않았을 때, 위 코드에 어떤 값들이 출력되는지 예상해보자.

function a () {
    var x;
    var x;
    var x;

    x = 1;
    console.log(x);		// 1
    console.log(x);		// 1
    x = 2;
    console.log(x);		// 2
}
a(1);

 

호이스팅을 마친 상태의 코드다.

 

 

함수 선언문과 함수 표현식
함수 선언문이란, function 정의부만 존재하고 별도의 할당 명령이 없는 것이고, 함수 표현식은 정의한 function 을 별도의 변수에 할당하는 것이다.

function a () {/* ... */ }           // 함수 선언문. 함수명 a가 곧 변수명
a();    // 실행 OK

var b = function () {/* ... */ }     // (익명) 함수 표현식. 함수명 b가 곧 변수명
b();    // 실행 OK

var c = function d () {/* ... */ }   // 기명 함수 표현식. 변수명 c, 함수명 d
c();    // 실행 OK
d();

 

다음은 this 에 대해 공부해보자.

* 출처 : '코어 자바스크립트 - 핵심 개념과 동작 원리로 이해하는 자바스크립트 프로그래밍', 정재남 지음

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기