본문 바로가기

Flash Programming 란?

Flash/Flex AS3 - Flash 에서의 객체 : DisplayObject 와 DisplayObjectContainer Part 5

 지금까지 Flash 에서의 Timeline 에 대해 알아보았습니다. Timeline 에 대한 개념이 정리가 되셨는지요? 보통 사람들은 아래 그림 A와 같이 흰 도화지 안에 Timeline이 존재 하는 줄 알고 있습니다. 하지만 실제로는 반대입니다.



그림 A

그림 B



 그림 B와 같이 Timeline 안에 희 도화지가 속해 있는 형식으로 구성되어 있습니다. Timeline의 한 프레임 당 하나의 흰 도화지를 가지고 있고, 코드를 입력 할 수 있는 공간을 가지고 있습니다. 그림 A와 B는 단순히 Timeline 이 흰 도화지 보다 크다 (Timeline > 흰 도화지) 라는 의미를 뜻하지만, Flash의 구조 안쪽으로 들어가면 Flash에서의 객체라는 것의 뿌리가 되는 개념입니다. 왜냐 하면 모든 객체들은 이 Timeline에 속하게 되므로서 사용자들에게 보일 수 있게 되는 것이기 때문입니다. 이번 장을 진행하면서 왜 Timeline이 Flash의 구조의 뿌리가 되는 이유에 대해 살짝 엿보고, Flash에서의 객체가 어떻게 정의 되어 있고, 생성 되었다가 소멸 되는 과정에 대해 이야기 해 볼 것입니다.


 Flash는 객체기반 툴입니다. Flash에서 사용되는 것들 중에 객체가 아닌 것은 없을 정도로 모두 객체로 이루어져 있습니다. 지금 말하고 있는 객체란, MovieClip과 Button 그리고 툴로 그릴 수 있는 모든 것들을 의미 합니다. 잠시 객체의 의미에 대해 잠깐 짚고 넘어가겠습니다. 사전에서는 객체를 이렇게 정의 하고 있습니다.



 객체 [客體, object]

객체 지향 프로그래밍(OOP)이나 설계에서, 데이터(실체)와 그 데이터에 관련되는 동작(절차, 방법, 기능)을 모두 포함한 개념. 예를 들어 기차역에서 승차권을 발매하는 경우, 실체인 ‘손님’과 동작인 ‘승차권 주문’은 하나의 객체이다. 실체인 ‘역무원’과 동작인 ‘승차권 발매’도 하나의 객체이다.



백과 사전에서 정의한 것과 같이 동작의 주체가 되는 사람이나, 사람이 하는 동작 자체도 모두 객체라고 할 수 있습니다. 프로그래밍을 처음 접하는 사람들은 객체를 이해 할 때 사람과 같은 정해진 사물은 객체라고 이해 하지만, 동작이나 수학 공식을 처리해 주는 객체 같은 경우에는 객체가 아니라고 생각하는 경우가 많습니다. 객체는 보통 생각하는 것 보다 더 커다란 의미를 가지고 있습니다. 예를 들어 놀이터에 철수와 영희라는 객체가 놀고 있습니다. 놀이터에는 그네 객체, 미끄럼틀 객체가 있고 철수와 영희는 이들 놀이 기구 객체들을 사용할 수 있습니다. 이 경우는 모두 객체의 구분이 분명하기 때문에 이해하기에 어려움이 없을 것입니다. 하지만, 객체는 이러한 경우뿐만 아니라 우리가 행하는 동작이나, 기계들이 가지고 있는 기능들의 모음 또는 문서에 저장되는 데이터 모두 객체라고 할 수 있습니다. 이러한 객체들을 이용하는 툴을 객체 기반 툴이라고 하고, 객체 기반 언어라고 하는 것입니다. 그럼 Flash 에서의 객체는 어떤 것이 있을까요? 예를 들어 보겠습니다. Flash를 실행시키면 바로 보이는 것은 흰 도화지입니다. 그리고 그 아래 타임라인, 옆에는 Color패널과 Properties 와 라이브러리패널이 위치하고 있습니다. 이들 모두 객체입니다. 그리기 툴을 이용해서 사각형을 그린다고 하면, Color 패널을 사용하여 그리고 난 후에 사각형의 색상을 변화 시킬 수 있습니다. 왜 변화 시킬 수 있을까요? 그건 그려진 사각형에 color 라는 속성을 가지고 있기 때문에 변경을 할 수 있는 것입니다. 객체는 아무 것도 없는 빈 상태로 다른 객체를 담을 수 있는 역할도 하고, 속성과 메소드를 추가하여 그 자체로서 역할을 갖기도 합니다.

