1. 개요
클로저(Closure)는 JavaScript의 핵심 개념 중 하나로, 함수가 자신이 선언된 환경(Lexical Environment)의 변수에 접근할 수 있는 기능을 의미한다. 이를 통해 캡슐화(Encapsulation), 데이터 유지, 함수형 프로그래밍 등의 다양한 활용이 가능하다.
JavaScript 개발자라면 클로저를 깊이 이해해야 메모리 관리, 콜백 함수, 이벤트 핸들링, 비동기 처리 등에서 효과적으로 활용할 수 있다. 이 글에서는 클로저의 개념을 쉽게 설명하고, 실무에서 활용할 수 있는 다양한 예제를 소개한다.
2. 클로저의 개념과 원리
(1) 클로저란?
클로저는 함수가 생성될 때, 자신이 선언된 렉시컬 스코프(Lexical Scope)에 접근할 수 있는 특성을 의미한다.
✅ 클로저의 특징
- 내부 함수 inner는 외부 함수 outer의 변수 message를 기억하고 있다.
- outer 함수가 실행이 끝나도, inner 함수는 message 변수에 접근할 수 있다.
- 클로저는 **변수를 보호(캡슐화)**하고, 특정 데이터의 **유지(메모리에 저장)**가 가능하다.
(2) 클로저의 동작 원리 (Lexical Scope & Execution Context)
1) 렉시컬 스코프(Lexical Scope)
JavaScript에서는 함수가 선언된 위치(렉시컬 환경)에 따라 스코프가 결정된다.
함수 inner는 자신이 생성된 환경(outer 함수의 스코프)을 기억하므로, a 변수에 접근할 수 있다.
2) 실행 컨텍스트(Execution Context)와 클로저
클로저는 외부 함수의 실행이 끝나도 내부 함수가 변수를 유지할 수 있는 이유와 관련이 있다.
✅ 왜 count 값이 유지될까?
- counter()가 실행되면 count 변수가 생성된다.
- counter() 실행이 끝나도 내부 함수가 count를 참조하고 있어, count가 사라지지 않는다.
- increment() 실행 시마다 count가 유지되면서 증가한다.
3. 클로저의 활용 예제
(1) 데이터 은닉(Encapsulation) – 프라이빗 변수 구현
클로저를 활용하면 객체의 private 변수처럼, 외부에서 직접 접근할 수 없는 변수를 만들 수 있다.
✅ 클로저를 활용한 데이터 은닉의 장점
- balance 변수는 외부에서 직접 접근할 수 없어 보안성이 향상된다.
- deposit, withdraw, getBalance 메서드를 통해서만 balance 값을 변경 가능하다.
(2) 반복문과 클로저 – setTimeout 활용
클로저를 활용하면 반복문에서 setTimeout이 올바르게 작동하도록 설정 가능하다.
✅ 이슈: setTimeout 내부의 함수는 i의 최종 값을 참조하므로 4가 세 번 출력됨.
✅ 해결 방법 (클로저 사용)
즉, 즉시 실행 함수(IIFE)를 사용하면 각각의 i 값이 클로저에 저장되어 올바른 값이 출력된다.
(3) 이벤트 핸들러에서 클로저 사용
✅ 클로저 덕분에 각 버튼이 클릭될 때 해당 label 값을 유지할 수 있다.
4. 클로저의 단점과 주의할 점
✅ 메모리 누수 발생 가능
- 클로저는 불필요한 변수까지 메모리에 유지할 수 있어, 메모리 누수를 초래할 수 있다.
- 필요하지 않은 클로저는 null로 설정하여 해제해야 한다.
✅ 클로저의 남용을 피하기
- 무조건 클로저를 사용하기보다는, 단순한 변수나 객체를 활용하는 것이 더 나을 수 있다.
- 불필요한 클로저 사용은 성능을 저하시킬 수 있다.
5. 결론
JavaScript에서 클로저는 데이터 유지, 은닉, 이벤트 핸들링, 비동기 처리 등에서 매우 유용하게 사용된다.
✅ 클로저의 핵심 정리
- 내부 함수가 외부 함수의 변수를 기억하는 개념
- 데이터 은닉, 메모리 관리, 반복문과 비동기 처리에서 활용 가능
- 메모리 누수 방지를 위해 필요 없는 클로저는 해제할 것
클로저를 잘 활용하면 코드를 더욱 효율적이고 안전하게 작성할 수 있다.
'IT & 웹개발' 카테고리의 다른 글
브라우저 로컬 저장소(LocalStorage, SessionStorage, IndexedDB) 비교 (0) | 2025.04.03 |
---|---|
JavaScript의 this 바인딩 – call, apply, bind 차이점 (0) | 2025.04.03 |
함수형 프로그래밍과 JavaScript – 개념 및 예제 (0) | 2025.04.02 |
JavaScript 이벤트 루프(Event Loop)와 비동기 처리 원리 (0) | 2025.04.02 |
JavaScript 메모리 관리와 가비지 컬렉션(Garbage Collection) 이해하기 (0) | 2025.04.02 |