이 글은 하인도님의 2009년 11월 18일에서 2009년 12월 10일까지의 미투데이 내용입니다.

728x90

예전 포스팅 중 [ Javascript, 객체화 하기 ] 라는 제목으로 올린 것이 있다.
그 때 쓴 포스팅 방법에 의거해서 예제 소스를 하나 구성하면 아래와 같다.

var objTest = {
      valDisplay : "",
      displayValue : function () {
            alert(this.valDisplay);
      }
     
      setValue : function(val) {
            this.valDisplay = val;
      } 
};

위의 예제를 실행해 보려면, 적절한 위치에서 아래와 같은 코드를 실행해 보면 된다.

objTest.setValue("Go Go Objected Javascript World");
objTest.displayValue();

그런데, 위와 같은 코드를 하게 되면 문제가 하나 있다. 예를 들어 objTest와 같은 로직을 부르는 곳이 많을 때다. 여기서 부르는 곳이 많다는 의미를 단순히 호출 자체의 횟수가 아니고, valDisplay를 독립적으로 운영해야 되는 경우를 말하는 것이다.
예를 들어 아래와 같은 코드를 보도록 하자.

objTest0.setValue("Go Go Objected Javascript World");
objTest0.displayValue();
objTest1.setValue("No, I Want to new display valueGo Go Objected Javascript World");
objTest1.displayValue();

위와 같은 코드를 실행하려면 아래 처럼, 처음 코드를 두개 넣어야 한다.

var objTest0 = {
      valDisplay : "",
      displayValue : function () {
            alert(this.valDisplay);
      }
     
      setValue : function(val) {
            this.valDisplay = val;
      } 
};
var objTest1 = {
      valDisplay : "",
      displayValue : function () {
            alert(this.valDisplay);
      }
     
      setValue : function(val) {
            this.valDisplay = val;
      } 
};

처음에는 단순하게 생각했었다. objTest0 = objTest; objTest1 = objTest; 이렇게 하면 되지 않을까 하고....그런데, 그렇게 쉽게 되지는 않았다. 두개의 변수는 하나의 objTest를 바라보고 있어, 결국 값은 valDisplay를 공유한 꼴이 되버린 것이다.

이에 구글링과 테스트를 반복하여 그 방법을 드디어 찾아냈다.
즉 첫번째 소스를 이렇게 변경하면 된다.

objTest = function() {
     this.valDisplay = "";
     this.displayValue = function () {
            alert(this.valDisplay);
      }     
      this.setValue = function(val) {
            this.valDisplay = val;
      } 
};

실제 실행하는 코드는 아래 처럼 짜면 된다.

var objTest0 = new objTest();
objTest0.setValue("Test0 objTest!!!!");
var objTest1 = new objTest();
objTest1.setValue("Test1 objTest!!!!");

new 라는 것을 사용해서 만들기 때문에, 새로운 인스턴스가 생성되며 별개의 메모리 상에서 동작하게 되는 것이다. 이렇게 될 수 있는 건 자바스크립트의 미묘한 마법때문이다. 예전에 이런 문제 발생한적이 있지 않은가?

var realVar = "Init Data";
reelVar = "Update value!!!";
alert(realVar);

결과는 의도한 "Update value!!!"는 안찍히고 "Init Data"가 찍힌다. 그 이유는? reelVar 라는 변수 명이 잘못된 것이다. 그러나 씹고 그냥 진행되고 도리어 reelVar라는 변수가 하나 더 생기고 그 안에 값이 들어가 버린다. 맨 아랫줄에 alert(reelVar) 찍어보면 그제서야 "Update value!!!" 가 찍힌다. 자바 스크립트에서는 새로운 형태의 변수가 발견되면 일단 변수를 멋대로 만든다.

이런 기묘한 자바스크립트의 성질을 이용해 구성하는 것이다.
코드를 하나씩 뜯어 보도록 하자.

objTest = function() {      
};
일단 함수를 만드는 것이다. 함수 객체 자체를 objTest에 담는 것이다. 즉 objTest는 변수이긴 하지만 실제로 들어 있는 것은 함수인 것이다.
     this.valDisplay = "";
여기서 부터가 진짜 마법이다. this를 처음 접하신 분들은 순간 당황하실 것이고, 객체 지향을 하시던 분이라면 저 this가 어딜 가르키는 this인지 도무지 판단이 안서실 것이다. 저 this란 바로 function() 즉 objTest를 가르키는 것이다. 즉 objTest 라는 이름의 함수 내에 valDisplay 라는 변수를 정의하는 것이다. 이처럼 정의하는 이유는 아래의 또다른 함수의 형태 때문이다. 
     this.displayValue = function () {
            alert(this.valDisplay);
      }

이번에는 displayValue 라는 형안에 또다른 함수를 때려 박는다. 이 함수는 objTest.displayValue로 호출 된다. 그런데 만일 아까 this.valDisplay = ""; 가 아닌 var valDisplay = "" 라고 쓴다면 저 함수 안에서는 밖에서 정의한 변수를 쓸 수 없다. (물론 무한한 자바스크립트 세계에서 "완전 불가"/"절대" 란 없으니 "완전 불가"/"절대" 라는 말을 뺐다.) 즉 내부에서 사용하기 위한 변수로 쓰기 위해서 this. 라는 것을 붙여서 처리한 것이다.

여튼, 지금 필자는 MOSS 2007에 WebPart라는 개념이 있는데, AJAX 스럽게 만들려다 보니, 같은 스크립트를 여러 다른 웹파트들이 쓰게 되었는데, 일단 저렇게 간신히 해결하는데 성공했다. 미묘한 감동 찌리리링 상태다.

728x90

+ Recent posts

728x90