AS3.0 에 들어와서 가장 많은 분들이 어려워하고 계시는 부분이 이벤트와 더불어 container 개념인거 같습니다.

제가 메신져로 가장 많이 듣게 되는 질문이 이벤트랑 DisplayList 를 이해하고 있지 못해서 발생하는 문제들이 많은거 같습니다.

2.0때도 눈에 안보이게 이미 존재했었고 몇몇 고수분들은 잘 이해하고 사용하고 계셨기 때문에 전혀 생소한 개념은 아니지만

마냥 this.parent.friend.child 로 접근하던 방식이 이제는 그 틀을 벗어날때가 된거 같습니다.

이미 2.0때부터 빠삭하게 파악하고 계신분들에게는 식상한 얘기일수도 있겠으나 이제 시작하시는 분들을 위해 마련해봤습니다.^^


자세한 내용 들어가기 전에 용어를 먼저 정리하죠.

DisplayObjectContainer : 클래스입니다. Sprite나 Stage의 상속클래스죠. 눈에 보이는 클래스가 아닙니다.

DisplayObject : 클래스입니다. 눈에 보이게 되는 모든 요소의 상속클래스죠. Bitmap, Video, MovieClip 의 상속클래스를 따라가다보면 반드시 DisplayObject 클래스가 있게 됩니다.

DisplayList : 화면에 보여줘야할 목록이라는 의미의 단어입니다. 실존하는 클래스가 아닙니다.

contains : "포함한다"라는 추상적인 의미입니다. 집안에 내가 있고, 내 안에 심장이 있고, 심장안에 혈액이 있겠죠.


자 살살 시작해보겠습니다.

우리는 무비클립 안의 무비클립에 접근할때 2.0때는 main.sub 로 바로 접근했었죠.

물론 3.0에서도 똑같이 접근할 수 있습니다.

바로 이 점 때문에 많은 분들이 2.0때의 그대로 모든것을 시도하기 때문에 혼동이 일어납니다.


우선 DisplayObject 라는 것은 화면에 보여질 수 있는 "보이는 객체"입니다.

즉 화면에 보여질 수 있는 데이타를 가지고 있는 객체라는 뜻이죠.

int 3 이나 string "abc" 는 화면에 보이는 그런 값이 아니죠.

하지만 BitmapData 나 Shape 은 화면에 보여질 수 있는 객체입니다.

이런 객체들은 DisplayObject 라고 불려집니다.

이런 객체들이 "①화면에 보여줘야할때"는 render 라는 과정을 거쳐서 실제 모니터에 그 모습을 보여주게 되죠.

우리가 swf 를 실행하면 FlashPlayer 가 실행되서 그안에서 우리가 만든 플래시가 보이게 됩니다


이 FlashPlayer 를 우리는 Stage 라고 이해합시다.

Stage 는 swf안에 있는게 아닙니다.

즉, 우리가 this.stage 라고 접근하는것이 내가 만들고 있는 객체의 "그냥 모든것"이라고 치부하면 안됩니다.

Stage 라는 것은 FlashPlayer 의 "화면 자체"를 의미한다고 보면 됩니다.

그래서 this.stage 에 이벤트를 걸면 어디서든 다 작동하는게 바로 그 원리입니다.

stage 에 MoueEvent를 걸면 어떤 위치에서든 다 작동하고 무조건 최상위로 작동하는게 그 원리입니다.

swf 보다 한단계 위에 있는 객체라는 뜻이죠.


①에서 말한 보여줘야 할때라는 것은

바로 이 Stage 에 "②포함되었을때" 를 말합니다.

왜냐면 Stage 에 포함되지 않은건 어디에도 보일 일이 없다는 뜻이기 때문에 render 를 할 필요가 없는것이죠.


위에서 말한 "②포함되었을때" 라는 것이 바로 contains 개념입니다.

child 라는 객체를 뜻하죠.

DisplayObject 는 누군가에게 child 가 될 수 있습니다.

하지만 동시에 두군데에 child 될 수는 없습니다.

