JavaScript 실행 컨텍스트

김진효·2026년 5월 4일

[CS] FE

목록 보기
3/3
post-thumbnail

실행 컨텍스트는 스코프 체인, 클로저, 변수 호이스팅, this 등의 동작 원리를 담고있다
모두 다 면접에 많이 나오는 개념이라 이를 이해해야 함 ·ࡇ·

찾아보니 ES3 시점과 ES5 이후에 실행 컨텍스트가 달라졌다고 하는데
이걸 포스팅 쓰는 중간 지점에 알았다...
그래서 이왕 정리한거 이를 같이 다뤄볼까 한다
근데 깊게 들어가지는 않을거다 정말 정말 가볍게 보자..!

실행 컨텍스트

Execution Context
자바스크립트 코드가 실행되는 환경
실행에 필요한 여러가지 정보들을 담고 있음

ES3 기준

execution_context_es3

실행 컨텍스트는 크게 전역, 함수 컨텍스트가 있다
전역 컨텍스트는 최상단에 위치하고 전역이라 호출 주체가 없으니 매개변수와 인수 정보 프로퍼티를 가지지 않는다

  • Variable Object
    변수객체
    코드 실행에 필요한 변수 및 함수 정보를 저장하는 곳
    변수, 함수 선언, 매개변수의 인수 정보 등이 담긴다

  • Scope Chain
    Scope(스코프) : 식별자(변수, 매개변수, 함수)의 유효 범위
    스코프 체인은 현재 스코프 레벨에서 변수가 존재하지 않는 경우 상위 스코프에서 찾는, 안에서 바깥쪽으로 단계적으로 변수를 탐색하는 과정을 의미한다 (내부 → 외부 → 전체)
    참고로 객체의 프로퍼티를 검색하는 과정은 프로토타입 체인(Prototype Chain)이라고 함!

  • this
    함수가 호출되는 방식에 따라 자신이 속한 객체나 생성할 인스턴스를 동적으로 가리키는 자기 참조 변수


ES5 이후

'물리적인 객체 구조(Object-based)'에서 '논리적인 환경 구조(Environment-based)'로 변화!

execution_context_es5

실행 컨텍스트 종류로 Eval 실행 컨텍스트가 추가로 있지만
JS에서는 eval()을 사용하지 말라는 이야기가 무성하기 때문에 자세한 설명은 스킵..
그 이유는 아래 영상을 참고하면 될 것 같다.. ^-^
요즘 사람들은 잘 모르는 위험한 JS 함수

VariableEnvironmentLexicalEnvironment는 변수의 유효 범위(Scope)를 결정하고 식별자를 바인딩하는 환경
LexicalEnvironment 가 중요하므로 이를 중점적으로 설명하겠다

  • VariableEnvironment
    선언 시점의 초기 상태의 변수를 보존하는 LexicalEnvironment의 스냅샷
    생성 당시의 모습을 그대로 유지하며 변경사항은 반영되지 않음
    var의 유효 범위를 보장
  • LexicalEnvironment
    변수의 변경 사항이 실시간으로 반영되며 변수의 최신 상태을 보존하는 환경
    • EnvironmentRecord
      변수 및 함수 선언이 저장되는 공간으로 식별자와 값의 바인딩을 관리
    • OuterEnvironmentReference
      호출된 함수가 선언될 당시의 Lexical Environment를 참조하는 포인터
      연결리스트의 형태를 띈다
      스코프 체인을 가능하게 함
  • ThisBinding
    this 식별자가 바라보고 있는 대상 객체를 결정

왜 이런식으로 바꿨을까?

  • 객체 형태로 저장하는게 아닌 논리적이고 추상적인 환경 구조로 정의하여 JS 성능을 올리기 위해 (HashMap과 같이)
    → 간단히 말하면 최적화 및 성능 개선
  • es3 때는 변수 선언 타입이 var 밖에 없었으며 이는 블록 스코프가 적용되지 않음
    → 이후 등장할 let, const 및 블록 스코프를 지원하기 위해 구조 분리 준비

실행 컨텍스트의 생성 과정

ES3

  1. 스코프 체인의 생성과 초기화
  2. Variable Instantiation(변수 객체화) 실행
  3. this value 결정

