3-실행컨텍스트와-스코프
코드 블록의 Try it Yourself 버튼으로 직접 실행할 수 있다.
구문
목차
ECMAScript는 4가지로 소스코드를 구분한다. 4가지 타입의 소스코드는 실행 컨텍스트를 생성한다.
- 전역코드 - 전역에 존재하는 소스코드
- 함수코드 - 함수 내의 코드
- eval 코드 - eval 함수의 인수로 전달된 실행 코드
- 모듈코드 - 모듈내의 코드 위 4가지 타입별 실행컨텍스트의 생성과정과 관리방법의 차이가 있으나 1과 2의 사용빈도가 높으므로 이것만 다루도록 한다.
1-실행컨텍스트(Excution Context)
1-1-정의
자바스크립트 코드가 실행되는 공간(환경)
1-2-종류
ECMA사양은(ECMAscript 표준) 소스코드를 4가지로 구분한다. 그리고 이 4종류의 소스코드는 실행콘텍스트를 생성한다.
- 전역코드
- 함수코드
- eval 코드
- 모듈코드 그러나 이번에는 전역코드와 함수코드의 실행 컨텍스트 만을 다룬다.
2-스코프
2-1-정의
식별자를 참조할수 있는 범위
2-1-종류
- 전역 스코프
- 지역 스코프
3-호이스팅
3-1-정의
코드를 선언과 할당으로 분리하고 선언부분을 최상위로 끌어올리는것
3-2-순서도
아래 그림에 표시된 단계에서 발생한다.

3-3-실습
3-3-1-선언적 함수
abc()
//함수'선언문'
function abc(){ console.log('bb')}
위의 함수는 선언문** ****으로 생성 되었으므로 **호이스팅이 발생하여 최상위로 끌어올려진다 함수의 정의전 호출이 되었음에도 값이 출력된다.
3-3-2-표현식 함수
:2: const, let
df();
const fn = function df() { console.log('bb') }
위의 함수는 오류가 반환된다. df 함수는 fn 변수에 할당 되었기 때문에 더이상 df 로 호출할수 없다.

그렇다면 fn을 호출하는 것은 가능할까?
**fn();**
//df();
const fn = function df() { console.log('bb') }
이번에도 오류가 나는데 콘솔 오류 메시지가 다르다.
이 부분은 실행컨텍스트를 학습하면 이해할수 있다.
변수의 키워드를 const, let 으로 선언하면 모두 위와 같은 오류메시지가 확인된다.
:2: var
var 키워드에 함수를 할당하면 어떻게 될까?
fn();
var fn = function df() { console.log('bb') }
오류메시지의 내용이 다르게 확인된다.
fn 이라는 식별자는 어디에도 선언되지 않았음에도 왜 함수가 아니라고 하는걸까?
var 키워드로 선언된 변수는 아래와 같은 순서로 평가된다.

19: fn 에는 undefined 가 할당되어 초기화된다. 20: fn이 존재하긴 하나 undefined 가 할당되어 있으므로 함수가 아니다. 21: fn 식별자에 df 함수를 재할당 한다.
4-실행컨텍스트 이해
자바스크립트 엔진이 소스코드를 평가하고 실행하는 독립적인 공간이다. 실행 컨텍스트는 정확히 Environment Record, **Outer **Environment Reference, This Binding으로 구성된다. 그러나 이번에는 쉬운 이해를 위해 레코드와 아우터만 다룰것이다.
4-1-구성요소
| 이름 | 설명 |
|---|---|
| 레코드(Environment Record ) | 변수, 함수 선언 등을 저장하는 공간 |
| **아우터 환경 참조(****Outer **Environment Reference) | 외부 실행 컨텍스트(상위 스코프)를 가리키는 참조값 |
| this 바인딩 | 해당 컨텍스트에서의 this 값 |
- 실행컨텍스트는 레코드와 아우터를 가지며 스택이라는 자료구조로 쌓여서 관리된다.

4-2-관리(스택)
- 실행 컨텍스트는 **실행 컨텍스트 스택(Call Stack)**이라는 자료구조에 쌓여서 관리된다.
- 자바스크립트 엔진은 현재 실행 중인 실행 컨텍스트를 스택의 **맨 위(top)**에 두고, 코드 블록 단위가 실행될 때마다 새 컨텍스트를 생성한다.
- 코드의 실행이 끝나면 해당 컨텍스트를 스택에서 제거한다.
4-2-1-스택의 자료관리 방법

- 실행이 끝난 스택의 실행컨텍스트는 제거되는데 이때의 순서는 위에서부터 제거된다.
- 3→2→1 순으로 스택에서 제거된다.

