jgjgill

클로저(Closure)란?

No Filled

함수가 선언될 당시의 렉시컬 환경 (Lexical Environment)을 기억하여, 함수가 스코프 밖에서 실행될 때도 그 환경에 접근할 수 있는 자바스크립트의 특성

기본 개념

  • 클로저는 함수와 그 함수가 선언된 렉시컬 환경의 조합
  • 내부 함수가 외부 함수의 변수에 접근할 수 있고 외부 함수가 종료된 후에도 그 변수들에 계속 참조 가능

등장 배경

  • 데이터 은닉 문제: JS에는 초기에 private 변수 개념 없었음
  • 상태 유지 필요성: 함수 실행이 끝나도 특정 값을 보존해야 하는 상황
  • 함수형 프로그래밍: 함수를 일급 객체로 다루면서 자연스럽게 발생한 패턴
  • 콜백과 비동기: 이벤트 핸들러나 비동기 처리에서 외부 컨텍스트 접근 필요

동작 원리

1단계 - 함수 선언 시

  • 함수가 생성될 때 해당 함수는 자신이 선언된 렉시컬 환경을 내부 슬롯 [[Environment]]에 저장

2단계 - 실행 컨텍스트

  • 외부 함수 실행 시 실행 컨텍스트와 렉시컬 환경 생성
  • 내부 함수는 외부 렉시컬 환경에 대한 참조 유지

3단계 - 외부 함수 종료

  • 일반적으로 실행 컨텍스트는 콜 스택에서 제거
  • 하지만 내부 함수가 외부 함수의 변수를 참조하고 있으면 가비지 컬렉션 대상이 되지 않음

4단계 - 내부 함수 실행

  • 내부 함수가 호출되면 스코프 체인을 통해 외부 변수에 접근
  • 저장된 렉시컬 환경을 통해 값을 읽거나 수정

예시 코드

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

  return function () {
    // 내부 함수 (클로저)
    count++
    return count
  }
}

const counter1 = createCounter()
const counter2 = createCounter()

console.log(counter1()) // 1
console.log(counter1()) // 2
console.log(counter1()) // 3

console.log(counter2()) // 1
console.log(counter2()) // 2

헷갈리기 쉬운 부분

클로저 vs 스코프

  • 스코프: 변수의 유효 범위 (어디서 접근 가능한가)
  • 클로저: 함수가 선언된 환경을 기억하는 현상 (어떻게 접근하는가)

렉시컬 환경 vs 실행 컨텍스트

  • 렉시컬 환경: 변수와 함수 선언을 저장하는 구조 (정적)
  • 실행 컨텍스트: 코드 실행에 필요한 환경 (동적, 콜 스택에서 생성/제거)

개념 정리

클로저란 무엇인가요?

클로저는 함수가 선언될 당시의 렉시컬 환경을 기억하여, 함수가 스코프 밖에서 실행될 때도 그 환경에 접근할 수 있는 자바스크립트 특성입니다.

자바스크립트에서 함수가 생성될 때 그 함수는 자신이 선언된 위치의 렉시컬 환경을 내부적으로 참조합니다. 일반적으로 함수가 실행을 마치면 그 함수의 지역 변수들은 메모리에서 제거되지만, 내부 함수가 외부 함수의 변수를 참조하고 있다면 가비지 컬렉션의 대상이 되지 않습니다. 외부 함수의 실행이 종료된 후에도 내부 함수는 외부 함수의 변수에 계속 접근할 수 있는 것입니다.

주의할 점으로 클로저가 외부 변수를 계속 참조하고 있으면 메모리에서 해제되지 않기 때문에, 불필요한 클로저를 많이 만들거나 제대로 정리하지 않으면 메모리 사용량이 늘어날 수 있습니다.

핵심 문장

  • 클로저는 함수가 자신이 선언된 렉시컬 환경을 기억하는 것입니다.
  • 내부 함수가 외부 함수의 변수를 참조할 때 발생하며, 외부 함수 실행이 종료된 후에도 그 변수에 접근할 수 있게 해줍니다.
@2023 powered by jgjgill