JavaScript 클로저 이해하기: 코드 예제와 함께 배우는 방법
JavaScript 클로저 이해하기: 코드 예제와 함께 배우는 방법
JavaScript를 배우다 보면 클로저
라는 개념을 만나게 됩니다. 클로저는 많이 언급되지만, 초보자들에게는 자주 헷갈리는 개념 중 하나입니다. 이 글에서는 클로저의 정의, 동작 원리, 그리고 이를 실제 코드 예제로 설명하여 이해를 돕겠습니다.
클로저란 무엇인가?
클로저는 자바스크립트의 중요한 특성 중 하나로, 함수와 그 함수가 선언된 렉시컬 환경의 조합을 의미합니다. 먼저 자바스크립트의 함수 스코프와 렉시컬 스코프를 이해하는 것이 중요합니다.
함수 스코프와 렉시컬 스코프
자바스크립트는 함수 스코프를 따릅니다. 이는 변수가 함수 내에서 선언되었을 때, 그 함수 내에서만 접근 가능하다는 의미입니다. 렉시컬 스코프는 함수가 어디서 정의되었는지에 의해 결정됩니다.
예를 들어:
javascriptfunction outerFunction() { var outerVariable = 'I am outside!'; function innerFunction() { console.log(outerVariable); // 'I am outside!' } innerFunction(); } outerFunction();
이 코드에서 innerFunction
은 outerVariable
에 접근할 수 있습니다. innerFunction
는 outerFunction
내에서 정의되었기 때문입니다. 이는 렉시컬 스코프 덕분입니다.
클로저의 정의
위의 예제를 조금 변형해보겠습니다:
javascriptfunction outerFunction() { var outerVariable = 'I am outside!'; function innerFunction() { console.log(outerVariable); } return innerFunction; } var closureFunction = outerFunction(); closureFunction(); // 'I am outside!'
이 예제에서는 innerFunction
을 반환하고 이를 closureFunction
에 할당합니다. 놀랍게도 closureFunction
을 호출하면 innerFunction
이 여전히 outerVariable
을 참조할 수 있습니다. 이는 클로저의 힘입니다.
클로저의 활용
클로저는 다양한 상황에서 유용하게 사용될 수 있습니다. 그 중 몇 가지 예를 살펴보겠습니다.
1. 데이터 프라이버시
클로저를 사용하여 데이터 프라이버시를 구현할 수 있습니다. 이는 변수와 함수가 외부에서 접근되지 않도록 하는 방법입니다.
javascriptfunction createCounter() { let count = 0; return function() { count++; return count; } } const counter = createCounter(); console.log(counter()); // 1 console.log(counter()); // 2
위의 코드에서 count
변수는 createCounter
함수 내에서만 접근 가능합니다. 이를 통해 외부에서 변경할 수 없는 프라이빗 데이터를 생성할 수 있습니다.
2. 함수 공장
클로저를 사용하면 함수 공장을 만들 수 있습니다. 이는 서로 다른 설정으로 여러 함수를 생성하는 데 유용합니다.
javascriptfunction greetingFactory(greeting) { return function(name) { return `${greeting}, ${name}!`; } } const sayHello = greetingFactory('Hello'); const sayHi = greetingFactory('Hi'); console.log(sayHello('Alice')); // 'Hello, Alice!' console.log(sayHi('Bob')); // 'Hi, Bob!'
이 예제에서는 greetingFactory
가 각기 다른 인사말의 함수를 생성합니다.
3. 콜백과 이벤트 핸들러
클로저는 콜백과 이벤트 핸들러에서 자주 사용됩니다. 특히 비동기 코드에서 유용합니다.
javascriptfor (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, i * 1000); }
이 코드는 5개의 타이머를 설정하고 순서대로 0부터 4까지 출력을 기대하지만, 실제로는 모두 같은 값이 출력됩니다. 클로저를 사용하여 문제를 해결할 수 있습니다.
javascriptfor (var i = 0; i < 5; i++) { (function(i) { setTimeout(function() { console.log(i); }, i * 1000); })(i); }
여기서 각 i
값이 클로저에 캡쳐되어 기대한 출력 결과를 얻을 수 있습니다.
실전 예제
추가로 클로저를 사용하여 실제로 유용한 예제를 만들어 보겠습니다. 캐싱 함수입니다:
javascriptfunction createCache() { const cache = {}; return function(key, value) { if (value !== undefined) { cache[key] = value; } return cache[key]; } } const cache = createCache(); cache('a', 100); console.log(cache('a')); // 100 cache('b', 200); console.log(cache('b')); // 200
이 예제에서는 값을 키로 저장할 수 있는 캐시를 생성합니다. 클로저를 사용하여 캐시 데이터를 보호하면서 접근할 수 있게 합니다.
결론
JavaScript의 클로저는 강력한 개념으로, 다양한 방식으로 활용될 수 있습니다. 클로저를 제대로 이해하면 보다 효율적이고 안전한 코드를 작성할 수 있습니다. 이 글에서 소개한 개념과 예제를 통해 클로저의 동작 원리와 그 활용 방법을 충분히 이해할 수 있기를 바랍니다.