[JS]클로저

kimminjunnn·2025년 5월 8일

CS

목록 보기
18/34

클로저란?

클로저란, 우선 자바스크립트에서만의 용어가 아니다.
클로저란 함수를 '일급 객체'로 취급하는 함수형 프로그래밍 언어(얼랭(Erlnag), 스칼라(Scala), 하스켈(Haskell), 리스프(Lisp)…)에서 사용되는 중요한 특성이다.

클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 상태 또는 그 상태를 말한다.

예시로 이해하기

function outer() {
  let count = 0; // 외부 함수의 지역 변수

  function inner() {
    count++;
    console.log(count);
  }

  return inner;
}

const counter = outer(); // outer 함수 실행 -> inner 함수 반환 , 즉 변수 counter에 inner() 를 담은 것임.
counter(); // 1
counter(); // 2
counter(); // 3

outer()가 호출되면 count는 outer의 지역 변수로 생성된다.
일반적으로 함수가 끝나면 그 안의 지역 변수(count)는 소멸된다.
하지만 inner 함수가 count에 접근하고 있기 때문에,
자바스크립트는 count를 메모리에서 지우지 않고 유지해 준다.
이 "변수를 기억하는 기능"이 바로 클로저이다.

만약 클로저라는 개념이 없다면?
1. outer() 실행 → count = 0 생성
2. inner() 정의하고 리턴
3. outer() 종료 → count는 지역 변수니까 사라짐
4. counter() 실행 → innter 호출해서 count++ 하려는데... ❗ count가 없음!

에러 발생: Uncaught ReferenceError: count is not defined

변수 count가 정의 되지 않는다고 나올 것이다.

정확히 클로저는 함수인가? 현상인가?

클로저는 "함수의 형태를 가진 개념(현상)"이다.
즉,
“클로저”는 함수 그 자체를 말하는 게 아니라,
그 함수가 어떤
스코프(환경)를 기억하고 있는 상태를 말한다.

클로저란, "어떤 함수가 자신이 선언된 렉시컬 환경(Lexical Environment)을 함께 기억하는 현상 또는 구조"

클로저의 생성 조건

조건설명
1. 함수 안에 또 다른 함수가 정의되어 있어야 함중첩 함수 (inner function)
2. 내부 함수가 외부 함수의 변수를 참조해야 함count, message, secret 등
3. 내부 함수가 외부 함수 밖으로 반환되거나 살아남아야 함return, callback, event 등

이렇게 세 가지 조건을 만족하는 함수가 클로저 함수라고 불릴 수 있다.


클로저를 잘 쓰면 뭐가 좋을까?

1. 캡슐화

데이터를 외부에서 직접 접근 못하게 막고, 함수로만 접근하게 만들 수 있다.

function createCounter() {
  let count = 0; // 외부에서 접근 불가

  return {
    increment() {
      count++;
      return count;
    },
    decrement() {
      count--;
      return count;
    }
  };
}

const counter = createCounter();
counter.increment(); // 1
counter.increment(); // 2
// count 변수는 외부에서 직접 접근 불가능!

2. 상태유지

함수 호출이 끝나도 지역 변수를 계속 기억할 수 있다.

function makeGreeting(name) {
  return function() {
    console.log(`Hello, ${name}`); // console.log를 바로 출력하지 않고 function 에 넣어 return해준 모습
  };
}

const greetAnybody = makeGreeting("아무개");
greetAnybody(); // Hello, 아무개

"아무개"의 값을 'name이라는 지역변수'에 저장하여 계속 기억함

주의할 점

불필요하게 사용된 클로저는 메모리 누수를 일으킬 가능성을 높인다는 문제점을 가지고 있기에 이 점을 인지하여 적재적소에 사용하면 좋겠다.

profile
Frontend Engineers

0개의 댓글