
아무생각없이 js 공부하던중 대충 개념만 알면 되겠지?라고 생각한 스코프가 요즘 들어 매우 중요한 개념이라고 생각되어 다시 한번 정리를 해보고자 한다.
우리말로 번역을 하면 '범위'라는 뜻을 가지고 있다. 즉, 스코프란 '변수에 접근할 수 있는 범위'라고 정의할 수 있다.
js에서 스코프는 2가지 타입을 가지고 있는데 바로 전역(Global)과 지역(Local)이다.
전역(Global) 스코프는 말 그대로 전역에서 선언되어있어 어느 곳이든지 해당 변수에 접근할 수 있다는 뜻이고 지역(Local) 스코프는 해당 지역에서만 접근할 수 있어 해당 지역이 아닌 다른 곳에서 접근이 불가능하다.
let a = 1; // 전역 스코프
function print() { // 지역(함수) 스코프
let a = 111;
console.log(a);
}
print(); // 111
console.log(a); // 1
위의 코드는 쉽게 이해가 갈것이다. 하지만 print 함수 안에 있는 console.log(a)를 지우면 print()값은 무엇이 나올까?
let a = 1; // 전역 스코프
function print() { // 함수 스코프
console.log(a);
}
print(); // 1
그럴 경우 print()는 1을 출력해준다. 이는 Scope Chain에 의해 일어나는 현상이다. 그렇다면 Scope Chain에 대해 알아보자
const myName = 'Serzhul'
function first() {
const age = 30
if (age >= 30) {
const decade = 3
var millenial = true
}
function second() {
const job = 'developer'
console.log(`hi, I'm ${myName}. I'm a ${age}-old ${job}`)
// Hi, I'm Serzhul. I'm a 30-old developer
}
second()
}
first()
스코프 체인은 우선 전역 스코프에서 시작한다. 위 코드에서 전역 변수에는 const로 myName이라는 변수만이 선언되어 있다.
엄밀히 말하자면 first 역시 전역변수에 선언되어 있는 function타입의 변수이지만 여기선 변수만을 고려한다.
전역변수 다음에는함수 스코프에 접근하게 된다. first 함수 스코프에는 const로 선언된 age 변수가 존재하며 또 그 안에 있는 second 함수 스코프에는 job이라는 변수가 선언되어 있다.
그런데 소스를 보면 second 함수 스코프 내부에서 console.log로 다양한 변수들을 호출하게 되는데 myName이나 age 같은 변수들은 함수 스코프 내에 존재하지 않음에도 호출을 할 수 있다.
그것이 가능한 이유는 스코프의 특성 때문인데, 바로 스코프는 모든 바깥의 스코프에 있는 변수들에 접근할 수 있다는 점이다.
먼저 second 함수 스코프 외부인 first 함수 스코프 내부에 age 변수가 있으므로 그 age 변수를 호출할 수 있는 것이고, 그 바깥 쪽에 있는 전역변수에서 myName변수가 있으므로 호출할 수 있게 되는 것이다. 이런 방식으로 다른 스코프에 접근 하는 것을 스코프 체인(Scope Chain)이라고 하며, 변수를 찾아가는 과정을 스코프 체인의 Variable lookup이라고 한다.
이러한 변수 조회는 내부 스코프에서 외부 스코프로 찾아가는 방식은 유효하지만, 외부 스코프에서 내부 스코프의 변수에는 접근할 수 없다는 특징이 있다.
추가로 first 함수 내부의 if문에는 블록 스코프가 존재하는데, 앞서 살펴보았듯이 두 개의 변수 중에서 블록 스코프의 적용을 받는 변수는 decade 하나 뿐이다.
millenial은 var로 선언되어 있기 때문에 if 블록 스코프의 적용을 받지 않고 first 함수 스코프의 적용을 받는다. 또한 스코프 체인에 따라 second 함수 스코프에서도 millenial 변수에 접근할 수 있게 된다.
단, if 블록 스코프와 second 함수 스코프는 같은 레벨의 스코프이기 때문에 서로의 변수에 접근할 수 없으며 오직 각각의 상위 스코프인 first 함수 스코프에 접근할 수 있다.