JavaScript를 깊이 있게 학습하다 보면 반드시 만나게 되는 개념이 Execution Context입니다.
대부분의 개발자는 변수 선언,
함수 호출,
스코프와 같은 문법을 먼저 배우지만,
실제로 JavaScript 엔진 내부에서는 이러한 코드들이 Execution Context라는 환경 안에서 실행됩니다.
Execution Context를 이해하면 Hoisting이 발생하는 이유,
Scope Chain이 만들어지는 과정,
this 바인딩이 결정되는 원리까지 함께 이해할 수 있습니다.
실제로 면접에서도 자주 등장하는 핵심 주제이며,
JavaScript 엔진이 코드를 처리하는 방식을 설명할 때 반드시 언급되는 개념입니다.
많은 개발자들이 결과만 외우는 경우가 많지만,
Execution Context의 생성 과정을 이해하면 예상하지 못한 코드 동작도 논리적으로 분석할 수 있습니다.
결국 Execution Context는 JavaScript 실행 구조의 중심이라고 볼 수 있습니다.
Execution Context란 무엇인가
Execution Context는 JavaScript 코드가 실행되기 위한 환경을 의미합니다.
엔진은 코드를 읽는 즉시 실행하지 않습니다.
먼저 현재 코드가 어떤 변수와 함수를 가지고 있는지 파악하고,
어떤 스코프를 사용할 것인지 결정한 뒤 실행을 시작합니다.
이 모든 정보가 저장되는 공간이 바로 Execution Context입니다.
쉽게 말해 JavaScript 엔진이 현재 실행 중인 코드를 관리하기 위해 생성하는 작업 공간이라고 생각할 수 있습니다.
모든 코드는 반드시 하나 이상의 Execution Context 안에서 실행됩니다.
따라서 JavaScript 프로그램이 동작한다는 것은
Execution Context가 생성되고 관리되는 과정이라고 볼 수 있습니다.
전역 실행 컨텍스트(Global Execution Context)
JavaScript 프로그램이 시작되면 가장 먼저 전역 실행 컨텍스트가 생성됩니다.
이는 프로그램 전체를 관리하는 최상위 실행 환경입니다.
전역 변수,
전역 함수,
전역 객체 등이 모두 이 영역에 포함됩니다.
브라우저 환경에서는 Window 객체가 전역 객체 역할을 수행하며,
Node.js 환경에서는 Global 객체가 해당 역할을 담당합니다.
프로그램이 종료될 때까지 전역 실행 컨텍스트는 유지됩니다.
모든 함수 실행 컨텍스트 역시 결국 전역 실행 컨텍스트를 기반으로 생성됩니다.
따라서 전역 실행 컨텍스트는 JavaScript 실행의 출발점이라고 할 수 있습니다.
함수 실행 컨텍스트(Function Execution Context)
함수가 호출되면 새로운 실행 컨텍스트가 생성됩니다.
이를 함수 실행 컨텍스트라고 부릅니다.
함수마다 독립적인 실행 환경을 가지며,
지역 변수와 매개변수도 이 공간에 저장됩니다.
만약 함수 내부에서 또 다른 함수를 호출한다면
새로운 실행 컨텍스트가 추가로 생성됩니다.
이러한 구조 덕분에 함수들은 서로 독립적으로 동작할 수 있습니다.
실행이 종료되면 해당 컨텍스트는 제거되고,
이전 실행 컨텍스트로 다시 돌아갑니다.
이 과정은 Call Stack을 통해 관리됩니다.
Execution Context 생성 단계
Execution Context는 크게 두 단계에 걸쳐 생성됩니다.
첫 번째는 생성 단계(Creation Phase)입니다.
두 번째는 실행 단계(Execution Phase)입니다.
생성 단계에서는 변수와 함수 정보를 수집합니다.
이 과정에서 스코프와 this 값도 결정됩니다.
실행 단계에서는 실제 코드가 한 줄씩 실행됩니다.
많은 개발자들이 변수 선언보다 함수 호출 결과에 집중하지만,
실제로 중요한 작업은 생성 단계에서 대부분 완료됩니다.
특히 Hoisting 현상 역시 이 생성 단계에서 발생합니다.
따라서 Execution Context를 이해하기 위해서는 생성 단계를 먼저 이해하는 것이 중요합니다.
Variable Environment 생성 과정
Execution Context가 생성되면 먼저 변수 저장 공간이 준비됩니다.
이를 Variable Environment라고 부릅니다.
함수 선언문은 이 단계에서 즉시 메모리에 저장됩니다.
따라서 코드 작성 위치와 관계없이 호출할 수 있게 됩니다.
var 키워드로 선언된 변수 역시 등록되지만
초기값은 undefined 상태로 설정됩니다.
이 때문에 선언 이전에도 접근이 가능해 보이는 현상이 발생합니다.
반면 let과 const는 별도의 방식으로 관리되며
초기화 전까지 접근할 수 없습니다.
이러한 차이가 Hoisting 관련 동작의 핵심 원인입니다.
Lexical Environment와 Scope Chain
Execution Context에는 Lexical Environment라는 구조도 생성됩니다.
이 공간은 현재 스코프에 존재하는 변수와 함수 정보를 관리합니다.
또한 외부 스코프와의 연결 정보도 저장됩니다.
JavaScript 엔진은 변수를 찾을 때
현재 Lexical Environment부터 탐색합니다.
만약 찾지 못하면 외부 환경을 순차적으로 탐색합니다.
이러한 탐색 구조를 Scope Chain이라고 부릅니다.
Closure 역시 이 Lexical Environment 구조를 기반으로 동작합니다.
따라서 Execution Context를 이해하면 Scope Chain과 Closure를 동시에 이해할 수 있습니다.
this 바인딩은 언제 결정될까
많은 개발자들이 this 때문에 어려움을 겪습니다.
실제로 this 값은 Execution Context 생성 과정에서 결정됩니다.
전역 실행 컨텍스트에서는 전역 객체가 this로 설정됩니다.
일반 함수 호출에서는 호출 방식에 따라 값이 달라집니다.
객체 메서드로 호출되면 해당 객체가 this가 되고,
생성자 함수로 호출되면 새로 생성된 객체가 this가 됩니다.
Arrow Function은 자체 this를 가지지 않고
외부 Execution Context의 this를 그대로 사용합니다.
이러한 동작 역시 모두 Execution Context 생성 과정에서 결정됩니다.
Call Stack과 Execution Context의 관계
Execution Context는 Call Stack에 저장됩니다.
프로그램이 시작되면 전역 실행 컨텍스트가 Stack에 추가됩니다.
함수가 호출될 때마다 새로운 실행 컨텍스트가 Stack 위에 쌓입니다.
현재 실행 중인 코드는 항상 Stack 최상단 컨텍스트에 존재합니다.
함수 실행이 끝나면 해당 컨텍스트는 제거됩니다.
이후 이전 컨텍스트로 제어권이 다시 이동합니다.
이러한 구조 덕분에 JavaScript는 함수 실행 순서를 체계적으로 관리할 수 있습니다.
Execution Context와 Call Stack은 사실상 함께 동작하는 핵심 시스템이라고 볼 수 있습니다.
실무에서 Execution Context를 알아야 하는 이유
Execution Context는 단순한 이론이 아닙니다.
실제 개발 과정에서 매우 중요한 역할을 합니다.
Hoisting 문제를 분석하거나,
this 동작 방식을 이해하거나,
Closure 관련 버그를 디버깅할 때 반드시 필요한 개념입니다.
또한 React Hook의 동작 원리나 상태 관리 흐름을 이해하는 과정에서도 도움이 됩니다.
복잡한 함수 호출 구조를 분석할 때 역시 Execution Context 지식이 큰 힘을 발휘합니다.
JavaScript를 단순히 사용하는 수준을 넘어
엔진 관점에서 이해하고 싶다면 반드시 학습해야 하는 핵심 개념이라고 할 수 있습니다.
Summary
Execution Context
• JavaScript 코드가 실행되는 환경을 의미함.
• 전역 실행 컨텍스트와 함수 실행 컨텍스트가 존재함.
• 변수, 함수, 스코프, this 정보를 관리함.
• JavaScript 실행 구조의 핵심 요소임.
Creation Phase
• 코드 실행 전 변수와 함수 정보를 수집함.
• Hoisting이 발생하는 단계임.
• Lexical Environment와 Scope Chain이 생성됨.
• this 바인딩이 결정되는 시점임.