Info: 나중에 들어온 것을 먼저 처리하고 처음에 들어온 것을 마지막으로 내보내어 스택을 **후입선출(LIFO:Last In Fist Out) **라고 부른다.
4-3-동작
실행컨텍스트의 동작은 크게 생성단계과 실행단계으로 나누어 볼수있다.
:3:4-3-1-생성(Creation Phase)
생성 단계에서는 코드블럭의 선언부를 레코드에 수집한다.
| 구분 | 설명 |
|---|---|
| 환경 레코드(Environment Record) 생성 | 변수, 함수 선언 정보를 저장할 메모리 공간을 확보. |
| 선언부(변수 선언, 함수 선언) 수집 | 이 선언 정보들을 환경 레코드에 등록 (호이스팅 과정과 연결됨). |
| 외부 환경 참조 (Outret Environment Reference)설정 | 상위 스코프 정보 저장. |
| this 바인딩 결정 | 실행 컨텍스트에서 사용할 this 값 결정. |
:3:4-2-3-2-실행(Execution Phase)
실행 단계는 말 그대로 "코드를 실제로 실행하는 단계"이다.
| 구분 | 설명 |
|---|---|
| 변수 값 할당 | 선언된 변수에 실제 값 채워넣기 |
| 함수 실행 | 함수 호출 시 실행하고 반환값 처리 |
| 연산 및 로직 처리 | if, for 등 조건문, 반복문 실행 |
| this 활용 | 컨텍스트에 설정된 this 값을 코드에서 참조 |
:3:4-3-3-코드 평가 순서
자바스크립트 엔진은 프로그램 실행시 최소 한개의 실행 컨텍스트가 생성되며 프로그램 종료시까지 유지한다.

- 소스코드가 로드되면 실행컨텍스트가 생성되고 스택에 푸쉬한다.
- 실행컨텍스트 내에 렉시컬 환경(Lexical Environment)이 생성된다.
- 렉시컬환경에서 레코드와 아우터로 구성된다.
:3:4-3-3-1-레코드(Environment Record)
- 기능: 변수와 함수의 선언 수집,저장 (환경레코드)
- 환경레코드의 종류
| 환경 레코드 | 종류 | 설명 |
|---|---|---|
| 객체 환경 레코드 | 전역 환경 레코드 | var변수선언, 전역 객체(window, globalThis)와 연결됨 |
| with 환경 레코드 | with 문 사용 시 생성됨 | |
| 모듈 환경 레코드 | ES6 모듈의 import, export를 관리. | |
| 선언적 환경 레코드 | 함수 환경 레코드 | 함수 실행 시 매개변수 및 변수 저장. |
| 블록 환경 레코드 | {} 블록 내부에서 let, const 선언 관리. | |
| catch 환경 레코드 | catch (error)에서 예외 변수 관리. | |
| 클래스 환경 레코드 | 클래스 선언 시 생성됨. |
- 특징:
- 선언적 환경 레코드는 객체 형태가 아니라 별도의 내부 구조로 저장됨.
let,const변수는 **TDZ(Temporal Dead Zone)**에 영향을 받으며, 초기화 전에 접근 시 에러가 발생함.- 함수 실행 시 매개변수 정보도 환경 레코드에 저장됨.
:3:4-3-3-2-아우터(외부환경참조 Outer Environment Reference)
- 기능: 스코프 체인을 따라 탐색하는 과정에서 사용되는 참조값 변수 및 함수가 내부환경에 없으면 Outer를 통해 상위 실행 컨텍스트의 렉시컬환경 내 환경 레코드를 탐색

5-스코프(Scope)의 이해
- 정의 : 변수나 함수의 유효범위
- 스코프에서 접근 가능한 값은 렉시컬 환경의 환경 레코드에 저장된 변수 및 함수의 값이다.

| 종류 | 설명 | |
|---|---|---|
| 전역 스코프 (Global Scope) | 코드 어디서든 접근 가능한 변수 (var, let, const 가능). | |
| 지역 스코프 (Local Scope) | 함수 스코프 (Function Scope) | 함수 내부에서 선언된 변수는 함수 내부에서만 사용 가능 (var, let, const 적용). |
| 블록 스코프 (Block Scope) | {} 중괄호 내부에서 선언된 변수는 해당 블록 내에서만 사용 가능 (let, const 적용). | |
| 모듈 스코프 (Module Scope) | ES6 import, export를 사용하는 모듈 내부의 변수는 해당 모듈에서만 접근 가능. | |
| 캣치 스코프 (Catch Scope) | try...catch에서 catch(error)의 error 변수는 catch 블록 내부에서만 접근 가능. |
6-실습
이제 실행컨텍스트의 동작과정을 연상하면서 변수의 호이스팅에 대해 이해해보자.
6-1-전역 실행 컨텍스트
Info: 전역코드는 평가시 전역 실행 컨텍스트가 생성된다.
6-1-1-var, let, const 의 호이스팅
6-1-1-1-**:3:**var
console.log(x);
var x=1;