객체의 의미에 대해서 어느 정도 감이 왔을 것이라 생각이 듭니다. 그럼 본격적으로 Flash의 객체 구조에 대해서 다뤄 보도록 하겠습니다.


  • Flash 의 Display 구조

 Flash는 기본적으로 가지고 있는 구조가 있습니다. 과일을 담으려면 바구니가 필요하듯, Flash는 자체적으로 객체를 담을 그릇을 가지고 있습니다. 그 그릇이 바로 이전 포스팅에서 배웠던 Timeline입니다. 지금까지는 Timeline이라고 말했지만, 이 Timeline은 실제로 MainTimeline이라고 불리는 Flash에서 최상위 부모(바구니) 역할을 하는 객체입니다. 하지만 바구니가 있다고 해서 그 바구니가 가장 크기가 큰 개념은 아닙니다. MainTimeline 위에는 Stage 라는 객체가 더 존재하게 됩니다. 이러한 관계는 부모와 자식의 관계로 비유 하는 경우가 많으나, 여기에서는 바구니를 놓는 공간과 큰 바구니의 관계로 비유해 보겠습니다. Flash는 기본적으로 Stage 라는 공간 안에, MainTimeline 이라는 Timeline을 가지고 있는 바구니가 들어가게 됩니다. 그리고 그 MainTimeline 안에 모든 객체들이 만들어 지는 것입니다. 아래 그림을 보면 그러한 관계가 나타나 있습니다. 실제로 이러한 관계는 코드를 통해 확인해 볼 수 있습니다.





첫 번째 프레임에 아래 코드를 입력 합니다.

trace("this.parent : "+this.parent);

trace("this : "+this);


실행결과

this.parent : [object Stage]

this : [object MainTimeline]

 


실행 결과에서 볼 수 있듯이, 아무 것도 존재 하지 않은 상태의 this 는 MainTimeline을 가리키고 있습니다. 그리고 부모 객체를 알 수 있게 해 주는 parent 속성을 통해 MainTimeline의 부모를 보니 Stage 라고 나오는 것을 확인할 수 있습니다. 이와 같이 Flash는 사용자가 객체를 만들기 전에 그 객체가 담겨질 그릇에 해당하는 Stage와 MainTimeline을 준비해 놓고 객체가 만들어 지기만을 기다립니다.

Flash의 display 구조는 Stage-MainTimeline-만들어지는객체 로 이루어져 있습니다. 하지만 같은 객체를 나타내는 것이라도, 표현 방법은 여러 가지가 있습니다.



// 기본 display list

trace("this :"+this);

trace("this.parent :"+this.parent);

trace("this.stage :"+this.stage);

trace("-------------------------");


// root 에 관하여

trace("root : "+root);

trace("this.root :"+this.root);

trace("this.stage.root :"+this.stage.root);


//결과

this :[object MainTimeline]

this.parent :[object Stage]

this.stage :[object Stage]

-------------------------

root : [object MainTimeline]

this.root :[object MainTimeline]

this.stage.root :[object Stage]

 



이와 같이 같은 의미 이지만, 다르게 표현 될 수 있는 경우가 많이 있습니다. 또한 코드를 MainTimeline에 작성했을 경우에는 위와 같은 결과를 나타내지만, 빈 스테이지에 무비클립을 만든 후 그 안에 아래와 같은 코드를 입력할 경우에는 결과가 달라집니다.



 

