호이스팅(Hoisting)과 TDZ(Temporal Dead Zone)에 대해 알아보자. 이 두 가지 개념은 변수와 함수의 선언, 초기화, 그리고 접근 순서에 영향을 미치는 개념이다. 이 글에서는 호이스팅과 TDZ에 대한 개념과 작동 방식, 그리고 예제 코드를 통해 살펴본다.
호이스팅이란 무엇인가
호이스팅은 자바스크립트에서 변수와 함수 선언을 스코프의 맨 위로 끌어올리는 동작을 말한다. 이는 코드에서 변수와 함수를 선언하기 전에 사용할 수 있다는 특징을 가지고 있다. 호이스팅은 실제로 코드의 위치가 변경되는 것이 아니라, 컴파일 단계에서 메모리에 공간을 할당하고 변수와 함수에 대한 참조를 스코프의 맨 위로 이동시킨다.
호이스팅의 작동 방식을 이해하기 위해 예제 코드를 살펴보자.
console.log(name); // undefined
var name = "Spencer";
console.log(name); // Spencer
위 코드에서 첫 번째 `console.log` 문에서 `name` 변수에 접근하면 `undefined`가 출력된다. 이는 호이스팅에 의해 변수가 선언되었지만 아직 값이 할당되지 않았기 때문이다. 그러나 `var name = "John";` 라인에서 변수를 초기화하고 나서는 `name` 변수에 접근할 때 "John"이 출력된다.
호이스팅으로 변수의 선언을 끌어올리지만, 변수의 할당은 호이스팅되지 않는다. 변수를 사용하기 전에 선언하는 것은 좋은 습관이지만, 초기화하지 않고 사용하는 경우 `undefined`으로 할당된다. 또한, 호이스팅은 `var` 키워드로 선언된 변수와 함수 선언에만 적용되며, `let`, `const`, 함수 표현식은 호이스팅되지 않는다. 함수 선언은 변수 선언보다 우선순위가 높으며, 함수와 변수의 이름이 충돌하는 경우 함수 선언이 변수 선언을 덮어쓴다.
TDZ란 무엇인가?
TDZ(Temporal Dead Zone)는 자바스크립트의 변수 호이스팅 동작과 관련이 있다. TDZ는 변수가 선언되기 전에 접근하면 발생하는 현상을 말한다. 이는 초기화되지 않은 변수에 접근하려고 할 때 예외가 발생한다는 의미이다.
예를 들어, 다음의 코드를 살펴보자.
console.log(name); // ReferenceError: Cannot access 'name' before initialization
let name = "Spencer";
console.log(name);
console.log(name); // ReferenceError: Cannot access 'name' before initialization
const name = "Spencer";
console.log(name);
위 코드에서 `let` 또는 `const`로 지정된 `name` 변수를 선언하기 전에 접근하면 초기화에 대한 `ReferenceError`가 발생한다. 이는 TDZ에 의해 변수가 초기화되기 전에 접근하려고 하면 예외가 발생한다는 것을 보여준다.
위의 이미지에서 빨강 박스는 변수 job에 의해 결정되는 Temporal Dead Zone을 나타낸다.
`let` 또는 `const`로 지정된 변수가 존재할 경우 스코프의 시작부분에서 그 변수가 정의된 라인까지는 TDZ가 된다.
TDZ는 ES6에서 도입되었고 이러한 기능은 설정되지 않은 변수로 인해 생기는 심각한 버그를 피하거나 찾아내는데 훨씬 쉽게해준다.
그리고, TDZ를 이해하기 위해서는 변수의 생명주기에 대해 알아야 한다. 변수의 생명주기는 세 가지 단계로 나눌 수 있다. 선언 단계, 초기화 단계, 할당 단계. TDZ는 선언 단계와 초기화 단계 사이에 위치하며, 변수가 아직 초기화되지 않았지만 스코프에 등록되어 다른 코드에서 접근할 수 있다는 의미이다.
Function에서 호이스팅과 TDZ 알아보기
호이스팅과 TDZ에 대한 개념을 자세히 이해하기 위해 예제 코드를 살펴보자.
1. Function Declarations
console.log(addDeclaration(2, 3)); // 5
function addDeclaration(a, b) {
return a + b;
}
2. Function Expressions
console.log(addExpression(2, 3)); // ReferenceError: Cannot access 'addExpression' before initialization
const addExpression = function (a, b) {
return a + b;
}
3. Function Arrows
console.log(addArrow(2, 3)); // ReferenceError: Cannot access 'addArrow' before initialization
const addArrow = (a, b) => a + b;
위의 세 가지 예시 코드를 보면 addDeclaration에서만 결과가 정상 출력이 되었고, 나머지 두 경우에는 ReferenceError가 표시되었다. addDeclaration은 호이스팅에 의해 끌어올려졌으나 `const`로 지정된 addExpression과 addArrow는 그렇지 못했다.
var로 지정된 functions 알아보기
var로 지정된 addExpression과 addArrow의 예제를 보자.
console.log(addExpression(2, 3)); // TypeError: addExpression is not a function
var addExpression = function (a, b) {
return a + b;
}
console.log(addArrow(2, 3)); // TypeError: addArrow is not a function
var addArrow = (a, b) => a + b;
undefined(2, 3); // TypeError: undefined is not a function
두 개의 함수 코드를 실행하면 `not a function` 에러가 나타난다. 이는 `undefined()`를 실행한 결과와 같은 에러를 보여준다.
정리하기
Hoisting과 TDZ는 자바스크립트의 작동에 대한 개념으로, 변수와 함수의 선언, 초기화, 접근에 영향을 미친다. 호이스팅은 변수와 함수 선언을 스코프의 맨 위로 끌어올리는 동작을 말하며, TDZ는 변수가 선언되기 전에 접근하면 발생하는 현상을 말한다. 설정되지 않은 변수에 대해 버그를 찾아내는데 용이하다.
호이스팅은 변수의 선언을 끌어올리지만, 할당은 호이스팅되지 않고, `var` 키워드로 선언된 변수와 함수 선언에만 적용되며, `let`, `const`, 함수 표현식은 호이스팅되지 않는다. 함수 선언은 변수 선언보다 우선순위가 높으며, 이름이 충돌하는 경우 함수 선언이 변수 선언을 덮어쓴다.