반응형

자바스크립트 개발 환경 Microsoft Visual Studio 2015 버전 HTML 기능 및 Chrome을 이용하고 있습니다.





클로저를 알아보기전에 다음과 같은 코드가 있다 치자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html>
<head>
    <title>test title</title>
    <script>
 
        /*
            클로저에 대해 알아보기
            1. 우선 다음과 같은 함수를 정의하고 alert를 한다 치자.
            이때 msg는 출력되지 않는다. 
            왜냐면 함수 내부에서 쓰는 변수는 
            지역 변수이므로 함수 외부에서 사용할 수 없다.
            (함수가 종료되면 사라지기 때문)
        */
        function func(name) {
            var msg = 'Hello' + name;
        }
 
        alert(msg);
 
    </script>
</head>
 
</html>
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus


이 값에 대한 출력은 어떻게 될까?



클릭하시면 결과 화면을 확인 할 수 있습니다.



이상하게도 아무런 값이 나타나지 않는다.



왜 그런가 생각해보면 다음과 같다.


msg는 함수 내에 정의된 변수이다.


따라서 함수가 소멸하면 msg자체가 존재하지 않게 된다.


이때 alert(msg)를 하면 없는 변수를 참조시키는 것이니 아무 내용이 출력되지 않게 된다.




이때 클로저라는 개념을 사용하면 자바스크립트 프로그래밍을 할 때 이러한 방식 즉, 규칙을 무시하고 코딩을 가능하게 해준다.


바로 예를 들어보자.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html>
<head>
    <title>test title</title>
    <script>
 
        /*
            1. 클로저라는 기능을 쓰면 우리는 이러한 방법을 넘어
            외부에서도 이용할 수 있게 된다.
        */
 
        function funcCloser(name) {
            var msg = 'Hello ' + name;
 
            return function () {
                alert(msg);
            };
        }
 
        funcCloser('World')();
 
    </script>
</head>
 
</html>
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus




클릭하시면 결과 화면을 확인 할 수 있습니다.



msg라는 변수는 'Hello World'라는 값을 가지게 되고 함수가 종료 될 때 없어져야 한다.


하지만 이때 변수가 사라지지 않고 남겨지므로 이 코드를 실행하면 위의 결과 화면과 같은 값을 얻을 수 있다.



아직 감이 제대로 잡히지 않을 수 있다.


따라서 또다른 예를 하나 더 살펴보자.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html>
<head>
    <title>test title</title>
    <script>
 
        /*
            1. 클로저라는 기능을 쓰면 우리는 이러한 방법을 넘어
            외부에서도 이용할 수 있게 된다.
        */
 
        function funcCloser(a) {
 
            return function(b) {
                return a * b;
            }
 
        }
 
        x = funcCloser(10);
        y = funcCloser(20);
 
        alert(x(3));
        alert(y(4));
        alert(y(5));
    </script>
</head>
 
</html>
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus





클릭하시면 결과 화면을 확인 할 수 있습니다.





이제 조금 더 감이 잡힐 것이라 생각이 든다.


x = funcCloser(10)을 통해 a 매개변수에는 10이라고 자리를 잡아버리고 만다.


이때 b에는 아직 어떠한 값도 오지 않았다.


그런데 alert(x(3));을 실행해보면 답이 30이 나온다.


이것이 클로저라는 의미이다. a는 분명 소멸했었어야 했는데 a를 남겨둔 채 3을 받으면 10*3을 실행하여 결과를 출력해주는 것이다.





마지막으로 다른 예를 하다 더 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html>
    <head>
        <title>test title</title>
    </head>
 
    <body>
        <h2> JavaScript </h2>
 
        <p id="test">자바 스크립트 </p>
 
        <button type="button" onclick="myFunction()"><< 더하기 버튼 >></button>
        <p id="output"></p>
 
        <script>
            
            var add = (function() {
                var counter = 0;
                return function() { return counter += 1; }
            })();
 
            function myFunction() {
                document.getElementById('output').innerHTML = add();
            }
        
        </script>
 
    </body>
</html>
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
cs




클릭하시면 결과 화면을 확인 할 수 있습니다.


위의 코드는 self-invoking을 이용하여 클로저를 나타낸 것이다.


self-invoking은 함수를 ()로 감싸고 마지막에 ();로 실행하면 된다.


즉, (함수)();로 나타낼 수 있다.



동작 원리는 다음과 같다.


변수 add는 self-invoking 함수를 리턴한다.


self-invoking 함수는 오직 한번 실행되는데 이때 counter는 0으로 초기화되있고, 함수를 리턴한다.


이때 counter는 부모 스코프의 카운터를 참조할 수 있게된다.


따라서 이 방법을 클로저라하며 "private" 변수를 가지는 함수를 가능하게 할 수 있는 것이다.


counter는 결국 일시적으로 만들어낸 함수에 의해 초기화 되지 않고 add 함수를 이용하여 계속해서 값을 변경 할 수 있는 것이다.




클로저는 메모리 누수를 일으킨다!



위와 같이 클로저를 이용하면 값을 계속해서 보관하고 있다보니 메모리 누수가 일어날 것이라는 것은 어려운 생각이 아닐듯 하다.


따라서 자바스크립트의 가비지 컬렉션과 

서로 다른 브라우저들이 자신만의 가비지 컬렉션을 이용하여 메모리 누수를 최소화 해주는데,


가장 좋은 방법은 이 프로그램을 만든 프로그래머 자신이 메모리 누수를 최소화 시켜야 한다는 것이다.



그러한 방법에 대해서는 정리가 잘 되어 있는 아래의 링크를 참조해보길 바란다.


https://developer.mozilla.org/ko/docs/A_re-introduction_to_JavaScript
















반응형