ES5 이후

  1. 생성 단계(Creation Phase)
    • LexicalEnvironment 생성 (식별자 바인딩+스코프 체인)
    • VariableEnvironment 생성
    • ThisBinding 결정
  2. 실행 단계(Execution Phase)
    모든 변수에 대한 할당이 수행되고 코드가 최종적으로 실행

실행 컨텍스트 실행 과정

execution_context_stack

실행 컨텍스트는 call stack에서 생성되고 소멸된다
현재 실행 중인 컨텍스트에서 새로운 함수가 호출되면 새로운 실행 컨텍스트가 생성되는데, 해당 컨텍스트가 그대로 스택에 쌓이면서 제어권이 이동한다고 보면 된다.
함수 실행이 끝나면 해당 컨텍스트는 스택에서 제거되고, 제어권은 자동으로 아래에 있던 컨텍스트로 돌아온다


호이스팅(hoisting)

변수 및 함수 선언문이 스코프 내의 최상단으로 끌어올려지는 것처럼 동작하는 현상
선언이 되어 엔진이 변수의 존재를 알고 있다는 것에 초점을 맞추자!
이는 변수의 선언 처리에 대한 이해가 필요하며 var, let, const 모두 호이스팅이 일어나긴 하나 동작 방식에서 차이가 있다

- 선언 단계(Declaration phase)
	환경 레코드(Environment Record)에 식별자를 등록
	이 변수 객체는 스코프가 참조할 수 있는 대상이 된다
    
- 초기화 단계(Initialization phase)
	환경 레코드에 등록된 식별자를 위한 메모리 공간을 확보하고 바인딩
    - var: 선언과 동시에 undefined로 초기화
    - let, const: 실제 선언문에 도달하기 전까지는 초기화되지 않아 '비어있는' 상태(TDZ)가 유지
  
- 할당 단계(Assignment phase)
  실행 단계(Execution Phase)에서 코드가 실행되며, 식별자에 실제 값을 연결(바인딩)한다

var 로 선언한 변수의 경우 '선언+초기화'가 한번에 이루어지기 때문에 선언문 이전에 변수에 접근하여도 에러가 발생하는 대신 초기화 값인 undefined를 반환하게 된다

// 호이스팅
console.log(x); // undefined
var x = 5;		// 선언 및 할당
// 위 코드와 동일하게 동작
var x; 			// 선언
console.log(x); // undefined

var x = 5;		// 할당

간혹 보면 이 호이스팅 때문에 var을 사용을 권장하지 않는다라는 말도 있는데, 바로 이 undefined를 반환하면서 예기치 못한 문제가 발생할 수 있기 때문이다!
서비스 화면에 undefined 라고 뜬다..? 서비스 구현 전에 에러로 떴다면 알았을텐데 ( ˘̩̩̩ω˘̩̩̩ )

TDZ (Temporal Dead Zone)

일시적 사각지대
선언만 되고 아직 초기화 되지 않는 변수가 머무는 공간
변수가 호이스팅 되어 스코프에 등록은 되지만 초기화 되지 않아 메모리에는 없기 때문에 접근 시 참조 에러(ReferenceError)를 발생 → 잠재적인 오류 방지

처음에는 이 개념을 보고 에러가 나는데 왜 letconst도 호이스팅이 된다고 표현할까? 라고 의문이 들었었다 🤔
그래서 이에 대해 조그만 더 풀어보자면
호이스팅이 일어나지 않았을 때 에러 메시지가 어떻게 나왔을지 가정해보고 예시를 살펴보자

// 만약 엔진이 변수 존재를 아예 몰랐다면
Uncaught ReferenceError: x is not defined

// 그 변수 존재하는거 아는데 초기화가 안됐으니 사용하지마
Uncaught ReferenceError: Cannot access 'x' before initialization

let x = "전역";       // 전역 스코프
{
  // (만약 호이스팅이 없다면?) "전역"이 출력되어야 하지만 ReferenceError 발생
  console.log(x);    // TDZ 구간 
  let x = "블록";    // 블록 스코프
}

위와 같이 let, const 또한 호이스팅이 되지만 var와 동작 방식이 다르다고 이해하면 될 것 같다

또한, 변수에 초점을 맞추어서 이야기했는데 함수의 경우 함수 선언은 호이스팅 되지만 함수 표현식은 호이스팅 되지 않음 (변수 호이스팅의 규칙을 따르기 때문)

// 함수 선언 (호이스팅 O)
console.log(func1()) // True (정상실행)
function func1(){
	return true
}


