기초 개념
클로저(closure)가 대체 뭐길래!!
dv_jamie
2022. 5. 9. 16:23
클로저(Clousure)란?
- 어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상 (가비지 콜렉터의 동작 방식 때문)
const A = () => { // 어떤 함수 A
let a = 1 // 에서 선언한 변수 a
const B = () => { // 를 참조하는 내부함수 B
return ++a // (스코프 체이닝에 따라 A에서 선언한 변수 a에 접근)
}
return B // (* A의 실행 컨텍스트가 실제로 종료되는 시점)
}
// 를 외부로 전달할 경우 A의 실행 컨텍스가 종료된 이후에도 (*return하면 그 함수는 생을 마감)
const newA = A()
// 변수 a가 사라지지 않는 현상
console.log(newA()) // 2 (반환된 함수 B를 실행)
console.log(newA()) // 3 (반환된 함수 B를 실행)
// => newA가 호출됨으로써 a를 참조하는 B 함수가 호출될 가능성이 열린 것
// => 즉, 가비지 컬렉터 대상에서 제외되므로 B 함수가 a에 계속 접근할 수 있음
- 여러 함수형 프로그래밍 언어에서 등장하는 보편적 특성 (자바스크립트 고유의 개념이 아님)
비교 코드 (클로저 현상 x)
const A = () => {
let a = 1
const B = () => {
console.log(++a) // 2
}
B()
}
A()
// => B 함수 실행 컨텍스트 종료 -> A 함수 실행 컨텍스트 종료
// -> A의 LexicalEnvironment에 저장된 식별자들(a, B)에 대한 참조 지움
const A = () => {
let a = 1
const B = () => {
return ++a // return 하면서 B 함수는 실행 컨텍스트 종료됨(생을 마감)
}
return B()
}
const newA = A // = B 함수를 실행한 결과값 (이 때 B 함수가 종료됨)
console.log(newA) // 2
- 두 경우의 공통점
- A 실행 컨텍스트 종료 전 내부함수인 B 실행 컨텍스트 이미 종료 + 이후 B 함수 호출 x
- A 함수가 종료되면서 a를 참조하는 대상이 없어져 가비지 콜렉터 대상이됨 (언젠가 소멸) - A의 실행 컨텍스트가 종료된 후에도 B 함수를 호출하면? (cf. 가장 첫번째 코드블럭) 이 때의 현상이 클로저
그래서 이걸 어떨 때 활용하는가
- 소프트웨어가 커질수록 많은 데이터가 생길텐데, 직접 접근하여 수정 가능하게 하면 오류 발생 가능성 높아짐
=> 내부함수로만 접근할 수 있도록 해서 안전성을 올림 (캡슐화) - 그 외 사용 이유가 더 있지만 아직은 여기까지만 이해함, 나중에 더 깊게 찾아봐야지!
클로저가 발생하는 경우와 메모리 관리법
- 추가로 공부할 것
단점 및 보완
- 클로저는 의도적으로 함수의 지역변수를 GC의 수거 대상이 되지 않도록 한 것이라 메모리를 소모하게 됨
=> 관리만 잘해주면 보완됨! - 관리 방법 : 필요성이 사라진 시점에 더는 메모리를 소모하지 않게, 즉, 참조 카운터를 0으로 만들어줌
내 표현대로 다시 정리
- 외부함수에서 선언된 변수를 참조하는 어떤 내부 함수가 있을 때 내부함수를 외부에서 호출하면, 외부함수가 종료되어도 변수는 계속 참조되어 소멸되지 않는 현상
- 어떤 데이터 값에 직접 접근하지 않고 내부함수를 통해서만 접근이 가능하도록 활용 가능 => 안전성 증가
나의 생각
- 코드 구현을 통해 메모리를 계속 사용한다는 클로저의 단점을 해결한다면 그 외 단점은 딱히 없는 것 같고 오히려 유용한 것으로 보임 (찾아봐도 메모리 소모 외에 딱히 언급 안되어 있는 듯)
- 큰 규모의 서비스, 혹은 여러 개발자와 협업을 하게 된다면 잘 활용해봐야할 것 같음
궁금한 점
- 내부함수로만 변수에 접근할 수 있게 한다면 메서드나 라이브러리는 이 클로저라는 개념을 활용한 것일까?
- O
- 전부 다 클로저를 활용하는 것은 아니지만, 많은 라이브러리들이 쓰고 있음 - 클래스와 비슷한 걸까?
- O
- 예전에는 클래스가 없었는데, 그 때 클로저를 많이 활용했음
- 클래스를 지원한 이후로부터는 메서드나 라이브러리 용도에 한해 클로저보다 클래스를 많이 사용
참고 서적
- 코어 자바스크립트 - 정재남