// 기본 display list

trace("this :"+this);

trace("this.parent :"+this.parent);

trace("this.stage :"+this.stage);

trace("-------------------------");

// root 에 관하여

trace("root : "+root);

trace("this.root :"+this.root);

trace("this.stage.root :"+this.stage.root);

// 결과

this :[object Symbol1_1]

this.parent :[object MovieClip] // MainTimline이 나올 것이라 예상했을 것이다.

this.stage :[object Stage]

-------------------------

root : [object MovieClip]

this.root :[object MovieClip]

this.stage.root :[object Stage]



stage 관련 코드를 제외 하고는 모두 결과가 바뀌었습니다. 왜 그럴까요? 결과 분석에 앞서 root의 개념에 대해 짚고 넘어 가겠습니다. root 속성은 어떠한 객체가 포함되고 있는 최상위 부모객체를 나타내는 속성입니다. 예를 들어 보겠습니다. 빈 스테이지에 SuperMother이 있고, 그 안에 Mother, 또 그 안에 Child 라는 무비 클립 객체가 있습니다.




// 각각의 무비 클립은 포함 관계에 있으며 instanceName이 부여 되어 있다.

trace(_supermother.root);

trace(_supermother._mother.root);

trace(_supermother._mother._child.root);

// 결과

[object MainTimeline]

[object MainTimeline]

[object MainTimeline]

 


결과와 같이 root는 자기 자신이 존재하고 있는 최상위의 부모를 나타냅니다. MainTimeline 과 Stage는 자기 자신이 최상위이기 때문에 root 속성을 보아도 자신이 출력 되는 것입니다.

 

Adobe에서 제공하고 있는 as3.0 설명서에서 DisplayObject에 root 속성을 찾아보면 상황에 따라 root 가 어떻게 다르게 쓰이는가를 볼 수 있습니다. 아직 배우지 않은 개념들을 이용해서 설명해야 하므로 관련된 포스팅에서 더 자세히 알아보도록 하겠습니다.

 

 다시 이전 예제로 돌아가서, MainTimeline으로 나올 것이라 생각했던 값이 MovieClip으로 출력되었습니다. 그 이유는 스테이지 위에 생성된 무비클립에서는 자기 자신의 부모의 타입이 MovieClip 이라는 것은 알고 있지만, 정확한 이름을 알고 있지 못하기 때문에 MovieClip 이라고 출력해준 것입니다. 해결 방법은 간단합니다. Flash에 이름을 알려주면 되는 것이지요. 소스는 생성된 무비 클립 안에 작성 되었으니, trace(this.root); 코드를 MainTimeline에 입력해 봅시다.



 

// 기본 display list

trace("this :"+this);

trace("this.parent :"+this.parent);

trace("this.stage :"+this.stage);

trace("-------------------------");

// root 에 관하여

trace("root : "+root);

trace("this.root :"+this.root);

trace("this.stage.root :"+this.stage.root);

// 결과

[object MainTimeline]

this :[object Symbol1_1]

this.parent :[object MainTimeline]

this.stage :[object Stage]

-------------------------

root : [object MainTimeline]

this.root :[object MainTimeline]

this.stage.root :[object Stage]



MainTimeline 에서는 자신이 MainTimeline이라는 것을 알고 있었기 때문에, MainTimeline이라 출력해 주었고, Flash는 가장 먼저 실행되는 trace(this.root);를 통해서 정보를 알게 되었기 때문에 MovieClip 으로 출력해 주었던 것은 MainTimeline 으로 좀 더 객체를 명확하게 나타내 주었습니다. 이와 같이, 같은 키워드를 사용하는데도 불구하고 자신의 의도와는 다르게 나타나는 경우가 있습니다. 특히 this 와 root 그리고 parent의 개념을 잘 알고 사용해야 버그를 줄일 수 있습니다. 


 

