[JS] 자바스크립트의 클로저(Closure)

kkyvvoo·2026년 1월 19일

JS

목록 보기
2/5
post-thumbnail

closure는 왜 이름이 closure일까? 사전에 closure을 검색하면 폐쇄하다,종료하다,닫다 라고 나온다.
함수가 생성될때 자신 주변의 변수들을 울타리치듯이 감싸 안아서 자기만의 배낭에 챙겨넣는다고 생각해봐라
함수가 실행될때 이 '배낭'을 닫아서(close)가지고 다니기 때문에,나중에 외부 함수가 사라져도 배낭안의 데이터는 안전하게 보존된다 라고 이해하면 쉽다.

1. 클로저(Closure)란 무엇인가?

클로저의 핵심 정의는 다음과 같다

"외부 함수보다 중첩함수(내부함수)가 더 오래 유지되는 경우,외부함수가 이미 종료(return)되었음에도 불구하고 내부 함수가 외부 함수의 변수를 여전히 참조할 수 있는 현상"

쉽게 비유하자면 "기억을 간직한 배낭을 멘 함수"이다. 함수가 생성될 때, 자신이 태어난 곳(렉시컬 환경)에 있던 변수들을 배낭에 담아서 가지고 다닌다. 그래서 나중에 어디서 호출되든 그 배낭 안의 변수들을 꺼내 쓸 수 있는 것이다.

다시말해, "외부함수가 종료된 후에도 그 변수를 기억하고 있는 내부함수"

보통 함수가 실행을 마치면 그 안의 변수들은 메모리에서 사라진다. 하지만 클로저는 자신이 생성될 당시의 렉시컬 환경기억해서, 나중에도 그 변수에 접근할 수 있게 해줌.

2. 코드로 봐보자

function outer(){
  const x = 10;
  const inner = function() {
    console.log(x);
  };
  return inner;
}
//outer 함수를 호출하면 inner 함수 자체를 반환하고 outer는 끝남
const myFunc = outer();

//여기서 outer 함수의 실행 컨텍스트는 이미 종료되어 사라짐
//그런데 myFunc(실제로는 inner) 를 호출하면?
myFunc(); //출력: 10
  1. outer()가 실행되고 inner함수를 반환한 뒤 종료됨
  2. 일반적이라면 outer 내부의 변수 x도 메모리에서 사라져야하지만
  3. inner 함수가 클로저가 되어 x를 참조하고있기 때문에, js엔진은 x를 메모리에서 지우지 않고 남겨둠
  4. 나중에 myFunc()를 실행할때, 이 남겨진 x에 접근하여 10을 출력함.

3. 클로저를 왜 쓸까?

클로저를 사용하는 가장 큰 이유는 상태 유지정보 은닉 때문이다.

예시: 카운터 만들기

만약 전역 변수로 카운터를 만들면 누구나 숫자를 바꿀 수 있어 위험하다. 근데 클로저를 사용하면 안전하게 만들수있음

function createCounter() {
  let count = 0; // 이 변수는 밖에서 절대 직접 접근할 수 없음. (은닉)

  // 이 함수들이 클로저
  return {
    increase: function() {
      count++;
      return count;
    },
    decrease: function() {
      count--;
      return count;
    }
  };
}

const counter = createCounter();

console.log(counter.increase()); // 1
console.log(counter.increase()); // 2
console.log(counter.decrease()); // 1

// console.log(counter.count); // undefined (접근 불가!)
  • 설명: count변수는 createCounter함수 안에 숨어있고, 오직 반환된 increase,decrease메서드를 통해서만 조작이 가능하다. 이것이 캡슐화와 정보 은닉의 기본

4. 클로저 사용시 주의점

1) 메모리 누수 주의
클로저는 "참조가 끊기지 않은 변수"를 메모리에 계속 붙잡고 있는것인데, 필요이상으로 클로저를 남발하면 메모리 사용량이 늘어남. 더이상 필요없는 클로저는 null을 할당하여 참조를 끊어주는 것이 좋음

let myFunc() = outer();
myFunc();
//더이상 안쓴다면?
myFunc() = null // 참조 해제 -> 가비지 컬렉터가 수거해감
profile
study archive

0개의 댓글