Back to posts

자바스크립트의 실행 컨텍스트에 대해 알아보자

자바스크립트 실행 컨텍스트의 구조와 생성 흐름을 중심으로 호출 스택, 렉시컬 환경, 스코프 체인, 전역 객체까지 핵심 개념을 단계적으로 정리한 글이다.

·5 min read
Javascript실행컨텍스트LexicalEnvironment

이전 글에서는 자바스크립트의 var, let, const의 차이와 호이스팅에 대해서 알아봤습니다.

이번 글에선 호이스팅을 설명하려면 빠질 수 없는 내용이며 자바스크립트의 핵심 중 하나인 실행 컨텍스트에 대해 알아보겠습니다.

렛츠고~!


1. 실행 컨텍스트란?

실행 컨텍스트(Execution Context)는 코드를 실행하는 데 필요한 환경 정보들을 담고 있는 객체다.

자바스크립트의 모든 코드는 실행 컨텍스트 안에서 실행되며, 실행 컨텍스트는 호출 스택(Call Stack) 위에 쌓이면서 관리된다.

(호출 스택에 관한 내용은 다음 순서에서 더 자세히 설명하겠습니다.)

자바스크립트 엔진이 코드를 해석하고 실행하는 모든 과정은 실행 컨텍스트를 기반으로 동작함.


2. 실행 컨텍스트의 생성과 흐름

위에서 실행 컨텍스트는 호출 스택 위에 쌓이면서 관리된다고 했는데, 그렇다면 호출 스택이란 뭘까?

호출 스택에 대해 알기 전에 우선 스택에 대해 알아보자.

스택은 자료구조의 일종으로, 한 방향으로만 데이터를 넣고 꺼낼 수 있다는 특성이 있다.

그렇다면 호출 스택은 뭘까?

말 그대로 자바스크립트 호출이 쌓이는 형태로 저장되는 스택을 의미한다.

