실행 컨텍스트 (Execution Context) 란? 자바스크립트 동작원리
(해당 포스팅은 개인 공부를 목적으로 작성된 포스팅으로 부족한 점이 있더라도 양해 부탁드립니다!)
<목차>
1. 실행 컨텍스트
2. 실행 컨텍스트의 3가지 객체
2-1. Variable Object (VO)
2-2. Scope Chain (SC)
2-3. this Value
3. 실행 컨텍스트의 생성 과정
3-1. 전역 코드에 진입
3-2. 전역 코드의 실행
3-3. foo()함수의 실행
1. 실행 컨텍스트
ECMA Script 스펙에 따르면 실행 컨텍스트를 '실행가능한 코드를 형상화하고 구분하는 추상적인 개념'이라고 정의합니다.
쉽게 말해서 실행 컨텍스트는 실행 가능한 코드가 실행되기 위한 환경이라고 말할 수 있습니다.
여기서 말하는 실행 가능한 코드는 아래와 같습니다.
- 전역 코드 : 전역 영역에 존재하는 코드
- Eval 코드 : eval 함수로 실행되는 코드
- 함수 코드 : 함수 내에 존재하는 코드
일반적으로 실행가능한 코드는 전역 코드와 함수내 코드이다.
자바스크립트 엔진은 코드를 실행하기 위해서 실행에 필요한 여러가지 정보를 알고 있어야 한다.
실행에 필요한 여러가지 정보란 아래와 같은 것들이 있다.
- 변수: 전역번수, 지역변수, 매개변수, 객체의 프로퍼티
- 함수 선언
- 변수의 유효범위 (Scope)
- this
이와 같이 실행에 필요한 정보를 형상화 하고 구분하기 위해 자바스크립트 엔진은 실행 컨텍스트를 물리적 객체의 형태로 관리한다.
var x = 'xxx';
function foo () {
var y = 'yyy';
function bar () {
var z = 'zzz';
console.log(x + y + z);
}
bar();
}
foo();
위의 코드를 실행하면 아래와 같이 실행 컨텍스트 스택(Stack)이 생성되고 소멸한다.
현재 실행중인 컨텍스트에서 이 컨텍스트와 관련없는 코드(ex. 다른 함수)가 실행되면 새로운 컨텍스트가 생성된다.
이 컨텍스트는 스택에 쌓이게 되고 컨트롤(제어권)이 이동한다.
- 컨트롤이 실행 가능한 코드로 이동하면 논리적 스택구조를 가지는 새로운 실행 컨텍스트 스택이 생성된다. 스택은 LIFO(Last In First Out, 후입선출)의 구조를 가지는 나열 구조이다.
- 전역코드(Global code)로 컨트롤이 진입하면 전역 실행 컨텍스트가 생성되고 실행 컨텍스트 스택에 쌓인다. 전역 실행 컨텍스트는 애플리케이션이 종료될 때(웹 페이지에서 나가거나 브라우저를 닫을 때)까지 유지된다.
- 함수를 호출하면 해당 함수의 실행 컨텍스트가 생성되며 직전에 실행된 코드 블록의 실행 컨텍스트 위에 쌓인다.
- 함수 실행이 끝나면 해당 함수의 실행 컨텍스트를 파기하고 직전의 실행 컨텍스트에 컨트롤을 반환한다.
2. 실행 컨텍스트의 3가지 객체
실행 컨텍스트는 실행 가능한 코드를 형상화하고 구분하는 추상적인 개념이지만,
물리적으로는 객체의 형태를 가지며 아래의 3가지 프로퍼티를 가진다.
2.1 Variable Object (VO , 변수 객체)
실행 컨텍스트가 생성되면 자바스크립트 엔진은 실행에 필요한 여러 정보들을 담을 객체를 생성한다.
이 객체를 Variable Object(VO, 변수 객체)라고 한다.
Variable Object는 아래의 정보를 담는 객체이다.
- 변수
- 매개변수(parameter)와 인수정보(arguments)
- 함수 선언 (함수 표현식은 제외)
Variable Object는 실행 컨텍스트의 프로퍼티이기 때문에 값을 갖는데 이 값은 다른 객체를 가리킨다.
그런데 전역 코드 실행시 생성되는 전역 컨텍스트의 경우와
함수를 실행할때 생성되는 함수 컨텍스트의 경우,
가리키는 객체가 다르다.
이는 전역 코드와 함수의 내용이 다르기 때문이다.
(한 예로 전역 코드에는 매개변수가 없지만, 함수에는 매개변수가 있다.)
Variable Object가 가리키는 객체는 아래와 같다.
[전역 컨텍스트의 경우]
Variable Object는 유일하며 최상위에 위치하고,
모든 전역변수, 전역 함수 등을 포함하는 전역 객체(Global Object/ GO)를 가리킨다.
전역 객체는 전역에 선언된 전역 변수와 전역 함수를 프로퍼티로 소유한다.
[함수 컨텍스트의 경우]
Variable Object는 Activaiton Object(AO, 활성 객체)를 가리키며 매개변수와 인수들의 정보를 배열의 형태로 담고 있는 객체인 arguments objects가 추가된다.
2.2 Scope Chain (SC)
스코프 체인은 일종의 리스트로서 전역 객체와 중첩된 함수의 스코프의 레퍼런스를 차례대로 저장한다.
다시 말해서, 스코프 체인은 해당 전역 또는 함수가 참조할 수 있는 변수/ 함수 선언 등의 정보를 담고 있는
전역 객체(GO) 또는 활성 객체 (AO)의 리스트를 가리킨다.
현재 실행 컨텍스트의 활성 객체(AO)를 선두로 하여 순차적으로 상위 컨텍스트의 활성 객체(AO)를 가리키며 마지막 리스트는 전역 객체 (GO)를 가리킨다.
스코프 체인은 식별자 중에서 객체(전역 객체 제외)의 프로퍼티가 아닌 식별자, 즉 변수를 검색하는 메커니즘이다.
식별자 중에서 변수가 아닌 객체의 프로퍼티(물론 메서드도 포함된다.)를 검색하는 메커니즘은 프로토타입 체인이다.
2.3 this Value
this 프로퍼티에는 this 값이 할당된다. this에 할당되는 값은 함수 호출 패턴에 의해 결정된다.
3. 실행 컨텍스트의 생성 과정
위에서 작성했던 코드를 다시 한번 살펴보면
var x = 'xxx';
function foo () {
var y = 'yyy';
function bar () {
var z = 'zzz';
console.log(x + y + z);
}
bar();
}
foo();
3.1 전역 코드에 진입
컨트롤이 실행 컨텍스트에 진입하기 이전에 유일한 전역 객체 (Global Object)가 생성된다.
전역 객체는 단일 객체로 존재해야 하고, 이 객체의 프로퍼티는 코드의 어떤 곳에서도 접근할 수 있다.
초기 상태의 전역 객체에는 빌트인 객체(Math, String, Array등)와 BOM, DOm이 설정되어 있다.
전역 객체가 생성된 이후, 전역 코드로 컨트롤이 진입하면 전역 실행 컨텍스트가 생성되고 실행 컨텍스트 스택에 쌓인다.
그리고 이후에는 해당 실행 컨텍스트를 바탕으로 아래의 처리가 실행된다.
- 스코프 체인의 생성과 초기화
- Variable Instantiation(변수의 객체화) 실행
- this Value 결정
3.2 전역 코드의 실행
여기까지는 코드 실행 환경을 갖추기 위한 사전 준비 과정이었다.
코드의 실행은 지금부터 시작된다.
var x = 'xxx';
function foo () {
var y = 'yyy';
function bar () {
var z = 'zzz';
console.log(x + y + z);
}
bar();
}
foo();
위의 예제에서 전역 변수 x에 문자열 'xxx'가 할당되고, foo()함수의 호출이 실행된다.
3.2.1 변수 값의 할당
전역변수 x에 문자열 'xxx'를 할당할 때, 현재 실행 컨텍스트의 스코프 체인이 참조하고 있는 Variable Object를
선두(0)부터 검색해서 변수명에 해당하는 프로퍼티가 발견되면 값('xxx')을 할당한다.
3.2.2 함수 foo()의 실행
전역 코드의 함수 foo가 실행되기 시작하면 새로운 함수 실행 컨텍스트가 생성된다.
함수 foo의 실행 컨텍스트로 컨트롤이 이동하면 전역 코드의 경우와 마찬가지로
1. 스코프 체인의 생성과 초기화
2. Variable Instantiation(변수의 객체화) 실행
3. this Value 결정
이 순차적으로 실행된다.
단, 전역 코드와 다른 점은 이번에 실행되는 코드는 함수 코드라는 것이다.
따라서
1. 스코프 체인의 생성과 초기화
2. Variable Instantiation(변수의 객체화) 실행
3. this Value 결정
이 전역 코드의 룰이 아닌 함수 코드의 룰이 적용된다.
3.2.2.1 스코프 체인의 생성과 초기화
함수 코드의 스코프 체인의 생성과 초기화는 우선 Activation Object에 대한 레퍼런스를
스코프 체인의 선두에 설정하는 것으로 시작된다.
Activation Object는 우선 arguments 프로퍼티의 초기화를 실행하고 이후에, Variable Instantiation가 실행된다.
Activation Object는 스펙상의 개념으로 프로그램이 Activation Object에 직접 접근할 수 없다.
(Activation Object의 프로퍼티로의 접근은 가능하다.)
3.3 foo 함수 코드의 실행
이제 함수 foo의 코드 블록 내의 구문이 실행된다.
위의 예제에서는 변수 y에 문자열 'yyy'의 할당과 함수 bar가 실행된다.
3.3.1 변수 값의 할당
3.3.2 함수 bar의 실행
긴글 읽어주셔서 감사합니다.
질문과 지적은 댓글로 환영합니다!
오늘도 즐코하세요! :)
참고자료
https://poiemaweb.com/js-execution-context
https://velog.io/@stampid/Execution-Context실행-컨텍스트란
https://hangeoreum.tistory.com/entry/JS-실행-컨텍스트Execution-Context
https://iamsjy17.github.io/javascript/2019/06/10/js33_execution_context.html
https://medium.com/su-s-daily-log/javascript-execution-context-hoisting-and-closures-6d64cbcb6bc8