JavaScript에서 스코프(Scope)가 어떻게 작동하는지 알아보고, 전역 스코프(Global Scope), 지역 스코프(Local Scope), 렉시컬 스코프(Lexical Scope)의 차이점까지 한 번에 정리해 드립니다.
스코프(Scope)란 함수나 변수에 접근할 수 있는 문맥, 즉 유효 범위를 의미합니다. JavaScript에는 세 가지 스코프 유형이 있습니다.
- 전역 변수(Global Variable): 코드 블록 밖에서 선언된 변수
- 지역 변수(Local Variable): 코드 블록 안에서 선언된 변수
알아두면 좋은 점: 함수는 자기 자신의 바깥쪽에 선언된 변수나 다른 함수에는 접근할 수 있지만, 다른 함수의 내부에 선언된 변수에는 접근할 수 없습니다.
곧 예제를 통해 확실히 이해하게 될 것입니다.
전역 스코프(Global Scope)
전역 스코프에 선언된 변수나 함수는 다른 함수 내부 어디에서든 접근할 수 있습니다.
// 전역 스코프
let dogBreed = "Labrador"
let getDogBreed = function() {
// dogBreed는 전역 스코프에 있으므로 접근 가능합니다.
console.log(dogBreed)
// "Labrador"
}
// 함수 실행
getDogBreed()
함수 안에 선언된 함수 역시 마찬가지로 전역 스코프의 변수에 접근할 수 있습니다.
// 전역 스코프
let dogBreed = "Labrador"
let getDogBreed = function() {
// 함수 안의 함수
let getDogBreedFromGlobalScope = function() {
// 전역 스코프의 dogBreed에 접근합니다.
console.log(dogBreed)
// "Labrador"
}
// 함수 실행
getDogBreedFromGlobalScope()
}
// 함수 실행
getDogBreed()
지역 스코프(Local Scope)
지역 스코프를 가진 변수나 함수는 오직 자신이 속한 문맥(스코프) 내부에서만 접근할 수 있습니다.
let getDogBreed = function() {
// 지역 변수 스코프
let dogBreed = "Labrador"
// dogBreed는 지역 변수이므로 여기서 접근할 수 있습니다.
console.log(dogBreed)
// "Labrador"
}
변수 dogBreed는 지역 스코프를 가지며, 중괄호 { .. }로 묶인 자신의 스코프 내부에서만 접근할 수 있습니다.
위의 코드와 동일하지만, 이번에는 console.log(dogBreed)를 지역 스코프 밖으로 옮겨 전역 스코프에 배치해 보겠습니다.
let getDogBreed = function() {
// 지역 변수 스코프
let dogBreed = "Labrador"
}
// 지역 스코프의 변수에 접근을 시도합니다.
console.log(dogBreed)
// Uncaught ReferenceError: dogBreed is not defined
전역 스코프에서 지역 스코프의 변수를 출력하려고 했기 때문에 "dogBreed is not defined"라는 참조 에러(ReferenceError)가 발생합니다.
렉시컬 스코프(Lexical Scope)
함수를 중첩하면(함수 안에 함수를 넣으면), 부모 함수(가장 바깥쪽 함수) 내부의 변수와 함수를 내부 함수에서 접근할 수 있습니다. 이를 렉시컬 스코프라고 부릅니다.
반대로 부모 함수 자체는 내부 함수 안에 선언된 변수나 함수에 접근할 수 없습니다. 말로 들으면 복잡해 보일 수 있으니, 예제를 통해 살펴보겠습니다.
// 전역 스코프
let animals = function() {
// 렉시컬 스코프
let dogBreed = "Labrador"
// 중첩 함수
let getAnimals = function() {
// dogBreed는 렉시컬 스코프에 있으므로 접근할 수 있습니다.
console.log(dogBreed)
// "Labrador"
// 여기는 지역 스코프 변수입니다.
let catBreed = "Persian"
console.log(catBreed)
// "Persian"
}
// 함수 실행
getAnimals()
// dogBreed 변수는 렉시컬 스코프에 있으므로 정상적으로 동작합니다.
console.log(dogBreed)
// "Labrador"
// catBreed는 렉시컬 스코프가 아닌 getAnimals() 함수의 지역 변수이므로 동작하지 않습니다.
console.log(catBreed)
// Uncaught ReferenceError: catBreed is not defined
}
animals()