this 의 의미 변화


AS2.0때까지만 해도 this가 의미 하는 것은 같은 코드 페이지에서 사용하여도 this를 사용하는 함수에 따라 달라졌습니다. AS2.0 코드에서는 아무것도 없는 스테이지상에서 trace(this);를 입력해 보면 _level0 이라는 최상위 표시객체를 나타내 줍니다. 하지만 스테이지 상에 mc 라는 무비 클립을 만든 후에 onRelease 이벤트를 걸어준 후에 나타나는 this는 _level0.mc입니다.


 이와 같이 같은 페이지(객체)에 코딩을 하고 있더라도, this의 의미는 어떤 이벤트에서 사용되는가에 따라 그 이벤트의 행위의 주체가 되는 객체로 의미가 바뀌면서 사용 됩니다. 아래의 코드를 보면 이벤트에 속해 있지 않았을 때의 this 는 _level0 은 나타내고 있지만, onRelease 라는 이벤트 안에서는 이벤트의 주체가 되는 _level0.mc를 가리키고 있는 것을 보면 이와 같이 동작하고 있다는 것을 알 수 있습니다. 하지만 as3.0 에서는 달라졌습니다.



trace(this);

mc.onRelease = function(){ // AS2.0 에서의 Click 이벤트입니다.

trace(this);

}

 

// 결과

_level0

_level0.mc // mc 라는 무비 클립을 클릭했을 때



 as3.0 의 경우 ‘같은 객체’ 안에서 사용되는 this의 의미는 항상 코드가 입력되고 있는 자기 자신을 나타냅니다. 우리가 지금 하고 있는 프레임 코딩 같은 경우에는 코드를 입력하는 장소가 MainTimeline 이기 때문에 최상위의 프레임일 경우 this는 항상 MainTimeline을 가리킵니다. 위에서 ‘같은 객체’ 라고 표현한 이유는 앞으로 우리들은 MainTimeline 뿐만 아니라, 새로운 객체(클래스)를 만들어서 그 안에 코딩 할 것이기 때문에 표현을 한정시킨 것입니다. 빈 스테이지에 무비 클립을 만든 후에 더블클릭으로 만들어진 무비클립의 타임라인에 trace(this); 라고 코딩해 보면 [object Symbol1_1] 라는 결과를 출력합니다. 무비 클립을 만들 당시에 객체 이름 즉, 클래스 이름을 정의 하지 않았기 때문에 Flash에서는 임의로 Symbol1_1 이라는 이름을 부여한 것입니다. 이 이름은 무비클립을 만들 때 입력했던 Name을 바탕으로 만들어 지는 것이나, 실제로 여기서 만든 무비 클립을 바로 동적으로 생성하여 사용할 수는 없습니다. Linkage 라는 클래스 연결 작업을 통해서 하나의 클래스 객체가 되는 것입니다. 다시 this의 의미로 돌아와서, as3.0 에서의 this는 항상 자기 자신을 가리킵니다. this를 통해서 자신의 부모객체인

this.parent 로 접근할 수 있으며, 자신의 자식 객체가 존재할 경우에는 this.자식객체이름 으로 접근 가능한 것입니다. 마지막 예로 AS2.0 에서는 이벤트에 포함했을 때 this의 의미가 바뀌었으니, as3.0 에서는 이벤트에 포함된 this 는 어떤 의미를 나타내는지 보겠습니다. 위의 예제와 같이 빈 스테이지에 무비 클립을 만든 후 이벤트를 걸어 줍니다.



trace(this);
mc.addEventListener(MouseEvent.CLICK, onClickHandler);  // as3.0의 Click이벤트
function onClickHandler(event:MouseEvent):void
{
trace(this);
}

// 결과
[object MainTimeline]
[object MainTimeline]     // mc 라는 무비 클립을 클릭했을 때



이와 같이 MainTimeline 에 작성된 this 는 모두 MainTimeline을 가리킵니다.