실행 컨텍스트와 스택 메모리

    728x90
    반응형
    SMALL

     

    실행 컨텍스트와 스택 메모리

    실행 컨텍스트는 스택 메모리에 저장됩니다.

    function outer() {
      let x = 10;  // outer의 스택
      
      function inner() {
        let y = 20;  // inner의 스택
      }
      
      inner();
    }
    
    outer();
    

    콜 스택 (Call Stack):

    ┌─────────────────┐
    │ inner 실행 컨텍스트 │  ← 현재 실행 중
    │ - y: 20         │
    ├─────────────────┤
    │ outer 실행 컨텍스트 │
    │ - x: 10         │
    ├─────────────────┤
    │ 전역 실행 컨텍스트  │
    └─────────────────┘
    

    실행 컨텍스트의 메모리 구성

    function example() {
      let num = 42;           // 스택
      let obj = { x: 1 };     // 스택(주소) + 힙(객체)
    }
    
    example();
    

    실행 컨텍스트 생성 시:

    콜 스택
    ┌──────────────────────┐
    │ example 실행 컨텍스트   │
    │                      │
    │ 렉시컬 환경:          │
    │  환경 레코드          │
    │  ┌────────┬────────┐ │
    │  │ num    │ 0x100  │ │ ──→ [스택 0x100]: 42
    │  │ obj    │ 0x200  │ │ ──→ [스택 0x200]: 0x5000 ──→ [힙 0x5000]: { x: 1 }
    │  └────────┴────────┘ │
    │                      │
    │  외부 렉시컬 환경 참조 │
    └──────────────────────┘
    

     

    스택과 힙의 역할

    스택 메모리

    • 실행 컨텍스트 저장
    • 렉시컬 환경 (환경 레코드)
    • 원시값
    • 객체의 참조(주소)

    힙 메모리

    • 실제 객체 저장
    • 배열, 함수, 객체 등
    • 실행 컨텍스트와는 별개

    상세 예시

    const global = 'global';
    
    function outer() {
      const outerVar = 10;
      const outerObj = { value: 1 };
      
      function inner() {
        const innerVar = 20;
        console.log(outerObj.value);
      }
      
      return inner;
    }
    
    const closure = outer();
    closure();
    

    메모리 구조:

    콜 스택 (실행 컨텍스트들)
    ┌─────────────────────────┐
    │ inner 실행 컨텍스트       │
    │  환경 레코드:            │
    │  - innerVar: 20 (스택)   │
    │  외부 참조 → outer 환경   │
    ├─────────────────────────┤
    │ (outer는 이미 종료)       │
    │ 하지만 클로저로 유지됨:    │
    │  환경 레코드:            │
    │  - outerVar: 10 (스택)   │
    │  - outerObj: 0x5000 (스택)│ ──→ [힙 0x5000]: { value: 1 }
    └─────────────────────────┘
    

    함수 호출과 스택

    function first() {
      let a = 1;
      second();
    }
    
    function second() {
      let b = 2;
      third();
    }
    
    function third() {
      let c = 3;
    }
    
    first();
    

    콜 스택 변화:

    1. first() 호출
    ┌─────────────┐
    │ first       │
    │ a: 1        │
    ├─────────────┤
    │ 전역         │
    └─────────────┘
    
    2. second() 호출
    ┌─────────────┐
    │ second      │
    │ b: 2        │
    ├─────────────┤
    │ first       │
    │ a: 1        │
    ├─────────────┤
    │ 전역         │
    └─────────────┘
    
    3. third() 호출
    ┌─────────────┐
    │ third       │
    │ c: 3        │
    ├─────────────┤
    │ second      │
    │ b: 2        │
    ├─────────────┤
    │ first       │
    │ a: 1        │
    ├─────────────┤
    │ 전역         │
    └─────────────┘
    
    4. third() 종료
    ┌─────────────┐
    │ second      │
    │ b: 2        │
    ├─────────────┤
    │ first       │
    │ a: 1        │
    ├─────────────┤
    │ 전역         │
    └─────────────┘
    
    5. 모두 종료
    ┌─────────────┐
    │ 전역         │
    └─────────────┘
    

    클로저와 힙 메모리

    function createCounter() {
      let count = 0;          // 스택
      const data = { x: 1 };  // 힙
      
      return function() {
        count++;
        data.x++;
        return { count, x: data.x };
      };
    }
    
    const counter = createCounter();
    

    메모리 상태:

    스택 (클로저로 유지)
    ┌────────────────────┐
    │ createCounter 환경  │
    │ - count: 0         │
    │ - data: 0x5000     │ ──→ [힙 0x5000]: { x: 1 }
    └────────────────────┘
             ↑
             │
        counter 함수의
        [[Environment]]가 참조
    

    가비지 컬렉션

    function example() {
      let obj1 = { value: 1 };  // 힙에 생성
      let obj2 = { value: 2 };  // 힙에 생성
      
      return obj1;  // obj1만 반환
    }
    
    const result = example();
    

    함수 종료 후:

    스택
    ┌──────────┐
    │ (example │  ← 실행 컨텍스트 제거
    │  종료)   │
    └──────────┘
    
    힙
    [0x5000]: { value: 1 }  ← result가 참조, 유지 ✅
    [0x6000]: { value: 2 }  ← 참조 없음, GC 대상 ♻️
    

    정리

    실행 컨텍스트와 메모리의 관계:

    실행 컨텍스트 (콜 스택에 저장)
    ├─ 렉시컬 환경
    │  ├─ 환경 레코드 (스택)
    │  │  ├─ 원시값 → 스택에 직접
    │  │  └─ 객체 → 스택에 주소, 힙에 실제 객체
    │  └─ 외부 렉시컬 환경 참조
    └─ this 바인딩
    

    핵심:

    • ✅ 실행 컨텍스트는 스택에 저장
    • ✅ 렉시컬 환경(환경 레코드)도 스택
    • ✅ 원시값은 스택에 직접
    • ✅ 객체는 힙에, 주소만 스택에
    • ✅ 실행 컨텍스트 종료 시 스택 정리
    • ✅ 힙의 객체는 참조가 있으면 유지 (클로저)
    // 요약
    실행 컨텍스트 → 콜 스택 (스택 메모리)
    원시값 → 스택 메모리
    객체 → 힙 메모리 (주소는 스택)
    

    완벽하게 연결되어 있습니다! 🎯

    728x90
    반응형
    LIST

    댓글