스코프와 변수 생명주기
- 4.1 스코프란?
- 4.2 스코프 체인
- 4.3 함수 레벨 스코프와 렉시컬 스코프
- 4.4 변수의 생명 주기
- 4.5 전역 변수의 문제점과 대안
- 4.6 var vs let vs const
- 4.7 블록 레벨 스코프와 TDZ
변수가 어디서 유효한지, 얼마나 오래 사는지, 어떤 키워드로 선언해야 하는지 — 스코프와 변수 생명주기를 확실히 잡아야 클로저와 실행 컨텍스트가 자연스럽게 풀려.
스코프는 식별자가 유효한 범위야. 같은 이름의 변수가 있어도 스코프가 다르면 다른 변수지. JS 엔진은 변수를 참조할 때 스코프를 기준으로 어떤 변수를 참조할지 결정하는데, 이걸 **식별자 결정(identifier resolution)**이라 해. 전역 스코프는 코드의 가장 바깥이고 전역 변수는 어디서든 참조 가능해. 지역 스코프는 함수 몸체 내부이고 지역 변수는 해당 함수와 그 하위 함수에서만 참조 가능하지.
스코프는 중첩될 수 있고 계층 구조를 이뤄. 변수를 참조할 때 JS 엔진은 현재 스코프에서 시작해서 상위 스코프로 올라가며 검색하는데, 이걸 스코프 체인이라 하고, 검색은 항상 아래에서 위로만 가능해.
var는 오직 함수의 코드 블록만을 지역 스코프로 인정해. if문이나 for문의 블록은 스코프를 만들지 않거든.
var x = 1;
if (true) {
var x = 10; // 같은 스코프의 x를 덮어씀
}
console.log(x); // 10 (의도치 않은 변경!)
JS는 **렉시컬 스코프(정적 스코프)**를 따라. 함수의 상위 스코프는 함수가 호출된 위치가 아니라 정의된 위치에 의해 결정돼.
var x = 1;
function foo() { console.log(x); }
function bar() { var x = 10; foo(); }
bar(); // 1 (foo의 상위 스코프는 전역)
이 렉시컬 스코프 개념이 클로저의 핵심 기반이 되지.
변수의 생명 주기도 중요해. 지역 변수는 함수가 호출될 때 생성되고, 함수가 종료될 때 소멸해. 전역 변수는 프로그램이 종료될 때까지 살아있지. var로 선언한 전역 변수는 **전역 객체(window/global)**의 프로퍼티가 되니까, 전역 객체가 살아있는 한 전역 변수도 사라지지 않아.
전역 변수의 문제점은 네 가지야. 암묵적 결합(모든 코드가 전역 변수를 참조하고 변경 가능), 긴 생명 주기(메모리 소비 + 상태 변경 위험), 스코프 체인의 종점(검색 속도가 가장 느림), 네임스페이스 오염(파일이 분리되어도 하나의 전역 스코프 공유). 대안으로 IIFE, 네임스페이스 객체, 모듈 패턴이 있지만, 가장 근본적인 해결책은 ES6 모듈이야. import/export를 사용하면 파일 자체가 독립된 모듈 스코프를 가지거든.
그래서 어떤 키워드를 쓸 것인가가 핵심이야. var의 문제점은 세 가지 — 변수 중복 선언 허용, 함수 레벨 스코프, 호이스팅으로 인한 혼란. let은 이 문제들을 해결해. 블록 레벨 스코프를 지원하고, 중복 선언을 금지하고, **일시적 사각지대(TDZ, Temporal Dead Zone)**가 있어서 선언 전에 접근하면 ReferenceError가 나.
console.log(x); // ReferenceError (TDZ)
let x = 10;
const는 let의 특성에 추가로, 선언과 동시에 초기화가 필수이고 재할당이 금지야. 하지만 객체를 할당한 경우 프로퍼티 변경은 가능해. const가 보장하는 건 변수 바인딩의 불변성이지, 값의 불변성이 아니니까.
const person = { name: 'Lee' };
person.name = 'Kim'; // OK — 프로퍼티 변경은 재할당이 아님
person = {}; // TypeError — 재할당은 불가
저자의 권장사항은 명확해. const를 기본으로, 필요할 때만 let, var는 쓰지 마.
정리
4장 읽고 기억할 거 세 가지:
- 렉시컬 스코프는 함수가 정의된 위치에서 상위 스코프가 결정된다는 뜻이고, 이게 클로저의 핵심 기반이야.
- 전역 변수는 암묵적 결합, 긴 생명 주기, 네임스페이스 오염 문제가 있으니, 변수의 스코프를 최대한 좁게 만들자.
- const 기본, 필요할 때만 let. TDZ가 있는 let/const가 var보다 훨씬 안전해.