[JS] 변수가 메모리에 할당되는 과정

jiny·2025년 10월 21일

기술 면접

목록 보기
67/78

🗣️ 변수가 메모리에 할당되는 과정에 대해서 설명해주세요.

  • 의도: 지원자가 변수 선언과 할당이 메모리에서 어떻게 이루어지는지 이해하고 있는지 평가
    • 변수 선언 시 메모리 할당 과정을 간단히 설명한다.
    • 스택과 힙 메모리에 대한 기본 개념을 이해하고 있는지 설명한다.
  • 모범 답안

    자바스크립트에서 변수가 메모리에 할당되는 과정은 선언, 초기화, 할당의 세 단계로 이루어집니다.

    먼저 변수 선언 단계에서는 자바스크립트 엔진이 실행 전에 코드 전체를 스캔하며, 변수 이름을 메모리에 등록해 둡니다.
    이 과정은 호이스팅(Hoisting)이라고 합니다.

    그 다음 초기화 단계에서 var 키워드는 undefined로 초기화되고,
    letconst초기화되지 않은 상태일시적 사각지대(Temporal Dead Zone)에 머무릅니다.

    마지막으로 코드 실행 중 실제 값이 할당되면, 해당 메모리 공간에 그 값이 저장됩니다.

    즉, 변수 선언 시점부터 메모리 공간이 확보되지만, 값이 실제로 들어가는 시점은 할당 단계입니다.

    또한 원시값은 스택(Stack)에, 객체나 배열 같은 참조형 값은 힙(Heap)에 저장되며, 변수는 힙의 주소를 참조하게 됩니다.


📝 개념 정리

🌟 변수는 언제, 어디에, 어떻게 메모리에 생길까?

자바스크립트에서 변수는 선언 → 초기화 → 할당의 흐름으로 다뤄진다.
여기에 호이스팅(선언이 위로 끌어올려지는 효과), TDZ(일시적 사각지대), 스코프와 환경 레코드, 가비지 컬렉션이 얽히면서 실제 동작이 결정된다.


🌟 실행 준비 단계

자바스크립트 엔진은 실행 전에 코드를 한 번 훑으며 환경(스코프)과 바인딩(변수 이름 → 메모리 슬롯)을 준비한다.
이를 흔히 호이스팅으로 설명한다.

  • var
    • 같은 스코프 내에서 미리 선언 + undefined로 초기화
    • 선언 위치 이전에서도 접근은 가능하지만 값은 undefined
  • let / const
    • 실행 컨텍스트가 만들어질 때 만들어지지만 초기화되지 않은 상태
    • 초기화가 수행되기 전까지는 TDZ(Temporal Dead Zone)에 머물러 접근 시 ReferenceError가 남
    • const선언과 동시에 초기화(값 필요)가 규칙임
  • 함수 선언식 (function declaration)
    • 함수 식별자에 함수 객체까지 초기화되어 바인딩됨
    • 선언 이전에 호출이 가능
  • 함수 표현식 / 화살표 함수
    • 변수에 값으로서의 함수가 할당되는 형태라, 위 규칙(var/let/const)을 그대로 따름

🌟 실행 단계: 초기화와 할당의 순간

코드가 실제로 실행되면서 각 선언문을 만날 때 초기화가 일어난다.

  • let x; → 이 지점에서 비로소 x가 초기화(접근 가능)
  • const y = 10; → 이 줄에서 선언과 초기화, 할당이 동시에 이뤄져야 함
  • var z;이미 undefined로 초기화된 상태임
  • 할당(Assignment): 식의 평가 결과가 변수 슬롯에 기록됨
    • 원시값은 해당 슬롯에 값 자체가 저장됨
    • 객체, 배열, 함수힙에 할당된 값의 참조(주소)가 저장됨
console.log(a); // var: undefined
var a = 1;

console.log(b); // ❌ let: ReferenceError (TDZ)
let b = 1;

console.log(c); // ❌ const: ReferenceError (TDZ)
const c = 1;

🌟 스코프와 환경 레코드

자바스크립트는 렉시컬 스코프를 갖고, 각 스코프는 내부적으로 Lexical Environment로 표현된다.

  • Lexical Environment
    1. Environment Record: 식별자 → 값/슬롯 매핑 테이블
    2. Outer: 바깥 스코프를 가리키는 참조
  • 종류
    • Global Environment: 스크립트 전역, 모듈 전역
    • Function Environment: 함수 호출 시
    • Block Environment: {} 블록, let/const 바인딩 저장
  • 선언의 기록 위치
    • var함수 스코프(또는 스크립트 전역) 환경 레코드에 기록
    • let/const블록 스코프 환경 레코드에 기록
  • 이름 해석(변수 조회)
    • 현재 환경 레코드에서 찾고, 없으면 Outer를 따라 상위로 스코프 체인 탐색

