자바스크립트는 매우 유연한 언어이며, 다양한 방식으로 코드를 작성하고 구조화할 수 있습니다. 그중에서도 클로저(Closure) 와 렉시컬 스코프(Lexical Scope) 는 자바스크립트에서 핵심적인 개념으로, 함수 내부에서 외부 변수를 어떻게 접근하고 관리하는지를 결정하는 중요한 원칙입니다.
이 개념들을 깊이 이해하면 유지보수하기 쉬운 코드를 작성할 수 있을 뿐만 아니라, 비동기 프로그래밍과 같은 고급 기능을 효과적으로 활용할 수 있습니다. 이번 글에서는 렉시컬 스코프와 클로저의 개념을 살펴보고, 실전에서 어떻게 적용할 수 있는지 다양한 사례와 함께 알아보겠습니다.
🔹 렉시컬 스코프(Lexical Scope): 변수가 유효한 범위를 결정하는 원리
렉시컬 스코프란, 변수의 유효 범위(Scope)가 코드가 작성된 위치(정의된 위치)에 따라 결정된다는 개념입니다. 즉, 함수가 어디에서 실행되는지가 아니라, 어디에서 선언되었는지가 변수를 접근하는 방식에 영향을 줍니다.
📌 예제 코드: 렉시컬 스코프의 기본 원리
function outerFunction() {
let outerVariable = '나는 바깥에 있어요!';
function innerFunction() {
console.log(outerVariable); // "나는 바깥에 있어요!" 출력
}
return innerFunction;
}
const myInnerFunction = outerFunction();
myInnerFunction(); // 호출 시 outerVariable에 접근 가능
위 코드에서 innerFunction
은 outerFunction
내부에 선언되었으며, outerFunction
의 변수 outerVariable
에 접근할 수 있습니다.
이것이 가능한 이유는 자바스크립트의 렉시컬 스코프 때문으로, innerFunction
이 선언될 때 자신이 속한 스코프(상위 함수의 변수 포함)를 기억하기 때문입니다.
🔹 렉시컬 스코프의 핵심 특징:
- 스코프는 실행 시점이 아니라 선언 시점에서 결정된다.
- 내부 함수는 자신이 선언된 환경(상위 함수)의 변수에 접근할 수 있다.
- 함수가 호출된 위치와 관계없이, 선언된 위치를 기준으로 변수 접근 방식이 결정된다.
🔹 클로저(Closure): 외부 상태를 기억하는 함수
클로저(Closure) 는 함수가 생성될 당시의 외부 변수 및 환경을 기억하고, 나중에도 해당 변수에 접근할 수 있도록 해주는 기능 을 의미합니다.
이 개념은 함수가 실행된 후에도 기존 환경을 유지할 수 있도록 해주며, 데이터 은닉 및 상태 유지 등의 다양한 프로그래밍 패턴을 가능하게 합니다.
📌 예제 코드: 클로저의 동작 방식
function makeCounter() {
let count = 0; // 외부 변수 (private variable)
return function() {
count += 1;
return count;
};
}
const counter1 = makeCounter();
console.log(counter1()); // 1
console.log(counter1()); // 2
const counter2 = makeCounter();
console.log(counter2()); // 1 (새로운 카운터)
이 코드에서 makeCounter
함수는 실행될 때마다 새로운 count
변수를 가진 클로저를 반환합니다.
각 counter1
, counter2
는 서로 다른 count
변수를 유지하며 독립적인 상태를 가질 수 있습니다.
즉, 클로저를 활용하면 외부에서 직접 변수에 접근할 수 없도록 보호하면서도, 특정 로직을 수행할 때 내부 상태를 유지할 수 있습니다.
🔹 클로저의 실용적인 활용 사례
✅ 1. 데이터 은닉 (Encapsulation)
클로저를 사용하면 특정 데이터를 외부에서 직접 변경할 수 없도록 보호 할 수 있습니다.
이를 통해 정보 은닉(Information Hiding) 이 가능하며, 보안성이 향상된 코드를 작성할 수 있습니다.
function createSecretHolder(secret) {
return {
getSecret: function() { return secret; },
setSecret: function(newSecret) { secret = newSecret; }
};
}
const secretHolder = createSecretHolder('비밀 정보');
console.log(secretHolder.getSecret()); // "비밀 정보"
secretHolder.setSecret('새로운 비밀');
console.log(secretHolder.getSecret()); // "새로운 비밀"
위 코드에서는 secret
변수가 외부에서 직접 접근되지 않으며, getSecret
및 setSecret
메서드를 통해서만 조작할 수 있습니다.
이는 객체 지향 프로그래밍의 캡슐화(Encapsulation) 개념과 유사한 효과 를 제공합니다.
✅ 2. 함수 팩토리 (Function Factory)
클로저를 사용하면 특정 설정을 가진 여러 함수를 동적으로 생성할 수 있습니다.
function greetingGenerator(greeting) {
return function(name) {
console.log(`${greeting}, ${name}!`);
};
}
const sayHello = greetingGenerator('안녕하세요');
const sayHi = greetingGenerator('반가워요');
sayHello('철수'); // "안녕하세요, 철수!"
sayHi('영희'); // "반가워요, 영희!"
이처럼 클로저를 사용하면 공통적인 로직을 포함하면서도, 다양한 맞춤형 함수를 손쉽게 생성할 수 있습니다.
✅ 3. 이벤트 핸들러에서의 활용
웹 개발에서는 클로저를 이용하여 이벤트 핸들러 내부에서 변수를 유지 할 수 있습니다.
function attachEventHandlers() {
let count = 0;
document.getElementById('myButton').addEventListener('click', function() {
count += 1;
console.log(`버튼이 ${count}번 클릭되었습니다.`);
});
}
attachEventHandlers();
여기서 count
변수는 attachEventHandlers
함수가 실행될 때 생성되지만, 이후에도 이벤트 핸들러 내부에서 계속 유지됩니다.
즉, 버튼이 클릭될 때마다 count
값이 증가하며, 이를 클로저 덕분에 추적할 수 있습니다.
🔹 결론: 클로저와 렉시컬 스코프를 이해하면 코드가 쉬워진다
자바스크립트에서 클로저와 렉시컬 스코프는 함수의 동작 방식과 변수를 다루는 방법을 이해하는 핵심 개념 입니다.
이 개념들을 익히면 효율적인 코드 구조를 만들고, 데이터를 안전하게 보호하며, 다양한 패턴을 활용한 동적인 기능을 구현할 수 있습니다.
🚀 핵심 정리:
✔️ 렉시컬 스코프: 함수가 선언될 때의 위치에 따라 변수의 유효 범위가 결정된다.
✔️ 클로저: 함수가 생성될 당시의 외부 환경을 기억하여, 실행이 끝난 후에도 해당 변수를 유지할 수 있다.
✔️ 활용 사례: 데이터 은닉, 함수 팩토리, 이벤트 핸들러 등 다양한 프로그래밍 패턴에서 유용하게 사용된다.
'프로그래밍 > Javascript' 카테고리의 다른 글
자바스크립트 개발의 게임체인저: ES6 모듈 시스템 완벽 가이드 (0) | 2025.02.14 |
---|---|
CommonJS 모듈 시스템 완벽 가이드: 개념부터 활용까지 (1) | 2025.02.14 |
자바스크립트 비동기 프로그래밍 완벽 가이드: 콜백, 프로미스, 그리고 async/await (0) | 2025.02.14 |
자바스크립트 비동기 프로그래밍 완벽 가이드: 프로미스(Promise)부터 async/await까지 (0) | 2025.02.14 |
자바스크립트 비동기 프로그래밍 완벽 가이드: 콜백부터 async/await까지 (0) | 2025.02.14 |