위와 같은 결과가 나오는 원인을 실행 콘텍스트에 대입하여 추론 해볼수 있다.
- 우선 아래와 같은 순서로 소스코드는 평가 된다.

var,const,let으로 선언한 변수들은 호이스팅이 발생하며 호이스팅이란 실행컨텍스트가 생성되는 단계에서 발생하는 것을 이해할수 있다.- 호이스팅은 앞서 코드를 선언과 할당으로 나누고 선언부를 우선 기록해 놓는것 이라고 설명했다.
- 위 코드의 선언부는 var 키워드로 정의하고 있으며 var은 객체 환경 레코드로 수집된다.
- 객체 환경 레코드는 자바스크립트에서 내부적으로 선언과 동시에 undefined로 초기화 된다.
- 그러므로 아래와 같은 과정에 의해 값이 undefined 로 평가 된 것 이다.

6-1-1-2-**:3:**const, let
console.log(x);
const x=1;

- 변수의 선언 키워드를 const 나 let 으로 변경하고 결과를 보면 초기화 되지않아 접근할수 없다는 메시지가 나온다.
- const,let 은 선언적 환경 레코드 > 블록레코드 이고 이것은 자바스크립트에서 선언과 초기화를 분리하여 쓰도록 설계되어 있다.

- 이제 초기화 되지않아 접근할수 없다는 메시지가 나오는것을 납득할수 있다.
Info:
- `let`, `const`는**초기화되지 않고, 선언만 메모리에 올라가므로 **그래서 선언 전에 접근하려고 하면 **ReferenceError**가 발생한다.
- 이 구간을 **"TDZ(Temporal Dead Zone, 일시적 사각지대)" **라고 부른다
:3::3: 3-3-2-표현식 함수** 또한 위와 같은 내용이다.**
6-1-2-문제
아래의 두 코드의 실행결과를 확인후 실행과정을 설명해주세요
- 전역실행컨텍스트의 생성과 실행 단계를 나누어 보세요.
1번코드
console.log(x);
let x = 1;
2번코드
let x;
console.log(x);
x = 1;
6-2-함수 실행 컨텍스트
Info: 함수코드는 평가시 함수 실행 컨텍스트가 생성된다.
✅ 생성 단계 이 단계에서는 실행 컨텍스트가 생성되지만 아직 코드가 실행되지 않는다
- 함수 스코프(환경) 생성
- 실행 컨텍스트를 위한 VO(Variable Object) 또는 Lexical Environment가 만들어진다.
- 함수 내부에서 선언된 변수, 함수 선언문,
arguments객체 등이 저장.
- 변수 및 함수 선언 처리
var키워드로 선언된 변수는 **초기값 **undefined로 설정.let과const로 선언된 변수는 일시적 사각지대(TDZ: Temporal Dead Zone) 에 배치되어 접근이 불가.- 함수 선언문(Function Declaration)은 전체 함수가 메모리에 저장.
this** 바인딩 결정**- 실행 컨텍스트가 전역 함수라면
this는window(브라우저 환경) 또는global(Node.js 환경)을 가리킨다. - 실행 컨텍스트가 객체의 메서드라면
this는 해당 객체를 가리키다. bind,call,apply를 사용하면this가 명시적으로 지정된다. ✅ 실행 단계 함수 내부의 코드의 실행
- 실행 컨텍스트가 전역 함수라면
- 변수 할당
var변수는 이미undefined로 초기화되어 있으므로, 이제 실제 값을 할당한다.let,const변수는 선언 시점(= 코드 실행 시점)에서 할당된다.
- 연산 및 로직 실행
- 함수 내부에서 연산, 조건문, 반복문 등이 실행된다.
return문이 실행되면 함수가 종료되며 실행 컨텍스트가 제거된다.
6-2-1-선언적함수
아래의 코드를 살펴보자
function a() {
console.log("my name is a");
}
a();
console.log("2");

위와 같은 결과값이 나온다. 그럼 과정을 살펴보자.
- 생성

- 실행


- 프로그램이 종료될 때까지 전역실행컨텍스트는 존재한다. 아래의 코드를 살펴보자
function sum() {
//console.log(arguments);
return arguments['0'] + arguments['1'];
}
console.log(sum(1, 2));
sum 함수는 매개변수가 없는데 return의 값을 확인할수 있다. 이유는 함수실행컨텍스트> 렉시컬환경>arguments 라는 객체가 포함되어 있으며 함수 호출시 전달된 모든 인수를 담고 있기 때문이다.
6-2-2-문제
아래 코드가 실행될 때, 함수 실행 컨텍스트의 실행 과정을 단계별로 설명하세요.
function a() {
console.log("my name is a");
function c() {
console.log("my name is c");
}
}
a();
console.log("2");