🐨CoalaCoding
DocsExamplesTry itBoardB반B반
🐨CoalaCoding

개발자를 위한 한국어 웹 기술 문서

문서

  • JavaScript
  • Web Publishing
  • React
  • Python

커뮤니티

  • 게시판
  • 예제 모음
  • Try it 에디터

기타

  • GitHub
  • 관리자
© 2026 CoalaCoding. All rights reserved.
  • start
  • class
  • ai이미지-생성기-구현
  • 자료형
  • async--await
  • 변수와자료형
  • xmlhttprequest-부터axios-까지
  • 1-자바스크립트와-ecma
  • reduce
  • 캘린더-만들기
  • generator
  • destructuring
  • spread-operator
  • module-export-import
  • http-통신-이란
  • 시작
  • 2-자바스크립트-코드-실행-과정-및-용어정리
  • map
  • 동기와-비동기
  • 연산자
  • promise-thencatch
  • 3-실행컨텍스트와-스코프
  • 콜백-함수
  • 제어문
  • 4-클로저
  • windowlocation
  • 함수
  • 5-객체
  • 이벤트
  1. 홈
  2. 문서
  3. JavaScript
  4. JavaScript 기초
  5. 4-클로저

4-클로저

코드 블록의 Try it Yourself 버튼으로 직접 실행할 수 있다.

구문

목차

1. 가비지컬렉션

콜스택에서 메모리를 자동으로 삭제하는 과정을 가비지 컬렉션이라고 하고 이 시스템을 가비지 컬렉션 이라고 한다. 메모리의 누수를 방지하려는 목적으로 평가가 완료된 코드를 콜스택에서 제거하는 것인데 자바스크립트는 이것을 자동으로 지원한다.

1-1-**가비지 컬렉터(Garbage Collactor): **

메모리에서 더이상 사용되지 않는 실행컨텍스트 감지하고 해당 메모리를 회수 하여 삭제하는 시스템

function outer() {
  let a = 10;
  return function inner() {
    a++;
    console.log(b);
  }
}
const fn = outer();
fn();

위 코드의 결과를 예상해 보자

11이라는 값이 평가되고 가비지컬렉터로 컨텍스트가 이동하면서 콜스택은 비워져 있을것이다.

function outer() {
  let a = 10;
  return function inner() {
    a++;
    console.log(a);
  }
}
const fn = outer();
fn();
fn();
fn();

하지만 호출할때 마다 값이 증가하는 이상한 일이 발생한다.

1-2-예외

컨텍스트의 레코드 값이 참조중 일 때는 가비지컬렉터가 자동으로 수행되지 않는다.

inner 의 a 가 상위컨텍스트인 a의 값을 참조하므로 outer 는 가비지컬렉터 대상이 되지 않는다.

2-클로저

클로저는 1-2에서 발생하는 현상을 말한다.

2-1-정의

Info: 함수가 생성될 때 그 주변의 변수 환경(스코프)을 기억하고, 생성 이후에도 접근할 수 있는 기능


가비지컬렉션의 대상이 되지 못하고 메모리 제거가 되지 못해 메모리에 남아 있는 현상

2-2-개념요약

  1. 함수가 만들어질 때의 변수 환경을 기억 → 함수가 실행될 때만 아니라, 이후에도 해당 변수에 접근 가능
  2. 내부 함수가 외부 함수의 변수를 참조 → 내부 함수가 실행되는 동안 외부 함수의 변수는 유지됨
  3. 데이터 은닉(캡슐화) → 클로저를 활용하면 외부에서 직접 접근할 수 없는 변수를 만들 수 있음

2-3-활용

  1. 변수의 유지 (상태 유지 기능) → 한 번 실행된 함수의 값을 저장하고 다시 사용할 때
  2. 데이터 보호 (정보 은닉) → 외부에서 직접 변경할 수 없도록 변수를 보호할 때
  3. 콜백 함수 활용 → 비동기 처리나 이벤트 핸들러에서 이전 상태를 유지할 때

2-4-예시

정보를 안전하게 은닉(Information Hiding)