🌟 TDZ (Temporal Dead Zone)

  • 선언된 위치에 도달해 초기화되기 전까지의 구간
  • let/const선언문 실행 시점에 초기화가 이루어지므로, 그 전 접근은 ReferenceError
  • 블록 시작부터 선언문 실행 직전까지TDZ 범위가 됨

🌟 모듈/스크립트, 전역 바인딩의 차이

  • 스크립트 전역 + var: 전역 객체(브라우저의 window)에 동일 이름의 프로퍼티를 생성
  • 모듈 전역 또는 let/const: 전역 객체 프로퍼티와 분리된 모듈/전역 레코드에 저장
  • 모듈은 기본이 Strict Mode이며, 전역 바인딩 동작이 스크립트와 다름

    🔎 스크립트 전역, 모듈 전역

    브라우저에서 자바스크립트를 넣는 방식은 크게 두 가지

    1. 스크립트 전역: <script src="..."></script> (기본)
    2. 모듈 전역: <script type="module" src=".."></script>

    두 방식은 전역 바인딩 방식엄격 모드, top-level this 등이 다름

    🔎 스크립트 전역에서의 바인딩

    var 또는 함수 선언식

    • 전역에서 var x = 1;를 쓰면 전역 객체(window)동일 이름의 프로퍼티가 생김
    • 즉, window.x === xtrue
    • 이 프로퍼티는 삭제 불가(non-configurable)라서 delete window.xfalse를 반환함
    • 함수 선언식(function f() {})도 전역에서는 전역 객체 프로퍼티로 바인딩됨
      <script>
        var x = 1;
        function f() {}
        console.log(window.x === x); // true
        console.log('x' in window); // true
        console.log(delete window.x); // false (삭제 불가)
      </script>

    let/const

    • 전역에서 let y = 1; const z = 2;전역 객체(window)프로퍼티를 만들지 않음
    • 즉, window.ywindow.zundefined
    • 그래도 전역 스코프에서 식별자로는 접근됨 (전역 환경 레코드에 존재)
    • delete y 같은 시도는 문법/동작상 허용되지 않음
      <script>
        let y = 1;
        const z = 2;
        console.log(window.y); // undefined
        console.log(typeof y); // "number"
        console.log('y' in window); // false
      </script>

    ✅ 정리

    • var/함수 선언식 ⇒ window 프로퍼티 생성(전역 객체 오염 가능, 삭제 불가)
    • let/constwindow와 분리된 전역 바인딩(클린)

    🔎 모듈 전역에서의 바인딩

    ✅ 공통 규칙

    • 모듈은 항상 Strict Mode
    • 모듈의 전역은 모듈 전역 스코프로, 전역 객체와 분리
    • 따라서 var이라도 모듈 최상위에서 window 프로퍼티를 만들지 않음
      <script type="module">
        var a = 1;
        let b = 2;
        const c = 3;
        console.log(window.a); // undefined
        console.log(window.b); // undefined
        console.log(window.c); // undefined
      </script>

    ✅ top-level this

    • 스크립트 전역(비엄격)에서는 this === windowtrue
    • 모듈 전역에서는 this === undefinedtrue
      <script>
        console.log(this === window); // true (비 엄격 스크립트)
      </script>
      <script type="module">
        console.log(this); // undefined (모듈)
      </script>

    🔎 왜 이 차이가 중요할까?

    1. 전역 오염 위험

    • 스크립트 전역에서 var/함수 선언window에 그대로 노출되어 네임스페이스 충돌 위험이 큼
    • 모듈(또는 전역 let/const)window와 분리되어 전역 오염을 줄임

    2. 삭제/재선언/속성 속성(attribute)

    • 스크립트 전역의 var/함수 선언삭제 불가(non-configurable) 프로퍼티라 delete가 실패한다.
    • 반면 모듈 전역window 프로퍼티를 만들지 않으므로 이런 이슈가 없다.

    3. 엄격 모드 & 안전성

    • 모듈은 기본적으로 strict mode라서, 암묵적 전역 생성 등 위험한 패턴이 차단된다.

    🔎 표로 정리하기

    구분스크립트 전역(<script>)모듈 전역(<script type="module">)
    var x = 1window.x 생성됨 (삭제 불가)window.x 생성 안 됨
    function f() {}window.f 생성됨 (삭제 불가)window.f 생성 안 됨
    let/const전역 바인딩은 생기지만 window 프로퍼티 아님동일 (window와 분리)
    top-level this비 엄격이면 this === windowthis === undefined
    엄격 모드기본 아님('use strict' 필요)기본 엄격 모드

🌟 가비지 컬렉션(GC)과 수명

  • 자바스크립트 엔진은 도달 가능성(reachability) 기반으로 메모리를 회수
  • 클로저상위 스코프의 환경 레코드를 참조하기 때문에, 해당 함수가 살아있는 한 캡처된 변수들도 수명 연장
  • 이벤트 리스너/타이머에 의해 참조가 유지되면 GC되지 않음 → 해제(cleanup) 중요

0개의 댓글