View

반응형

실행 컨텍스트란?

실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체입니다. 실행 컨텍스트는 자바스크립트의 동작 원리를 담고 있는 가장 중요한 핵심 개념 중 하나로 클로저를 지원하는 대부분의 언어에서는 이와 유사하거나 동일한 개념이 적용되어 있습니다. 실행 컨텍스트를 바르게 이해하면 다음과 같은 자바스크립트의 동작 방식을 이해하는데 큰 도움이 됩니다.

 

  • 스코프 기반 변수와 값을 관리하는 방식
  • 호이스팅이 발생하는 이유
  • 클로저의 동작 방식
  • 태스크 큐와 함께 동작하는 이벤트 핸들러와 비동기 처리의 동작 방식
  • this 바인딩

우선 들어가기 전 ECMAScript 사양에서 정의한 4가지 소스코드 타입에 관해서 알아보고 갑시다.

 

소스코드의 타입 설명
전역 코드 전역에 존재하는 소스코드를 말합니다. 전역에 정의된 함수, 클래스 등의 내부 코드는 포함되지 않습니다.
함수 코드 함수 내부에 존재하는 소스코드를 말합니다. 함수 내부에 중첩된 함수, 클래스 등의 내부 코드는 포함되지 않습니다.
eval 코드 빌트인 전역 함수인 eval 함수에 인수로 전달되어 실행되는 소스코드를 말합니다.
모듈 코드 모듈 내부에 존재하는 소스코드를 말합니다. 모듈 내부의 함수, 클래스 등의 내부 코드는 포함되지 않습니다.

 

소스코드를 4가지 타입으로 구분하는 이유는 소스코드의 타입에 따라 실행 컨텍스트를 생성하는 과정과 관리 내용이 다르기 때문입니다.

 

  • 전역 실행 컨텍스트
    전역 코드는 최상위 스코프인 전역 스코프를 생성합니다. 그리고 var 키워드로 선언된 전역 변수와 함수 선언문으로 정의된 전역 함수를 전역 객체의 프로퍼티와 메서드로 바인딩하고 참조하기 위해 전역 객체와 연결하는 과정이 있어야 합니다. 이를 위해 전역 코드가 평가되면 전역 실행 컨텍스트가 생성됩니다.

  • 함수 실행 컨텍스트
    함수 코드는 지역 스코프를 생성하고 지역 변수, 매개변수, arguments 객체를 관리해야 합니다. 그리고 생성한 지역 스코프를 전역 스코프에서 시작되는 스코프 체인의 일원으로 연결해야 합니다. 이를 위해 함수 코드가 평가되면 함수 실행 컨텍스트가 생성됩니다.

  • eval 실행 컨텍스트
    eval 코드는 strcit mode에서 자신만의 독자적인 스코프를 생성합니다. 이를 위해 eval 코드가 평가되면 eval 실행 컨텍스트가 생성됩니다.

  • 모듈 실행 컨텍스트
    모듈 코드는 모듈별로 독립적인 모듈 스코프를 생성하며 이를 위해 모듈 코드가 평가되면 모듈 실행 컨텍스트가 생성됩니다.

  자바스크립트는 소스코드를 2개의 과정 “소스코드의 평가”와 “소스코드의 실행” 과정으로 나누어 처리하며 모든 소스코드는 실행에 앞서 평가 과정을 거쳐 코드를 실행하기 위한 준비를 합니다. 소스코드 평가 과정에서는 실행 컨텍스트를 생성하고 변수, 함수 등의 선언문만 먼저 실행하여 생성된 변수나 함수 식별자를 키로 실행 컨텍스트가 관리하는 스코프(렉시컬 환경의 환경 레코드)에 등록합니다. 소스코드 평가 과정이 끝나면 선언문을 제외한 소스코드가 순차적으로 실행되는데 이를 “런타임”이라 합니다.

 

  이때 소스코드 실행에 필요한 변수나 함수의 참조를 실행 컨텍스트가 관리하는 스코프에서 검색해서 취득합니다.  그리고 변수 값의 변경 등 소스코드의 실행 결과는 다시 실행 컨텍스트가 관리하는 스코프에 등록됩니다. 앞서 언급한 4가지 소스코드 타입에 따라 생성되는 실행 컨텍스트들 중 자동으로 생성되는 전역 실행 컨텍스트와 사용이 금지된 eval 실행 컨텍스트를 제외하면 일반적으로 함수를 이용한 실행 컨텍스트를 많이 사용합니다.

실행 컨텍스트의 역할

ECMAScript에서 정의한 4가지 소스코드 타입에 따라 생성되는 실행 컨텍스트의 종류에 대해 알아봤습니다. 그럼 이 실행 컨텍스트는 어떤 역할을 하는 친구일까요?

 

자바스크립트에서는 코드가 실행되려면 다음과 같이 스코프, 식별자, 코드 실행 순서 등의 관리가 필요합니다.

  • 선언된 모든 식별자(변수, 함수, 클래스 등)를 스코프에 등록하고 값의 변화와 같은 상태 변화를 지속적으로 관리할 수 있어야 합니다.
  • 스코프 체인을 통해 상위 스코프로 이동하며 식별자를 검색할 수 있어야 합니다.
  • 실행 순서를 보장합니다. 예를 들어 실행 중인 코드가 함수 호출에 의해 실행 순서가 변경되었고 해당 함수가 종료되면 다시 원래 실행 중인 코드로 되돌아갈 수 있어야 합니다.