새롭게 child 하게 되면 이전에 contain 되었던 곳에서는 사라지게 됩니다.

이 점 꼭 잊지 마시길 바랍니다.


자 그럼 실제로 하나 예를 들어서 풀어보겠습니다.

참고로 FrameScript 는 고려하지 않겠습니다.

권장하는 방법도 아니며 올바른 객체지향 개발도 아니기때문에 전혀 고려할 대상이 아니라고 판단하기 때문입니다.


2중 뎁스 메뉴를 예로 들겠습니다.

fla 안에는 menu 라는 무비클립이 있습니다.

이 menu 안에는 sub라는 무비클립을 생성해서 그때 그때 메뉴의 갯수가 달라지는 그런 메뉴라고 하겠습니다.

menu 안에는 txt 라는 텍스트가 있어서 메뉴의 이름을 정해주도록 하겠습니다.

그러면 2.0방식으로는 root 메인 프레임에

var sub:SubMenu = this.menu.attachMovie();
sub.txt.text = "홈으로";

이런식으로 개발을 했겠죠.

그렇다면 3.0은 어떻게 개발하는게 좋은지 살펴보죠.

우선 가장 처음부터 다르게 시작하죠.

DocumentClass 를 만듭니다.

fla 의 Property 창에서 하단에 Document class : 라는 곳이 있죠.

이곳에 클래스 명을 적습니다.

MenuSample 이라고 가정하죠.

그러면 fla 와 같은 위치에 MenuSample.as 라는 파일이 있어야겠죠.

package
{
 import flash.display.Sprite;
 
 public class MenuSample extends Sprite
 {
  public function MenuSample():void
  {
   
  }
 }
}

 

라고 기본 소스를 적어줍니다.

클래스를 생성해줬죠.

자 그렇다면 바탕에 있는 menu 라는 무비클립에 접근하려면 어떻게 해야할까요?

(여기서 잠깐. Properties > Settings > ActionScript version > ActionScript 3.0 Settings > Stage 에서 자동으로 인스턴스 선언해주는 부분에 체크가 되어 있다면 반드시 풀어주십시요. 편하다고 능사가 아닙니다. 우리는 정석을 배워야하죠.)

위에 적힌 DC (DocumentClass)는 에러를 발생합니다.

왜냐면 menu 라는 객체가 이미 있는데 저 클래스의 내용을 보아하니 menu 라는 무비클립을 인식시켜주는 부분이 없기 때문에죠.

DocumentClass 는 fla 자체라고 보시면 됩니다.

fla 바탕에 menu 라는 무비클립이 있으면 DC 에도 menu 라는 무비클립이 있어야합니다.

자 이렇게 적어줍니다.

package
{
 import flash.display.Sprite;
 import flash.display.MovieClip;
 
 public class MenuSample extends Sprite
 {
  public var menu:MovieClip;
 
  public function MenuSample():void
  {
   
  }
 }
}

그러면 이제 Ctrl + Enter 를 해도 에러가 나지 않습니다.

올바르기 때문이죠.

그러면 menu 안에 sub 를 만들어서 넣어야합니다.

MenuSample() 메소드 안에 이렇게 적습니다.

var sub:SubMenu = new SubMenu();

menu.addChild(sub);

이렇게 하면 SubMenu 라는 객체를 만들어서 menu 에 child 로 추가한것입니다.

즉 생성을 한 후에 menu 라는 무비클립에 contain 시킨것입니다.

2.0때는 바로 menu 라는 무비클립 안에 만들어버렸죠.

생성과 child 개념은 다른것이기 때문에 보다 올바른 개발방법이 된것입니다.

그러면 menu 안에 넣은 sub 라는 객체의 텍스트를 변경하려면 어떻게 해야할까요?

여기서 2.0때의 습관을 못버리신 분들이 많이 골탕먹는 부분이 이부분입니다.

menu.sub.txt.text = "홈으로";

이렇게 하면 에러가 나죠.

위에서 var sub:SubMenu = new SubMenu() 라고 선언했죠.

var 라는것은 변수를 의미합니다.