호출스택은 다음과 같은 동작 과정을 가진다.

  • 코드 실행 중 함수가 호출되면 해당 함수의 실행 컨텍스트가 스택의 최상단에 push
  • 함수 실행이 끝나면 해당 컨텍스트는 스택에서 pop
  • 현재 실행 중인 컨텍스트는 항상 스택의 맨 위에 위치
  • 예제 코드와 함께 살펴보자.

    javascript
    function foo() {
      bar();
    }
    function bar() {
      baz();
    }
    function baz() {
      console.log("Hello");
    }
    foo();

    위 코드가 실행되면 다음과 같은 흐름을 가진다.

  • 1우선적으로 전역 실행 컨텍스트가 호출 스택에 쌓인다.
  • 2호출된 foobarbaz가 순서대로 호출 스택에 쌓인다.
  • 3baz까지 호출된 뒤에 위에서부터 차례로 제거된다.
  • 4전역 컨텍스트까지 제거된 뒤에 프로그램이 종료된다.
  • 실행 컨텍스트와 호출 스택 정리

  • 가장 먼저 전역 실행 컨텍스트(Global Execution Context)가 생성됨.
  • • 이후 함수가 호출될 때마다 각각의 함수 실행 컨텍스트(Function Execution Context) 가 생성되어 호출 스택에 쌓임.

    • eval() 같은 예외적인 경우 외에는 함수 호출이 아니면 실행 컨텍스트가 새로 만들어지지 않음.

    • 현재 실행 중인 컨텍스트가 끝나면 호출 스택에서 제거되고, 다음 컨텍스트가 실행됨.


    3. 실행 컨텍스트의 구성 요소

    앞부분에서 실행 컨텍스트를 코드를 실행하는 데 필요한 환경 정보라고 설명했었다.

    그렇다면 코드를 실행하는 데 필요한 환경 정보에는 어떤 것들이 있을까?

    실행 컨텍스트는 다음의 세 가지 요소로 구성된다.

    VariableEnvironment

  • 초기 변수 선언, 함수 선언 등을 기록하는 공간
  • 선언 시점의 스냅샷을 유지함 (정적임)
  • 실행 컨텍스트가 생성될 때, 먼저 이 VariableEnvironment가 만들어짐
  • 이후 LexicalEnvironment에 복사됨
  • LexicalEnvironment

  • 실제 실행 중에 사용되는 환경 정보
  • 실시간으로 변경됨 (동적임)
  • 내부 구조는 VariableEnvironment와 동일하게 구성되어 있음
  • Environment Record와 Outer Environment Reference로 구성되어있다.
  • 스코프 체인, 클로저 등의 핵심 개념이 이 안에서 동작함
  • ThisBinding

  • 현재 실행 중인 컨텍스트의 this가 가리키는 대상
  • 전역 컨텍스트에서는 전역 객체(window, global 등)를 가리킴
  • 함수 컨텍스트에서는 호출 방식에 따라 this가 결정됨 (bind, call, apply, 화살표 함수 등)
  • 이 중 실제 실행 중에 사용되는 환경 정보인 LexicalEnvironment에 대해 더 자세히 알아보자!


    4. LexicalEnvironment의 구조

    LexicalEnvironment는 아래 두 가지 요소로 구성된다.

    Environment Record

  • 현재 컨텍스트에서 선언된 변수명, 함수 선언, 매개변수 이름 등 식별자 정보를 저장하는 객체.
  • 코드가 실행되기 전에 선언 정보가 미리 수집되어 기록됨.
  • 이 안에서 호이스팅이 발생함.
  • 호이스팅에 대한 더 자세한 정보는 이 글을 참조 해주세요.

    Outer Environment Reference

  • 외부 렉시컬 환경에 대한 참조.
  • 현재 컨텍스트가 생성될 당시, 어디서 선언됐는지에 따라 외부 스코프를 기억함.
  • 이걸 기반으로 식별자 검색 시 내부 → 외부 → 전역 순으로 검색함.
  • 즉, 스코프 체인의 핵심임. (스코프 체인이 뭔지는 다음 순서에 계속...)

  • 5. 스코프 체인

    위에서 말한 스코프 체인이란 무엇일까?

    스코프 체인이란 한마디로 식별자를 참조할 때 탐색하는 일종의 연결 리스트 구조 이다.

    자바스크립트의 x라는 변수가 사용됐다고 가정해보자.

    우선 해당 변수가 현재 범위에 있는지 확인해볼 것이다.

    그런데 만약 현재 범위에 x라는 변수가 없다면 어떻게 할 것인가?

    자바스크립트는 현재 범위의 바깥 범위를 이어서 탐색하게 된다.

    예제 코드와 같이 살펴보자.

    javascript
    const x = 1;
    
    function outer() {
      const y = 2;
      function inner() {
        const z = 3;
        console.log(x, y, z);
      }
      inner();
    }
    
    outer();

    호출 스택은 global(전역)outerinner 순으로 쌓이게 되며, 변수는 가장 안쪽에서부터 바깥쪽으로 탐색한다.

    이에 따라

    z는 inner 스코프에서 발견,

    y는 outer 스코프에서 발견,

    x는 전역 스코프에서 발견한다.

    이를 더 자세히 풀어서 설명해보면 다음과 같다.

  • z는 inner의 LexicalEnvironment에 선언되어 있다. 따라서 바로 탐색이 종료된다.
  • y는 inner의 LexicalEnvironment에 선언되어있지 않다. 따라서 inner의 Outer Environment Reference인 outer의 LexicalEnvironment를 다음으로 탐색하게 된다. outer LexicalEnvironment에서 y를 발견하고 탐색이 종료된다.
  • x는 inner의 LexicalEnvironment에 선언되어있지 않다. 따라서 inner의 Outer Environment Reference인 outer의 LexicalEnvironment를 다음으로 탐색하게 된다. outer의 LexicalEnvironment에도 x는 선언되어 있지 않다. 따라서 outer의 Outer Environment Reference인 global(전역 스코프)의 LexicalEnvironment를 다음으로 탐색하게 된다. 전역 스코프에서 x를 발견하고 탐색이 종료된다.
  • 또 주의깊게 볼 점은, 스코프 체인은 함수가 호출되는 시점이 아닌, 선언된 위치를 기준으로 결정된다는 것이다.

    예제 코드와 함께 살펴보자.

    javascript
    const x = 1;
    
    function foo() {
      console.log(x);
    }
    
    function bar() {
      const x = 2;
      foo();
    }
    
    bar();

    foo선언된 시점의 OuterEnvironment는 전역 환경이고,

    foo호출된 시점의 OuterEnvironment는 bar의 LexicalEnvironment다.

    만약 스코프 체인이 함수가 호출되는 시점을 기준으로 한다면 콘솔에 2가 찍히겠지만, 실제로는 1이 찍히게 된다.

    이를 통해 스코프 체인이 함수 호출 시점 기준으로 동적으로 변경되는 게 아닌

    선언 당시의 LexicalEnvironment를 정적으로 참조한다는 것을 알 수 있다.

    스코프 체인 정리

  • 함수가 호출되는 시점이 아닌, 선언된 위치 기준으로 스코프를 결정함.
  • 검색은 현재 LexicalEnvironment → OuterEnvironment → (...) → 전역 순으로 진행됨.
  • 검색은 안쪽에서 바깥쪽으로만 가능하며, 그 반대 방향은 허용되지 않음.
  • 동일한 식별자가 여러 스코프에 존재할 경우, 가장 가까운 환경의 식별자만 사용됨.
  • 찾으면 즉시 반환하며, 더 이상 검색하지 않음.

  • 6. 스코프의 종류

  • 전역 스코프 어디서든 접근 가능한 영역, 전역 실행 컨텍스트에서 생성됨
  • 모듈 스코프 ES6 모듈 단위에서 생성되는 스코프, 전역과 격리됨
  • 함수 스코프 함수 내부에서 선언된 변수의 유효 범위
  • 블록 스코프 {} 블록 내부에서 유효한 범위 (let, const만 해당됨, var는 제외됨)

  • 7. 전역 객체

    전역 객체는 자바스크립트 실행 환경에서의 최상위 객체를 의미한다.

    전역 객체는 환경별로 이름이 다른데,

    브라우저에서는 window, Node.js에서는 global라는 이름을 가지며,

    ES2020부터는 환경과 상관없이 전부 globalThis라는 이름으로 통일된 접근이 가능하다.

    전역 객체는 전역 변수와 함수의 컨테이너 역할을 하며,

    전역 스코프에서 선언된 varfunction 변수들은 전역 객체의 프로퍼티가 된다.

    단, let, const, class전역 스코프에서 선언해도 전역 객체의 프로퍼티가 되지 않는다.

    예제 코드와 함께 살펴보자.

    javascript
    var a = 1;
    let b = 2;
    
    console.log(window.a); // 1
    console.log(window.b); // undefined

    ab 모두 전역 스코프에서 선언된 변수지만

    a는 전역 객체인 window의 프로퍼티가 된 반면, b는 프로퍼티로 들어가지 않은 것을 확인할 수 있다.

    번외) 네이티브 객체와 호스트 객체

    네이티브 객체는 ECMAScript 명세에서 정의한 표준 객체들로, 실행 환경에 관계없이 항상 동일하게 동작한다.

    Array, Object, Promise, Date 같은 우리가 일상적으로 사용하는 대부분의 내장 객체들이 여기에 속한다.

    이들은 자바스크립트 엔진 자체가 제공하는 객체이기 때문에 브라우저든 Node.js든 동일한 API를 제공한다.

    반면 호스트 객체는 자바스크립트가 실행되는 환경(호스트)이 제공하는 객체들이다.

    브라우저에서는 document, XMLHttpRequest, localStorage 같은 DOM/BOM 객체가,

    Node.js에서는 fs, http, process 같은 모듈들이 대표적이다.


    참고 자료

    Call stack - Glossary | MDN

    스코프 - MDN Web Docs 용어 사전: 웹 용어 정의 | MDN

    Global object - Glossary | MDN

    © 2026 Bit by Bit Blog. All rights reserved.