클로저(Closure)란?
MDN에서는 클로저를 다음과 같이 정의하고 있다.
클로저는 독립적인 (자유) 변수를 가리키는 함수이다. 또는, 클로저 안에 정의된 함수는 만들어진 환경을 ‘기억한다’.
흔히말해 함수 내에서 함수를 선언하고 사용하면 클로저라고 한다. 여기서 바깥쪽 함수는 외부함수, 그 안에서 선언한 함수는 내부함수라고 부른다. 대개 내부함수를 리턴하고 사용은 외부함수의 바깥에서 하게된다. 말로 설명하면 어려우니 아래 코드를 보자.
function hello(name) {
let _name = name; // 변수명 앞에 underscore(_)를 포함하면 private val임을 의미
return function() { // 클로저 함수
console.log('Hello, '+_name);
}
}
let hello1 = hello('백산');
hello1(); // [출력] : Hello, 백산
위 코드에서 hello()는 외부함수이고 리턴한 무명함수가 내부함수, 즉 클로저이다. 내부함수는 외부함수의 지역변수인 _name을 참조할 수 있고 외부함수의 실행이 끝나서 소멸된 후에도 내부함수가 외부함수의 변수에 접근할 수 있다. 이게 일반 함수와 클로저함수가 포함된 함수가 다른점이다.
일반 함수와 내부함수(클로저)의 차이점
일반함수와 클로저의 가장 큰 차이점은 아래와 같다.
- 은닉화와 캡슐화를 지원한다
- 외부함수가 소멸한 후에도 환경(변수)을 기억하고 이를 제공한다
아래 예제를 통해 일반 함수와 클로저가 어떻게 다른지 알아보자.
일반함수
function hello(name) {
let _name = name;
console.log('Hello, '+_name);
}
hello('백산'); // [출력] : Hello, 백산
hello('신우'); // [출력] : Hello, 신우
내부함수(클로저)
function hello(name) {
let _name = name;
return function() {
console.log('Hello, '+_name);
}
}
let hello1 = hello('백산');
let hello2 = hello('신우');
hello1(); // [출력] : Hello, 백산
hello2(); // [출력] : Hello, 신우
일반함수에서는 hello('백산')를 정의한 시점에서 _name은 '백산'이라는 string으로 결정된다. 출력이 끝난 후에는 해당 함수는 소멸(해당 함수의 전역변수가 초기화됨)되어 다시 같은 함수를 사용하기 위해서는 또다시 백산이라는 string을 받는 함수를 선언해야만 한다.
그에 비해 내부함수의 경우 hello('백산')으로 정의된 함수가 소멸하지 않고 내부의 클로저가 외부함수의 전역변수 값을 기억하고 있다. 따라서 hello1()을 사용하기만 해도 클로저가 외부함수의 전역변수값을 가져와 출력한다.
이점이 일반함수와 내부함수가 다른점이다. 일반함수는 선언할때마다 내부의 전역변수가 초기화되지만 내부함수는 선언했을때의 환경을 기억하고 있다가 여러번 실행할 수 있다.
결론
클로저는 일반함수와 달리 함수 내부에 선언되는 함수로 함수가 실행될때 외부변수에 접근하기 위한 객체이다. 이 경우 원래대로라면 소멸되었어야 할 객체들이 메모리상에 남아있기 때문에 클로저를 남발하면 오버플로우가 발생할 수도 있다. 따라서 클로저에 대해 정확히 이해하고 필요한곳에 사용해야 할 것이다.
'Developer > 기술면접' 카테고리의 다른 글
동기(Sync), 비동기(Async)란? (0) | 2021.07.20 |
---|---|
HTTP 상태 코드 (0) | 2021.07.20 |
var, let, const 차이점 (0) | 2021.07.18 |
비동기 프로그래밍이란? (0) | 2021.07.18 |
함수형 프로그래밍이란? (0) | 2021.07.18 |