Romantic Developer : )

(Javascript) 자바스크립트 심화 (3) 클로저 본문

Romantic Developer/JavaScript

(Javascript) 자바스크립트 심화 (3) 클로저

Romantic_Developer 2018. 7. 16. 15:00

안녕하세요 ~ 영감을 주는 개발자 방민방민입니다.


오늘은 자바스크립트 심화 3번째 시간으로 클로저에 대하여 알아보고자 합니다.

클로저는 자바스크립트 고난이도 테크닉에 있어서 반드시 필요한 내용이라고 합니다!!! 

어렵지만 정확한 개념을 잡고 가야합니다.!!


클로저는 내부함수가 외부함수의 맥락에 접근할 수 있음을 나타냅니다.

예를 통해 자세하게 알아보도록 하겠습니다.



1. 내부함수


내부함수와 외부함수의 개념에대해서 먼저 생각해보도록 하겠습니다.

아래의 예제를 보며 내부함수의 개념에 대해서 생각해보겠습니다.

function outter(){
	
	function inner(){
		var title = 'coding';
		alert(title);
	}
	inner();
}
outter();


위의 간단한 예제를 보시면, 위의 예제는 outter라는 외부함수 내부에 inner 라는 내부 함수를 생성하고 

변수 title 을 알림으로 출력하는 예제입니다.


하나의 함수 내에서만 사용되는 함수를 외부에 고정적으로 생성해두고 사용하는 것은 메모리의 낭비가 될 수 있기 때문에 하나의 특정 함수 내에서 선언과 호출을 하는 방식으로 코딩을 하게 됩니다.


위의 예제는 title 에 저장된 coding 이라는 값을 출력합니다.


그러면 아래의 다른 예에 대하여 살펴 보도록 하겠습니다.


function outter(){
	var title = 'coding';	
	function inner(){
		alert(title);
	}
	inner();
}
outter();


위의 예제를 잘 보시면, 이번에는 title 이라는 변수가 inner 함수 내부가 아닌 outter 라는 외부함수에 선언되어 있습니다.

이때 inner 함수는 outter 함수에 있는 title 이라는 변수에 접근할 수 있습니다!!

따라서 위의 예제는 아래의 결과를 출력합니다.




2. 클로저


다시한번, 클로저는 내부함수에서 외부함수에 접근할수 있다는 개념을 나타냅니다.

그런데 더욱이 신기한것은 , 클로저의 개념에서 내부함수는 외부함수가 종료되고 난 뒤에 그 내부에 있는 변수가 소멸되고 난 뒤에도 접근이 가능합니다. 이 개념에 대해서는 아래의 예제를 통해 알아보도록 하겠습니다.


function outter(){
	var title = 'coding';
	return function(){
		alert(title);

	}
}

inner = outter();
inner();

위의 예제에서 outter 에서 return 으로 반환되는 함수를 inner 에 저장합니다. 즉 inner 라는 임의의 변수에 outter 에서 리턴되는 함수를 저장한 상태에서 inner 을 호출하였을 때, coding 이 저장된 title 이라는 변수는 사실상 소멸된 상태이지만! 브라우저는 아래의 결과를 출력합니다.



즉, outter 라는 함수는 종료 되었지만, 내부함수 inner 는 title 에 접근하여 그 내용인 coding를 정확하게 출력하였다는 것입니다.


조금더 심화된 예제를 살펴보도록 하겠습니다.


function factory_movie(title){
	return {//두개의 메소드를 포함하는 객체를 리턴
		get_title : function(){
			return title;
		},
		set_title : function(_title){
			title = _title
		}
	}
}

ghost = factory_movie('Ghost');//객체를 ghost 에 저장
matrix = factory_movie('Matrix');//객체를 Matrix 에 저장

alert(ghost.get_title());
alert(matrix.get_title());

ghost.set_title('공각기동대');

alert(ghost.get_title());
alert(matrix.get_title());


위의 예제에서 factory_moive 는 title 을 인자로 받아서 get_title 과 set_title 이라는 두개의 메소드를 갖는 객체를 리턴합니다. 이때 , title 이라는 변수는 factory_movie 라는 함수가 종료된 뒤에도, ghost 와 matrix 각각의 변수에서 접근할 수 있게 됩니다.


즉, ghost 에서는 set_title 을 통해 title 에 'Ghost'를 저장하고, matrix 에서도 set_title 을  통해 title에 'Matrix'를 저장합니다. 하지만 이때 생성되는 클로저가 다르기 때문에 각각의 title 변수는 다른 title 입니다.


아래의 ghost.get_title()과 matrix.get_title() 은 각각 위에서 저장된 'Ghost' 와 'Matrix'로 다른 값을 출력합니다. 정리하면 아래와 같습니다.


1. 클로저는 객체의 메소드에서도 사용할 수 있다. 위의 예제는 함수의 리턴값으로 객체를 반환하고 있다. 이 객체는 메소드 get_title과 set_title을 가지고 있다. 이 메소드들은 외부함수인 factory_movie의 인자값으로 전달된 지역변수 title을 사용하고 있다.

2. 동일한 외부함수 안에서 만들어진 내부함수나 메소드는 외부함수의 지역변수를 공유한다. 17행에서 실행된 set_title은 외부함수 factory_movie의 지역변수 title의 값을 '공각기동대'로 변경했다. 19행에서 ghost.get_title();의 값이 '공각기동대'인 것은 set_title와 get_title 함수가 title의 값을 공유하고 있다는 의미다.

3. 그런데 똑같은 외부함수 factory_movie를 공유하고 있는 ghost와 matrix의 get_title의 결과는 서로 각각 다르다. 그것은 외부함수가 실행될 때마다 새로운 지역변수를 포함하는 클로저가 생성되기 때문에 ghost와 matrix는 서로 완전히 독립된 객체가 된다.

4. factory_movie의 지역변수 title은 2행에서 정의된 객체의 메소드에서만 접근 할 수 있는 값이다. 이 말은 title의 값을 읽고 수정 할 수 있는 것은 factory_movie 메소드를 통해서 만들어진 객체 뿐이라는 의미다. JavaScript는 기본적으로 Private한 속성을 지원하지 않는데, 클로저의 이러한 특성을 이용해서 Private한 속성을 사용할 수 있게된다.

[출처 : 생활코딩]


주의해야 하는 점은 이러한 클로저의 개념은 외부함수 내부에 있는 내부함수 일때만 가능합니다.

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(){
        return i;
    }
}
for(var index in arr) {
    console.log(arr[index]());
}

이 경우 클로저의 개념을 생각하면 아래 for 문에서 위의 각각 function 에 저장된 0부터 4를 출력하는 것이 저장될 것 같지만, 실제로는 5를 5번 출력합니다.

이것은 for 문 내부에 function 이 내부함수가 아니기 때문에, i에 접근할 수 없기 때문에 발생합니다.



오늘은 간단하게 클로저의 개념에 대하여 알아보았습니다.


클로저는 중급 개발 이상에서는 반드시 필요한 개념입니다. 


어렵지만 화이팅 하시기 바랍니다!! 

오늘도 영감을 주는 개발자 방민방민이었습니다.