javascript 코드가 실행되는 환경 또는 연산 범위를 나타내는 추상 영역
실행 컨텍스트는 말만 가지나게 썼을 뿐, 개발자가 작성한 코드가 실행되기 위한 환경을 구성한 컨테이너다.
쉽게 말해서 우리가 계란 후라이를 하기 위해 가스 레인지와 프라이팬이 필요한 것 처럼 코드를 실행시키기 위해 선언해놓은 변수, 함수를 설정해놓고 실행시키는 개념이라 보면된다.
앞서 javascript 런타임 엔진은 Heap과 Stack 영역으로 구성된다는 것을 알고있다. 그럼 그 Stack에 실행될 코드가 어떤 구성으로 적재되는지 알아보겠다.
개발에서는 어떤 개념이 존재하면 항상 분류가 나뉜다. 그래서 피곤하지.. 실행 컨텍스트도 2가지로 분류할 수 있다.
런타임 엔진이 코드를 실행할 때 글로벌 실행 컨텍스트 영역이 생긴다. 생성 과정에서 전역 객체인 Window Object가 생성된다.
javascript 코드로 선언된 함수가 호출될 때마다 호출된 함수 전용 실행 컨텍스트가 생긴다.
런타임 엔진이 코드를 실행할 때 최초 한번 Global Execution context 영역을 생성하고 함수가 호출될 때 마다 함수 전용 Function Execution context를 생성한다.
Call Stack에 실행 컨텍스트를 쌓아가며 코드를 실행시킨다.
떡꼬치로 비유해서 생각하면 쉽다. 분식집 아주머니가 떡꼬치를 만들때 밑에서 부터 차례대로 꽂으신다. 그리고 우리가 쳐묵쳐묵할땐 위에서 부터 먹는다. 그런 구조와 같이 LIFO (Last in, First out) 구조를 띈 형태다.
코드와 그림으로 실행 과정에 대해 설명하겠다. 다음 코드는 요로코롬 실행된다.
// ES6
const first = () => {
console.log('first')
second();
}
const second = () => {
console.log('second');
}
first();
// first
// second
이런 코드가 있다 가정해보자. first
함수에서 second
를 호출하는 구조를 띄고 있다. 내부적으로는 글로벌 실행 컨텍스트가 최초 1번 생기고 그 위에 함수별로 실행컨텍스트가 1개씩 생긴다. CallStack에 쌓을 땐 PUSH, 제거할 땐 POP이 이루어진다.
step1 : 코드 실행 전 Global Execution context 생성 및 PUSH
step2 : first
함수 호출
(first
함수 Function Execution context 생성 및 PUSH)
step3 : first
함수 내부 console.log('first')
호출
(console.log
함수 Function Execution context 생성 및 PUSH)
step4 : console.log(‘first’)
종료
(console.log
함수 Function Execution context POP)
step5 : second
함수 호출
(second
함수 Function Execution context 생성 및 PUSH)
step6 : second
함수 내부 console.log('second')
호출
(console.log
함수 Function Execution context 생성 및 PUSH)
step7 : console.log(‘second’)
종료
(console.log
함수Function Execution context POP)
step8 : second
함수 종료
(second
함수 Function Execution context POP)
step9 : first
함수 종료
(first
함수 Function Execution context POP)
step10 : 실행이 끝난 뒤 Global Execution context POP
first
안에 console.log
함수, second
함수 호출 코드가 있다. console.log
함수는 로그만 찍는 녀석이기 때문에 마지막 뎁스다. console.log
함수 컨텍스트 수행 이후 second
함수 실행 컨텍스트가 생성되는데 그 내부에서도 console.log('second')
를 호출하기 때문에 console.log
용 실행 컨텍스트가 생성되고 코드를 실행시킨다. 그 함수의 실행이 끝날때 까지 Function Execution context 는 유지된다고 생각하면 된다.
실행 컨텍스트의 생성은 생성과 실행 단계를 거쳐 구성된다.
모든 실행 컨텍스트를 생성하는데 create > execute 단계를 거친다. 생성이랑 생성 단계의 구분을 위해 생성 단계는 create로 명시한다. 이 단계를 거치면서 this 객체 생성, 호이스팅이 일어나게 된다. 그리고 실행 컨텍스트가 글로벌이냐 함수냐에 따라 global object, argument 등 생성 인자의 차이가 존재한다.
글로벌 실행 컨텍스트는 다음 create 단계를 거친다.
이후 execute 단계에서 undefined가 할당되어 있는 변수를 찾아 실제 값을 할당한다. 맞다. 호이스팅이 일어난다.
var name = 'carrots';
var age = 29;
function getUserInfo() {
return {
name: name,
age: age
}
}
// 생성 단계 결과
Global Execution context : {
Window : Global Object,
this : Window,
name : undefined,
age : undefined,
getUserInfo : function object
}
// 실행 단계 결과
Global Execution context : {
Window : Global Object,
this : Window,
name : 'carrots',
age : 29,
getUserInfo : function object
}
함수 실행 컨텍스트도 create, execute 단계를 거쳐 생성된다.
글로벌 실행 컨텍스트와 차이는 전역 객체(Global Object) 대신 arguments 객체가 생성된다는 점이 다르다. 기타 다른 사항은 거의 동일하다. 함수 내부에서 사용되는 변수에 대해 호이스팅이 발생하는 점 또한 똑같다. arguments는 그 함수를 호출할 때 사용되는 파라미터의 모음이다.
var name = 'carrots';
var age = 29;
function getUserInfo(param) {
var sex = '상남자';
return {
name: name,
age: age
}
}
getUserInfo(1); // 실행 컨텍스트 생성
// 생성 단계 결과
Function Execution context : {
argument : { 0 : 1, length : 1 }
this : Window
param : 1,
sex : undefined
}
// 실행 단계 결과
Global Execution context : {
argument : { 0 : 1, length : 1 }
this : Window
param : 1,
sex : '상남자'
}
javascript의 실행 단위인 컨텍스트의 종류와 내부적인 구조를 알아봤다. 떡꼬치를 상상하자.
오늘 저녁은 떡꼬치다. 🥕