자바스크립트에는 클래스 기반 언어와 달리 private 키워드가 없기 때문에, 외부에서 직접 접근할 수 없는 변수를 만들려면 별도의 기법이 필요합니다. 이럴 때 가장 널리 사용되는 방법이 바로 클로저(Closure)입니다.
클로저란 무엇인가?
클로저는 함수가 자신이 생성된 환경(렉시컬 스코프)을 기억하고, 그 환경에 있는 변수에 계속 접근할 수 있게 해주는 자바스크립트의 핵심 개념입니다. 함수 내부에 선언된 지역 변수는 함수 외부에서 직접 접근할 수 없으므로, 이 특성을 활용하면 외부로부터 보호되는 프라이빗 속성을 흉내 낼 수 있습니다.
예제 코드
다음은 클로저를 사용해 카운터 값을 외부에서 변경할 수 없도록 보호하면서 증가시키는 전체 예제입니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>클로저로 구현한 프라이빗 속성</title>
<style>
body {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
.result {
font-size: 20px;
font-weight: 500;
color: blueviolet;
}
</style>
</head>
<body>
<h1>클로저를 활용한 프라이빗 속성</h1>
<div class="result">0</div>
<br />
<button class="Btn">클릭하세요</button>
<h3>위 버튼을 클릭하면 클로저를 통해 카운터가 증가합니다</h3>
<script>
let BtnEle = document.querySelector(".Btn");
let resEle = document.querySelector(".result");
function test() {
let a = 0; // 외부에서 직접 접근 불가능한 프라이빗 변수
return function incrementA() {
a++;
return a;
};
}
let storeVal = test();
BtnEle.addEventListener("click", (event) => {
resEle.innerHTML = storeVal();
});
</script>
</body>
</html>코드 동작 원리
이 코드의 핵심은 test() 함수 내부에 있습니다.
- 변수
a는test()함수 내부에 선언된 지역 변수이므로, 함수 외부에서는 어떤 방법으로도 직접 접근하거나 수정할 수 없습니다. test()는 내부 함수incrementA()를 반환하는데, 이 내부 함수는 자신이 생성될 당시의 스코프를 기억하여 변수a에 계속 접근할 수 있습니다. 이것이 바로 클로저입니다.storeVal = test()를 호출하는 순간 변수a가 메모리에 유지되며, 버튼을 클릭할 때마다storeVal()이 실행되어a의 값이 1씩 증가합니다.
실행 결과
페이지를 실행하면 초기 카운터 값이 0으로 표시됩니다.

'클릭하세요' 버튼을 누를 때마다 카운터가 1씩 증가하는 것을 확인할 수 있습니다.

정리
이처럼 클로저를 활용하면 별도의 문법 없이도 외부 접근이 차단된 프라이빗 상태를 유지할 수 있습니다. 참고로 최신 자바스크립트(ES2022)에서는 클래스 필드 앞에 #을 붙이는 진짜 프라이빗 필드 문법도 제공되지만, 클로저 방식은 오래된 브라우저에서도 동작하며 함수형 프로그래밍에서 여전히 유용하게 쓰이는 패턴입니다.