스코프(Scope)에 대해 알아보자
안녕하세요! 오늘은 자바스크립트에서 매우 중요한 개념 중 하나인 스코프(Scope)에 대해 알아보겠습니다. 스코프를 잘 이해하면 코드의 가독성을 높이고, 버그를 줄이며, 메모리 관리를 효율적으로 할 수 있습니다. 그럼 바로 시작하겠습니다.
스코프(Scope)란 무엇인가?
스코프는 프로그래밍에서 변수가 정의되고 접근할 수 있는 유효 범위를 의미합니다. 자바스크립트의 스코프는 크게 두 가지 유형으로 나뉩니다: 전역 스코프(Global Scope)와 지역 스코프(Local Scope). 스코프는 변수의 생명 주기를 결정하고, 변수 접근 규칙을 정의합니다.
스코프의 주요 유형
1. 전역 스코프(Global Scope)
전역 스코프에 선언된 변수는 코드 어디서나 접근할 수 있습니다. 전역 스코프에 변수를 선언하면, 해당 변수는 애플리케이션 전체에서 사용할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
var globalVar = 'I am global';
let globalLet = 'I am also global';
const globalConst = 'I am global too';
function showGlobals() {
console.log(globalVar); // 'I am global'
console.log(globalLet); // 'I am also global'
console.log(globalConst); // 'I am global too'
}
showGlobals();
2. 지역 스코프(Local Scope)
지역 스코프에 선언된 변수는 해당 스코프 내부에서만 접근할 수 있습니다. 일반적으로 함수나 블록 내부에 선언된 변수가 지역 스코프를 가집니다.
1
2
3
4
5
6
7
function localScopeExample() {
var localVar = 'I am local';
console.log(localVar); // 'I am local'
}
localScopeExample();
console.log(localVar); // ReferenceError: localVar is not defined
스코프의 종류
1. 함수 스코프(Function Scope)
함수 내에서 선언된 변수는 함수 내부에서만 유효합니다. var
키워드를 사용하여 선언된 변수는 함수 스코프를 따릅니다.
1
2
3
4
5
6
7
function functionScopeExample() {
var functionScopedVar = 'I am function scoped';
console.log(functionScopedVar); // 'I am function scoped'
}
functionScopeExample();
console.log(functionScopedVar); // ReferenceError: functionScopedVar is not defined
2. 블록 스코프(Block Scope)
블록({}
) 내에서 선언된 변수는 블록 내부에서만 유효합니다. let
과 const
키워드를 사용하여 선언된 변수는 블록 스코프를 따릅니다.
1
2
3
4
5
6
7
8
9
if (true) {
let blockScopedVar = 'I am block scoped';
const blockScopedConst = 'I am also block scoped';
console.log(blockScopedVar); // 'I am block scoped'
console.log(blockScopedConst); // 'I am also block scoped'
}
console.log(blockScopedVar); // ReferenceError: blockScopedVar is not defined
console.log(blockScopedConst); // ReferenceError: blockScopedConst is not defined
스코프 체인(Scope Chain)
스코프 체인은 변수나 함수가 정의된 스코프에서 시작하여 상위 스코프를 순차적으로 탐색하는 과정을 의미합니다. 자바스크립트는 변수를 찾기 위해 현재 스코프에서 시작하여 전역 스코프까지 차례대로 검색합니다. 이는 변수의 접근 권한을 결정하는 데 중요한 역할을 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let globalVar = 'I am global';
function outerFunction() {
let outerVar = 'I am outer';
function innerFunction() {
let innerVar = 'I am inner';
console.log(globalVar); // 'I am global' (전역 스코프에서 찾음)
console.log(outerVar); // 'I am outer' (외부 함수 스코프에서 찾음)
console.log(innerVar); // 'I am inner' (내부 함수 스코프에서 찾음)
}
innerFunction();
}
outerFunction();
렉시컬 스코프(Lexical Scope)
자바스크립트는 렉시컬 스코프(정적 스코프)를 사용합니다. 이는 함수가 정의된 위치에 따라 스코프가 결정된다는 의미입니다. 함수가 호출될 때가 아니라 정의될 때의 스코프 체인을 따릅니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let outerVar = 'I am outer';
function outerFunction() {
let innerVar = 'I am inner';
function innerFunction() {
console.log(outerVar); // 'I am outer'
console.log(innerVar); // 'I am inner'
}
return innerFunction;
}
const innerFunc = outerFunction();
innerFunc(); // 렉시컬 스코프에 따라 outerVar와 innerVar에 접근 가능
클로저(Closure)
클로저는 함수와 함수가 선언된 렉시컬 환경의 조합입니다. 클로저는 함수가 외부 함수의 변수에 접근할 수 있게 합니다. 클로저는 스코프를 활용하여 데이터 은닉 및 상태 유지를 가능하게 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
function outerFunction() {
let count = 0;
return function innerFunction() {
count++;
console.log(count);
};
}
const counter = outerFunction();
counter(); // 1
counter(); // 2
counter(); // 3
스코프의 활용
1. 변수 은닉
스코프를 활용하여 중요한 데이터를 외부에서 접근할 수 없도록 숨길 수 있습니다. 이를 통해 데이터의 보안성과 무결성을 유지할 수 있습니다.
2. 모듈 패턴
클로저와 스코프를 이용하여 모듈을 만들고 데이터를 은닉할 수 있습니다. 이는 코드의 재사용성과 유지보수성을 높여줍니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Module = (function () {
let privateVar = 'I am private';
return {
getPrivateVar: function () {
return privateVar;
},
setPrivateVar: function (value) {
privateVar = value;
}
};
})();
console.log(Module.getPrivateVar()); // 'I am private'
Module.setPrivateVar('I am updated');
console.log(Module.getPrivateVar()); // 'I am updated'
3. 메모리 관리
불필요한 변수를 전역 스코프에 선언하지 않음으로써 메모리 누수를 방지할 수 있습니다. 지역 변수를 사용하여 필요한 범위 내에서만 변수를 사용하고, 범위를 벗어나면 해제됩니다.
결론
스코프는 변수가 어디에서 정의되고 접근할 수 있는지를 결정하는 중요한 개념입니다. 전역 스코프, 지역 스코프, 함수 스코프, 블록 스코프 등 다양한 스코프 유형을 이해하면 더 나은 코드 구조와 효율적인 메모리 관리를 할 수 있습니다. 스코프 체인과 렉시컬 스코프의 원리를 이해하면 복잡한 코드에서도 변수의 유효 범위를 정확히 파악할 수 있습니다. 이를 통해 코드의 가독성과 유지보수성을 높이고, 예기치 않은 버그를 방지할 수 있습니다.
오늘도 제 글을 읽어주셔서 감사합니다. 다음 시간에 더 흥미로운 주제로 찾아뵙겠습니다.