안녕하세요! JavaScript 개발자라면 반드시 정확하게 이해해야 할 두 가지 핵심 개념, 바로 스코프(Scope)와 호이스팅(Hoisting)입니다. 이들은 JavaScript 변수의 생명주기와 코드 실행 방식에 깊이 관여하며, 이를 제대로 알지 못하면 예상치 못한 버그를 만나거나 효율적인 코드를 작성하기 어렵습니다. 이번 포스팅에서 스코프와 호이스팅을 완벽하게 파헤쳐 보겠습니다.
1. 스코프(Scope)란 무엇인가?
스코프는 '변수 접근 규칙' 또는 '식별자(변수, 함수명 등)를 찾기 위한 규칙'을 의미합니다. 즉, 어떤 변수나 함수가 어디에서 선언되었으며, 어디까지 접근 가능한지를 정의하는 범위입니다. JavaScript에는 크게 세 가지 종류의 스코프가 있습니다.
1.1. 전역 스코프 (Global Scope)
코드의 가장 바깥 영역에 선언된 변수나 함수는 전역 스코프를 가집니다. 전역 스코프에 선언된 식별자는 코드의 어느 곳에서든 접근하고 사용할 수 있습니다.
const globalVar = '저는 전역 변수입니다.';
function accessGlobal() {
console.log(globalVar); // 함수 내부에서도 접근 가능
}
accessGlobal(); // "저는 전역 변수입니다."
console.log(globalVar); // 전역에서 접근 가능
전역 변수를 너무 많이 사용하는 것은 코드의 재사용성을 낮추고, 다른 코드와의 충돌 가능성을 높여 바람직하지 않습니다.
1.2. 함수 스코프 (Function Scope)
함수 스코프는 함수 내부에서 선언된 변수나 함수가 유효한 범위입니다. var
키워드로 선언된 변수는 함수 스코프를 따릅니다. 함수 내부에서 선언된 변수는 함수 외부에서는 접근할 수 없습니다.
function myFunction() {
var functionVar = '저는 함수 스코프 변수입니다.';
console.log(functionVar); // 함수 내부에서는 접근 가능
}
myFunction(); // "저는 함수 스코프 변수입니다."
// console.log(functionVar); // ReferenceError: functionVar is not defined (함수 외부에서는 접근 불가)
1.3. 블록 스코프 (Block Scope)
ES6(ECMAScript 2015)에서 도입된 let
과 const
키워드는 블록 스코프를 가집니다. 블록 스코프는 {}
(중괄호)로 둘러싸인 코드 블록 내에서만 유효한 범위입니다. if
문, for
문, while
문 등의 블록 내부에서 선언된 변수는 해당 블록 외부에서 접근할 수 없습니다.
if (true) {
let blockLet = '저는 블록 스코프 변수입니다 (let).';
const blockConst = '저는 블록 스코프 변수입니다 (const).';
console.log(blockLet); // 블록 내부에서 접근 가능
console.log(blockConst); // 블록 내부에서 접근 가능
}
// console.log(blockLet); // ReferenceError: blockLet is not defined
// console.log(blockConst); // ReferenceError: blockConst is not defined
현대 JavaScript에서는 var
대신 let
과 const
를 사용하는 것이 권장됩니다. 이는 블록 스코프를 통해 예상치 못한 오류를 줄이고 코드의 예측 가능성을 높이기 위함입니다.
2. 호이스팅(Hoisting)이란 무엇인가?
호이스팅은 JavaScript에서 **'선언'이 스코프의 최상단으로 끌어올려지는 것처럼 동작하는 현상**을 의미합니다. 즉, 변수나 함수를 코드 어디에서 선언하든, JavaScript 엔진은 코드를 실행하기 전에 해당 선언을 해당 스코프의 맨 위로 이동시킨 것처럼 처리합니다.
2.1. 변수 호이스팅 (var)
var
로 선언된 변수는 선언과 초기화가 분리되어 호이스팅됩니다. 선언은 스코프 최상단으로 끌어올려지지만, 초기화(값 할당)는 원래 위치에서 실행됩니다. 이때, 초기화되기 전에는 undefined
로 초기화됩니다.
console.log(varHoisted); // undefined 출력 (선언은 호이스팅되었지만 초기화는 아직)
var varHoisted = 'var 변수입니다.';
console.log(varHoisted); // "var 변수입니다." 출력
2.2. 함수 호이스팅 (함수 선언문)
함수 선언문(Function Declaration)은 변수와 달리, 선언과 동시에 초기화까지 호이스팅됩니다. 따라서 함수 선언문은 코드 어디에서든 호출할 수 있습니다.
hoistedFunction(); // "저는 호이스팅된 함수입니다." 출력 (함수 선언보다 먼저 호출 가능)
function hoistedFunction() {
console.log('저는 호이스팅된 함수입니다.');
}
2.3. let, const, 그리고 함수 표현식의 호이스팅
let
과 const
로 선언된 변수, 그리고 함수 표현식(Function Expression)은 **호이스팅되지 않는 것처럼 보입니다.** 정확히는 선언은 호이스팅되지만, 초기화되기 전까지는 '일시적 사각 지대(Temporal Dead Zone, TDZ)'에 머물러 접근할 수 없습니다. 이 때문에 런타임 에러가 발생합니다.
// console.log(letHoisted); // ReferenceError: Cannot access 'letHoisted' before initialization (TDZ)
let letHoisted = 'let 변수입니다.';
// console.log(constHoisted); // ReferenceError: Cannot access 'constHoisted' before initialization (TDZ)
const constHoisted = 'const 변수입니다.';
// console.log(functionExpression); // ReferenceError: Cannot access 'functionExpression' before initialization
const functionExpression = function() {
console.log('저는 함수 표현식입니다.');
};
functionExpression();
이러한 이유로 현대 JavaScript에서는 var
대신 let
과 const
를 사용하고, 함수 선언문보다는 함수 표현식을 선호하는 경향이 있습니다. 이는 호이스팅으로 인한 혼란을 줄이고 코드의 예측 가능성을 높이기 위함입니다.
결론: 스코프와 호이스팅의 중요성
스코프와 호이스팅은 JavaScript 코드가 어떻게 실행되고 변수가 어떻게 관리되는지를 이해하는 데 필수적인 개념입니다. 특히 var
, let
, const
의 차이점과 함수 선언문/함수 표현식의 동작 방식을 정확히 아는 것은 예기치 않은 버그를 피하고, 더욱 견고하며 유지보수하기 쉬운 JavaScript 코드를 작성하는 데 큰 도움이 됩니다.
- 스코프: 변수의 유효 범위. 전역, 함수, 블록 스코프를 이해하고
let
/const
사용을 습관화하세요. - 호이스팅: 선언이 스코프 최상단으로 끌어올려지는 현상.
var
와 함수 선언문의 특성을 이해하고, TDZ를 인지하여let
/const
사용 시 주의하세요.
이 포스팅이 스코프와 호이스팅에 대한 깊이 있는 이해를 돕는 데 유용했기를 바랍니다. 궁금한 점이나 추가하고 싶은 내용이 있다면 언제든지 댓글로 남겨주세요!
댓글 없음:
댓글 쓰기