JavaScript에서 const a = 10 + 20이라고 쓰면 내부에서 어떤 일이 벌어질까? 변수는 단순히 "값을 담는 상자"가 아니다. 메모리 할당, 호이스팅, 가비지 컬렉션까지 — 변수 하나를 제대로 이해하면 JavaScript 엔진의 동작 방식이 보이기 시작한다.
변수란 무엇인가
내가 알고있는 변수란 값이 저장되어있는 메모리의 주소를 가리키는 참조값이다. 즉 호출하면 값을 가져올 수 있는 주소값. JavaScript에서도 그런지 한번 공부해봤다.
const a = 10 + 20;
이 코드가 실행되면:
- 좌변과 우변의 숫자값을 메모리에 저장한다
- CPU가 이 값을 읽어들여 연산을 수행한다
- 결과값 30이 메모리의 임의 위치에 저장된다
a라는 이름이 그 메모리 주소를 가리킨다
이때 메모리 주소로 직접 접근하는 건 치명적인 문제가 발생할 수 있다 (잘못된 주소 참조 시 보안 문제, 매번 값이 할당되는 메모리 주소가 달라짐). 그래서 JavaScript는 개발자의 직접적인 메모리 제어를 허용하지 않고, 대신 변수라는 이름표를 통해 간접 접근하게 한다.
정리하면 변수란 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름이다.
식별자: 값이 아니라 주소를 기억한다
변수는 식별자(Identifier)라고도 부른다. 개인적으로 변수보다는 식별자가 좀 더 와닿는것같은데, 식별자는 값이 아니라 메모리 주소를 기억하고 있다. 그래야 찾아가서 그 메모리에 저장되어있는 값을 가져올 수 있으니.
갑자기 궁금해서 그럼 변수 이름은 어떻게 메모리에 저장하고 찾아가는지 알아봤더니, JavaScript 엔진 내부의 실행 컨텍스트에 변수 테이블이 있고 여기에 이름과 주소값을 key-value로 저장한다고 한다. value에 해당하는 주소값으로 찾아가면 값 또는 객체가 있다.
변수 선언과 초기화
변수를 선언하면 메모리 공간을 확보하고, 변수 이름과 확보된 메모리 공간의 주소를 연결한다. 이렇게 확보된 메모리 공간은 해제되기 전까지는 누구도 사용할 수 없도록 보호된다.
var score;
console.log(score); // undefined
선언만 하고 값을 할당하지 않으면 undefined로 자동 초기화된다. 만약 undefined를 할당해서 초기화해주지 않으면 이전 메모리에 기록되어있던 쓰레기값이 나올수도 있다고 한다.
호이스팅: 선언이 먼저 실행되는 이유
console.log(score); // undefined (에러가 아니다!)
var score = 100;
선언하기 전에 접근했는데 ReferenceError가 뜨는 대신 undefined가 나온다. 이것이 호이스팅(Hoisting) 이다.
JavaScript 엔진은 코드를 순차적으로 실행하기에 앞서 먼저 평가 과정을 거치는데, 이때 변수 선언을 포함한 모든 선언문을 먼저 실행한다. 먼저 선언문을 실행시켜서 등록시켜주는건 처음 알았다.
그래서 위 코드는 실질적으로 이렇게 동작한다:
var score; // 평가 단계에서 선언 + undefined 초기화
console.log(score); // undefined
score = 100; // 런타임에 할당
핵심은 선언은 호이스팅되지만 할당은 호이스팅되지 않는다는 것이다.
let/const는 다르게 동작한다
let, const, class도 호이스팅은 된다. 하지만 var와 달리 초기화는 실제 선언문에 도달했을 때 이뤄진다. 선언 시점부터 초기화 시점까지의 구간을 TDZ(Temporal Dead Zone) 라고 하며, 이 구간에서 접근하면 ReferenceError가 발생한다.
console.log(x); // ReferenceError
let x = 10;
console.log(y); // undefined (var는 OK)
var y = 10;
| 키워드 | 호이스팅 | 초기화 시점 | TDZ |
|---|---|---|---|
| var | O | 선언과 동시 (undefined) | X |
| let | O | 선언문 도달 시 | O |
| const | O | 선언문 도달 시 | O |
var, let, const 사용 가이드
| 특성 | var | let | const |
|---|---|---|---|
| 스코프 | 함수 | 블록 | 블록 |
| 재선언 | O | X | X |
| 재할당 | O | O | X |
var의 가장 큰 문제는 블록 스코프를 무시한다는 점이다:
if (true) {
var x = 10;
}
console.log(x); // 10 (밖에서 접근 가능!)
현대 JavaScript에서는 기본적으로 const를 사용하고, 재할당이 필요한 경우에만 let을 쓴다. var는 레거시 코드에서만 볼 수 있다.
재할당의 메모리 동작
let score = 80;
score = 100;
재할당은 기존 메모리를 덮어쓰는 것이 아니다. 새로운 메모리 공간을 확보하고 거기에 100을 저장한 뒤, score가 새 주소를 가리키도록 바꾼다. 이렇게 연결이 끊어진 값은 쥐도새도 모르게 가비지 컬렉터가 정리해버린다.
이 원리가 const가 재할당을 막는 이유이기도 하다. const는 변수가 가리키는 주소를 바꿀 수 없게 고정한다. 단, 객체의 프로퍼티 변경은 주소 변경이 아니므로 허용된다:
const user = { name: "Kim" };
user.name = "Lee"; // OK (프로퍼티 변경 ≠ 재할당)
// user = {}; // TypeError (재할당 불가)
정리
변수는 "값을 담는 상자"가 아니라 메모리 주소를 가리키는 이름표다. JavaScript 엔진은 코드 실행 전에 선언을 먼저 처리(호이스팅)하고, let/const는 TDZ를 통해 var의 느슨한 동작을 개선했다. 재할당 시에는 새 메모리를 할당하고 이전 값은 가비지 컬렉터에 맡긴다.
'코딩딩 > Javascript' 카테고리의 다른 글
| 날것 - 데이터 타입 (0) | 2026.03.11 |
|---|---|
| 날것 - 표현식과 문 (0) | 2026.03.11 |
| JavaScript 비동기 처리 흐름 정리: 콜백부터 async/await까지 (0) | 2026.03.08 |
| 자바스크립트에서 this와 화살표 함수의 컨텍스트 유지 (1) | 2024.10.02 |
| Web (0) | 2023.08.28 |