이 모든 것을 관리하는 것이 바로 실행 컨텍스트입니다. 실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역입니다. 구체적으로 실행 컨텍스트는 식별자를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 메커니즘으로 모든 코드는 실행 컨텍스트를 통해 실행되고 관리되는거죠.

 

즉, 식별자와 스코프는 실행 컨텍스트의 렉시컬 환경으로 관리하고 코드 실행 순서는 실행 컨텍스트 스택(콜스택이라고 부릅니다.)으로 관리합니다.

실행 컨텍스트 스택 - 콜스택

실행 컨텍스트 스택(이하 콜스택)은 이름에서 알 수 있듯이 스택 자료구조로 관리됩니다. 우선 아래의 코드를 살펴보겠습니다.

const x = 1;

function foo() {
	const y = 2;

	function bar() {
		const z = 3;
		console.log(x + y + z);
	}
	bar();
}

foo(); // 6

위 코드를 실행하면 코드가 실행되는 시간의 흐름에 따라 콜스택에는 다음과 같이 실행 컨텍스트가 추가(push)되고 제거(pop)됩니다.

 

실행 컨텍스트 스택

위 이미지처럼 콜스택은 코드의 실행 순서를 관리하며 최상위에 존재하는 실행 컨텍스트는 언제나 현재 실행 중인 코드의 실행 컨텍스트입니다.

 

렉시컬 환경 (Lexical Environment)

실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체로 VariableEnvironment, LexicalEnvironment, ThisBinding으로 구성되어 있습니다.  그 중 렉시컬 환경(Lexical Enviroment)은 키와 값을 갖는 객체 형태의 스코프를 생성하여 식별자를 키로 등록하고 식별자에 바인딩된 값을 관리하는 저장소 역할을 하며 렉시컬 스코프의 실체입니다. 실행 컨텍스트가 초기에 생성될 때 LexcialEnviroment 컴포넌트와 VariableEnviroment 컴포넌트는 하나의 동일한 렉시컬 환경을 참조합니다.

 

실행 컨텍스트와 렉시컬 환경

 

이 때 VariableEnvironment에 담기는 내용은 LexicalEnvironment와 같지만 최초 실행 시의 스냅샷을 유지한다는 점이 다릅니다. 실행 컨텍스트를 생성할 때 VariableEnviroment에 정보를 먼저 담은 다음, 이를 그대로 복사해서 LexicalEnviroment를 만들고 이후에 LexicalEnviroment를 주로 활용하게 됩니다. 즉, 초기화 과정 중에는 사실상 완전히 동일하고 이후 코드 진행에 따라 서로 달리지게 됩니다.

 

실행 컨텍스트 구성 정보

 

  1. 환경 레코드 (Environment Record)
    스코프에 포함된 식별자를 등록하고 등록된 식별자에 바인딩된 값을 관리하는 저장소입니다. 환경 레코드는 소스코드의 타입에 따라 관리하는 내용에 차이가 있습니다. 이 환경 레코드로 인하여 호이스팅이 발생합니다.

  2. 외부 렉시컬 환경에 대한 참조 (Outer Lexical Environment Refernce)
    외부 렉시컬 환경에 대한 참조는 상위 스코프를 가리킵니다. 이때 상위 스코프란 외부 렉시컬 환경, 즉 해당 실행 컨텍스트를 생성한 소스코드를 포함하는 상위 코드의 렉시컬 환경을 말합니다. 외부 렉시컬 환경에 대한 참조를 통해 단방향 링크드 리스트인 스코프 체인을 구합니다. 즉, 외부 렉시컬 환경에 대한 참조로 스코프스코프체인이 형성됩니다.

 

ThisBinding

실행 컨텍스트의 thisbindg에는 this로 지정된 객체가 저장됩니다. 실행 컨텍스트 활성화 당시 this가 지정되지 않은 경우 this는 전역 객체가 저장됩니다. this 자체만으로도 설명해야될 분량이 많기 때문에 여기서는 다루지 않겠습니다.

 

마무리

실행 컨텍스트에 대해 전반적인 개념을 알아봤습니다. 실행 컨텍스트를 잘 이해하면 왜 호이스팅이 발생하고 스코프 체인이 어떻게 구성되는지 알 수 있었습니다. 이 글은 모던 자바스크립트 딥다이브, 코어 자바스크립트 책을 기반으로 작성하였습니다. 개인적으로 딥다이브를 먼저 보고 코어 자바스크립트 책을 보면 뭔가 조각 조각 떨어져 있던 개념들이 하나로 합쳐지는 경험을 하게 됩니다. 특히 코어 자바스크립트에서 Environment Record와 호이스팅 관련 내용과 스코프 체인 내용이 예제 코드와 함께 설명되어 있는 부분이 있는데 정말 이해가 잘되었습니다. 만약 주변에 자바스크립트를 공부하고 싶어하시는 분이 계신다면 이 두 책을 함께 보라고 권유드리고 싶네요!

 

참고 자료

  • 모던 자바스크립트 딥다이브
  • 코어 자바스크립트
반응형

'Language > Javascript' 카테고리의 다른 글

[JS] 클로저  (0) 2023.05.01
Share Link
reply
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30