스코프(Scope)란?
- 스코프란 범위를 뜻하며 JavaScript에서 스코프는 '변수 접근 규칙에 따른 유효범위' 이다.
- 스코프에는 크게 2가지의 타입이 있는데 가장 바깥 영역에 선언되어 있어서 어디서나 변수에 접근이 가능한 전역 스코프(Global Scope)와 해당 지역에서만 변수에 접근할 수 있는 지역 스코프(Local Scope)가 있다.
스코프 규칙
1. 안쪽 스코프에서 바깥쪽 스코프로는 접근할 수 있지만 반대는 불가능하다.
블록 레벨 스코프
let name = 'lee';
if (name) {
let msg = `Hello, ${name}!`;
console.log(msg); // Hello, lee!
}
console.log(msg); // ReferenceError: msg is not defined
- 중괄호를 기준으로 범위가 구분된다.
- 첫번째 콘솔 출력 결과는 'Hello, lee!' 이다. 변수 name을 블록{...} 외부에서 가져왔기 때문에 정상적으로 출력된다.
- 하지만 변수 msg는 블록 내부에 선언되어 있기 때문에 외부에서는 접근이 불가능하고
'ReferenceError: msg is not defined'를 출력한다.
- 이처럼 변수에 접근할 수 있는 범위가 존재하는데 변수가 블록 내부에 선언 되었는지, 외부에 선언되었는지가 중요하며 이 범위를 스코프라고 부른다.
함수 레벨 스코프
let greet = 'Hello';
function greetSomeone() {
let name = 'lee';
return greet + ' ' + name;
}
console.log(greetSomeone()); // Hello lee
console.log(name); // ReferenceError: name is not defined
- function 키워드가 등장하는 함수 선언식 및 함수 표현식은 함수 스코프를 만든다.
- 변수 greet는 함수 외부에 정의되어 있으므로 함수 내부에서 사용할 수 있다.
- 하지만 변수 name은 함수 내부에 정의되어 있으므로 함수 외부에서는 접근이 불가능하고 'ReferenceError: name is not defined'를 출력한다.
화살표 함수
let getAge = user => {
return user.age;
}
- 같은 함수여도 화살표 함수를 사용하면 함수 레벨 스코프가 아닌 블록 레벨 스코프로 취급된다.
2. 스코프는 중첩이 가능하다.

- 가장 바깥쪽의 스코프는 전역 스코프(Global Scope)라고 부르며 전역이 아닌 다른 스코프는 전부 지역 스코프(Local scope)이다.
- 지역 스코프에 선언한 변수는 지역 변수, 전역 스코프에서 선언한 변수는 전역 변수이며 지역 변수는 전역 변수보다 더 높은 우선순위를 가진다.
let name = 'lee';
function showName() {
let name = 'park';
console.log(name); // park
}
console.log(name); // lee
showName();
console.log(name); // lee
- 첫번째 출력은 함수 외부에서 선언된 변수인 'lee'를 출력한다.
- 두번째 출력은 함수 내부에서 선언된 변수가 더 높은 우선순위를 가지기 때문에 지역변수 name인 'park'을 출력한다.
- 동일한 변수 이름으로 인해 바깥쪽 변수가 안쪽 변수에 의해 가려지는(shadow) 현상을 쉐도잉(variable shadowing)이라고 부른다.
- 세번째 출력은 첫번째 출력과 마찬가지로 전역 변수 name을 출력하고 지역 변수인 name 변수는 안쪽 스코프이므로 접근이 불가능하다.
전역변수 사용시 주의사항
- 전역 변수는 가장 바깥 스코프에 정의한 변수이며 어디서든 접근이 가능하다.
얼핏 "모든 변수를 바깥으로 빼면 스코프 걱정을 하지 않아도 되겠네?" 라는 생각이 들 수도 있겠지만 전역 변수를 많이 만드는 것은 그다지 좋은 선택이 아니다.
- 보통 애플리케이션을 만들 때에는 내가 직접 작성하지 않은 수많은 다른 함수와 로직이 포함되며 너도나도 똑같은 이름으로 전역 변수를 선언하려고 한다면 분명 문제가 발생할 것이다.
- 이를 부수 효과(side effect)라고 하며 전역 변수를 최소화하는 것은 side effect를 줄이는 좋은 방법이다. 전역 변수는 꼭 필요한 경우가 아니라면 자제하는 것이 좋다.
var 키워드
var console = 'hello';
window.console; // 'hello'
console.log('hello') // TypeError: console.log is not a function
- var 키워드는 블록 스코프를 무시한다. 또한 재선언을 해도 에러를 내지 않으므로 let과 const를 주로 사용하는 것이 좋다.
- 전역 변수를 var로 선언하는 것은 브라우저의 내장 기능을 사용하지 못하게 만들 수도 있다.
function showAge() {
age = 90;
console.log(age); // 90
}
showAge();
console.log(age); // 90
console.log(window.age); // 90
- 선언 키워드 없이 변수를 할당하면 해당 변수는 var로 선언한 전역 변수처럼 취급되므로 let과 const 키워드를 사용하여 변수를 선언하는 것이 좋다.
- Strict Mode를 사용하면 브라우저가 보다 엄격하게 작동하여 이러한 문제점을 방지해주는데, 선언 없는 변수 할당의 경우 Strict Mode는 에러로 판단한다.
- Strict Mode를 적용하려면 js 파일 상단에 'use strict' 라고 입력한다.