지난번 호이스팅에 대해 설명하면서 실행 컨텍스트에 대해 먼저 정리하고 했으면 더 좋겠다는 생각을 하게 됐다. 그래서 뒤늦게나마 실행 컨텍스트란 무엇인가에 대해 내 생각과 개념 그리고 과정을 정리해 보려고 한다!
지난 포스팅 : 호이스팅에 대해 설명하시오
- 실행 가능한 코드가 실행되기 위해 필요한 환경정보들을 모아놓은 객체
- scope, hoisting, this, function, closure 등의 동작원리를 담고 있는 자바스크립트의 핵심 원리이다.
- 이 과정에서 다른 언어에선 볼 수 없는 자바스크립트의 동적 언어로서의 성격을 가장 잘 파악 할 수 있는 개념이다.
프로그램 내의 코드들이 모두 하나의 컨텍스트로 정리되지 않는다.
아래와 같이 3가지 종류의 컨텍스트들로 이루어져있다.
- 전역 실행 컨텍스트 => 전역 영역에 존재하는 코드
- 함수 실행 컨텍스트 => 함수 내에 존재하는 코드
- Eval 실행 컨텍스트 => eval 함수로 실행되는 코드
이중 세번째의 Eval컨텍스트는
MDN: eval(), eval 코드 지양 을 읽어보면 수 많은 취약점이 발견되어 사용을 지양하기를 권한다. 따라서, 사용하지 않을 것이기 때문에 생성한다는 것만 명심하고 넘어가자!
💡 그리고 전역코드를 사용하기 보다는 함수코드를 사용하는 것이 바람직한 코드 작성법이기 때문에, 대부분의 경우 실행 가능한 코드란 콜 스택에 쌓이는 함수 코드 정보를 의미 한다고 한다.
콜 스택에 실행 컨텍스트가 어떤 순서로 쌓이고, 어떤 순서로 코드 실행에 관여하는지에 대해 그림을 참고하면서 한번 살펴보자 !
💡 JavaScript 에서는
콜 스택
을실행 컨텍스트 스택
이라고도 부르기도 한다. 하지만 편의상콜 스택
이라고 많이 부른다.
var a = 1;
function outer() {
function inner() {
console.info(a); // undefined
var a = 3;
}
inner();
console.info(a); // 1
}
outer();
console.info(a); // 1
- 제일 먼저 코드가 실행되면서 콜 스택에 Global 실행 컨텍스트가 담긴다.
- Global 컨텍스트와 관련된 코드들을 순차로 진행하다가 Outer()라인에서 JS엔진은 Outer에 대한 환경 정보를 수집해서 Outer 실행 컨텍스트를 생성한 후 콜 스택에 담는다.
- Global 컨텍스트와 관련된 코드 실행을 일시 중단 후 Outer 실행 컨텍스트와 관련된 코드를 실행한다.
- Inner() 라인에서 Inner함수의 실행 컨텍스트가 Outer때와 같이 동일하게 콜 스택에 담기게 되고, JS는 Inner함수 내부 코드를 진행한다.
- 이어서 내부 함수가 종료되면, Inner는 콜 스택에서 제거되고, 순차적으로 Outer, Global 컨택스트 들이 스택에서 나오게 된다.
이렇게 어떤 실행 컨텍스트가 활성화 될 때 JS엔진은 해당 컨텍스트에 관련된 코드들을 실행하는 데 필요한 환경 정보들을 수집해서 실행 컨텍스트 객체에 저장한다.
위에 설명한 객체는 아래와 같은 정보들을 담고 있다.
- VariableEnvironment: 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보
- LexicalEnvironment: 처음엔 VariableEnvironment와 같지만 변경 사항이 실시간 반영 됨
- ThisBinding: this 식별자가 바라봐야 할 대상 객체
더 자세히 설명하자면,
VariableEnvironment
와 LexicalEnvironment
의 내부는
environmentRecord
와 OuterEnvironmentReference
로 구성되어있다.
VariableEnvironment (변수환경)
실행 컨텍스트를 생성할 때 VariableEnvironment
에 정보를 먼저 담은 다음, 이를 복사해서 LexicalEnvironment를 만들고, 이후엔 LexicalEnvironment
를 주로 활용 한다.
LexicalEnvironment(어휘적 환경)
처음에는 VariableEnvironment
와 같지만, 변경 사항이 실시간으로 반영 된다.
함수 선언과 변수 (let 과 const)의 바인딩 저장한다.
DeclaretiveEnvironmentRecord
-> 변수, 함수, 인수(arguments)를 저장한다.
ObjectEnvironmentRecord
-> global code에 대한 LexicalEnvironment
이다. Global 바인딩 객체(브라우저 윈도우객체)를 저장 하며, 각각의 바인딩 객체의 속성에 대해 레코드에 새로운 항목이 포함된다.
ThisBinding
- this의 값이 여기서 결정 된다. Global 컨텍스트에 서는 기본으로 글로벌, 윈도우로 설정되어 있다.(실행 컨텍스트가 활성될 때 this가 지정되지 않은 경우 this에는 전역 객체가 저장)
뭔가 글로 설명하다보니 머릿속에 안그려져서 그림으로 아래와 같이 정리해 봤다.
VariableEnvironement 와 LexicalEnvironment 공통 내부
Reference Error
가 발생 한다.앞서 말한 것과 같이 실행컨텍스트에 대해 공부하고 정리하면서 호이스팅과 스코프 개념과 같이 연결되는거 같아 호이스팅에 대해 공부를 할 때 애매했던 개념부분에 대해서 이번 실행 컨텍스트 정리를 통해 더 알게 된거 같다. 처음에는 그림없이 글로만 정리를 하는데 도저히 글로는 머릿속에 안그려져 직접 그려보거나 그림으로 남기니 더 이해가 잘되는거 같다.
https://junilhwang.github.io/TIL/Javascript/Domain/Execution-Context/#_4-outerenvironmentreference%E1%84%8B%E1%85%AA-scope
https://poiemaweb.com/js-execution-context
https://junilhwang.github.io/TIL/Javascript/Domain/Execution-Context/#reference
https://bohyunkang.tistory.com/26
https://kellis.tistory.com/136
https://velog.io/@kwonh/ES6-Javascript-Execution-Context%EC%8B%A4%ED%96%89%EB%AC%B8%EB%A7%A5-%EC%8B%A4%ED%96%89%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8
https://www.youtube.com/watch?v=pfQfEwnJHRs
정확하지 않은 정보가 있을 수 있습니다. 댓글을 통해 피드백 주시면 적극적으로 반영하겠습니다🥲