// 함수표현식
console.log(func2);   // var라면 undefined, let/const라면 TDZ 에러!
console.log(func2()); // 당연히 호출 불가능 (is not a function)

var func2 = function() { return true; };

클로저

함수가 선언될 당시의 렉시컬 환경을 기억하여, 함수가 해당 스코프 밖에서 실행될 때도 그 스코프에 접근할 수 있게 하는 기능이다

function outer() {
  let a = 2;
  // inner 함수 객체 자체가 생성될 때 자신의 내부 슬롯 [[Environment]]에 당시의 렉시컬 환경 주소를 저장
  function inner() {
    console.log(a);
  }
  return inner;
}
var func = outer();
func(); // 2

OuterEnvironmentReference를 타고 올라가서 EnvironmentRecord에 적힌 변수 값을 읽어옴!

추가 개념

Lexical Scope (렉시컬 스코프)

함수를 호출한 곳이 아닌 선언한 곳을 기준으로 스코프를 결정하는 원칙
정적 스코프(Static Scope)라고 부르기도 한다

렉시컬 환경과 렉시컬 스코프는 엄연히 다르니 구분하자..
렉시컬 스코프는 범위를 결정하는 규칙이고
렉시컬 환경은 변수의 변경 사항이 실시간으로 반영되며 변수의 최신 상태을 보존하는 환경

면접 질문과 답변

실행 컨텍스트에 대해 설명해주세요

실행에 필요한 여러 정보들을 담고 있는 추상적인 객체이자 환경으로 변수 및 함수 선언, 스코프와, this 바인딩 정보들을 담고 있습니다.
실행 컨텍스트는 크게 전역 컨텍스트와 함수 컨텍스트로 나뉘며, 전역 컨텍스트부터 최상위에 만들어져 콜스택에 쌓이며 함수 등을 만나면 새로운 실행 컨텍스트 생성에 따라 제어권이 이동하는 형태로 실행이 됩니다.

(구체적으로)
VariableEnvironment와 LexicalEnvironment, ThisBinding 으로 구성되어 있으며 VariableEnvironment가 선언 시점의 초기 상태를 보존하고 LexicalEnvironment가 실행 시점의 변수의 최신 상태를 보존하는 환경입니다.
내부적으로 변수 및 함수 선언이 저장되는 EnvironmentRecord와 연결리스트 형태로 스코프 체인을 가능하게 하는 OuterEnvironmentReference 를 가지고 있습니다.

스코프 체인에 대해 설명해주세요

스코프 체인은 안에서 바깥쪽으로 단계적으로 변수를 탐색하는 과정을 의미합니다. 따라서 현재 스코프 레벨에서 변수가 존재하지 않을 경우 상위 스코프에서 해당 변수를 찾게 됩니다.

호이스팅에 대해 설명해주세요

변수 및 함수 선언문이 스코프 내의 최상단으로 끌어올려지는 것처럼 동작하는 현상을 말합니다.
실행 컨텍스트 생성 단계에서, 스코프 내의 식별자들을 미리 환경 레코드에 등록하기 때문에 발생하는 현상입니다.
이로 인해 실제 선언되는 코드 이전에 변수를 출력하려고 할 시 변수의 존재를 인지하고 있으며 undefind 또는 참조 에러가 나타나게 됩니다.

클로저에 대해 설명해주세요

함수가 선언될 당시의 렉시컬 환경을 기억하여, 함수가 해당 스코프 밖에서 실행될 때도 그 스코프에 접근할 수 있게 하는 기능입니다
즉, 자신의 실행 컨텍스트를 기억하고 있다가 다른 곳에서 호출되더라도 그 환경에 접근할 수 있게 해줍니다


참고

[JS] 📚 자바스크립트 실행 컨텍스트 원리
호이스팅(hoisting)이란?
클로저(Closure)란?
실행 문맥(실행 컨텍스트)
실행 컨텍스트, 어떻게 설명할 수 있을까?
클로저와 더 가까워지기
var/let/const로 알아보는 호이스팅과 TDZ
실행 컨텍스트와 자바스크립트의 동작 원리
[ES6] Javascript Execution Context(실행문맥, 실행컨텍스트)
자바스크립트의 실행 컨텍스트 (execution context)
[Javascript] 스코프 체인과 렉시컬 스코프

0개의 댓글