실행 컨텍스트
실행 컨텍스트는 자바스크립트 동작 원리를 담고 있는 핵심 개념이다. 이를 잘 이해하면 자바스크립트의 여러가지 동작원리에 대해 자세하게 이해할 수 있다.
- 스코프를 기반으로 식별자와 식별자에 바인딩 된 값을 관리하는 방식
- 호이스팅이 발생하는 이유
- 클로저의 동작 방식
- 태스크 큐와 함께 동작하는 이벤트 핸들러
- 비동기 처리의 동작 방식 등등
등을 이해하는데 도움이 된다. 차근차근 알아보자
실행 컨텍스트의 구성 요소
실행 컨텍스트는 크게 세 가지 주요 구성 요소를 가진다.
- 변수 환경(Variable Environment)
- 로컬 스코프에 선언된 변수, 함수 선언, 매개변수 등을 저장하는 환경
- 최초 생성 시점의 환경 스냅샷을 유지
- 렉시컬 환경(Lexical Environment)
- 실행 중인 코드의 식별자(변수, 함수, 클래스 등)가 저장되는 구조
- 변수 환경과 유사하지만,
let
,const
로 선언된 변수의 호이스팅과 같은 더 세분화된 정보를 다룬다.
- this 바인딩
- 실행 컨텍스트가 참조하는
this
의 값이 결정되고 저장 - 함수 호출 방식(일반 함수 호출, 메서드 호출, 생성자 함수 호출 등)에 따라
this
의 값이 달라진다.
- 실행 컨텍스트가 참조하는
실행 컨텍스트의 생성 및 수명 주기
실행 컨텍스트의 수명 주기는 다음과 같은 단계로 이루어지다.
- 생성 단계
- 실행 컨텍스트 스택(EC Stack)에 새로운 컨텍스트가 푸시된다.
- 스코프 체인이 형성되고, 변수 객체가 활성화된다.
- 외부 환경 정보와
this
바인딩이 설정된다.
- 실행 단계
- 변수와 함수 선언이 메모리에 할당되고 초기화된다.
- 코드 실행이 진행되며, 실시간으로 변수 값이 업데이트되거나 함수가 호출된다.
- 종료 단계
- 실행 컨텍스트의 코드 실행이 완료되면 해당 컨텍스트는 스택에서 팝된다.
- 모든 로컬 변수와 함수 정의가 메모리에서 제거(클로저가 있는 경우를 제외).
소스코드의 타입
ECMAScript 사양은 소스코드를 4가지 타입으로 구분하는데 이는 4가지 타입에 따라 실행 컨텍스트를 생성하는 과정과 관리 내용이 다르기 때문이다.
소스코드 타입 | 설명 | 동작 방식 |
---|---|---|
전역 코드 | 스크립트 최상위 레벨의 코드를 의미합니다. 전역 변수와 함수가 여기에 속합니다. | - 전역 컨텍스트가 생성되고, 전역 객체(window 또는 global)와 연결됩니다. - var 키워드로 선언된 변수와 함수 선언이 전역 객체에 저장됩니다. - 전역 코드가 평가되면 전역 실행 컨텍스트가 생성됩니다. |
함수 코드 | 함수 내부에서 작성된 코드를 의미합니다. | - 함수 컨텍스트가 생성되며, 각 함수 호출마다 새로운 컨텍스트가 스택에 푸시됩니다. - 지역 변수, 인자, 내부 함수, arguments 객체가 스코프에 포함됩니다. |
eval 코드 | eval() 함수 내부에 있는 코드 블록을 의미합니다. | - 독립적인 컨텍스트가 생성되어, eval 내부의 코드를 평가합니다. - eval 코드의 스코프는 eval이 호출된 컨텍스트에 종속됩니다. |
모듈 코드 | ES6 모듈의 코드를 의미합니다. 모듈 스코프는 해당 모듈 내부로 제한됩니다. | - 모듈별로 독립된 컨텍스트가 생성됩니다. - 모듈 내부에서 선언된 변수, 함수, 클래스 등이 모듈 스코프에 포함됩니다. |
소스코드의 평가와 실행
모든 소스코드는 실행하기 전에 평가 과정을 거치며 코드를 실행하기 위한 준비를 한다. 자바스크립트엔진은 소스코드의 평가
와 소스코드의 실행
과정으로 나누어 처리한다.
소스코드 평가 과정에서 실행 컨텍스트를 생성하고 변수, 함수의 선언문만 먼저 실행하여 생성된 변수나 함수 식별자를 키로 실행 컨텍스트가 관리하는 스코프(렉시컬 환경의 환경 레코드)에 등록한다.
소스코드가 평가되고 끝나면 선언문을 제외한 소스코드가 순차적으로 런타임이 시작된다. 이때 소스코드가 실행하기 위한 정보, 즉 변수나 함수의 참조를 실행 컨텍스트가 관리하는 스코프에서 검색해 얻는다.
값이 변경된 변수나 소스코드의 실행결과는 다시 실행 컨텍스트가 관리하는 스코프에 등록된다.
예를 들자면
var x;
x = 1;
자바스크립트 엔진에서는 소스코드의 **평가
와** **실행**
2가지 과정으로 나누어 처리하는데, 먼저 평가 과정에서 변수 선언문 var x
를 실행한다. 생성된 변수 식별자 x
는 실행 컨택스트
가 관리하는 스코프
에 등록되고 undefined
로 초기화한다.
실행 과정에서는 변수 할당문 x = 1;
만 실행된다. 이때 x
변수에 값을 할당하려면 먼저 x
변수가 선언된 변수인지 확인해야 하는데 이를 위해 실행 컨텍스트
가 관리하는 스코프에 x
변수가 선언 되어있는지 확인하고 선언 되어있다면 값을 할당하고 할당 결과를 실행 컨텍스트
에 등록하여 관리한다.
실행 컨텍스트의 역할
실행 컨텍스트의 역할은 무엇이 있을까? 예제를 살펴보자
// 전역 변수 선언
const x = 1;
const y = 2;
function foo(a) {
// 지역 변수 선언
const x = 10;
const y = 20;
//메서드 호출
console.log(a + x + y);
}
// 함수 호출
foo(100);
// 메서드 호출
console.log(x + y);
- 전역 코드 평가
전역 코드 평가 과정
에서는 선언문만 먼저 실행된다. 따라서변수 선언문
과함수 선언문
이 먼저 실행되고, 그결과 생성된전역 변수
와전역 함수
가실행 컨텍스트
가 관리하는전역 스코프
에 등록된다. 이때var 키워드
로 선언된전역 변수
와함수 선언문으로 정의된 전역 함수
는전역 객체
의 프로퍼티와 메서드가 된다.- 전역 코드 실행
전역 코드 평가 과정
이 끝나면 런타임이 시작되어 전역 코드가 순차적으로 실행되기 시작한다.- 전역 변수에 값이 할당 및 함수 호출
- 함수 호출시 순차적으로 실행되고 있던 전역 코드의 실행이 일시 중단하고 함수 내부로 진입한다.
- 함수 코드 평가
- 전역 코드 실행중 함수가 호출되면
함수 코드 평가 과정
이 시작된다. - 매개변수와 지역 변수 선언문이 먼저 실행하여
매개변수
와지역 변수
가실행 컨텍스트
가 관리하는**지역 스코프**
에 등록된다. - 함수 내부에서 지역 변수처럼 사용할 수 있는
arguments
객체가 생성되어지역 스코프
에 등록되고this 바인딩
도 결정된다.
- 전역 코드 실행중 함수가 호출되면
- 함수 코드 실행
매개변수
와지역 변수
에 값이 할당되고console.log
메서드가 호출된다.console.log
메서드를 호출하기 위해스코프 체인
을 통해 검색한다. 이를 위해함수 코드의 지역 스코프
는 상위 스코프인 전역 스코프와 연결되어야 하는데console 식별자
는 전역 객체에 프로퍼티에 존재한다. 이는 전역 객체의 프로퍼티가 마치 전역 변수처럼 전역 스코프를 통해 검색이 가능해야 한다는 의미이다.log
프로퍼티를console 객체
의프로토타입 체인
을 통해 검색한다.console.log
메서드에 인수로 전달된 표현식 a + x + y가 평가된다. (a, x, y 식별자는스코프 체인
을 통해 검색한다).console.log
메서드의 실행이 종료되면 함수 코드 실행 과정이 종료되고 함수 호출 이전으로 되돌아가 전역 코드 실행을 계속한다.
위 코드를 실행하기 위해서는 스코프를 구분하여 식별자
와 바인딩된 값
이 관리되어야한다. 그리고 중첩 관계에 의해 스코프 체인
을 형성하여 식별자
를 검색할 수 있어야하고, 전역 객체
의 프로퍼티도 전역 변수
처럼 검색 할 수 있어야 한다. 즉 스코프
, 식별자
, 코드 실행 순서
등의 관리가 필요하다.
실행 컨텍스트
는 식별자(변수, 함수, 클래스 등의 이름)을 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 메커니즘으로, 모든 코드는 실행 컨텍스트
를 통해 실행되고 관리된다.
식별자
와 스코프
는 실행 컨텍스트
의 렉시컬 환경으로 관리하고 코드 실행 순서
는 실행 컨텍스트 스택으로 관리한다.
실행 컨텍스트 스택
[출처: 모던 자바스크립트]
const x = 1;
function foo() {
const y = 2;
function bar() {
const z = 3;
console.log(x + y + z);
}
bar();
}
foo(); // 6
위 소스코드는 전역 코드와 함수 코드로 이루어져 있다.
실행 컨텍스트는 스택 자료구조로 관리한다. 이를 실행 컨텍스트 스택
이라고 부른다.
📔 스택(stack)은 말 그대로 '쌓아놓은 더미'를 뜻합니다. 식당에 쌓여있는 접시 더미, 책상에 쌓인 책, 겹겹이 쌓인 상자 모두 스택의 예에 해당합니다. 이 중에서도 가장 대표적인 예시로 '프링글스(Pringles)'를 들 수 있겠습니다. 스택의 가장 큰 특징은 후입선출('LIFO') 입니다.가장 최근에 들어온 데이터가 가장 먼저 나간다
- 전역 코드의 평가와 실행
- 자바스크립트 엔진은 전역 코드를 평가하여
전역 실행 컨텍스트
를 생성하고실행 컨텍스트
에 푸시한다. 전역 변수 x
와전역 함수 foo
는 전역 실행 컨텍스트에 등록된다.- 전역 코드가 실행되기 시작하면
전역 변수 x
에 값이 할당되고전역 함수 foo
가 호출된다.
- 자바스크립트 엔진은 전역 코드를 평가하여
- foo 함수 코드의 평가와 실행
전역함수 foo
가 호출되면 전역 코드의 실행은 일시 중단되고 코드 제어권이 foo 함수 내부로 이동- 자바스크립트 엔진은
foo 함수
내부의 함수 코드를 평가하여foo 함수 실행 컨텍스트
를 생성하고실행 컨텍스트 스택
에 푸시한다. - foo 함수의
지역 변수 y
와중첩 함수 bar
가 foo함수 실행 컨텍스트에 등록된다. **foo 함수
코드가 실행되기 시작하여 지역 변수 **y
에 값이 할당되고 중첩 함수 bar가 호출된다.
- bar 함수 코드의 평가와 실행
중첩 함수 bar
가 호출되면 foo 함수 코드의 실행은 일시 중단되고 코드의 제어권이 bar 함수 내부로 이동한다.- 자바스크립트 엔진은 bar 함수 내부의 함수 코드를 평가하여
bar 함수 실행 컨텍스트
를 생성하고실행 컨텍스트 스택
에 푸시한다. - bar 함수의 지역 변수 z가 bar 함수 실행 컨택스트에 등록된다.
- bar 함수코드가 실행되기 시작하여 지역 변수 z에 값이 할당되고 console.log 메서드를 호출한 이후 bar 함수는 종료된다.
- foo 함수 코드의 평가와 실행
- bar 함수가 종료되면 foo함수로 제어권이 다시 넘어간다.
- 자바스크립트 엔진은 bar 함수 실행 컨텍스트를 실행 컨텍스트 스택에서 팝하여 제거한다.
- foo 함수는 더 이상 실행할 코드가 없어 종료된다.
- 전역코드 복귀
foo 함수
가 종료되면 전역 코드로 제어권이 이동된다.- 자바스크립트 엔진은
foo 함수 실행 컨텍스트
를 실행 컨텍스트 스택에서 팝하여 제거한다. - 더 이상 실행할 코드가 존재하지 않아
**전역 실행 컨텍스트**
도 스택에서 팝하여 제거한다.
결론
실행 컨텍스트 스택
은 코드의 실행 순서를 관리한다. 실행 컨텍스트 스택
의 최상위에 존재하는 실행 컨텍스트
는 언제나 현재 실행 중인 코드의 실행 컨텍스트
다.
'Javascript' 카테고리의 다른 글
자바스크립트 - this (0) | 2024.04.17 |
---|---|
프로토타입 (0) | 2024.04.15 |
자바스크립트 - 일급 객체 (0) | 2024.04.09 |
자바스크립트 - 프로퍼티 어트리뷰트(property attribute) (0) | 2024.04.09 |
자바스크립트 - var, const, let? (0) | 2024.04.09 |