let n = 0;
const increase = function () {
  return ++n;
}
console.log(increase());
console.log(increase());
console.log(increase());

위의 코드는 잠재적으로 버그가 있다. 변수 n은 increase 함수의 호출시에만 변경되어야 전역변수라 다른 코드에 의해값을 변경할수 있기 때문이다.

const increase = function () {
  let n = 0;
  return ++n;
}
console.log(increase());
console.log(increase());
console.log(increase());

위와 같이 수정하면 n은 지역변수로 increase 함수만 변경할수 있게된다. 누산을 하지 못하는 것이다.

2-4-1-클로저패턴

const increase = (function () {
  let n = 0;
  return function () { return ++n }
}())
console.log(increase());
console.log(increase());
console.log(increase());

위와 같이 수정해보자 increase 변수의 함수를 즉시실행함수로 수정한다.

2-4-2-소스코드의 평가단계

1단계: 전역 실행 컨텍스트 생성

  • 코드 실행이 시작되면, 자바스크립트 엔진은 전역 실행 컨텍스트(Global Execution Context) 를 생성한다.
  • 전역 컨텍스트에는 increase 변수와 즉시 실행 함수(IIFE)가 포함된다.

2단계: 즉시 실행 함수 (IIFE) 실행

  • 즉시 실행 함수 (function() \{ ... \}()) 가 실행되면서 새로운 실행 컨텍스트 가 생성된다.
  • n이라는 렉시컬 환경(Lexical Environment) 내부 변수가 선언되고, 초기값 0이 할당된다.
  • 이 함수는 실행된 후 내부에서 또 다른 익명 함수를 반환하고 종료된다.

3단계: 반환된 함수가 increase에 할당됨

  • 즉시 실행 함수가 종료될 때 return function () \{ return ++n \} 문으로 인해 내부 함수가 반환된다.
  • 즉, increase 변수에는 반환된 내부 함수의 참조(클로저) 가 저장된다.

4단계: increase() 호출 과정 (클로저 활용)

이제 console.log(increase()) 를 실행할 때마다 함수 실행 컨텍스트가 어떻게 변하는지 보자.

**첫 번째 호출: **console.log(increase());

  1. increase() 실행 → 내부 함수가 실행됨.
  2. increase 내부의 n 값을 증가 (++n → 1)하고 반환.
  3. console.log(1) 출력.
  4. 중요한 점: 내부 함수 실행이 끝나도 n 값(=1)은 유지됨.

**두 번째 호출: **console.log(increase());

  1. increase() 실행 → 내부 함수가 실행됨.
  2. 기존의 n 값(1)에서 ++n → 2로 증가.
  3. console.log(2) 출력.
  4. n** 값(=2)이 여전히 유지됨.**

**세 번째 호출: **console.log(increase());

  1. increase() 실행 → 내부 함수가 실행됨.
  2. 기존의 n 값(2)에서 ++n → 3으로 증가.
  3. console.log(3) 출력.
  4. n** 값(=3)이 계속 유지됨.**

이렇게 클로저를 활용하면 함수내부에서 사용하는 데이터를 은닉하여 안정성이 보장된 코드를 구현할 수 있다.


2-5-클로저 활용시 유의사항

클로저는 결국 가비지 컬렉션이 되지 않는 코드를 의미한다. 클로저가 발생한 데이터의 참조가 끝나더라도 메모리에서 자동삭제가 되지 않으므로 수동삭제 하는 로직을 작성해야 한다.

2-5-1-클로저의 삭제1

2-4-1의 예시처럼 즉시실행함수를 사용하면 함수의 실행후 콜스택에서 삭제 되므로 메모리 누수를 방지할수 있다.

2-5-2-클로저의 삭제2

아래와 같이 선언적 함수를 식별자에 할당하여 호출하는 경우

function counter() {
  let a = 0;
  return function inner() {
    ++a;
    console.log(a);
  }
}
let fn = counter();
**fn();
fn();
fn();
fn();
fn();
fn=null**

counter 함수의 호출이 끝나면 fn 에 null을 할당하여 메모리를 비워야 한다.

목차

  • 구문