JavaScript

[Javascript] 실행 컨텍스트 (Execution Context)

prefer2 2021. 9. 13. 15:40

 

실행 컨텍스트는 자바스크립트의 동작 원리를 담고 있는 핵심 개념이다. 실행 컨텍스트를 이해하면 자바스크립트가 스코프를 기반으로 식별자와 식별자에 바인딩된 값(식별자 바인딩)을 관리하는 방식과 호이스팅이 발생하는 이유, 클로저 동작 방식, 그리고 태스크 큐와 함께 동작하는 이벤트 핸들러와 비동기 처리의 동작 방식을 이해할 수 있다.

 

실행 컨텍스트 (Execution Context)


실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다. 식별자(변수, 함수, 클래스 등의 이름)를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 메커니즘으로, 모든 코드는 실행 컨텍스트를 통해 실행되고 관리된다.

식별자와 스코프는 실행 컨텍스트의 렉시컬 환경으로 관리하고 코드 실행 순서실행 컨텍스트 스택으로 관리한다.

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

 

실행 컨텍스트의 종류

1. 전역 실행 컨텍스트: 코드를 실행하며 단 한 개만 정의되는 전역 컨텍스트. global object를 생성하며 this 값에 global object를 참조한다. 전역 실행 컨텍스트는 Call Stack에 가장 먼저 추가되며 앱이 종료 될 때 삭제된다.

2. 함수 실행 컨텍스트: 함수가 실행될 때 마다 정의되는 컨텍스트. 전역 실행 컨텍스트가 단 한 번만 정의되는 것과 달리, 함수 실행 컨텍스트는 매 실행시마다 정의되며 함수 실행이 종료(return)되면 Call Stack에서 제거된다.

3. eval 실행 컨텍스트: eval함수로 실행한 코드의 Context. 보안상 취약한 점이 있어 비권장 함수이다.

 

실행 컨텍스트 스택


var global = 'globalVar' 

function foo() { 
    var fooVar = 'fooVar' 
    console.log(global) 
    function bar() { 
    	var barVar = 'barVar' 
    } 
    
    bar() 
} 

foo()

위 코드를 실행하면 아래와 같이 작동한다.

자바스크립트 엔진은 먼저 전역 코드를 평가하여 전역 실행 컨텍스트를 생성한다. 그리고 함수가 호출되면 함수 코드를 평가하여 함수 실행 컨텍스트를 생성한다. 이때 생성된 실행 컨텍스트는 스택 자료구조로 관리된다. 이를 실행 컨텍스트 스택이라고 부른다.

Call Stack은 최대 stack 사이즈가 정해져있다. Call Stack에 쌓인 Context Stack이 최대치를 넘게 될 경우 ‘RangeError: Maximum call stack size exceeded’라는 에러가 발생한다. 이 에러는 Stack Overflow라고 부르기도 한다.

 

실행 컨텍스트 객체


  • Variable Object(변수 객체)
  • Scope Chain(스코프 체인)
  • this keyword

 

1. Variable Object (변수 객체)

실행 컨텍스트가 생성되면 자바스크립트 엔진은 실행에 필요한 여러 정보들을 담을 객체를 생성한다. 이를 Variable Object(VO / 변수 객체)라고 한다. Variable Object는 코드가 실행될 때 엔진에 의해 참조되며 코드에서는 접근할 수 없다. 이후 Hoisting(호이스팅)과 연관이 있다.

  • 변수
  • 매개변수(parameter)와 인수 정보(arguments)
  • 함수 선언(함수 표현식은 제외)

Variable Object는 실행 컨텍스트의 프로퍼티이기 때문에 값을 갖는데 이 값은 다른 객체를 가리킨다. 그런데 전역 코드 실행시 생성되는 전역 컨텍스트의 경우와 함수를 실행할 때 생성되는 함수 컨텍스트의 경우, 가리키는 객체가 다르다. 이는 전역 코드와 함수의 내용이 다르기 때문이다. 예를 들어 전역 코드에는 매개변수가 없지만 함수에는 매개변수가 있다.

2. Scope Chain (SC)

스코프 체인(Scope Chain)은 일종의 리스트로서 전역 객체와 중첩된 함수의 스코프의 레퍼런스를 차례로 저장하고 있다. 다시 말해, 스코프 체인은 해당 전역 또는 함수가 참조할 수 있는 변수, 함수 선언 등의 정보를 담고 있는 전역 객체(GO) 또는 활성 객체(AO)의 리스트를 가리킨다.

자바스크립트 엔진은 스코프 체인을 통해 렉시컬 스코프를 파악한다(스코프 체인은 호출 순서와 연관이 없다). 상위 함수, 전역 스코프 등을 참조할 수 있는 이유가 스코프 체인이 검색을 하기 때문이다.
(하위 -> 상위 -> 전역) 순서로 참조해가며 만약 참조에 실패한다면 스코프 체인에 담겨진 순서대로 계속해서 참조를 이어나간다. 검색에 실패하게 된다면 정의되지 않은 변수에 접근하는 것이기 때문에 에러를 발생시킨다. 참조는 한 방향으로만 가능하다.

Lexical scope (렉시컬 스코프)

함수를 어디서 호출하는지가 아니라 어디에 선언하였는지에 따라 결정되는 것을 말한다.

즉, 함수를 어디서 선언하였는지에 따라 상위 스코프를 결정한다는 뜻이며, 가장 중요한 점은 함수의 호출이 아니라 함수의 선언에 따라 결정된다는 점이다. 다른 말로, 정적 스코프(Static scope)라 부르기도 하다.

var x = 1; // global

function first() {
  var x = 10;
  second();
}

function second() {
  console.log(x);
}

first(); // 1
second(); // 1

위 예제의 실행 결과는 함수 second()의 상위 스코프가 무엇인지에 따라 결정된다. 자바스크립트는 렉시컬 스코프(Lexical Scope)를 따르므로 함수를 선언한 시점에 상위 스코프가 결정된다.

그렇기 때문에, second() 함수가 first() 함수 안에서 호출된 것과 상관없이 second() 함수는 global 범위에 선언되어 있으므로, global 범위에 있는 변수 x의 값 1이 두 번 출력이 된다.

스코프 체인과 렉시컬 스코프를 이해하기 좋은 예시

3. this

this 프로퍼티에는 this 값이 할당된다. this에 할당되는 값은 함수 호출 패턴에 의해 결정된다.

 

참조


 

Execution Context | PoiemaWeb

Execution Context(실행 컨텍스트)는 scope, hoisting, this, function, closure 등의 동작원리를 담고 있는 자바스크립트의 핵심원리이다. 실행 컨텍스트를 바로 이해하지 못하면 코드 독해가 어려워지며 디버

poiemaweb.com

 

Learn Modern Javascript (Build and Test Apps) - Full Course

The modern JavaScript course for everyone! Master JavaScript with projects, challenges and theory. Many courses in one!

www.udemy.com

 

반응형