여기서 만든 객체를 menu 안에 addChild 했다고 객체가 menu 안으로 들어가는게 아닙니다.

객체는 그대로 존재합니다.

var sub:SubMenu = new SubMenu();

menu.addChild(sub);

sub.txt.text = "홈으로";

라고 코딩하시면 됩니다.

addChild 한다는 뜻은 화면에 보여주기 위해서 menu 안에 넣어서 보여주겠다라는 의미입니다.

객체를 menu 안에 주겠다라는 뜻이 아닙니다.

menu 는 이미 fla 안에 있기 때문에 자동으로 DisplayList 에 포함되어 있습니다.

때문에 menu 에 sub 를 contain 시키면 자동으로 DisplayList 에 꼬리를 물고 포함되겠죠.



여기서 또한가지 많이 물어보는 것이 있습니다.

바로 menu 를 "없앨려면" 어떻게 해야하는것이죠.

이 질문에는 두가지 뜻이 혼동되어 있습니다.

즉, DisplayList 에서 사라지게만 할것이냐, 아니면 객체를 메모리에서 지우겠느냐

라는 두가지 뜻이 불분명한것이죠.

단지 눈에서만 사라지게 하려면 this.removeChild(menu) 하면 DisplayList에서 제거되기 때문에 눈에 보이지 않습니다.

하지만 객체를 없애려면 객체 자체를 없애야겠죠.

객체를 없애는 방법은 쉽지 않습니다.

플래시는 메모리를 직접 건드릴 수 없기 때문에 한번 생성한 객체를 지우려면 여러가지 조건이 있어야합니다.

때문에 2.0때의 removeMovieClip 이라는 애매모호한 메소드에 익숙해있던 개발자들에게

removeChild 는 먼가 구리고 개운치 않게 느껴질수도 있습니다.

하지만 removeChild 라는 의미는 굉장히 정확합니다.

더이상 나의 chlid 가 아니라는 의미기 때문이죠.

이제 child 가 아니게된 menu 는 어디에든 속할 수 있습니다.

아마 많은 현장에서 직접 경험해보시면 이해하실 수 있을겁니다.


여기서 child 가 되고 DisplayList 에 포함되었다가 빠졌다가 하는 개념이 바로

DisplayObjectContainer 클래스가 하는 역할입니다.

즉, 눈에 보여질 수 있는 객체(DisplayObject)를 넣었다 뺐다(contain) 하는 것이죠.

이때 대상이 되는게 바로 DisplayObject 인것입니다.

DisplayObject들은 어디든지 addChild, removeChild 될 수 있습니다.

이 개념이 바로 3.0들어서 가장 많이 어려워하시는 DisplayObjectContainer 개념과 DisplayObject 라는 클래스의 의미입니다.


p.s) 3.0 에 대해서 많이 푸념하시는것들 중에 하나가 바로 "소스가 너무 길어진다" 인데요,

소스가 짧다고 능사가 아니며 소스가 짧다는 이야기는 그 소스 한줄로 "많은" 처리가 이뤄진다는 이야기입니다.

즉, 내가 모르는 일들이 많이 일어나고 있다는 뜻이며

소스가 길어졌다는 의미는 "모든 처리"가 내 손에 의해서 이뤄진다는 것을 의미합니다.

저는 3.0을 하고부터 얼마나 개발이 재밌어졌는지 모릅니다.

거의 모든 일을 처리해주는 이벤트와 정확한 OOP 구조를 가지게 된 구조,

물론 2.0때도 있었다고 하면 할말이 없지만

거의 활용성이 없었죠.

한가지 자신있게 말씀드릴수 있는건

2.0 때의 습관으로 3.0 을 접하신다면

아예 모르는 쌩초보보다 늦게 배우실 수도 있습니다.

왜냐면 제가 그랬듯이 아주 기본적인 개념부터 달라졌기 때문입니다.

"달라졌다"라는 의미보다는 "제대로" 됐다 라는 의미가 정확하겠죠.

이상, 도움되셨길 바랍니다.

+ Recent posts