Actionscript3.02011.05.01 16:29


 ApplicationDomain 에 대한 개념만 잘 이해 하고 있다면, 이 포스팅은 보지 않으셔도 됩니다. 최근까지 ApplicationDomain 에 대한 개념 자체를 다르게 이해 하고 있어서 어렵다고 생각했던 부분들은 정리 합니다.


 Flash/Flex 를 사용하면서 가장 많이 사용하는 클래스중 하나는 Loader 일 것 입니다. Loader 클래스는 SWF 나, 이미지 (JPG, PNG 등등) 을 로드 하는데 사용 합니다. 많은 분들이 이미지를 로드 하는데 자주 사용하고 있을거라 생각 합니다. 외부에서 이미지를 로드 하면 로드된 리소스는 Bitmap 으로 처리가 되어 BitmapData 의 clone 메소드를 통해서 해당 이미지를 재사용 할 수 있습니다. 코드는 아래와 같습니다.


 // 이미지 로드

package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.net.URLRequest; public class ApplicationDomainTest extends Sprite { public function ApplicationDomainTest() { var loader:Loader = new Loader(); loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler); loader.load(new URLRequest("TestAsset.png")); } private function loadCompleteHandler(event:Event):void { var image:Bitmap = event.target.content as Bitmap; var imageData:BitmapData = image.bitmapData.clone(); trace(imageData); } } }



이미지는 위와 같이 재사용하면 되고, 이미지가 아닌 SWF 파일은 어떻게 재사용 할까요? 제가 사용한 방법은 ApplicationDomain 을 이용한 것 입니다. ApplicationDoamin 에 대한 자세한 내용은 다음 블로그에 잘 정리 되어 있으니 참고해 주세요.


Flex 모듈 프로그래밍의 기초 - Application domain의 이해

http://blog.jidolstar.com/469

http://blog.jidolstar.com/346 


 Loader 를 통해 외부 리소스를 로드 하면 해당 리소스는 load 메소드의 LoaderContext 의 ApplicationDomain 설정에 따라 새로운 ApplicationDoamin 또는 로드를 객체의 ApplicationDoamin 에 정의가 저장 됩니다.


 load(request:URLRequest, context:LoaderContext = null):void


LoaderContext 에서 applicationDoamin 값을 (new ApplicationDoamin, ApplicationDomain.currentDoamin 등) 어떤 값으로 설정하는가에 상관 없이 로드된 외부 리소스는 자신의 ApplicationDomain 을 알 수 있습니다. 


 // 로드된 리소스 ApplicationDomain 알기

package {    

    import flash.display.Loader;    
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;        

    public class ApplicationDomainTest extends Sprite {        

        public function ApplicationDomainTest()    {

            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
            loader.load(new URLRequest("TestAsset.swf"));    
        }

        private function loadCompleteHandler(event:Event):void {

            var swf:* = event.target.content;

            trace(swf.loaderInfo.applicationDomain);
        }
    }
}


이 ApplicationDomain 에는 로드된 자기 자신의 정의 들을 가지고 있기 때문에 해당 정의(클래스)를 불러와서 사용 할 수 있습니다. 예를 들어 아래와 같이 작성 되어 있는 외부 SWF 를 로드 한다고 하면 각각의 객체 정의 들은 불러 오는 방법은 다음과 같습니다. 


// TestAsset

package { import com.ddongkang.AssetLoader; import com.ddongkang.Circle; import com.ddongkang.List; import flash.display.Sprite; public class TestAsset extends Sprite { private var loader:AssetLoader; private var circle:Circle; private var list:List; public function TestAsset(){ }

} 


 // Main

package {    

    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.ApplicationDomain;

    public class ApplicationDomainTest extends Sprite {
        

        public function ApplicationDomainTest()    {

            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
            loader.load(new URLRequest("TestAsset.swf"));    

        }

        private function loadCompleteHandler(event:Event):void {
            var swf:* = event.target.content;
            trace(ApplicationDomain(swf.loaderInfo.applicationDomain).getDefinition("com.ddongkang.AssetLoader"));
            trace(ApplicationDomain(swf.loaderInfo.applicationDomain).getDefinition("com.ddongkang.Circle"));

            trace(ApplicationDomain(swf.loaderInfo.applicationDomain).getDefinition("com.ddongkang.List"));

        }

    }

}



getDefinition 으로 불러온 정의는 클래스 정의 이기 때문에 객체를 생성 할 수 있습니다. 


// 외부에서 로드한 Circle 객체 생성

var circle:* = new ((swf.loaderInfo.applicationDomain).getDefinition("com.ddongkang.Circle"))();
addChild(circle);            
trace(circle); 


로드된 TestAsset.swf 는 AssetLoader, Circle, List 정의를 가지고 있기 때문에 컴파일 될때 해당 정의도 SWF 에 포함됩니다. 로드한 클래스는 TestAsset 이지만, TestAsset 이 가지고 있는 정의들이 같은 ApplicationDomain 안에 포함되어 있기때문에 이러한 접근이 가능 합니다. 여기서 SWF 자체인 TestAsset.swf 도 다음 코드를 통해 접근 가능 합니다.


// TestAsset 접근 

var asset:* = new ((swf.loaderInfo.applicationDomain).getDefinition("TestAsset"))(); 


주의할 점은 getDefinition 에 사용한 이름이 package 까지 포함된 이름이라는 점 입니다. getDefinition 을 통해 해당 클래스 정의에 접근 할때는 해당 정의가 ApplicationDomain 에 존재 하지 않을수도 있기 때문에 hasDefinition 를 통해 있는지 확인 후 접근해야 런타임 에러를 방지 할 수 있습니다.


// hasDefinition 사용


 private function createAssetByName(loaderInfo:LoaderInfo, name:String):* {

            
     var applicationDomain:ApplicationDomain = loaderInfo.applicationDomain;
     if(applicationDomain.hasDefinition(name)) {
          return new (applicationDomain.getDefinition(name))();                
     }
            
     return null;
            
}


로드할 자원을 만들때, Flash Builder/ Flex Builder 를 사용할 경우 컴파일 된 자원 이름 (위의 경우에는 TestAsset.swf)이 클래스 이름(TestAsset)과 동일 하기 때문에 외부 리소스가 단일 자원으로 컴파일 될 때는 swf 이름으로 클래스를 접근해도 무방 합니다. 해당 swf 이름을 이용하여 Dictionary 를 만들어서 정의를 저장해 놓고 사용할 수도 있습니다. (http://mrdoob.com/blog/post/612


 하지만 Flash IDE 로 외부 리소스를 만들때는 반드시 Document 클래스를 지정하고 지정된 Document 클래스 이름을 통해 클래스를 접근해야 합니다. Flash/Flex Builder 에서 만든 리소스는 swf 자체가 클래스가 되지만 Flash IDE 에서는 Document 클래스로 연결이 안되어 있는 swf는 swf 자체가 클래스가 아니기 때문에(?) 정의를 불러 올 수 없습니다. 그러나Flash IDE 를 통해 Linkage 를 이용하여 클래스를 정의한 경우에는 Builder 에서 만들때와 마찬가지로 컴파일된 SWF 에 Linkage 를 통해 클래스화 된 객체 정보들을 가지고 있기 때문에 접근이 가능 합니다.  정리해 보면 다음과 같습니다.


로드할 자원 만들 때 주의 사항

1. 클래스 이름을 package 까지 포함하여 알고 있어야 한다.

2. Flash IDE 로 자원을 만들때는 Document 클래스를 연결해 주고 Document 클래스의 이름을 알아야 한다.

3. Flash IDE 의 라이브러리 Linkage 를 사용하여 클래스를 만들면 컴파일된 swf 에서 해당 정의를 불러올 수 있다. ( http://goo.gl/xrY8q ) 


로드한 자원 (클래스) 를 재사용하기 위해서는 로드된 클래스 이름을 알아야 한다는게 핵심입니다. 그 클래스정의는 로드된 swf 의 ApplicationDomain 안에서 있고 해당 클래스 이름을 통해서 가져 올 수 있습니다. 그리고 그 정의를 통해 new 를 통해 객체를 생성하여 사용 합니다.


잘못된 내용이나 개발 중 고민하고 있는 부분들은 댓글을 통해 공유 주세요~ 






Posted by Flash 동강
Flash Programming 란?2010.01.30 15:34

  • Timeline 제어

 Flash의 Timeline이 그냥 시간에 따라 진행 되는 것만은 아닙니다. AS를 통해서 이를 제어하고 코드가 발생하는 순서를 정할 수 있습니다. 기본적으로 Timeline을 제어 하는데 사용하는 액션은 다음과 같습니다.


- stop() : Timeline에 있는 재생헤드를 정지합니다.

- play() : Timeline에 있는 재생헤드를 움직입니다.

- gotoAndPlay(frame, scene =null) : 해당 Scene 에 존재하는 frame으로 이동한 후 재생헤드를 움직입니다.

- gotoAndStop(frame, scene =null) : 해당 Scene 에 존재하는 frame으로 이동한 후 정지 합니다. (정지상태)



 gotoAndPlaygotoAndStop의 파라미터로 들어가는 scene 의 경우는 생략이 가능합니다. 위에서 =null 이라고 선언되어 있는 것은 해당 파라미터가 입력되지 않았을 때는 scene 값을 null 값으로 처리 하겠다는 의미입니다. Timeline에 여러개의 프레임이 존재 하고 있을 때 재생헤드는 현재 머물고 있는 프레임에 해당하는 일을 마친 뒤 다음 프레임이 존재 한다면 다음 프레임으로 자동으로 넘어가서 또 그 프레임에 있는 일을 처리 합니다. 하지만 이러한 동작은 사용자가 원하지 않는 것일 수도 있습니다. 평소에는 프레임 1에 있는 것을 보여 주다가 어떠한 이벤트가 발생 했을 때 다른 프레임으로 이동 시키고 싶은 경우 평소에는 재생 헤드가 항상 프레임 1에 존재해야 되기 때문에 stop() 함수를 사용하게 됩니다. Timeline을 제어 하는 액션은 아주 다양한 용도로 사용 되고, 많은 것을 만들 수 있게 도움을 주는 메소드입니다. 예를 들어, Flash에는 마우스가 오버, 다운, 업 일 때의 이벤트를 처리를 미리 구현해 놓은 SimpleButton이라는 객체가 있습니다. SimpleButton은 내부적으로 구현되어 있는 객체지만 위의 Timeline을 제어 하는 메소드만을 이용하여 만들 수 있습니다. 우선 SimpleButton이 어떻게 구성되어 있는지부터 알아보겠습니다. 



 1. Flash File(Actionscript3.0) 로 새로운 파일을 생성 한후, Rectangle Tool(R)을 이용하여 사각형을 만듭니다.



2. 사각형을 선택 한 후, F8 또는 Modify-Convert to Symbol...을 선택하고 Type을 MovieClip으로 선택 한 후 OK를 누릅니다. 




3. 만들어진 MovieClip 객체를 마우스로 클릭 한 후, 우측 상단에 있는 Properties에 Instance Name을 입력하는 곳에 rect_mc라고 이름을 입력합니다.

 


4. 사각형을 더블클릭하여 하위 객체의 Timeline으로 이동한 후 2,3 프레임에 마우스 오버일 때의 상황과 마우스 버튼을 클릭 했을 때의 상황을 정의 합니다. 이 예제에서는 3개의 프레임에 각각 아래와 같은 도형을 그려 넣었습니다. 그리고 프레임 1에 stop(); 메소드를 입력 합니다.


 




5. 다시 상단에 있는 네비게이션 버튼을 클릭하여 Scene1(상위객체)로 올라 와서 프레임 1에 아래의 코드를 입력 합니다.




// 코드

stop();                   // 재생헤드가 움직이지 않게 정지 시킨다.// 각각의 이벤트를 등록해 준다.rect_mc.addEventListener(MouseEvent.MOUSE_UP,onUphandler);rect_mc.addEventListener(MouseEvent.MOUSE_OVER,onOverhandler);rect_mc.addEventListener(MouseEvent.MOUSE_OUT, onOuthandler);rect_mc.addEventListener(MouseEvent.MOUSE_DOWN,onDownhandler); function onUphandler(event:MouseEvent):void{        rect_mc.gotoAndStop(1);}function onOverhandler(event:MouseEvent):void{         rect_mc.gotoAndStop(2);}function onOuthandler(event:MouseEvent):void{         rect_mc.gotoAndStop(1);}function onDownhandler(event:MouseEvent):void{         rect_mc.gotoAndStop(3);}



 위에서 만든 사각형에 rect_mc 라는 이름(Instance Name)을 적용하므로써 코드에서 접근을 할 수 있게 되었습니다. rect_mc 에 Flash가 정의하고 있는 4가지 마우스 이벤트를 정의하고, 이벤트에 종류에 따라 gotoAndStop 문을 써서 재생헤드의 위치를 변경 하였습니다. 이 예제에서는 마우스의 움직임에 따라 rect_mc안에 있는 Timeline을 조작하므로 SimpleButton와 같은 동작을 하게 됩니다. (객체에 마우스 이벤트가 발생하는 과정은 후에 자세히 다룰 것임으로 생략 합니다.) 이러한 원리를 이용하면, 사용자의 마우스 움직임에 따라 마우스 이벤트가 발생한 객체뿐만 아니라, Timeline을 가지고 있는 모든 객체의 Timeline 속성을 조절할 수 있습니다. 여러 웹 사이트를 돌아다니다 보면, 화려한 모션과 함께 사용자의 반응에 따라 액션이 일어나는 사이트들이 많이 존재 합니다. 이러한 사이트들의 대부분이 이러한 Timeline을 메소드를 사용하는 이벤트만으로도 쉽게 만들 수 있습니다. 다만 Adobe AfterEffect 와 같은 모션 툴에서 한 작업을 Flash 의 Timeline으로 가져와서 조절하기 때문에 가능해지는 것입니다. 물론 Flash로 작업한 애니메이션도 가능합니다. 이렇게 타임라인을 이용한 작업은 간단하게 멋진 결과물이 나올 수 있게 도와줍니다. 


 하지만, Timeline 의 프레임 번호만을 가지고 재생헤드를 이동시키는 것은 여간 번거로운 작업이 아닐 수 없습니다. 프레임 번호를 맞춰가면서 gotoAndPlay를 사용해 가며 인터렉션을 만들었다고 해도, 유지보수가 있을 때 Timeline의 길이가 변하거나, 효과가 변하는 일은 비일비재 하게 일어나는 일이기 때문에 또 다른 방법을 요구 하게 됩니다. 그래서 Flash는 이러한 번거로움을 줄이기 위해 Timeline에 label 속성을 제공해 주고 있습니다. label 속성이란, Timeline을 조절할 때 프레임 번호로 위치를 참조해야 하는 번거로움을 없애기 위해 해당 프레임에 이름을 부여 하는 기능입니다. 아래 그림과 같이 마우스로 프레임을 선택하면 Properties 창에 LABEL 속성이 나타나게 됩니다. Name 에 해당 프레임으로 지정하고 싶은 Name을 입력하게 되면 해당 프레임은 지정된 이름의 참조 값을 갖게 됩니다. 



이 그림에서는 프레임 1에 Out, 프레임 10에 Over, 프레임 20에, Down 이라는 이름을 지정하였습니다. 이렇게 LABEL 값이 정해지게 되고, 위에서 구현했던 소스를 다음과 같이 변경하면 같은 기능을 하게 됩니다.


// 코드

부록 CD: Example\1-4\1_4_3.fla// 이벤트 등록 부분이 동일함으로 생략하였습니다.// 바뀐 부분은 bold 처리 되었습니다.function onUphandler(event:MouseEvent):void{	rect_mc.gotoAndStop("Out");}function onOverhandler(event:MouseEvent):void{	rect_mc.gotoAndStop("Over");}function onOuthandler(event:MouseEvent):void{	rect_mc.gotoAndStop("Out");}function onDownhandler(event:MouseEvent):void{	rect_mc.gotoAndStop("Down");}


 이러한 간단한 구조의 Timeline 에서는 필요하다는 느낌을 받지 못할 수도 있습니다. 하지만, 언제 바뀔지 모르는 프레임 번호를 신경 쓰기보다는 label을 지정함으로서 예측 할 수 없는 유지 보수에 대해 대비 할 수 있고, 훨씬 유연하게 대처할 수 있는 작업 방법입니다.


 지금까지 Timeline을 제어 하는 방법에 대해 알아보았습니다. Timline을 어떻게 조절하고 어떤 효과를 삽입하느냐에 따라 gotoAndPlay 만으로도 멋진 Flash를 만들 수 있는 비결이 될 수 있습니다. 그만큼, Timeline을 기반으로 하고 있는 Flash 프로그래밍에서 Timeline 제어는 중요한 부분을 차지하고 있습니다. 

 

Posted by Flash 동강
Actionscript3.02010.01.12 01:06

외부 데이터를 불러 와서 TextField 에 넣어 줄때, 외부 데이터 문자 길이를 UI 에 맞게 잘러서 나타내는 경우가 있습니다. 기본적으로 String 클래스에서 제공하는 substr 등을 이용하여 문자열을 보기 좋게 자르는데요. 여기서 소개 하는 방법은 substr 과 TextField 의 getLineOffset를 이용하여 한정된 라인에만 글짜를 출력 하는 방법 입니다.

var field:TextField = new TextField();
field.width = 250;
field.wordWrap = true;
field.text = "안녕하세요.이것은 테스트 입니다.안녕하세요.이것은 테스트 입니다.안녕하세요.이것은 테스트 입니다.";
addChild(field);
위의 코드를 출력하면 아래와 같은 결과가 나옵니다.


위와 같이 width 값은 고정되어 있고 wordWrap = true 로 TextField 의 자동 줄바꿈이 설정 되어 있을때 getLineOffset 을 이용하여 원하는 최대 라인수 보다 넘어 갔을때 그 다음 라인의 첫번째 문자 인덱스 값을 가져온 뒤에 그 인덱스의 -2 만큼 String 값을 잘라 버리는 방식 입니다. getLineOffset 의 설명은 아래와 같습니다. 

var field:TextField = new TextField();
field.width = 250;
field.wordWrap = true;
field.text = "안녕하세요.이것은 테스트 입니다.안녕하세요.이것은 테스트 입니다.안녕하세요.이것은 테스트 입니다.";
cutNumLines(field,2);
addChild(field);
function cutNumLines( $field:TextField,$maxLen:int ):void{
	if($field.numLines-1 < $maxLen) return;
	
	var idx:int = $field.getLineOffset($maxLen);
	$field.text = $field.text.substr(0,idx-2)+"..";
}

getLineOffset(lineIndex:int):int
lineIndex 매개 변수로 지정된 행에 있는 첫 문자의 문자 인덱스를 반환합니다.


위의 함수를 실행한 후의 결과는 다음과 같습니다.



'Actionscript3.0' 카테고리의 다른 글

AS3 vs Javascript Performance Test  (0) 2010.01.14
[AS3] TextField 에 한정된 라인에만 글짜 넣기  (0) 2010.01.12
Avoid ints in Actionscript  (10) 2009.11.14
Factory Pattern (AS3)  (0) 2009.10.25
Posted by Flash 동강
i'T news2009.10.26 00:00

 발행한지 얼마 되지 않았지만, 언제나 일요일 저녁에 오픈캐스트를 발행하는것 같습니다. 포스팅해야지 해야지 생각만 하고 하지 않는 일상이 반복 되고 있네요. 하고 싶어도 못한다는 말은 그냥 핑계 인것 같습니다.


 세번째 캐스트를 발행하였습니다. 이번에도 마찬가지로 액션스크립트를 처음 접하거나 초보자를 위한 캐스트 이고요. 어떤 방법을 알려주는 링크라기 보단 초심자가 한번쯤을 읽어 봐야 하는 내용들로 모아 보았습니다.


몇주째, 캐스트만 홍보 하는 블로그가 되고 있네요. ㅜㅜ


캐스트 : http://opencast.naver.com/DO718



Posted by Flash 동강
Actionscript3.02009.09.22 12:41


목차

DiplayList 란?

- DisplayList의 3가지 요소

- DisplayList의 구조

- DisplayList 구조의 장점

- Index 개념

- Shape, Sprite, MovieClip

- DisplayList의 부모 자식 노드 관계 탐색이 간편해짐

DisplayObject 클래스

- DisplayObject를 상속받는 클래스

- 속성 메소드 및 이벤트

- root , parent, stage 에 접근하기

- Loader 를 사용해 불러온 외부 swf 의 root 와 stage

DisplayObjectContainer 클래스

- DisplayObjectContainer 의 상속

- 속성 및 메소드


DisplayList 란?


DisplayList 란 SWF안에 존재 하는 객체들 중에 눈에 보이는 객체들을 총칭한다. 눈에 보이는 객체라고 하니 잘 이해가 안될수도 있으나, 간단하게 MovieClip 과 같이 addChild 를 통해 사용자에 눈에 보일수 있는 객체들을 뜻한다. 반면에 Date 클래스와 같은 객체는 단순히 시간에 대한 데이터를 처리 하는 객체 이므로 DisplayList 에 속하지 않는다. (빈 MovieClip 이나 Sprite, Shape 도 비어 있지만 모두 DisplayList 이다)


DisplayList의 3가지 요소


Flash Actionscript 에서는 이러한 DisplayList 구조가 아래와 기본 골격을 가지고 있다.


가장 상위에 Stage가 존재 하고 그 아래 MainTimeline 그리고 사용자가 만들어 내는 객체들로 눈에 보이게 되는 것이다. 그러면 어떠한 객체들이 "만들어지는 객체" 에 속하는 것인가? 바로 DisplayObject 와 DisplayObjectContainer 클래스를 상속받은 객체 들이다.

- DisplayObject : 화면에 표시 되는 객체 (Shape, Sprite, MovieClip, SimpleButton 등등)

- DisplayObject : 화면에 표시 되고 다른 객체들을 포함 할수 있는 객체 (Sprite, MovieClip, Loader 등등)



결국 SWF 안에 존재 하는 DisplayList 구조는 위와 같은 구조로 만들어 지게 된다.


DisplayList 구조의 장점


AS1.0, AS2.0 때 까지만 해도 위와 같은 DisplayList 구조를 가지고 있지 않았다. Flash CS3 이전 버젼에서는 MovieClip 이 거의 대부분의 객체의 기본이 되었고 그렇기 때문에 단점이 많았다. 하지만 위와 같은 DisplayList 를 가지게 되고 여러 장점을 가질수 있게 되었다.

- Shape, Sprite, MovieClip 등과 같이 객체가 다양해 져서, 효율적인 화면 구성을 할수 있다 되었다.

AS2.0 까지만 해도 MovieClip 만이 화면을 구성 하였으므로, 효율성이 떨어졌었다. 하지만, MovieClip 에서 타임라인을 제거한 Sprite 와 단지, 드로잉 기능만 가지고 있는 Shape 객체로 인해 좀더 효율적인 렌더링이 가능해 졌다.


Depth 개념에서 Index 개념으로 변화


AS2.0 까지는 객체의 위,아래 순서 개념을 Depth 개념이다. Depth 개념을 말 그대로 절대적인 깊이를 적용하여 z-index를 바꾸는 방식이었다. 예를 들어 mc 라는 객체가 depth 10에 존재 하고 mc2 라는 객체가 depth100에 존재 한다면 mc는 mc2 보다 아래 위치하게 되고 만약 영역히 겹쳐 졌을 경우에는 mc가 mc2에 가려 않 보인다. 여기서 중요한 점은 depth10 과 depth100 사이에는 아무것도 존재 하지 않아도 된다는 점이다. 빈 공간으로 둬도 상관없는 상태 이다. 하지만 AS3.0 부터 적용된 Index 개념에서는 조금 다르다. 항상 순서에 맞게 객체에 index 가 적용 된다. addChild 메소드를 통해 객체를 DisplayList 에 등록했다면, 제일 처음으로 등록한 객체는 index 0 을 할당 받고 그 다음은 1 다음은 2. .....7,8,9 등등 순서대로 할당 받게 된다. 순서를 가지고 있다는 점은 여러 가지 특징을 함께 가지고 있다는 뜻과 같다. 일상 생활에서 10개의 박스가 아래에서 부터 순서대로 쌓여 있다는 경우를 예로 들어 보면, 어떠한 사람이 제일 아래 있는 1 index 에 있는 박스를 가지고 간다면, 1 index 위치가 비게 되므로 위에 있는 박스들이 차례로 아래로 다시 쌓여 제 정렬 되게 됩니다. (1<-2 , 2<-3, 3<-4 등등) AS3.0 에서의 Index 도 같은 개념 이다.


Depth방식에 비해 Index방식이 효율적인 점



 첫번째로 Index방식은 객체에 순서를 부여 하므로 해서 부모 객체에서 자식 객체를 탐색할 때, 매우 빠르게 조회 할 수 있게 해준다. 아래 코드는 어떠한 DisplayObjectContainer 에 속해 있는 객체들을 탐색 하는 메소드 이다.



function displayChild(&prt:DisplayObjectContainer):void{

for(var i:int = 0; i < &prt.numChildren; i++){

var child:DisplayObject = &prt.getChildAt(i);

if(child as DisplayObjectContainer)

{

trace(child.name);

displayChild(child as DisplayObjectContainer);

}

else

{

trace(child.name);

}

}

}


 두번째로 또 다시 일상생활의 예를 들어 보면, Depth 방식으로 책을 만드는 사람들과 Index 방식으로 책을 만드는 사람들이 있다고 하자. 두 사람 모두 150쪽 짜리 책을 완성 하였다. 하지만, 중간에 잘못된 부분을 발견하여 50쪽에 100쪽 분량의 내용을 삭제 하려고 한다. Depth 방식의 사람들은 엄청 고생을 해야 할 것이다. 왜냐하면 기존에 있던 100쪽 부터 150쪽까지의 분량을 일일히 앞으로 옮겨야 하기 때문이다. 하지만 Index 방식으로 책을 만드는 사람들은 옮기는 수고를 할 필요가 없다. 50쪽부터 100쪽까지 의 분량을 삭제 하면 알아서 100쪽에서 150쪽까지 있었던 분량이 알아서 정렬하기 때문이다. Actionscript 에서도 이 예제와 똑같은 원리가 적용 된다.


DisplayObject 와 DisplayObjectContainer


아래 구조도에서 볼수 있듯이 AS3.0 의 DisplayList 는 DisplayObject 와 DisplayObjectContainer 를 통해 만들어 진다. 자주 사용하는 MovieClip 이나 Sprite 의 속성중 x, y, visible, alpha 등등의 속성을 가지고 있는 것은 모두 DisplayObject 클래스를 상속 받았기 때문이다. DisplayObject 란 DisplayList (표시목록) 에 배치 할 수 있는 모든 객체의 기본 클래스 이다. 그러면 DisplayObjectContainer 는 무엇인가 아래 구조도를 보면 DisplayObjectContainer 가 DisplayObject의 상속을 받아서 만들어 졌다는 것을 볼 수 있다. 이 말은 DisplayObject 의 기능은 모두 가지고 있으면서 어떠한 것을 포함 할 수 있는 즉, addChild 와 removeChild 와 같은 DisplayObject 의 객체 컨테이너(바구니) 역할을 할 수 있는 객체들의 기본 클래스 이다.



DisplayObject

상속 받는 구상 클래스 : 실제 객체를 생성 할 수 있는 클래스


Bitmap, Loader, Shape, SimpleButton,Sprite, MovieClip, TextField, Video


상속 받는 추상 클래스 : 실제 객체를 생성 할 수 없고, 기능만을 가지고 있는 추상 클래스이다. 이 추상클래스를 통해 객체를 생성하려고 하면 ArgumentError 가 발생한다.

var mc:DisplayObjectContainer = new DisplayObjectContainer() 를 실행 하면 ArgumentError 가 발생한다.


AVM1Movie, DisplayObjectContainer, InteractiveObject, MorphShape, Stage, StaticText


속성 및 메소드

http://help.adobe.com/ko_KR/AS3LCR/Flash_10.0/flash/display/DisplayObject.html


이벤트

Event.ADDED , Event.ADDED_TO_STAGE,


DisplayObject 는 객체에 addChild 될수 있으므로 A 객체가 B 객체에 addChild 되면 Event.ADDED 이벤트가 발생한다.

Event.REMOVED, Event.REMOVE_FROM_STAGE


DisplayObject 는 객체에 removeChild 될수 있으므로 A 객체가 B 객체에 removeChild 되면 Event.REMOVED 이벤트가 발생한다.


root / parent / stage 의 의미 알기



DisplayObjectContainer



속성 및 메소드

http://help.adobe.com/ko_KR/AS3LCR/Flash_10.0/flash/display/DisplayObjectContainer.html

주요 메소드

추가 / 제거 


addChild / removeChild

addChildAt / removeChildAt : 특정 index에 객체를 추가/삭제 한다.


 addChild(child:DisplayObject):DisplayObject

 addChildAt(child:DisplayObject,index:int):DisplayObject

 removeChild(child:DisplayObject):DisplayObject

 removeChildAt(child:DisplayObject,index:int):DisplayObject

자식 객체에 대한 정보


numChildren : DisplayObjectContainer 안에 addChild되어 있는 (포함되어 있는) 객체의 갯수를 반환한다.


Index 값 정보


getChildAt / getChildByName / getChildIndex : DisplayObjectContainer 안에 존재 하는 객체들을 Index 값(getChildAt), 이름(getChildByName)에 따라 찾아 주고, getChildIndex 는 특정 객체의 Index 위치를 반환한다.


getChildAt(index:int):DisplayObject

getChildByName(name:String):DisplayObject

getChildIndex(child:DisplayObject):int


Index 값 교환


setChildIndex / swapChildren / swapChildrenAt : DisplayObjectContainer 안에 존재하는 객체들의 Index 값을 서로 바꿔주는 메소드 들이다.


setChildIndex(child:DisplayObject,index:int):void

swapChildren(child1:DisplayObject,child2:DisplayObject):void

swapChildrenAt(index1:int,index2:int):void





'Actionscript3.0' 카테고리의 다른 글

Factory Pattern (AS3)  (0) 2009.10.25
Actionscript3.0의 DisplayList  (2) 2009.09.22
What is "Flashplatform" ?  (3) 2009.08.25
OpenCV in Flash  (2) 2009.08.21
Posted by Flash 동강
Actionscript3.02009.06.24 13:51
Front - End 개발을 하다 보면 Flash player의 보안 범위를 판단하지 못해 곤란한 일을 겪은 일이 있을것이다.  Flash 개발자의 경우에는 미쳐 알지 못한 내부 보안 설정을 하지 않아서 데이터를 못불러 온다거나, 바뀐 Flash player 보안 정책 때문에 고생을 했을 수도 있고, UI개발자의 경우에는 Flash 개발자가 없는 상태에서 여러 상황을 판단을 해야 하지만 Flash player의 보안 규칙에 대해 알지 못해서 혼란 스러운 경우가 있을 것이다. 이 문서는 모든 Flash 개발자와 UI개발자가 알아야 할 Flash player의 보안에 대해 기초적인 내용을 다룰 것이다.

Flash player 보안 개요

Flash player의 보안은 Flash, Flex 로 만들어진 SWF 파일이 발생 시킬 수 있는 보안 이슈에 대해 정의 및 제한 하고 있다. 텍스트 파일이나 이미지, 오디오 파일들을 로드 하거나 SWF 사이에 크로스 스크립팅을 할때 발생 할 수 있는 이슈들이 모두 여기에 포함 되어 있다. 예를 들어 SWF에서 http://www.ddongkang.com 에 존재 하는 http://www.ddongkang.com/data.xml 을 로드 한다고 할때, http://www.ddongkang.com 도메인에 crossdomain.xml 파일이 없다면 SecurityError를 발생시킨다. Flash player의 보안은 위와 같은 문제에 대해 Flash player 구현상으로 올바른 접근법을 제시 하고 있다. 

기본적으로 다음과 같은 보안 규칙이 적용 된다.

  • 동일한 보안 샌드 박스의 리소스를 항상 서로 접근(Excess) 할 수 있다.
  • 원격 샌드박스의 SWF파일에서는 로컬 파일과 데이터에 접근 할 수 없다.


안 샌드 박스 타입


Actionscript는 Flashplayer가 로드하는(열거나, 불러온 파일 포함) 모든 SWF파일에 보안 샌드박스 타입이라 불리는 보안 상태를 할당한다. Flashplayer는 아래와 같이 4가지 경우의 보안 샌드 박스 타입이 존재 한다.

  • remote 샌드박스 - Flash Player는 인터넷의 SWF 파일을 포함하여 에셋을 해당 웹 사이트의 원래 도메인에 해당하는 별도의 샌드박스에 분류한다. 기본적으로 이러한 파일은 해당 서버의 모든 리소스에 대한 액세스가 허용된다. 원격 SWF 파일은 URL 정책 파일 및 Security.allowDomain() 메서드와 같은 명시적인 웹 사이트 및 제작자 권한을 사용하여 다른 도메인의 데이터에 추가로 액세스할 수 있다.

  • local-with-filesystem 샌드박스 - 보안을 위해 Flash Player는 기본적으로 모든 로컬 SWF 파일을 local-with-file-system 샌드박스를 적용한다. 이 샌드박스에서 SWF 파일은 URLLoader 클래스 등을 사용하여 로컬 파일을 읽을 수 있지만, 네트워크와는 어떤 방식으로도 통신할 수 없다.


  • local-with-networking 샌드박스 - SWF 파일을 컴파일할 때, 로컬 파일로 실행되지만 네트워크 액세스가 가능하도록 지정할 수 있다. 이러한 파일은 local-with-networking 샌드박스가 적용 된다. local-with-networking 샌드박스에 할당된 SWF 파일에서는 해당 로컬 파일에 액세스할 수 없다. 대신, SWF 파일은 네트워크의 데이터에 액세스할 수 있다. 하지만 URL 정책 파일이나 Security.allowDomain() 메서드에 대한 호출을 통해 권한이 부여되지 않는 한 local-with-networking SWF 파일은 여전히 네트워크의 데이터를 읽을 수 없다. 이러한 권한을 부여하려면 URL 정책 파일에서<allow-access-from domain="*"/> 또는 Security.allowDomain("*")을 사용하여 모든 도메인에 권한을 부여해야 한다.


  • local-trusted 샌드박스 - 사용자나 설치 프로그램에 의해 신뢰할 수 있는 파일로 등록된 로컬 SWF 파일은 local-trusted 샌드박스에 배치된다. 시스템 관리자와 사용자는 보안 고려 사항에 따라 local-trusted 샌드박스에 또는 해당 샌드박스로부터 로컬 SWF 파일을 재할당하거나 이동할 수도 있다. local-trusted 샌드박스에 할당된 SWF 파일은 다른 SWF 파일과 상호 작용하고 원격이나 로컬의 모든 위치에서 데이터를 로드할 수 있다.


 각각의 보안 샌드 박스 타입은 종류에 따라 Flashplayer의 보안 수행 범위가 정해 진다. 다음은 모든 보안 샌드 박스 타입에서 금지 할 가능성이 수도 외부 작업 들이다.

  • 데이터 불러오기
  • 데이터에 접근하기 
  • 크로스 스크립팅 
  • 외부 URL에 데이터 보내기
  • 사용자의 카메라와 마이크로폰에 접근하기
  • 로컬 공유 객체에 접근하기
  • 사용자가 선택한 파일 업로드 또는 다운로드
  • .swf 파일에서의 HTML (javascript) 페이지 스크립팅과 그 반대 작업
  • LocalConnection 채널에 연결하기


보안 샌드 박스 타입이 할당 되는 방법

.SWF 파일의 보안 샌드박스 타입을 결정하기 위해 액션스크립트는먼저 .SWF 파일을 불러오거나 연 위치를 고려한다. 원격 샌드 박스(주로 에서 구동되는 SWF)는 remote 샌드박스가 적용되고, 컴파일러 설정, 환경 설정 파일등 로컬에서 구동되는 SWF 컨텐츠는 local-with-filesystem, local-with-networking, local-trusted 샌드박스에서 선택하여 작업 해야 한다.(각각 보안 기준이 다르다)

UI개발시 고려해야 할 Flash player의 보안

주로 UI개발시 고려해야 하는 상황은 웹이기 떄문에 remote 샌드박스를 고려 하면 된다. 아래 4가지 경우는 UI개발과 Flash개발 사이에 발생 할 수 있는 보안 이슈들이다.

1. SWF에서 외부 파일 로드 (이미지,오디오,텍스트파일 등등)

아무런 통신을 안하는 SWF에 대해서는 이러한 보안 이슈에 대해 주의해야 할 점들이 없지만, 대부분은 SWF들은 데이터를 불러오는 작업을 한다. SWF안에서 좀 더 깔끔한 폰트 처리를 위해서 font.swf를 로드 한다거나, 외부 데이터 파일을 불러와서 뿌려줘야 되는 경우가 종종 발생한다. 이때 font.swf 파일이나, data.xml 파일이 메인이 되는 SWF와 같은 도메인에 있다면 따로 보안 설정을 안해줘도 되지만, 다른 도메인에 존재 할 경우에는 설정을 해 줘야 한다. 좀 더 쉬운 상황 설명을 위해 로딩의 주체가 되는 SWF 파일을 main.swf , 로드 되어 지는 파일인 폰트 파일을 font.swf, 로드 되어 지는 데이터 파일을 data.xml 이라고 하자.

상황 1 .3개의 SWF파일들은 모두 http://www.ddongkang.com/flash/ 폴더안에 존재 하고 main.swf 에서 font.swf 와 data.xml 를 로드 하는 경우

모두 같은 폴더에 존재 하기 때문에 따로 보안 설정을 해줄 필요가 없다.

상황 2 .main.swf 파일은 http://www.ddongkang.com/flash/ 폴더에 존재 하고, font.swf 와 data.xml 은 http://www.daum.net/flash/data/ 에 존재 하는 경우

주체가 되는 main.swf 와 로드 되어 지는 데이터가 도메인에 존재 하기 때문에 Flash player의 보안에 막히게 된다. main.swf 에서 font.swf 와 data.xml 을 로드 하기 전에 main.swf 는 데이터가 존재 하는 http://www.daum.net 에 크로스 도메인 파일(정책파일)이 존재 하는지 확인 하고 그 설정이 맞는다면 로드를 하게 된다. (따로 확인 하지 않아도 Flash에서 Load 를 하게 되면 crossdomain.xml 파일을 로드 한다. 크로스 도메인 파일의 이름을 바꿔서 로드 하고 싶은 경우
Security.loadPolicyFile("파일URL"); 을 로드 하기 전에 호출 하면 된다. 주의 해야 할 점은 crossdomain.xml 파일의 위치이다. main.swf 가 data.xml의 로드를 시작 하면 Flashplayer에서는 우선 data.xml 파일이 존재 하는 폴더에서 crossdomain.xml 파일이 존재 하는지 확인 한다. 존재하면 바로 확인이 되어 로드를 하겠지만, 존재 하지 않는다면 상위 폴더에 crossdomain.xml 파일이 존재 하는지 확인하게 된다. 처음에 flash/data/ 폴더를 확인 하고 없으면 flash/ 폴더를 확인한다. crossdomain.xml(정책 파일)이 계속 존재 하지 않는다면 계속 상위 폴더에서 확인하고 결국엔 서버의 루트까지 확인하게 된다. 위의 예제에서는 http://www.daum.net 이 루트이다. 루트에도 crossdomain.xml(정책파일)이 존재 하지 않으면 Flashplayer는 로드를 못하게 되고 보안 에러를 발생 시키게 된다. 그러므로 상황에 따라 crossdomain.xml 파일의 위치를 잘 판단하여 업로드 해야 한다.

상황 3 .이미지 오디오 파일 로드

이미지 파일이나 오디오 파일을 로드 할때도 crossdomain.xml(정책파일)이 필요 하다. 하지만 정책 파일이 있더라도 Actionscript에서 보안 설정을 안해주면 이미지 파일의 크기를 조작하거나, 오디오 파일을 불러와서 조작 할 수 없다. 이미지를 조작할때 이러한 문제가 자주 발생하는데, 보안 설정을 안해주고 이미지의 크기가 변하지 않는 다고 이상하게 생각했던 경험을 가지고 있는 사람들이 많이 있을것이다. Flash 상에서 이미지를 로드 하는 것은 결국에는 Flash player에서 이미지를 BitmapData 로 가지고 있는 것이기 때문에 다음과 같은 설정을 해줘야만 로드된 이미지의 BitmapData에 접근할 수 있어서 이미지 크기 조작과 같은 동작이 가능하다.

LoaderContext 설정 방법 소스
// 정책파일이 기본 위치에 없다면
Security.loadPolicyFile("정책파일의위치");			
var loadcontext:LoaderContext = new LoaderContext();
loadcontext.checkPolicyFile = true;
var loader:Loader = new Loader();
loader.load(new URLRequest("이미지 URL"),loadcontext);			

사운드의 경우도 마찬가지로 다음과 같은 설정을 해줘야 한다.

SoundLoaderContext 설정 방법 소스
// 정책파일이 기본 위치에 없다면
Security.loadPolicyFile("정책파일의위치");			
var soundcontext:SoundLoaderContext = new SoundLoaderContext();
soundcontext.checkPolicyFile = true;
var sloader:Sound = new Sound();
sloader.load(new URLRequest("오디오 URL"),soundcontext);			

crossdomain.xml (정책 파일)



위의 정책파일은 www.ddongkang.com 과 ddongkang.com 에 대해 접근 허락을 나타내고 있다. 더 자세한 정책 파일 옵션은 웹 사이트 컨트롤(정책파일) 에서 확인할 수 있다.



2. SWF에서 HTML 브라우져 객체의 접근

AS3.0의 통신 - 브라우저와의 통신 에서 다뤘듯이 SWF는 자신을 가지고 있는 HTML객체와 통신을 할 수 있다. SWF를 HTML에 Embed 할때 allowScriptAccess매개변수를 설정하는데, 이 매개변수는 SWF파일 내에서 HTML에 있는 객체를 접근하는 것에 대한 기능을 제어한다.


<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
             id="FlashVar" width="500" height="375"
             codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
         <param name="movie" value="FlashVar.swf" />
         <param name="quality" value="high" />
         <param name="bgcolor" value="#869ca7" />
         <param name="allowScriptAccess" value="sameDomain" />
    <param name="FlashVars" value="data0=DongHyuk&data1=동혁&data2=http:www.ddongkang.com" />
         <embed src="FlashVar.swf" quality="high" bgcolor="#869ca7"
             width="500" height="375" name="FlashVar" align="middle"
             play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
             type="application/x-shockwave-flash"
             FlashVars="data0=DongHyuk&data1=동혁&data2=http:www.ddongkang.com"
             pluginspage="http://www.macromedia.com/go/getflashplayer">
         </embed>
 </object>


allowSCriptAccess는 "always","sameDomain","never" 값중 하나를 가질 수 있다.

allowScriptAccess="always" : SWF파일은 HTML 페이지와 다른 도메인에 있는 경우에도 SWF파일이 포함된 HTML페이지와 통신 할 수 있다.

allowScriptAccess="sameDomain" : SWF파일은 HTML 페이지와 동일한 도메인에 속해 있는 경우에만 SWF파일이 포함된 HTML 페이지와 통신할 수 있다.

allowScriptAccess="never" : SWF파일에서 어떠한 HTML페이지와도 통신 할 수 없다.

allowScriptAccess에 따라 ExternalInterface.call 을 이용하여 HTML 에 있는 javascript 함수를 자유롭게 호출 할 수 있다. 하지만, HTML 객체에서 SWF 객체에 접근 할 때는 SWF 내부의 보안 정책이 필요 하다.  javascript에서 아무런 제약 없이 SWF에 있는 모든 객체들에 접근 할 수 있다면, 심각한 보안 문제가 발생할 것이다.

상황 1. 같은 도메인에 HTML과 SWF파일이 존재 하는 경우(html파일이 swf파일을 포함할때)

같은 도메인에 존재 하기 때문에 따로 보안 설정을 안해줘도 된다. 예를 들어 http://www.ddongkang.com/html/ 폴더에 index.html이 있고 http://www.ddongkang/html/flash/ 에 swf파일이 존재할 경우 HTML에서 SWF에 존재 하는 객체에 제한 없이 접근 할 수 있다.

상황 2. 다른 도메인에 HTML과 SWF파일이 존재 하는 경우(html파일이 swf파일을 포함할때)

index.html 파일이 http://www.daum.net/html/ 폴더에 있고, movie.swf파일이 http://www.ddongkang.com/html/flash 폴더에 있을 경우 movie.swf파일에서 반드시 Security.allowDomain("http://www.daum.net/html/"); 해줘야 index.html 파일에서 movie.swf 에 있는 객체로 접근이 가능해 진다. AS3.0의 통신 - 브라우저와의 통신 에서 다뤘듯이 ExternalInterface.addCallback 을 이용하여 html 에서 swf에 있는 메소드를 실행 하는 것이 이 경우에 해당 한다.

3. 크로스 스크립팅

AS3.0 부터는 서로 다른 SWF 간에 크로스 스크립팅이 가능하다. 크로스스크립팅이란, 아래 그림과 같이 swfA.swf 에서 swfB.swf 를 로드 했을 경우 swfA.swf 에서 swfB.swf의 객체에 접근하여 스크립팅 하거나 swfB.swf 에서 swfA.swf로 접근하여 스크립팅 하는 것을 말합니다. 두개의 SWF파일이 같은 도메인에 있으면 따로 보안 설정을 안해줘도 되지만, 다른 도메인에 있으면 설정을 해 줘야 한다



siteA.com 에 있는 swfA.swf가 siteB.com 에 있는 swfB.swf를 로드 하여 크로스 스크립팅 하는 경우 swfB.swf 에서 Security.allowDomain("siteA.com") 를 호출해야만 swfA.swf에서 swfB.swf로의 접근이 가능하다. allowDomain으로 설정된 보안은 비대칭적이기 때문에 swfB.swf 에서는 swfA.swf 로 크로스 스크립팅을 할 수 없다. swfA.swf 에서도 위와 마찬가지로 Security.allowDomain("siteB.com") 이라 해줘야 쌍방향으로 크로스 스크립팅이 가능하다. 더 자세한 내용은
Adobe Actionscript3.0 Document - Security 에서 확인 할 수 있다.


이 문서에서는 Flash player의 보안중 극히 일부분만을 다루었다. 그 만큼 방대한 보안 설정이 존재 하고 때에 따라 보안 규약을 맞춰서 작업해야 발생할 가능성이 있는 보안 취약점들은 미리 파악하여 대처 할 수 있다. 지금 까지 나온 다양한 이슈들에 대해 Adobe Flash Developer Center - Security 에서 다루고 있으니 참고하라.



Posted by Flash 동강
Actionscript3.02009.06.02 23:40

 Flash의 컴파일 결과물인 SWF는 그 자체로 UI 나 GAME 그리고 어플리케이션(AIR)이 될 수 있지만, 대부분은 브라우저에 Embeded 되어 사용됩니다. 배너와 같이 단순하게, 보여 주기 위해서 브라우저에 Embeded하는 경우도 있겠지만, UI 나 웹 어플리케이션을 구현할 때는 브라우져나, 서버사이드 언어와의 통신이 필요 하게 됩니다. AS3.0으로 거의 대부분의 Front-End 단의 개발작업을 모두 할 수 있긴 하지만, 퍼포먼스나 구현의 편의성을 위해 Javascript를 사용해야 하는 경우가 많습니다. 이 문서는 앞으로 몇개의 포스팅을 통해 다루게 될 AS3.0의 통신 방법에 대한 첫 문서로서 AS통신의 가장 기본이라 할 수 있는 브라우저와의 통신에 대해 다루고 있습니다.

 SWF와 브라우저와 통신 하는 방법은 크게 두가지로 구분할 수 있습니다.

첫번째, SWF 를 브라우저에 Embeded 시킬때 변수를 전달해 주는 방법
아래와 같이 main.swf 파일을 브라우저에 Embeded할때 "FlashVars" 변수를 SWF에서 접근 하는 방식입니다.

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
             id="FlashVar" width="500" height="375"
             codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
         <param name="movie" value="FlashVar.swf" />
         <param name="quality" value="high" />
         <param name="bgcolor" value="#869ca7" />
         <param name="allowScriptAccess" value="sameDomain" />
    <param name="FlashVars" value="data0=DongHyuk&data1=동혁&data2=http:www.ddongkang.com" />
         <embed src="FlashVar.swf" quality="high" bgcolor="#869ca7"
             width="500" height="375" name="FlashVar" align="middle"
             play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
             type="application/x-shockwave-flash"
             FlashVars="data0=DongHyuk&data1=동혁&data2=http:www.ddongkang.com"
             pluginspage="http://www.macromedia.com/go/getflashplayer">
         </embed>
 </object>


object 와 embed 를 함께 사용해야 하는 이유

마이크로소프트의 Internet Explore(IE) 에서는 특정한 속성과 함께 <object>를 사용해야 하고, IE 외의 다른 브라우져에서는 이와 다른 속성을 설정한 <object>태그를 사용하거나, 아예 <embed>태그를 사용해야 하기 때문입니다. 모든 브라우저에서 크로스 브라우징을 하기 위함입니다.


object 태그를 사용하여 SWF 를 브라우져에 올릴때, FlashVars 값을 지정해서 넘겨 주는 방식 입니다. 위의 코드에서 볼드로 처리해 놓은 부분을 주의 깊게 보면, 두 부분에서 정의 하고 있는 변수들이 (data0,data1,data2)과 그 값들이 똑같아야 정상적으로 SWF에 넘어가게 됩니다.

AS3.0에서 FlashVars 변수를 통해 넘어 오는 값을 받는 방법은 다음과 같습니다.

package
{
    import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.text.TextField;
   

    public class FlashVarsExample extends Sprite
    {
        private var field:TextField;
        public function FlashVarsExample()
        {
            field = new TextField();
            field.autoSize = "left";
            addChild(field);
           
            var keyStr:String;
              var valueStr:String;
           
            var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters;
            for (keyStr in paramObj) {
                valueStr = String(paramObj[keyStr]);
                field.appendText("\t" + keyStr + ":\t" + valueStr + "\n");
            }
        }
       
    }
}

LoaderInfo(this.root.loaderInfo).parameters 는 위의 object 태그에서 넘겨 주는 FlashVars를 받아 오고 paramObj를 for..in 구문을 사용하여 그 안에 있는 변수들을 뽑아 오는 방법 입니다. SWF 가 브라우저 또는 다른 SWF에 로드 되었을때, 자신의 로드 정보를 LoaderInfo 객체에 담고 있기 때문에 사용할 수 있는 방법 입니다. 자세한건 LoaderInfo 클래스를 참고 하세요.

플래시에서 로드 하는 xml의 url이 유동적으로 바뀌거나, 상황에 따라 다른변수를 SWF에 전달해 주고 싶을때 간단하게 사용할 수 있는 방법 입니다. 예를들어 브라우저의 현재 위치를 SWF에 전달하여 네비게이션 Depth를 구현 하는 것도 이 방법을 사용하면 됩니다. 하지만, 비교적 작은 변수만 넘길 수 있다는 점과 변수 값이 그대로 외부에 노출 된다는 단점이 있습니다.

두번째, Flash API 의 ExternalInterface 객체를 사용하는 방법

ExternalInterface는 SWF와 Flash Player컨테이너(브라우져나 Flashplayer를 소유할 수 있는 모든 것들)간에 직접 통신 할 수 있도록 도움을 주는 클래스 입니다. Javascript와의 통신을 위한 중요한 기능을 제공하고 있으며 Adobe에서는 Javascript와의 통신에 ExternalInterface를 사용하도록 권장합니다.

통신은 양방향으로 모두 가능 합니다. SWF에서 Javascript의 함수나 변수에 접근할 수 있으며 변경도 가능합니다. 반대로 Javascript에서 SWF 안에 있는 Flash 객체들도 접근 가능 합니다. 하지만 ExternalInterface는 운영체제와 브라우저가 지원 하지 않으면 사용할 수 없습니다. 지원하는 OS와 브라우저들은 다음과 같습니다.

 브라우저  운영체제  운영체제
 Internet Explorer 5.0 이상
 Windows  
 Netscape 8.0 이상
 Windows  MacOS
 Mozilla 1.7.5 이상
 Windows  MacOS
 Firefox 1.0 이상
 Windows  MacOS
 Safari 1.3 이상
   MacOS

위와 같이 사용할 수 있는 환경이 존재 하기 때문에 사용전 체크를 해 줘야 합니다.

ExternalInterface.available :Boolean = 이 값이 true를 반환하면 사용가능하고 false이면 사용 불가능 합니다.
if(ExternalInterface.available){// 통신 실행}

위와 같은 코드를 통해 사용 가능 여부를 체크 하고 사용해야만 합니다. ExternalInterface는 통신을 위한 두가지 메소드를 제공합니다.

ExternalInterface.call(functionName:String,...arguments):*
먼저 ExternalInterface.call은 SWF를 임베디드(소유)하고 있는 컨테이너의 메소드를 호출하는 함수 입니다.그함수를 수를 호출 할 수 있을 뿐만 아니라, 변수를 전달하여 실행 할 수 있습니다. 예를들어 다음과 같이 메소드를실행 하면 브라우져에서 alert()창을 띄웁니다. (여기서는 주로 사용되는 브라우저를 예를들어 설명하겠습니다.)

ExternalInterface.call("alert","alert function is called");

전달할 인수가 없을때는 빈공간으로 호출할 수 있고, 전달한 인수가 많아지면 그 갯수 만큼 arguments 자리에 넣어
주면 됩니다.

ExternalInterface.addCallback(functionName:String, closure:Function):void
addCallback의 첫번째 인수인 functionName은 Javascript에서 SWF안에 있는 Actionscript 함수를 호출할때 사용하는 이름이고, closure는 실제로 SWF 에서 호출 되는 함수명 입니다. 이 두가지 파라미터가 처음 사용할때 많이 헛깔리는 부분인데요.

예를 들어 SWF에서 addCallback 메소드를 아래와 같이 호출 하면

ExternalInterface.addCallback("sendToActionScript", receivedFromJavascript);

sendToActionScript는 Javascript에서 SWF 에 있는 receivedFromJavascript 함수를 호출 한다는 의미 입니다. 결국 sendToActionScript는 Javascript에서 사용하는 함수이고 receivedFromJavascript는 Actionscript에서 호출되는 함수 입니다. 예를 들어 보겠습니다. (Adobe 도움말에 있는 예제)

예제 샘플
if (ExternalInterface.available) {             
                output.appendText("Adding callback...\n");
                ExternalInterface.addCallback("sendToActionScript", receivedFromJavaScript);
                if (checkJavaScriptReady()) {
                    output.appendText("JavaScript is ready.\n");
                } else {
                    output.appendText("JavaScript is not ready, creating timer.\n");            
                }
               
            } else {
                output.appendText("External interface is not available for this container.");
            }
우선 ExternalInterface.available로 ExternalInterface 객체를 사용할 수 있는지 확인한 후에 addCallback 메소드를 실행 시켰습니다. addCallback 메소드를 등록 한 후에 checkJavaScriptReady() 메소드를 호출하여 javascript 호출이 가능한지 판단 합니다. 호출이 가능한지 체크 하는 이유는 브라우져가 모두 로드가 된 후에 Javascript 메소드를 호출 할 수 있기 때문 입니다. 그래서 Javascript안에 있는 isReady 메소드를 호출하여 반환 값이 true가 넘어 오면 준비가 된걸로 생각하고 스크립트가 진행 됩니다.

ExternalInterface.addCallback 을 등록했기 때문에, 해당 SWF를 임베디드한 브라우져의 Javascript에서 sendToActionScript 메소드를 호출하면 SWF 안에 있는 receivedFromJavaScript 메소드가 실행 됩니다.
private function receivedFromJavaScript(value:String):void {
            output.appendText("JavaScript says: " + value + "\n");
        }

ExternalInterface.call 메소드와 같이 Javascript에서도 SWF로 변수를 전달할 수 있기 때문에 전달된 value값을 받아서 Javascript에서 어떤 값이 넘어 왔는지, TextField에 뿌려 주는 메소드 입니다.

주의해야 할 점 브라우저에 SWF 를 object 태그나, embed 태그를 이용하여 삽입할때, name 값과 id 값을 설정해 줘야 해당 SWF에 접근 할 수 있습니다. 페이지 안에는 여러개의 SWF가 존재 할 수 있기 때문에, id 값이나 name 값을 통해 해당 SWF를 찾아 내서 그 안에 있는 메소드에 접근 할 수 있는 것 입니다. Javascript에서 SWF를 찾아 내는 메소드는 다음과 같습니다.
function thisMovie(movieName) {

         if (navigator.appName.indexOf("Microsoft") != -1) {

             return window[movieName];

         } else {

             return document[movieName];

         }

     }




navigator.appName.indexOf("Microsoft") 를 이용하여 브라우져의 종류를 판단하여, 종류에 따라 접근 방법을 다르게 하여 SWF 를 찾아 내는 메소드 입니다.

전체 브라우저 소스는 아래와 같습니다.

<!-- saved from url=(0014)about:internet -->

 <html lang="en">

 <head>

 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

 <title>ExternalInterfaceExample</title>

 <script language="JavaScript">

     var jsReady = false;

     function isReady() {

         return jsReady;

     }

     function pageInit() {

         jsReady = true;

         document.forms["form1"].output.value += "\n" + "JavaScript is ready.\n";

     }

     function thisMovie(movieName) {

         if (navigator.appName.indexOf("Microsoft") != -1) {

             return window[movieName];

         } else {

             return document[movieName];

         }

     }

     function sendToActionScript(value) {

         thisMovie("ExternalInterfaceExample").sendToActionScript(value);

     }

     function sendToJavaScript(value) {

         document.forms["form1"].output.value += "ActionScript says: " + value + "\n";

     }

 </script>

 </head>

 <body onload="pageInit();">

 

     <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"

             id="ExternalInterfaceExample" width="500" height="375"

             codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">

         <param name="movie" value="ExternalInterfaceExample.swf" />

         <param name="quality" value="high" />

         <param name="bgcolor" value="#869ca7" />

         <param name="allowScriptAccess" value="sameDomain" />

         <embed src="ExternalInterfaceExample.swf" quality="high" bgcolor="#869ca7"

             width="500" height="375" name="ExternalInterfaceExample" align="middle"

             play="true" loop="false" quality="high" allowScriptAccess="sameDomain"

             type="application/x-shockwave-flash"

             pluginspage="http://www.macromedia.com/go/getflashplayer">

         </embed>

     </object>

 

     <form name="form1" onsubmit="return false;">

         <input type="text" name="input" value="" />

         <input type="button" value="Send" onclick="sendToActionScript(this.form.input.value);" /><br />

         <textarea cols="60" rows="20" name="output" readonly="true">Initializing...</textarea>

     </form>
 </body>
 </html>


Javascript 소스를 위에서 부터 보면 Flash 에서 ExternalInterface.call 로 호출한 isReady 메소드가 정의 되어 있습니다.
<body onload="pageInit();"> 태그가 있기 때문에 페이지가 모두 로드 되면 jsReady 변수가 true가 되어 Flash 에서 Javascript를 호출할 준비가 완료 되었다는 것을 알게 됩니다. 그리고 sendToActionScript 메소드를 실행 하면 thisMovie 를 이용하여 해당 SWF를 찾아낸 후에 그 안에 있는 receivedFromJavaScript 메소드를 호출하는 것 입니다.

thisMovie("ExternalInterfaceExample").sendToActionScript(value); 를 호출했다고 해서 SWF안에 있는 sendToActionScript메소드를 호출한다고 생각하면 안됩니다. addCallback을 통해 Javascript에서 sendToActionScript를 호출하였을때 SWF에서는 receivedFromJavasript 메소드를 호출한다고 등록 했기 때문에 receivedFromJavascript 메소드가 호출 됩니다.

그리고 SWF 에서 ExternalInterface.call 메소드를 통해 Javascript의 sendToJavaScript를 호출하면 form태그에 있는 textarea에 그 값이 추가 되는 예제 입니다.

위와 같이 ExternalInterface를 이용하면, Javascript에 있는 함수나 SWF 안에 있는 함수나 쉽게 접근 할 수 있습니다. 다만,
ExternalInterface.call 이나, ExternalInterface.addCallback 으로 등록한 함수만 접근 할 수 있는 단점이 있습니다. 그리고 ExternalInterface에는 몇가지 단점이 존재 합니다.

ExternalInterface의 단점

- 액션스크립트와 자바스크립트 모두에서 별도 코드의 라이브러리를 작성하여, 플렉스 어플리케이션의기능을 자바스크립에서 사용하거나 그 반대의 경우에 대해서도, ExternalInterface 클래스가 있어야 한다.


 - ExternalInterface 클래스는 또한 제약이 있다. 기본 데이터 타입, 배열, 심플 오브젝트들은 전달할 수 있지만, 속성과 메소드를 가지는 사용자 정의 클래스를 전달하는 것은 문제가 있다.


그래서 Adobe에서는 Flex Ajax Bridge (FABridge) 라는 ExternalInterface의 단점을 보완한 Flex framework 기반의 오픈 소스 라이브러리를 제공 하고 있습니다. FABridge의 기능은 다음과 같습니다.

 

FABridge

- 리치 플렉스 컴포넌트를 에이젝트 어플리케이션 안에서 사용하고자 하지만 플렉스 코드를 엄청나게새로 쓰는 것은 원하지 않는 경우이다.  브릿지를 사용하는 일부 어플리케이션 내에 컴포넌트를 감싸려고 한다면, 자바스크립트로 전체를 스크립트할 수 있고, 이것은 서버에서 생성된 eval() 함수를 사용하는 형태의 자바스크립트를 이용한다.


 - 우리 팀에 플렉스를 하는 사람이 한 두 사람뿐인 경우이다. FABridge 라이브러리는 팀의 모든 사람이 한 두 명의 플렉스 전문가가 만든 결과물을 사용할 수 있게 해준다.


 - 플렉스와 에이젝스로 만들어진 부분을 모두 가지는 RIA를 만드는 경우이다. 우리는 ExternalInterface만을 이용하여 통합할 수도 있고, 남보다 앞서 FABridge를 사용하여 더 빠른 방법을 찾을 수도 있다.


공개된 라이브러리는 Flex 에 한정되어 만들어 졌지만, Flash platform에 모두 사용할 수 있도록 컨버팅이 가능한 구조로 되어 있습니다. 다음 문서에서는 FABridge가 어떻게 사용되며, FABridge를 기반으로한 새로운 Javascript 통신 객체에 대해 다룰 것 입니다.

관련 문서 : FABridge (Adobe Lab)

위의 예제에 대한 Actionscript 파일 전체 소스
package
{
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.external.ExternalInterface;
	import flash.text.TextField;	

	public class FlashVarsExample extends Sprite
	{
		private var field:TextField;
		public function FlashVarsExample()
		{
			field = new TextField();
			field.autoSize = "left";
			addChild(field);
			
			var keyStr:String;
  			var valueStr:String;
			
			var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters;
			for (keyStr in paramObj) {
				valueStr = String(paramObj[keyStr]);
				field.appendText("\t" + keyStr + ":\t" + valueStr + "\n");
			}			
		}		
	}
}


Posted by Flash 동강
Actionscript3.02009.05.25 00:38

문서 원본 : Adobe 기술문서
작성된 날짜 : 2009-05
저자 : 강동혁(동강)
저자 소개 : Daum communications 에서 UI 개발 업무를 하고 있으며, Flash 커뮤니티에서동강이라는 닉네임으로 활동하고 있다. 뭐든지 사용하기 편해야 한다는 생각을 가지고 개발을 하고 있으며, 최근엔 새로산 자전거를 자주 못타고 다녀 아쉬워 하고 있다.


   <목차>

-Display 객체들의 다양화

-Display List구조의 변화

-객체의 심도 관리 향상(Depth에서 index)

-Depth방식에 비해 Index방식이 효율적인 점

-이벤트 모델의 변화



Flash를 하던 많은 사람들이 AS3.0이 나오고 나서 혼란스러웠던 이유는 두 가지이다.

첫 번째로 Flash에서 핵심이라고 할 수 있는 Display 객체생성을 정의하는 구조가 바뀐 점이고, 두 번째로는 사용자의 반응에 따라 이벤트를 발생 시켜 주는 이벤트 모델이 바뀐 점이다.

또한 AS2.0은 직관적인 문법이지만, AS3.0에서는 간단한 마우스 이벤트를 만들려고 할 때도 코드의 길이가 길어져 버려, AS2.0 사용자들에게 'Flash가 애니메이션 툴의 기능은 사라져 버리고 개발자를 위한 툴로 바뀌었다.' 는 원성을 듣기도 하였다.

하지만, AS3.0에서 코드를 길게 작성해야 이벤트를 만들 수 있다는 말은 AS3.0을 겉으로만 접한 사람들의 오해다. 오히려 AS3.0 은 이벤트 구조를 잘 설계하여 코드를 줄일 수 있고, 덩달아 SWF가 시스템에서 차지하는 메모리의 용량도 줄일 수 있는 장점을 안겨 주었다.

이번 장에서는 AS3.0 AS2.0에 비해 어떤 점이 달라졌고, AS3.0과 하위 언어와의 호환성에 대해 이야기해 보겠다.

 

-Display 객체들의 다양화

Flash 8까지의 AS1.0 2.0에서는 거의 대부분의 객체들은 MovieClip을 통해서 생성됐다.

여러 유형의 객체들이 MovieClip 객체 하나에 모두 포함됐기 때문에 불필요한 메모리와 시스템 리소스를 차지하는 원인이 되었다.

예를 들어 타임 라인이 필요 하지 않는 원을 만들거나, Flash에서 image를 불러와서 사용할 때도 MovieClip을 통해 객체를 만들었기 때문에, 만들어진 객체에는 항상 타임라인이 존재하였다. 이 타임라인이 불필요한 메모리를 차지했던 것이고, MovieClip에 있는 타임라인을 관리하기 위해 사용되었던 시스템 리소스가 증가하게 됐다. 하지만 AS3.0에서는 AS2.0에서 대부분 MovieClip으로 만들어졌던 Display List 객체들을 상황에 맞는 객체들로 만들 수 있도록 객체의 유형이 다양해졌다.

 

대표적인 유형은 MovieClip, Sprite, 그리고 Shape이다. Sprite MovieClip에서 Timeline을 제거한 객체이다. 타임라인을 제거하였기 때문에 MovieClip에 비해 메모리 및 리소스 사용을 줄일 수 있고, Timeline 외에는 MovieClip과 같은 속성 및 메소드를 가지고 있기 때문에 거의 비슷한 용도로 사용할 수 있다.

Shape Sprite와 비슷한 부분이 많다.(Graphics에 포함되어 있는 드로잉API를 이용할 수 있다.)

하지만, 자식 객체를 가질 수 없고 마우스 클릭 이벤트를 지원하지 않는 차이를 가지고 있다. Shape Sprite에 비해 오버헤드가 적고 Sprite가 지원하는 속성에 대한 메모리를 사용하지 않아도 되기 때문에 속도가 향상되고 메모리를 적게 사용한다.

그래서 마우스 이벤트가 필요없는 그래픽 객체를 만들고 싶을 때는 Shape를 사용하는 게 좋다.

각각의 객체를 하나씩 비교 한다면, 많은 차이가 없다. 하지만 객체의 수가 많아진다면, 덩달아 컴퓨터에 부담을 많이 주게 된다. 예를 들어 MovieClip Sprite가 컴퓨터 리소스를 차지하고 있는 양의 차이가 10이라고 하면, 이러한 객체들을 100개를 쓸 일이 생기게 되면 컴퓨터가 감당해야 할 리소스 부담은 MovieClip을 사용했을 때 Sprite보다 1000이 더 나게 된다.

덩치가 큰 프로그램에서 이러한 차이는 곧바로 퍼포먼스의 차이로 이어 지기 때문에, Timeline이 필요 하지 않은 객체는 Sprite로 정의 하는 습관을 가지고 있어야 한다.

 

- Display List구조의 변화

앞 절에서 자식 객체를 포함할 수 있는 객체는 Sprite이고, 포함할 수 없는 객체는 Shape라고 설명했다.

Sprite DisplayObjectContainer(표시객체컨테이너)이기 때문에 자식 객체를 가질 수 있고, Shape DisplayObject(표시객체)이기 때문에 자식 객체를 소유할 수 없다.

 

AS3.0에서 달라진 Display List의 구조는 DisplayObject를 기본으로 하여 구성된다.

SWF에서 사용자에게 보이게 되는 모든 객체들은 모두 DisplayObject 또는 DisplayObjectContainer의 상속을 받아서 만들어진 것이다. Display List의 구조는 아래와 같다.

그림 1 AS3.0 Display List 구조도

 그림에서 볼 수 있듯이 MovieClip, Sprite, Shape 모두 DisplayObject의 상속을 받아서 만들어진다. 하지만, MovieClip Sprite DisplayObjectContainer의 속성을 한 번 더 상속 받기 때문에 자식 객체를 포함하는 속성을 가지고 있다.

자식 객체를 소유할 수 있다는 의미는 바구니가 되어 이것, 저것을 담을 수 있다는 의미이다.

DisplayObjectContainer의 상속을 받은 객체 만이 addChild(담기) removeChild(꺼내기) 메소드를 사용할 수 있다. AS2.0에서는 아래 그림과 같은 구조로 객체들을 정의 하고 있다.


그림 2 AS2.0의 객체 구조도

 객체들을 AS3.0과 같이 상속에 의해 구현한 것이 아니라, Object를 통해 직접적으로 구현하고 있다. 그만큼 직관적으로 구조를 이해 할 수 있다는 장점이 있지만, 객체의 속성을 중복 구현하여, 효율이 떨어진다는 단점이 있다.

새로운 Display List Flash의 가장 핵심이라고 할 수 있다.

Flash에서 사용되는 모든 기능들은 Display List를 통해 구현이 되고 사용되기 때문이다. 그 만큼 중요한 부분을 차지하고 있기 때문에 비교적 이해하기 어려운 내용을 담고 있다.

 

- 객체의 심도 관리 향상(Depth에서 index)

 

Flash Display List에는 심도가 존재한다.

Layer와 별개로 같은 레이어 상에 존재하는 객체들도 위, 아래가 존재하여 위에 있으면 보이고 아래 있으면 위에 있는 객체에 가려서 안보인다. AS1.0 2.0에서는 다음과 같은 메소드를 사용하여 객체의 위, 아래를 조절 하였다.

 

AS2.0에서 객체 심도를 관리하기 위한 메소드

-getDepth() : Number

-getNextHighestDepth() : Number

-getInstanceAtDepth(depth: Number) : MovieClip

-swapDepths(target: Object) : Void


AS3.0
에서는 Display List 구조가 바뀜에 따라, 위와 같은 메소드는 모두 아래와 같이 바뀌었다.


AS3.0에서 객체 심도를 관리 하기 위한 메소드

getDepth() -> getChildIndex()

getNextHighestDepth() -> 직접적으로 대칭 되는 메소드는 없다. 하지만 구현 가능하다.

getInstanceAtDepth() -> getChildAt();

swapDepths() -> addChildAt(), setChildIndex(),swapChildren(), swapChildredAt() 


 

메소드 변경에 대한 더 자세한 내용은 Adobe에서 제공하는 AS2.0마이그레이션을 보면 자세히 기술 되어있다.

AS2.0에서 getNextHighestDepth()를 이용하여, 가장 높은 Depth를 할당하여 다른 객체들 보다 위에 위치하게 함으로서 사용자들에게 보이게 한다거나, swapDepths를 이용하여 이미 존재하고 있는 객체들의 Depth를 바꿔서 객체들끼리 가려지는 정도를 조절하였다.

AS2.0에서 적용되어 있던 심도 관리 개념은 Depth(깊이) 였지만 AS3.0에서는 메소드 이름 뿐만 아니라, 객체의 심도를 관리하는 개념 자체가 바뀌었다.

 

AS2.0에서는 Depth(깊이)개념을 사용하였다.

깊이란 순서가 없이 사용자가 지정한 깊이에 객체를 올려놓을 수 있음을 뜻한다. 사용자가 지정하는 깊이는 음수든 양수든 상관없고, 지정한 값들 사이에 빈 공간이 존재해도 상관없다. 아래 그림이 Depth의 특징에 대해 말해 주고 있다.


 

1) -1 depth부터 2 depth까지 객체들이 놓여 있다.

2) 100 depth에 객체를 추가한다. 100 depth는 추가되어, 존재하지만, 3~99depth까지의 공간은 빈 공간으로 남아 있다.

3) removeMovieClip()을 통해 1 depth에 있는 객체를 제거하면 1 depth는 빈 공간으로 존재하게 된다.

4) 2 depth에 객체가 있음에도 불구하고, 2 depth에 새로운 객체를 올려놓게 되면 기존에 있던 객체는 사라지게 된다.

 이렇게 AS2.0에서는 Depth로 절대적인 위치를 결정 하였다. 하지만 AS3.0에서는 Index라는 개념을 사용하여, 객체의 위치를 상대적으로 결정하도록 바뀌었다.

Index는 순서라는 의미이다.

Display List에 보여지는 객체들은 모두 순서가 부여 되고, 순서가 높을수록(숫자 크기가 클수록) 위에 위치하게 됩니다. 순서는 양수 값만이 가능하고, 0부터 차례대로 부여하게 된다. Depth처럼 2depth 다음에 100depth가 올 수가 없고, 빈 공간이 존재하지 않는다. 아래 그림이 Index의 특징에 대해 말해 주고 있다 



1) 0 index부터 3 index까지 객체들이 놓여 있다.

2) 100 index에 객체 추가를 시도하였지만, 에러가 발생한다.

3) 1 index에 객체를 추가하니, 기존의 index들이 한 칸씩 위로 올라가며 재정렬된다.

4) 3 index에 있는 객체를 삭제하니, 4 index에 있던 객체가 3 index로 내려오며 재정렬된다.

이렇게 AS3.0에서는 index를 이용해 상대적으로 위치를 정하는 방식으로 변경하였다.


 

-Depth방식에 비해 Index방식이 효율적인 점

Index방식은 객체에 순서를 부여해서, 부모 객체에서 자식 객체를 탐색할 때, 매우 빠르게 조회할 수 있게 해 준다. Index들은 단일 배열로 만들어져 getChildIndex() getChildAt()으로 탐색하는 것을 도와준다. 예를 들어 다음과 같은 코드를 사용하면, 파라미터로 넘어온 객체의 자식객체에 대해 빠르고, 쉽게 알 수 있다.



 그에 비해 Depth방식은 깊이의 위, 아래는 있어도, 그 위, 아래 정보가 단일 배열로 정리가 되어 있지 않기 때문에 탐색에 오랜 시간을 소요된다.
예를 들어, 1쪽부터 200쪽 분량의 책이 있다고 가정해보자. 그런데 갑자기 계획이 변경되어 100쪽 부근에 50쪽 정도의 새로운 챕터를 넣어야 한다.

Index 방법에서는 우리가 현실 생활에서 대처하는 방법대로, 새로운 챕터는 101쪽부터 번호가 매겨지고, 뒤에 있던 내용들은 50쪽이 끝나면 이어져서 250쪽 짜리 책이 완성된다.

하지만 Depth 방식으로 하면 문제가 발생한다. 기존의 200쪽 분량의 책에 50쪽 분량의 새로운 챕터를 넣으려면 기존의 100쪽부터 150쪽까지가 새로운 내용으로 덮어 씌어지게 된다. 이런 상황을 막기 위해 미리 swapDepths()를 통해 100쪽부터 200쪽까지를 150쪽부터 250쪽까지로 옮기고 빈 공간에 새로운 챕터를 넣으면 되지만, 시간과 리소스 낭비가 많아지게 된다. 더구나, 여기에서는 50쪽만 추가하는 것이었지만, 50쪽이 100쪽이 될 수도 있고, 1000쪽이 될 수도 있다. 이와 같이 Index방식은 Depth방식에 비해 사용하기 편하고, 휠씬 효율이 높은 심도 관리 방법이라고 말할 수 있다.

 

- 이벤트 모델의 변화

Flash에서 중요한 부분을 차지하고 있는 이벤트 모델 역시 바뀌었다. 이전 버전의 AS에서는 이벤트를 처리하는 방법이 여러 가지가 있었다


AS2.0에서의 이벤트 핸들링 방법

- on() 이벤트 핸들러와 onClipEvent()핸들러 : 객체 안에 코드를 입력하여 해당 객체에 대한 이벤트를 발생시키는 방법이다. 쉽게 사용할 수 있지만, 객체 안에 있는 코드를 찾기가 어려워서 프로젝트 협업 작업에 어려움이 발생한다.

- 콜백 함수 이벤트 핸들러 : 객체. onRelease XML.onload와 같이 객체에 직접 콜백 함수를 등록함으로써 발생시키는 방법이다. 지정된 이벤트에 대해 콜백 함수 하나만 사용할 수 있다. 예를 들어 AS2.0에서 아래와 같은 코드를 실행하면 두 번째 콜백 함수만이 동작 하게 된다.



- 이벤트 리스너 : addListener() addEventListener()를 이용하여 발생시키는 방법으로 리스너 객체와 함수를 만든 후에 리스너를 등록해야 하므로 번거롭지만, 콜백 함수와는 달리 해당 이벤트에 여러 개의 리스너를 만들어서 모두 사용할 수 있다.




여러 개의 이벤트 처리 방식이 상황에 따라 사용되었지만, AS3.0에서는 하나로 통일되었다. 하나로 통일된 새 이벤트 모델은 DOM Level3 이벤트를 기초로 하고 있다.

DOM Level3 이벤트는 기존의 이벤트 모델보다 더 빠르게 이벤트를 발생시킨 객체를 찾아낼 수 있고, 그에 따른 이벤트를 호출해준다. 또한 이전 버전의 이벤트 모델은 이벤트 흐름을 가지고 있지 않았다. 무조건 이벤트를 발생시킨 객체만이 콜백 함수나 이벤트 리스너를 호출 할 수 있었지만, AS3.0에서는 이벤트 흐름에 연관된 객체들은 모두 이벤트 리스너를 호출할 수 있다. 예를 들어 그림 3과 같이 A, B 객체가 있고 B 객체에 마우스 이벤트를 등록했다면, A B 두 객체 모두 이벤트 흐름 안에 있기 때문에 이벤트 리스너를 호출할 수 있다.








AS3.0을 시작하는 분들이 시작부터 어렵다고 느끼는 이유 중 하나가 바로 이벤트 모델 때문이다.

AS2.0에서는 그림4 코드와 같이 단 3줄에 끝나는 것이 AS3.0에서는 이벤트 리스너를 추가하고, 이벤트 핸들러를 만들고, 이벤트 핸들러에 해당 이벤트(MouseEvent)에 대한 파라미터를 넘기는 작업을 해야 하기 때문에 비교적 복잡하게 보이기 때문이다. 하지만 사용해 보면 휠씬 효율적이라는 것을 느낄 수 있다.

AS3.0의 이벤트모델만이 가지고 있는 이벤트 흐름을 이용하여 복잡한 이벤트 발생 구조도 단순화 시킬 수 있으며, 이벤트 리스너의 등록과 제거 과정을 통해, 효율적인 메모리 관리와 객체지향 코드를 구현할 수 있다.

 

글을 마치면서

1부와 2부에 걸쳐서 AS3.0을 왜 사용해야 되고, 어떻게 사용해야 하는가에 대해 다루었다. 많은 사람들이 Flash platform을 도입하면서 Flash 시장도 많이 넓어 지고 있지만, 한간에서는 아직도 “Flash는 배너를 만드는데 사용하는 애니메이션 툴이다.” “Flash를 사용하면 느려진다.” 라고 생각하는 사람들이 있다.

하지만, 이러한 걱정들은 구시대의 산물이 되어 가고 있고, Flash platform이 단지 표현(User Interface)을 위한 수단만이 아니라, 표현과 퍼포먼스를 모두 만족시킬 수 있는 도구로서 나아 가고 있다.

AS3.0은 좀 더 사용자를 만족 시키기 위해 반드시 이용해야 하는 언어이다.


관련 문서: 왜 Actionscript3.0을 사용해야만 하는가?



Posted by Flash 동강
Actionscript3.02009.03.30 16:57
package{                

	import flash.display.MovieClip;		
	import flash.display.Sprite;		

	/**	 * @author kang	 */		

	public class ResourceTest extends Sprite {		

		public function ResourceTest() {						

			var mc : MovieClip = new MovieClip();                        

			addChild(mc);			

			mc.addEventListener(Event.ENTER_FRAME, onEnterframeHandler);		

		}	
		private function onEnterframeHandler(event : Event) : void {			

			trace("execute event");		

		}	

	}

}
위와 같은 코드가 있다고 하자. mc는 Event.ENTER_FRAME 이벤트를 가지고 있는 객체 이다. 하지만 어떠한 상황이 발생하여 mc를 메모리 해제를 할 경우가 발생 하였다. 많은 AS개발자들이 아래와 같은 코드를 입력하여 메모리를 해제 할 것이다. 


private function disposeMc(_mc:MovieClip):void{	
	if(_mc.parent != null)		
	_mc.parent.removeChild(_mc);		
	_mc = null;
}
mc 라는 객체의 모든 참조 값이 제거 되었으므로 mc는 Garbage collection의 수집대상이 될 것이다. 그리고 곧 메모리 상에서 사라질 것이다. 하지만 이 코드에는 문제가 있다. 이벤트를 등록했던 객체는 사라졌지만, 등록된 이벤트 자체는 사라지지 않았다. 그래서 output 창에는 execute event 메시지가 계속호출 될 것이다. 많은 Flash 개발자들이 잘못 알고 있는게 해당 객체를 제거 하면 그 객체에 등록 되어 있던 이벤트들도 제거 된다고 생각한다. 이는 아주 심각한 문제를 발생 시킬수 있는 원인을 제공한다. 컴퓨터가 느려 진다던지, 메모리 사용량 증가로 프로그램 자체나, 브라우져가 멈춰 버리는 일이 발생 할 수도 있다. 그러므로 객체를 메모리 상에서 제거 하기 전에 반드시 removeEventListener로 이벤트를 반드시 해제 해야 한다. addEventListener 의 파라미터로 약한참조를 해 주면 객체가 제거 되면 그 객체에 등록되어 있는 이벤트들도 제거 되지만 약한 참조로 했을때 불편한 점이 많기 때문에 기본값은 강한참조로 되어 있다. 
addEventListener()메서드

public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void

useWeakReference는 false 값이 기본으로 강한 참조이다. 하지만 이 파라미터를 true로 넘겨 주면 약한 참조가 된다. 위에서 언급했듯이 약한 참조로 등록된 이벤트들은 해당 객체가 제거 되었을때 같이 메모리에서 제거 된다.



이와 비슷한 경우가 MovieClip을 사용할때 발생할 수 있다. 예를 들어 다음과 같이 1~40frame까지 계속
 

루프를 도는 MovieClip이 있다고 하자. 이렇게 루프를 돌고 있는 도중 갑자기 이 무비 클립을 메모리 상에서 제거 하면 어떤 일이 발생 할까?? 결과는 위 ENTER_FRAME 이벤트에서와 같이 계속 루프를 도는 현상이 발생한다. 계속 루프를 돈다는 것은 그 만큼 CPU를 사용한다는 말이 되고, 메모리 낭비를 하고 있다는 말이 된다. 하지만, 이걸 인식 하지 못하고 그냥 MovieClip만 제거 하면 해당 무비 클립에 대한 모든 것들이 메모리 상에서 없어 진다고 잘 못 생각하고 있는것이다. 그러므로 위와 같이 MovieClip을 사용한 작업을 할때는 꼭 MovieClip을 stop() 해 준뒤에 메모리를 해제 해 줘야 한다. stop 해주지 않고 메모리를 해제 했다간, 모든 참조 값들이 사라 졌기 때문에 해당 타임라인을 멈출 수 있는 방법이 존재 하지 않는다. 

이러한 리소스 관리 문제는 위의 두가지 경우에만 국한된 것이 아니다. AS에서 제공하는 Sound 나 Loader를 이용한 이미지로드 및 SWF 로드 또는 Video 작업을 할때 모두 위와 같은 메모리 문제가 발생 할 수 있다. 이 사실을 항상 유념하고 Flash 작업을 해야 한다. 더 자세한 AS3에서의 메모리 관리 방법은 다음 링크를 통해 확인 하길 바란다. 




예제다운로드

아무리 여러 테스트가 있어도, 정답은 "상황에 따라 맞는 방법을 쓴다." 이네요.



Posted by Flash 동강
Actionscript3.02009.03.30 10:57
Flash에서 MovieClip을 이용한 작업을 하다 보면 MovieClip에서 일어나는 동작을 코드상에서 알아 내서 이벤트를 발생 시켜야 하는 경우가 있다. 예를 들어 다음과 같은 Timeline이 있을때 재생헤드가 30 frame에 도달 할때 이 동작을 알아 내어 코드를 실행 시켜야 하는 경우가 있다.


이럴 경우 30 frame에 dispatchEvent를 사용하여 MovieClip을 가지고 있는 객체에 이벤트를 전달해 주는 방법을 사용할 수 있다.
dispatchEvent(new Event("playheadreached");
MovieClip에서 전달한 이벤트는
this.addEventListener("playheadreached",headreachedHandler);
private function headreachedHandler(e:Event):void{ // 코드 실행 }
를 통해 전달 받을 수 있다. 하지만, 이 방법은 반드시 Timeline에 코드를 입력해야만 가능한 방법이다. 많은 Flash 개발자들이 Timeline상에 코드를 입력하는 방법이 매우 비효율 적이라는 것을 느끼고 있을 것이다. 왜냐 하면 타입라인에 입력된 코드를 찾기 위해 낭비 하는 시간이 굉장히 많기 때문이다. 그래서, AS3.0에서는 addFrameScript 라는 메소드를 제공해 주고 있다.
adobe에서 제공하는 "AS3.0 Document"에는 이 메소드가 나와 있지 않지만 상당히 유용한 메소드 이다. 사용 방법은 다음과 같다.

package {

	import flash.display.MovieClip;

	public class FrameTest extends MovieClip{
		public function FrameTest()
		{
			this.addFrameScript("29",onFrameHandler);
			
		}		
		private function onFrameHandler():void
		{
			trace("reached");
		}
	}
	
}
Document class를 FrameTest라고 지정했을때, MainTimeline에 있는 재생헤드가 30frame에 위치하면 onFrameHandler 함수가 호출 된다. 주의해야 할 점은 30frame에 위치 했을때 함수를 실행 시키기 위해서는 this.addFrameScript("29",onFrameHandler); 게 해야 한다는 점이다. 29frame을 지난 직후에 메소드가 실행 되는 방식이기 때문이다. 또한 해당 타임라인이 존재 하지 않으면 이 메소드는 실행 되지 않는다.
addFrameScript는 상당히 직관적이고, 간편한 타임라인 컨트롤 방법을 제공해 주고 있다. 하지만 좀 더 간편한 타임라인 컨트롤을 지원해 주는 클래스가 있어 소개하려고 한다. 얼마 전에 Adobe Flash professional 커뮤니티에서 흥미 로운 기술 문서를 보았다. 이 기술 문서의 내용이 오늘 소개하려고 하는 클래스 이다.

타임라인에서 일어 나는 동작을 알려주는, TimelineWatcher

TimelineWatcher는 addFrameScript와 같은 타임라인 이벤트를 관리 해 주는 클래스 이다. EventDispatcher를 상속 받고 있기 때문에 내부적으로 dispatchEvent를 통해 타임라인의 위치를 전달해 주고 있다.


예를 들어 위와 같은 타임라인 모션이 있다고 하자. 그리고 Document class는 WatcherTest로 지정 한다.

package {
	
	import flash.display.MovieClip;
	import flash.text.TextField;
	
	import com.refunk.events.TimelineEvent;
	import com.refunk.timeline.TimelineWatcher;
	
	public class WatcherTest extends MovieClip {
		
		public var ball:MovieClip;
		
		private var timelineWatcher:TimelineWatcher;
		private var output:TextField;
		private var loops:uint = 0;
		
		public function WatcherTest() {
			super();
			stop();
			output = new TextField();
			addChild(output);
			timelineWatcher = new TimelineWatcher(this);
			timelineWatcher.addEventListener(TimelineEvent.LABEL_REACHED, handleTimelineEvent);
			timelineWatcher.addEventListener(TimelineEvent.END_REACHED, handleTimelineEvent);
			gotoAndPlay(1);
		}

		private function handleTimelineEvent(e:TimelineEvent):void {
			switch (e.type) {
				case TimelineEvent.LABEL_REACHED:
					output.text = "label: " + e.currentLabel + "\nloops: " + loops;
					break;
				
				case TimelineEvent.END_REACHED:
					loops++;
					if (loops > 10) {
						stop();
						timelineWatcher.removeEventListener(TimelineEvent.LABEL_REACHED, handleTimelineEvent);
						timelineWatcher.removeEventListener(TimelineEvent.END_REACHED, handleTimelineEvent);
						timelineWatcher.dispose();
						timelineWatcher = null;
					}
					break;
			}
		}
	}
}
		
우선 TimelineWatcher를 생성하고, 파라미터로 MovieClip 객체를 넘긴다. 그리고 TimelineWatcher에 이벤트리스너를 등록한다. TimelineWatcher가 캡쳐 할 수 있는 이벤트는 두가지 이다.

TimelineEvent.LABEL_REACHED : 타임라인에 Label 값이 있는 곳에 재생헤드가 위치해 있으면 호출 되는 이벤트 이다.
TimelineEvent.END_REACHED : 재생헤드가 타임라인의 처음부터 끝까지 돌았을때 호출되는 이벤트이다.
 
 위의 코드에서는 LABEL_REACHED END_REACHED 모두 handleTimelineEvent를 호출 메소드로 등록하고 있다. 같은 메소드라도 전달되는 이벤트의 종류가 같기 때문에 e.type을 이용하여 이벤트를 구분하고 각각에 맞는 이벤트를 처리 할 수 있다. 그리고 TimelineEvent.END_REACHED 이벤트를 이용해서 타임라인이 10번 돌았을때 LABEL_REACHED , END_REACHED removeEventListener 해주고 TimelineWatcher의 dispose 메소드를 이용하여 내부적으로 돌아 가고 있던 ENTER_FRAME 이벤트를 해제해 준다. (TimelineWatcher.as 를 참고)  ENTER_FRAME 이벤트 자체가 상당히 CPU 사용량이 크기 때문에 이벤트가 모두 종료된 후에 dispose 메소드를 반드시 호출해 줘야 한다. addFrameScript가 내부적으로 어떻게 구현되어 있는지는 모르겠으나, TimelineWatcher가 보다 더 유용하게 사용될 수 있는 클래스인거 같다.

  Flash는 타임 라인이라는 강력한 기능을 가지고 있다. 타임 라인이 존재 한다는것은 표현을 좀 더 자유롭게 할 수 있는 도구를 가졌다고 할 수 있다. 그러나, 디자이너는 너무 타임라인에 의존하는 프로젝트를 진행하고 있고, 개발자는 Flash를 Flash답게 사용하지 않고, Flex같이 사용하는 경향이 강하다. 타입 라인을 좀 더 자유롭게 사용할 수 있도록 도와주는 addFrameScript나 TimelineWatcher를 통해 좀 더 효율적인 업무 협업을 할 수 있겠다는 생각이 들었다. 익숙하지 않은 상태에서 다루기는 쉽지 않겠지만, 간단한 AS 구조이니 만큼 TimelineWatcher 나 TimelineEvent 클래스 구조도 살펴보는걸 추천한다.



TimelineWatcher에 대한 기술문서

예제 다운 로드
Posted by Flash 동강
Actionscript3.02009.03.17 20:38
Javascript나 Actionscript에서 긴 길이의 문자열을 고정된 너비의 TextField에 집어 넣으려면 substr(startIndex,length) 이나 substring(startIndex,endIndex)을 사용합니다. 원하는 문자의 길이 만큼 파라 미터를 넘겨서 처리 하면 손 쉽게 해결 됩니다.
var field:TextField = new TextField();
addChild(field);   
var str:String = "Flash Actionscript3.0 플레시 액션스크립트";
field.text = str.substring(0,20);
하지만, 위와 같은 방법에는 치명적인 단점이 있습니다. 영어와 한글의 너비값이 차이가 있기 때문에, 영문의 10글짜와 한글의 10글짜의 너비는 큰 차이가 나게 됩니다. 하나의 문자로만 사용하는 경우에는 상관없겠지만, 항상 한글만 쓰거나 하는 경우는 극히 드물고, 특수문자도 
하나의 문자로 인식 하기 때문에 substring 이나 substr 만 가지고는 해결 할 수가 없습니다. 그래서 textfield에 문자를 미리 입력 한 후에 textWidth 값을 체크하여 어느 정도의 문자까지 입력 할수 있는지 확인하는 메소드를 만들어 보았습니다. 
function longStringDot(_field : TextField,_str:String, _width : int):int
{
      var  str_len:int;
      for(var i:int =0; i < _str.length; i++ ){
          _field.text = _str.substr(0,i);
          if(_field.textWidth > _width){
	str_len = i;			
	break;
          }				
      }					
      return (str_len == 0)? _str.length : str_len;			
}
보통 substring 을 이용하여 아래와 같이 코딩을 하지만,
var str:String = "";
var maxLen:int = 20;   // 문자열이 들어 가는 공간크기를 일일히 맞춰줘야 하는 번거로움이 있다.
var feild:TextField = new TextField();
if(str.length > maxLen)
	feild.text = str.substring(0,maxLen);
else
	feild.text = str;
var str:String = "";
var maxWidth:int = 100;     
var feild:TextField = new TextField();
feild.text = str;
if(feild.textWidth > maxWidth)
	feild.text = str.substring(0,longStringDot(feild,str,maxWidth));		
메소드의 파라미터로 TextField를 넘겨 주는 이유는 TextField가 가지고 있는 TextFormat에 따라 textWidth 값이 달라지기 때문 입니다. 요즘 들어 String을 처리 해야 하는 일이 많아 지네요. 좀 정리좀 해야 겠습니다.
Posted by Flash 동강
Actionscript3.02009.03.15 17:45
var money:Number = 100000000;
trace(numberToDot(money));
function numberToDot(num:Number):String { 
       var str:String= String(num);	// 숫자값을 받아서 String유형으로 변경한다. 
       var str_arr:Array = new Array();       
       for (var i:int = 0; i < str.length; i++) {        
        // str에 있는 문자값을 charAt을 이용하여 하나씩 불러온 뒤, 배열에 넣는다.    
        // i%3 이 0일때 마다 쉼표를 삽입하여 문자들을 3개씩 나눈다.    
              if ( i % 3 == 0 && i != 0) { 
                  str_arr[i]=str.charAt(str.length-1-i)+",";
               } else {        
                  str_arr[i]=str.charAt(str.length-1-i);     
               }
         }        // Array의 reverse 메소드를 이용하여 배열의 순서를 뒤집는다.        str_arr.reverse();        // 배열의 요소를 문자열로 반환 한다.      
         return str_arr.join("");
}

// 결과
100,000,000

 자주 사용하는 코드 이지만, 갑자기 다시 짜려고 하면 귀찮니즘이 몰려 오기 때문에 종종 코드를 찾는데 시간을 소비 하곤 합니다.  AS3.0으로 제작되어서 javascript에서는 쓰일수 없지만, Actionscript나 Javascript에서 공통으로 사용할 수 있는 라이브러리를 만드는 것도 재미 있을것 같네요.


 

Posted by Flash 동강
TAG AS3.0
Actionscript3.02009.02.06 01:14

문서 원본 : AdobeRIA 기술문서


작성된 날짜 : 2009-02
저자 : 강동혁
저자 소개 : Daum communications에서 UI 개발 업무를 하고 있으며, Flash 커뮤니티에서 ‘동강’ 이라는 닉네임으로 활동 중이다. 뭐든지 사용하기 편해야 한다는 생각으로 개발을 하고 있으며, RIA와 HCI에 관심이 많다. 

Blog : www.ddongkang.com

목차
1. 서론 : 왜 Actionscript 3.0 인가? 

2. 본론 : Actionscript3.0을 배워야 하는 이유
  - 향상된 연산속도                          
  - 보다 엄격한 디버깅 기능
  - 크로스 스크립팅
  - OOP를 위한 지원
  - Flashplatform의 언어
  - Flash API와 Display 및 Event

3. 결론 : 다음 편 예고


 Actionscript 3.0 사용해야만 하는가?

 Actionscript 3.0(이하 AS3.0) 소개되고, Flash CS3 나와서 우리에게 정식으로  모습을보여   2 가까이 되었다. 이미 웹에는 AS3.0으로 만든 많은 결과물이 우리의 욕구를 충족해 주고 있다. 웹뿐만 아니라 AIR 이용한 데스크톱 애플리케이션과  밖에 여러 디바이스에서 AS3.0 기술을 느낄  있다. AS3.0 소개되고 나서, 많은 개발자와 디자이너는 코드의 유연함과 AVM2 강력함을 직접 체험하고 더욱  멋진 결과물을 만들  있는 무기를갖게 되었다. 반면에, 여러 가지 이유가 있지만 AS3.0 배우기를 꺼리거나, 어려워하는 사람이 많이 있음을 커뮤니티에서 느낄  있었다. 그래서  기술 문서는 AS3.0으로 Flash 플랫폼 개발을 시작하고 싶거나, AS2.0 사용하고 있지만 AS3.0 배우기를 원하는 디자이너와 개발자를 대상으로 하고, AS2.0 비해 달라진 점과, 강력해진 점을 중점적으로 다루고 Flash CS4 AS3.0 이야기할 것이다.

 

-   AS3.0인가?

 

 커뮤니티에 많이 올라오는   이런 질문이 있다.

Flash 시작하려고 하는데, AS1.0부터 순서대로 공부해야 하나요?

 무수히 많은 댓글이 달리고, 댓글 대부분은 AS3.0으로 시작해도 무방하다는 의견이다. 물론 나도  의견에 전적으로 동의한다. 물론 AS1.0 AS3.0까지 순서대로 공부하면, Actionscript 원리를 습득하고, AS3.0 배우는 것이라  수월해지기는 하겠지만, 시간 투자에 비해 얻는 것은 적다. 그리고 AS1.0, 2.0 비해 AS3.0 달라진 개념이 많아 AS2.0 주로 사용하는 디자이너나 개발자가 AS3.0으로 넘어오지 못하는 이유가 되기도 한다. AS3.0 배우라고 권장하는 사람들은 Java 공부를 하라고 권유하기도 한다.  이유가 AS3.0 컴파일하는 AVM2 JVM(Java Virtual Machine) 기반으로 하기 때문에, 문법 면에서 아주 비슷하다. 더구나 많은 양질의 Java 서적을 시중에서 쉽게 구해   있으니, 아직 국내에 뚜렷하게 AS3.0 대한 기초 개념서가 나오지 않은 상태에는 Java 서적을 보는  현명한 선택일지도 모른다. 물론 Java 대해  안다면 필요 없는 일이다.

AVM

Actionscript Virtual Machine(액션스크립트 가상 머신) Flash player 포함된 Actionscript 만들어진 SWF 재생하는 엔진이다. Java 실행되려면 JVM 있어야 하듯, Actionscript Java 실행되는 원리와 같다. Flash player(AVM) 설치되어 있다면 어느 디바이스라도 SWF 실행할  있다.


    Actionscript
에는 버전이 있다. 다른 언어에도 분명 버전은 존재하지만, 다른 언어에서보다Actionscript에서  부분을 중요하게 봐야 하는 이유는, AS1.0 2.0 같은 런타임(AVM1)에서 실행되지만 AS3.0 AVM2에서 실행되기 때문이다. 또한 AS2.0에서 AS3.0으로 넘어오면서 완전 다른 언어라고 착각할 정도로 문법 구조에서 많은 부분이 바뀌었다. 그래서 AS1.02.0 배우지 않아도 AS3.0    있다. AS3.0 공개된   2년이 지났지만, 아직 많은 사람이 AS1.0 2.0 사용 중이고  상에는 AS1.0, 2.0 시절에 만들어진 SWF 비율이  높은 비율을 차지하고 있다. 하지만  추세는 금방 뒤집어질 정도의 차이다.


 AS3.0 연산 속도가 이전 버전에 비해 최대   빨라졌다는 평가를 받는다. AS1.0 2.0 프로그래머에게 외면 아닌 외면을 받았던 이유도 C Java 비해 연산이 느렸기 때문이다. 하지만 AS3.0 들어와서는  문제가 어느 정도 해소되었다. 속도뿐만 아니라 더욱 강력한 Flash API 기능을 가지고 있다. 하지만  아직까지 AS2.0 사용하는 것일까?  물음에 대한 다양한 이슈가 존재한다.


1.
       
Flash player 호환성에 따른 문제

많은 사용자가 이용하는 서비스는, 모든 사람에게 똑같이 보여야 한다는 점이 최우선고려사항이다. AS3.0 재생할  있는 Flash player 9 보급률이 이미 98% 넘었지만, 아직 Flash player 8 설치된 나머지를 위해 AS2.0으로 작업하는 경우가 있다. 간단한 코딩이나 모션 작업 같은 경우에는 AVM2 컴파일했을  약간의 이익을   있겠지만 익숙하지 않은 AS3.0 사용으로 작업 능률이 떨어질 수도 있다는  단점이다.  보급률 문제는 점점 많은 사람이 Flash player 9 이상을 설치함에 따라 빠르게 해결될  있는 문제다. 

그림1. Flash player 보급률

2.       AS3.0을 다룰 수 있는 사람 부족

AS3.0이 나오고 난 직후에는 Flash 프로젝트에 AS3.0을 도입하길 꺼려했다결과물이 나와도 유지 보수할 인력이 없다는 이유였다하지만 2년이 지난 후 상황은 점점 나아지고 있다여러 책과 커뮤니티 기술 문서 덕에 AS3.0을 사용하는 사람도 많이 늘어났으며덩달아 상당수 프로젝트가 AS3.0으로 진행되고 있다.


3.       AS3.0은 어렵다

AS3.0은 분명 이전 버전보다시작하기 어렵다하지만 원리를 익히고 나면 이전 버전에 비해 휠씬 편리함을 느낄 수 있을 것이다왜 어렵게 느껴질까간단하게 컴퓨터에 있는 부품을 비유해 보겠다. AS2.0까지 객체를 다루고 구현하는 방법은 주로 이미 만들어진 기능을 사용하는 방식이었다예를 들어 이미 만들어져 있는 사운드 카드를 컴퓨터에 설치하는 것처럼, AS2.0는 많은 기능을 손 쉽게 가져다 쓸 수 있었다하지만 AS2.0에서 사운드 카드 자체를 만들 수는 없었다. AS2.0의 기본 기능들을 사운드 카드라 비유했다면 AS3.0의 기본 기능들은 사운드 카드 안에 들어 있는 각각의 부품이다(저항이나다이오드 같은 사운드 카드를 구성하는 부품들). 각각의 부품들로 이미 만들어져 있는 것이 아니라(AS3.0에서 제공되는 Flash API에서는 휠씬 많은 기능을 구현하여 제공한다), 자신만의 독창적인 것을 만들 수 있다. AS3.0을 시작하기 어려운 이유가 바로 여기에 있다부품 종류가 너무 많아 다 외워야 할 것 같은 느낌이 들기 때문이다하지만 뭐든 처음 시작할 때 가장 고생하는 법이다조금만 인내하면서 원리를 파악해 보자그럼 AS3.0이 어느 순간 다르게 보일 것이다 

AS2.0 사용자가 AS3.0으로 넘어오지 못하는(필요성을 느끼지 않아 AS2.0을 사용하는 것은 제외가장 큰 이유는 자신이 잘 하는 AS2.0으로는 간단히 만들 수 있는데문법도 제대로 알지 못하는 AS3.0으로 구현하기가 답답하고 힘들어서일 것이다이 글을 쓰는 나 자신도, AS2.0을 주로 사용하다 AS3.0을 사용했을 때 답답함을 많이 느꼈기 때문에 그 마음을 잘 안다하지만 조금만 고생한다면 몇 종류 안 되는 만들어진 기능이 아니라,마음대로 조절할 수 있는 자신만의 기능을 만드는 즐거움과 더욱 강력해진 Flash API(이미 구현되어 있어서제공되는 객체들)를 직접 느낄 수 있을 것이다.


 AS3.0의 좋은 점을 설명한다고 해서, AS1.0 2.0이 나쁘다는 말은 아니다그 자체로 충분히 좋은 언어다. AS3.0에 비해 구조가 더 직관적이고 이해하기 쉽다는 장점을 가지고 있다세계적인 Flash 아티스트인 Koshua Davis나 Erik Natzke도 작업을 할 때 AS1.0 2.0을 사용한다고 한다그만큼 비교적 쉽고구현이 간편하다하지만 AS3.0은 이러한 AS2.0의 장점을 다 커버하고도 남을 만한 장점을 가지고 있다지금부터  AS3.0  써야만 하는가? 대해 구체적으로 이야기  보겠다.

 

-AS3.0을 배워야 하는 이유

AS3.0이 완성도 있는 스펙으로 나온 계기는 Adobe Macromedia를 인수하면서 유능한 개발자가 많이 Flash 개발에 투입되었기 때문일 것이다. Flash 8 AS2.0 기반의 향상된 언어 스펙으로 런칭되고곧 바로 Adobe 개발자들은 Flash 9에 대한 준비를 하면서 AVM1 스펙으로 갈 수 없다고 생각하였다고 한다. AVM1 스펙으로는 사용자들에게 만족할 만한 속도와 메모리 관리를 제공하지 못하기 때문이었다그리고 결과적으로 AVM2라는 높은 성능을 내는 가상 머신을 만든다.


1.      향상된 연산 속도

기존 Flash 사용자들이 AS3.0이 나오고 난 뒤 가장 기뻐했던 것은 AS3.0의 속도가 놀라울 정도로 향상되었단 소식을 들었기 때문이다. Adobe AS3.0 도움말에는 속도 향상을 다음과 같이 기술하고 있다.

While Actionscript3.0 is not required for content that runs in Adobe Flash Player 9, it allows performance improvements that are available only with the new Actionscript Virtual Machine. Actionscript3.0 code can execute up to ten times faster than legacy Actionscript code

AS3.0만을 가지고 있는 코드(외부 데이터를 가지고 있지 않는 경우)를 실행할 경우 이전 버전에 비해 열 배의 속도 향상이 된다. Flash CS4에서의 AS2.0 AS3.0의 연산속도 비교는 그림 2와 같다.


그림2.

 

그림3 Flash CS4에서의 AS2.0(AVM1)과 AS3.0(AVM2) 수행 시간

 그림 2, 3을 보아 알 수 있듯이 같은 코드를 실행하였을 때, Flash CS4에서 AS2.0 AS3.0은 엄청난 수행 시간 차이가 났다위의 예제를 수십 번 반복했을 때도 결과는 같게 나왔다또한 수행 시간 격차를 줄일 의도로 for문의 수행 횟수를 1000에서 100000으로 올려 보았다. AVM2(AS3.0)에서는 제대로 수행되었지만 AVM1(AS2.0)에서는 그림 4와 같은 경고 팝업 메시지가 떴다.

그림 4 연산이 많은 코드를 실행했을 때 나타나는 경고 메시지

물론 코드와 컴퓨터 상태에 따라 수행 시간 차이는 줄어 들 수 있겠지만, AVM2가 AVM1에 비해 월등히 빠른 속도를 낸다는 것은 의심한 여지가 없는 사실이다또한 AVM2의 향상된 기능을 사용하려면 AS3.0을 사용해야 한다이러한 차이는 AS3.0이 내부적으로 새로운 바이트 코드 명령어를 도입해 객체 추적 시스템 개선자료구조 시스템 개선 작업을 함으로써 가능해졌다.

 

-         객체 추적 시스템 개선

AS2.0에서는 prototype을 사용하여이미 정의되어 있는 MovieClip이나 기타 객체들에 속성 메서드를 추가할 수 있었다코드를 짤 때 아무 곳이나, prototype을 사용하면 뭐든 기존 객체에 메서드를 추가할 수 있어 편리했다하지만 이렇게 동적으로 객체를 정의하는 방법은 굉장히 비효율적이었다. Flash player prototype을 사용했기 때문에 컴파일할 때 알아야 하는 객체 정보를 다시 추적해야 하는 문제가 있었다또한 AVM1에서는 prototype을 사용하든사용하지 않든 모든 객체의 정보 추적을 위한 테이블을 만들어 놓기 때문에 상당한 메모리를 쓰고 수행 속도를 떨어뜨리는 요인이 되기도 하였다그래서 AVM2에서는 기본적인 객체 선언은 정적(뒤에 다루는 봉인 클래스를 참고)으로 하게 했고객체를 선언할 때 dynamic 키워드를 사용해 동적으로 객체를 조작할 수 있는 기능을 남겨 두었다하지만 dynamic 키워드를 사용하는 것은 성능을 저하시키는 요인이 될 수 있다.

 

-         객체의 타입 선언

위에서 언급했듯이 AS2.0에서는 객체가 동적으로 생성되었기 때문에 객체의 타입 유형(런타임 유형)을 선언할 필요가 없었다. AS3.0에서 객체가 정적으로 생각되는 방식으로 바뀜에 따라 런타임 유형을 선언해줘야만 하고이렇게 객체 타입을 선언해 객체의 정보를 AVM에 미리 알려주는 방식은 시스템의 유형 안전성을 높이고메모리를 좀 더 효율적으로 관리하는 데 도움이 된다(AS2.0의 경우 내부적으로동적으로 만들어진 객체의 추적을 위한 메모리 테이블이 필요하다).


2.      더 엄격한 디버깅 기능

 AS3.0에서는 이전 버전보다 엄격한 디버깅 기능 및 런타임 오류 상황을 알려 준다. AS2.0을 사용하면 런타임 오류 상황을 알려주지 않는 경우가 많아서 어떤 이유인지 모르고 SWF가 다운되어 버리거나 메모리가 새는 경우가 있었다하지만 AS3.0의 더 엄격한 디버깅 기능은 어디에서 어떤 오류가 발생했는지 자세히 알려주므로 프로그램의 완성도를 높이는 데 기여하고 있다그리고 Flash player 9부터는 Debug 버전의 Flash player가 제공되어 브라우저에서 실행되는 SWF 파일의 에러를 실시간으로 확인할 수 있다.            


3.      크로스 스크립팅

 크로스 스크립팅이란, A.swf B.swf가 있을 경우 A에서 B를 로드한 후(B A 객체의 자식 객체가 된다) A에서 B.swf 파일의 변수객체속성메서드에 접근할 수 있는 기능을 말한다. AS3.0에서 크로스 스크립팅이 가능해지고 난 후에야 비로소 Flash 프로그래밍의 디자인 부분과 개발 부분을 확실하게 나눠서 처리할 수 있는 기반이 만들어졌다. Flash 콘텐츠를 만들기 위해 디자이너들은 여러 가지 도구를 이용하여 나온 작업 소스를 Flash로 객체화한 후 B.swf라는 파일을 Flash 개발자에게 넘겨 준다디자이너가 넘겨준 B.swf에는 디자이너가 작업한 무수히 많은 객체가 Flash CS3부터 제공된 ‘Linkage’라는 기능을 통해 객체화되어 있다. B.swf를 받은 개발자들은 디자이너들이 만들어 놓은 시안과 네이밍(객체의 이름즉 클래스 이름이다)대로 작업을 하면 된다디자인이 바뀌면 개발자가 fla 파일을 넘겨 줘야 한다거나포토샵으로 만든 디자인 파일을 fla 파일에 임포트할 필요 없이디자이너가 수정한 B.swf를 넘겨 주면 된다개발자들은 Loader로 B.swf를 로드한 후에 약간의 보안 처리만 해 준다면 손 쉽게 디자이너가 만든 객체를 불러와 사용할 수 있다이렇게 각각의 역할을 확실하게 구분해 줄 수 있게 도움을 주는 기능이 크로스 스크립팅 이다또한 중복 데이터 등 라이브러리의 관리 소홀로 인한 SWF의 용량 문제를 피하는 방법이기도 하다또한 따로 작업한 SWF를 하나의 부모 SWF로 로드하여자식 객체처럼 사용할 수 있는 방법을 제공한다.


그림 5. 크로스 스크립팅

 4.      객체 지향 프로그래밍(OOP)을 위한 지원


-  봉인 클래스

 AS3.0을 처음 접한 Java 개발자는 즐거웠을 것이다. Java와 굉장히 구조가 비슷하기 때문이다혹자는 AS3.0에 와서야 비로소 프로그램 언어다운 모습을 갖췄다고 말한다그 이유는 객체 지향 프로그래밍을 위한 다양한 지원을 하기 때문이다우선 AS3.0에서는 봉인 클래스 개념이 도입되었다. MovieClip으로 모든 것을 처리했던 AS2.0에서는 MovieClip이 동적으로 생성되기 때문에 이를 위한 메모리가 추가로 필요했다하지만 봉인 클래스 개념이 도입되면서 dynamic 클래스로 지정하지 않는 한 속성과 메서드를 동적으로 추가할 수 없었다하지만 이 덕에 불필요한 수정에 대해 객체를 보호하고덩달아 메모리 효율을 높일 수 있게 되었다.

- override

  override란 상위 클래스를 상속 받은 하위 클래스에서 상위 클래스의 함수를 변경하여 사용하는 것을 말한다그림 6에서, Parent를 상속 받은 Child override를 이용해 Parent init() 메서드를 재정의하고 있다이렇게 상속에 의한 확장을 할 때에 override를 이용하여 코드의 유연성을 더해주고객체 지향 프로그래밍을 도와 주는 기능이 AS3.0부터 도입됐다. 




그림 6. override  쓰임


-         Package


AS3.0에서는 클래스를 package 안에 정의하여 package로 클래스 경로를 지정한다이 경로는 클래스를 import로 로드할 때 위치 값으로 참조된다. Package 안에는 한 개 이상의 클래스가 존재할 수 없지만 package 밖에는 package 안에 있는 클래스 외의 클래스가 존재할 수 있다하지만 package 밖에 정의된 클래스는 외부에서 접근이 불가능하다그러므로 이러한 특성을 이용해 Singleton(디자인 패턴)을 구현하기도 한다.



5.       Flash, Flex, AIR  모든 Flash 플랫폼의 언어

 AS3.0 Flash Flex 그리고 AIR뿐만 아니라 앞으로 나올 모든 Flash 플랫폼의 기본이 되는 언어가  것이다최소한  언어를 기반으로 하여새롭게 업그레이드되어  것이다언어하나를 배워서 서너 가지를 동시에   있다는 것은 Flash 처음 배우는 사람이나 전부터Flash 플랫폼을 접해 왔던 사람이나욕심이 가는 장점 중에 장점일 것이다.


6.      강력한 Flash API, 달라진 Display 시각 표현 방법 및 이벤트

 AS3.0으로 풀어 낼 수 있는 Flash player API는 정말 다양해졌고이러한 객체들을 화면에 보여 주는 기능을 관장하는 Display 시각표현 방법이 바뀌었다또한 이벤트 핸들링 방식도 더욱 많은 것을 표현하고 조작할 수 있게 바뀌었다이 새로운 기능에 대한 것은 다음 편에 더욱 자세히 다루겠다.


글을 마치면서

지금까지 AS3.0 어떤 점이 달라졌고 이전 버전에 비해 업그레이드된 스펙이 우리에게 영향을 미칠  있는 좋은 점을 중심으로 이야기해 보았다분명 AS3.0 AS2.0 길들어진 사람에게는  나라 언어처럼 보일지도 모른다특히 AS2.0 현란하게 구사 하는 사람일수록 AS3.0 써야 하는 필요성을  느낄 것이다하지만, Flash 도구가 간단한 애니메이션을 만들  있는 도구에서 애플리케이션을 구축할  있을 정도로 발전한 것처럼새로운 것을 익혀서 우리에게 돌아 오는 것은 스트레스가 아니라 좋은 작품과 무한한 상상력일 것이다.

다음 편에서는 AS2.0에서 AS3.0으로 버전이 올라가면서 어떤 점이 달라졌는지 구체적으로 살펴볼 것이다. AS2.0 사용하는 사람들이라면다음 편이 AS3.0 이해하는  도움이 많이  것이다.




Posted by Flash 동강
Actionscript3.02009.01.20 23:49

 커뮤니티의 질문들 중에서 단연 1위를 달리고 있는 "Actionscript 학습법" 에 대해, 오직 제 견해와 경험을 통해 작성해 보려고 합니다.

- Flash MX , Flash 8, Flash CS3, Flash CS4 먼놈의 버젼이 이렇게 많은 건지 많이 혼동 됩니다.
 
시중에 나와 있는 책들을 보면 벌써 CS4가 출시 되었음에도 불구 하고, MX 버젼과 그 이하 버젼의 책들을 종종 보게 됩니다. 당연히 Flash를 처음 시작 해야 겠다고, 다짐하고 서점에 간 분들은 혼동 될 수 밖에 없지요. 보통 액션 스크립트 책은 Flash 라는 제목을 작게 표기 하고 Actionscript를 크게 표기 하기 때문에(?) Flash 8 이라 크게 적혀 있는 책을 고르게 됩니다. 그리고 카페에 와서 물어 봅니다. " Flash 8 책 샀는데, 이걸로 공부 시작 해도 될까요? " 많은 분들이 처음 시작 할때 혼동이 많았을 거라 생각 됩니다. 

 
Flash MX : AS1.0 과 AS2.0 지원
Flash 8 : AS1.0 과 AS2.0 지원 , AS2.0의 스펙이 향상 되었습니다.

Flash CS3 : AS3.0 지원, AS1.0 및 2.0 으로 작업 할 수 있으나, AS3.0 과는 같이 사용할 수 없다.
Flash CS4 : AS3.0 지원, AS3.0의 스펙이 향상 되었습니다.
 

버젼 별로 제공 하고 있는 언어 스펙은 위와 같습니다. 책을 고를 떄는 CS3 이나 CS4 라고 써 있는 것이나, Actionscript3.0 이라고 써 있는 책을 골라야 합니다. 중요한 점은 AS2.0 과 AS3.0 은 완전 다른 문법을 가지고 있는 언어 라는 점 입니다. (비슷한 부분이 많이 존재 하지만 ) AS2.0 에서 업그레이드 한 언어라고 보기엔 Java 와 더 닮아 있는 언어 입니다. 

-무슨 버젼으로 공부를 시작 해야 되나요?
 
 현재 Flash 최신 버젼은 Flash CS4 입니다. 스크립트는 AS1.0, 2.0, 3.0 모두 지원 합니다. Flash는 배우고 싶은데, 어떤 툴 버젼으로 어떤 언어 버젼을 공부 해야 해야 할까요. 

 회사에서 흥쾌히 Flash CS4를 제공해 준다면 Flash CS4로 시작 하는 것이 좋습니다. 언어야 뭐든 다 지원을 하고 있고, 무엇보다 Flash player10 을 지원 하므로 해서 Flash CS4에서만 구현 할 수 있는 다양한 스펙들을 비교적 손 쉽게 사용이 가능 합니다. 여건이 안된다면 Flash CS3를 사용해도 무관 합니다. Flash CS4에 대한 문서 라든지 책이 부족하고, 거의 대부분이 Flash CS3 의 Actionscript3.0 스펙을 기본으로 하고 있기 때문에 Flash CS3후에 추가로 Flash CS4에서 제공 하는 기능을 배우면 됩니다. 
 
 어떤 버젼으로 시작 해야 할까요. 많은 입문자들이 가장 혼동을 일으키고 있는 부분 입니다. Actionscript면 똑같은 Actionscript라고 생각하고 아무 책이나 덜컥 샀다가는 후회 합니다. 
Actionscript는 현재 3.0 버젼 까지 나와 있습니다. AS1.0 , 2.0, 3.0 모두 기본적인 프로그래밍 문법을 따르고 있지만, AS1.0 . 2.0 과 AS3.0 은 큰 차이가 있습니다. AS1.0 과 AS2.0 은 하나의 fla 에서 두 버젼을 동시에 사용가능 합니다. 하지만 AS3.0은 오직 AS3.0 단일로만 사용 가능 합니다. 그 이유는 Actionscript Virtual machine 이라 불리는 엔진이 다르기 때문입니다. AS1.0, 2.0 은 AVM1 을 사용하고 AS3.0 은 AVM2 를 사용 합니다. 

 어떤 언어가 좋다고는 견해 차이가 많지만, 분명한 것은 AS3.0 이 AS1.0,2.0 으로 구현한 것에 비해 훨씬 빠르다는 것 입니다. Actionscript3.0 설명서에서는 순수하게 Actionscript만 실행 시켰을때 AS3.0이 이전 버젼보다 최대 10배 빠른 연산 속도를 가진다고 합니다. 또한 AS3.0 은 Flash CS3 와 CS4 에서만 쓰이는 언어가 아닙니다. 현재 Flex 3, AIR 등에서도 같은 언어 스펙을 가지고 사용 되고 있으며 앞으로 나올 모든 Flash playform에서 쓰이는 언어들은 모두 AS3.0을 기반으로 하여 만들어 질 것 입니다. 하지만, 비교적 스크립트를 공부 하는 초기에 어렵게 느껴지는 부분이 존재 합니다. 하지만 그걸 극복 하면 쉽고, 더 많은 것을 구현하고 만들 수 있는 언어가 AS3.0 입니다.


- Actionscript 를 공부 하려고 하는데 무엇 부터 해야 하나요?
 
많은 분들이 AS3.0, 을 공부 하면서 고생을 많이 하셨을 꺼라 생각 됩니다. 저 또한 AS2.0 을 하다가 AS3.0이 나오고 왕성한 배움에 욕구로 무작정 달려들었지만 완전 "GG" 를 친 적이 하루 이틀이 아니었습니다. 그럼 무엇 부터 해야 하나, 저는 이렇게 하였습니다. 

 
1. Flash CS3 나 CS4 관련 무작정 따라 하기 책을 보고, Flash 툴을 무작정 따라해 보세요. Actionscript를 배우고 싶다고 해서 Flash 와 Actionscript를 따로 쓰는건 아닙니다. 어쩔 때는 툴로 해결 해야 하는 부분도 있고 스크립트로 해결 해야 하는 부분도 있기 때문에 툴에 대한 이해는 필수 입니다. 감이 않오는 분은 2권 3권 계속 따라해 보세요. 
 

2. 툴에 대한 충분히 되었다고 생각 되면 인터넷을 활용하여 AS3.0 에 대한 공부를 시작해 보세요. 인터넷에는 좋은 분들이 아주 쉽게(?) AS3.0 에 대한 강의를 진행 하고 있습니다. 
3. 위의 3 강좌들의 모두 보았고, 이해 했을 정도라면 AS의 기초는 되는 수준이 되었을 것 입니다. 이때 책을 구입 하세요. 책은 언노운님이 친절하게 리뷰를 해 놓으셨으니 참고 하세요. 
Actionscript 책 추천

동강의 AS3.0 기초 강좌
- 쎈님의 Actionscript 강좌 모음 
- 윤훈남님의 AS 동영상 강좌

 

 전 Essential Actionscript3.0 과 Actionscript3.0 Cookbook , 그리고 새롭게 시작하는 플래시 CS3 Actionscript3.0을 추천 합니다. 앞의 두 책은 Flash 를 하는 동안 계속 봐야 할 정도로 방대한 내용을 다루고 있습니다. 그리고 새롭게 시작하는 플래시 CS3 Actionscript3.0 로 그동안 인터넷 강좌로 봤던 개념을 리뷰 하세요. 전체적인 틀을 잡기 딱 좋은 책 입니다. 책은 보는 동안 모르는 부분이 생길 수 밖에 없습니다. 그럴때 마다 Flash 단축키 F1 을 눌러 설명서를 틈틈히 확인 하세요. F1은 없는게 없을 정도로 Actionscript에 대한 모든것을 설명 하고 있습니다. 그리고 검색을 생활화 하세요.

 

4. 책까지 봤겠다. 이제 무서울게 없는 이론을 갖췄다고, 착각의 늪에 빠져 있을 것 입니다. 하지만 지금 부터가 시작 입니다. 지금 까지의 강좌나 책은 혼자서 공부 할 수 있는 체력을 갖게 해 준 것 입니다. 이제 자신만의 프로젝트를 계획해 보세요. 그리고 시작 하세요. 그리고 삽질 하세요. 시행 착오를 겪고, 혼자 힘으로 생각해서 만들고, 시행 착오를 하면 할 수록 실력은 급격히 상승 하는 것을 느낄 수 있을 것 입니다. 그리고 항상 F1 을 살펴보는 습관을 가지세요.

 

Actionscript3.0 은 어렵다고들 많은 분들이 말 합니다. 하지만 어려운 만큼 재미 있습니다. 제가 AS3.0 을 공부 했던 방법이 정답은 아니지만, 새롭게 Flash를 시작하시는 분들이 더욱 많아 졌으면 하는 바람 입니다.

 
 

posted by 동강


  

Posted by Flash 동강
Actionscript3.02008.12.15 02:02



윤훈남님의 AS3.0 동영상 강좌


Content  


Chapter 01.플래시 액션 스크립트 3.0의 개요[1:10분]  


Chapter 02.액션 스크립트 3.0 기초 문법[36분]  


Chapter 03. 데이터를 저장할수 있는 공간 생성과 선언[47분]  


Chapter 04.05 반복문과 조건문[49분]  


Chapter 06. 명령들의 그룹, 함수[1:12분]  


Chapter 07. 계산을 위한 명령, 연산자[22분]  


Chapter 08.OOP 문법-데이터 형 정의 문법[1:13분]  


Chapter 08.OOP 문법-은닉성[1:03분]  


Chapter 08.OOP 문법-상속성 및 다형성[1:02분]  


Chapter 09.Display Object-DisplayObject 클래스 이해[1:03분]  


Chapter 09.Display Object-InteractiveObject 클래스 이해[39분]  


Chapter 09.Display Object-DisplayObjectContainer 클래스 이해[47분]  


Chapter 09.Display Object-Sprite와 MovieClip, Loader, Stage클래스[1:00분]  


Chapter 09. DisplayObject 관련 샘플 3개[1:17분]  


Chapter 10. 이벤트 모델1[50분]  

Chapter 10. 이벤트 모델2[1:10분]  


Chapter 10. 이벤트 모델3[43분]  


Chapter 10. 이벤트 모델4-이벤트 객체 처리 과정(중요!!)[33분]  


Chapter 10. 이벤트 모델5[55분]  


Chapter 11. Flash Security[1:05분]  


Chapter 12. XML 1- 개요[1:05분]  


Chapter 12. XML 2- E4X[1:12분]  


Chapter 12. XML 3- 클래스[44분]  


Chapter 13. Video 이해 1 - DirectShow[49분]  


Chapter 13. Video 이해 2 - Video,Camera,NetStream 클래스[27분]  

Chapter 13. Video 이해 3 - Cuepoint, MetaData[18분]  


Chapter 13. Video 이해 4 - Microphone[26분]  


Chapter 13. Video 이해 5 - Camera[20분]

 


 

 


Posted by Flash 동강
Mashup.OpenAPI2008.12.11 16:27

작년 매쉬업 대회 준비하면서 올린 파일인데, 오랜만에 보니 새롭게 느껴 지네요. 곧 매쉬업 대회 일정도 시작할것 같은데, Flash 로 매쉬업을 준비하시는 분들은 참고 하시기 바랍니다.   

오픈 API란 무엇인가요?

오픈 API(OpenAPI)란 자사의 API를 외부에 공개한 것으로 일반적으로 웹 서비스(Web Services)형태로 공개한 것을 말합니다. 위키피디어에서는 API를 "응용 프로그램에서 사용할 수 있도록 운영 체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있도록 만든 인터페이스"로 정의하고 있습니다.

즉, 원래는 운영체제나 언어가 제공하는 기능을 제어할 수 있는 인터페이스였으나 이를 웹서비스에서는 특정 서비스를 이용할 수 있는 인터페이스를 API라 지칭하였습니다. 또한 이것을 외부에서 사용할 수 있도록 공개한것이 오픈 API며, 웹 서비스의 개방지향적인 성격을 잘 나타내고 있습니다. 일반적으로 오픈 서비스 API, 웹 서비스 API등의 용어와 혼용하여 비슷한 의미로 사용되고 있습니다.  

이런 것이지요? ㅎㅎ 대표적으로 한국에서는 다음, 네이버, 옥션, 야후 등이 서비스를 하고 있습니다.  

 
  1. package yahweh.openapi
  2. {
  3.         import flash.system.System;
  4.         import flash.display.*;
  5.         import flash.events.*;
  6.         import flash.net.*;
  7.         import flash.xml.*;
  8.        
  9.                
  10.         public class ImageLoader extends EventDispatcher{
  11.                 private var mInfo:Object;// OpenAPI 를 쓰기 위한 준비 내용이 들어 있다.
  12.                 private var xmlInfo:Object;
  13.                 public var outXMLdata:XML;
  14.                        
  15.                 // constructor
  16.                 public function ImageLoader():void {// 초기화 시킨다.
  17.                                        
  18.                         mInfo={apiURL:"http://openapi.naver.com/search?target=image",
  19.                                         apiKey:"",          // 자신의 네이버 APIKEY 를 입력
  20.                                         query:"",
  21.                                         displayNum:10};
  22.                        
  23.                 }
  24.                
  25.                 // main function
  26.                 public function main_loadPage(_page:Number,_query:String):void {// 메인 페이지가 로드 될때 불러와 진다.
  27.                         var page = _page + 1;
  28.                         api_load(_query,page,mInfo.displayNum);
  29.  
  30.                 }
  31.                
  32.                 // API load function
  33.                 private function api_load(_query:String,_page:Number,_displayNum:Number):void {
  34.                         System.useCodePage = false;
  35.                         var page = _page*_displayNum;
  36.                         var loader:URLLoader=new URLLoader  ;
  37.                         loader.addEventListener(Event.COMPLETE,api_loadComplete);
  38.                         loader.addEventListener(IOErrorEvent.IO_ERROR,api_loadError);
  39.                         var requestURL=mInfo.apiURL + "&key=" + mInfo.apiKey + "&query=" +encodeURI(_query) + "&start=" + page + "&display=" + _displayNum;
  40.                         trace("requestURL = " + requestURL);
  41.                         var request:URLRequest=new URLRequest(requestURL);
  42.                         loader.load(request);
  43.                         //
  44.  
  45.                 }
  46.                 private function api_loadComplete(event:Event):void {
  47.                        
  48.                         trace("api load complete");
  49.                         var loader:URLLoader=URLLoader(event.target);
  50.                         var dataXML=new XML(loader.data);
  51.                         outXMLdata = dataXML;
  52.                         trace(dataXML);
  53.                         dispatchEvent(new Event(Event.COMPLETE));
  54.                         // 컨테이너에 연결 시킨다.
  55.                        
  56.                 }
  57.                 private function api_loadError(error:IOErrorEvent):void {
  58.                         trace("api load error");
  59.                                                
  60.                 }
  61.                                
  62.         }// End Class
  63. }

 

쿼리를 날리는 as 파일입니다. 제 api 키가 들어 있으니;; 무한 실행은 하지 마시고요;;

swf 를 올리니깐 인터넷상이라 그런지 이미지가 실시간으로 안불러와 지더군요. 소스 올릴테니 참고하세요. 

Posted by Flash 동강
Flash platform2008.12.11 16:07



Snapshot Explorer (click to launch)  

위의 예제에 대한 기술문서 링크

Posted by Flash 동강
Actionscript3.02008.12.11 15:44

Actionscript3.0 에서의 이중 배열을 만드는 방법은 여러가지가 있지만 전 이렇게 사용합니다. 

  1. var parent_arr:Array =new Array();
  2. var sub_arr1:Array = new Array();
  3. sub_arr1 = ["sub_1","sub_2","sub_3","sub_4","sub_5"];
  4.  
  5. var sub_arr2:Array = new Array();
  6. sub_arr2 = ["sub2_1","sub2_2","sub2_3","sub2_4","sub2_5"];
  7.  
  8. parent_arr = [sub_arr1,sub_arr2];
  9.  
  10. trace(parent_arr[0][0]);
  11. trace(parent_arr[0][1]);
  12. trace(parent_arr[0][2]);
  13. trace(parent_arr[0][3]);
  14. trace(parent_arr[0][4]);
  15. trace(parent_arr[1][0]);
  16. trace(parent_arr[1][1]);
  17. trace(parent_arr[1][2]);
  18. trace(parent_arr[1][3]);
  19.  
  20.   

parent_arr = [sub_arr1,sub_arr2]; 대신 아래 처럼 사용해도 됩니다.  

parent_arr.push(sub_arr1);

parent_arr.push(sub_arr2);  

이런식으로 사용하면 이중 배열 뿐아니라,  3,4중 배열도 가능하지 않을가요? 

그래서 해 봤습니다.. ㅎㅎ  

  1. var parent_arr:Array =new Array();
  2. var sub_arr1:Array = new Array();
  3. sub_arr1 = ["sub_1","sub_2","sub_3","sub_4","sub_5"];
  4.  
  5. var sub_arr2:Array = new Array();
  6. sub_arr2 = ["sub2_1","sub2_2","sub2_3","sub2_4","sub2_5"];
  7.  
  8. parent_arr = [sub_arr1,sub_arr2];
  9.  
  10. var sub_sub_arr:Array = new Array();
  11. sub_sub_arr = ["test0","test1"];
  12. //sub_arr1 의 5번째로 들어가게 됩니다.
  13. sub_arr1.push(sub_sub_arr);
  14. trace("sub_arr1[5] : "+sub_arr1[5]);
  15. trace("parent_arr[0][5][0] : "+parent_arr[0][5][0]);

이런식으로 하면 계속 몇차원이고 늘릴수 있을것 같습니다. 활용도는 떨어지겠지만..

이중 배열을 만드는 가장 간단한 방법은  

  1. var simple_arr:Array = new Array();
  2. simple_arr = [["0.0","0.1","0.2","0.3"],["1.0","1.1","1.2","1.3"]];
  3. trace(simple_arr[0][0]);
  4. trace(simple_arr[0][1]);
  5. trace(simple_arr[0][2]);
  6. trace(simple_arr[0][3]);
  7. trace(simple_arr[0][0]);
  8. trace(simple_arr[0][1]);
  9. trace(simple_arr[0][2]);
  10. trace(simple_arr[0][3]);

인거 같습니다. 보통 다른 언어에서는 [{},{}] 이렇게 쓰이곤 하는데 AS3.0 에서는 Syntax error가 발생하네요. 그래서 안되는 구나 했는데 쌩둥맞게 [[],[]] 로 하니깐 되네요.. 정말 없어서는 안될 Array 인거 같습니다. 

Posted by Flash 동강
TAG array, AS3.0
Flash platform2008.12.11 15:21

Flex 에서는 기본적으로 component 옵션으로 tooltip 을 제공 하고 있지만, Flash 에서 툴팁을 만들어 쓰기란 여간 귀찬은

작업이 아닐수 없습니다. 그래서 Flash 기반의 쓸만한 tooltip 을 소개해 봅니다.

 

ToolTip.as

static 메소드로 이루어져 있는 하나의 툴팁 클래스로 스테이지나 오브젝트에 생성되는 모든 tooltip 들을 관리 합니다. 사용법은 간단합니다. 우선 사용 예제 부터 보시면 아래와 같습니다. 해당 target 에 대한 MouseEvent.MOUSE_OVER 만으로 이벤트를 처리 하게 됩니다.

Out 이벤트를 따로 처리할 필요가 없이 단지 Over 이벤트만 처리 하면 됩니다.


 

사용시 두단계를 거쳐야 합니다. 우선 첨부한 ToolTip.as 파일을 import 한 후에,

Tooltip 설명을 사용할 target 에 이벤트 리스너를 추가 합니다. ( tc_mc 를 target 으로 정했습니다.)

 

 

  1. import src.util.ToolTip;
  2. var toolTipAlign:String = "center";
  3. var toolTipAlpha:Number = .85;
  4. var toolTipDelay:int = 200;
  5.  
  6.  
  7. tp_mc.addEventListener(MouseEvent.MOUSE_OVER, Overhandler);

  8. ToolTip.init(stage,{text_align:toolTipAlign, opacity:toolTipAlpha, default_delay:toolTipDelay});  // Tooltip 초기화
  9. ToolTip.attach(evt.target, "")
  10. function Overhandler(evt:MouseEvent):void
  11. {
  12.          ToolTip.init(stage,{text_align:toolTipAlign, opacity:toolTipAlpha, default_delay:toolTipDelay});
  13.         ToolTip.attach(evt.target, "this is a sample");
  14.  
  15. }



1. ToolTip.init(툴팁의부모:stage,{text_align: 정렬값 , opacity:알바값, default_deday:툴팁이나타나는시간});

툴집을 위한 초기 값을 설정 합니다. 툴팁의 부모에는 툴집을 어디에 속하게 할 것인지 정하고(stage:Stage) 를 주로 사용합니다.

 

2. ToolTip.attach(툴팁을적용시킬target(tp_mc) ,"툴팁 설명" );

 

더 유동적으로 사용하고 싶은 분들은 소스를 훑어 보시면 될것 같습니다. 그리고 툴팁이 표시 되는 네모 상자가 마음에 안든다 하시는

분들도 reset_bg 메소드에서 그리고 있는 bg:Shape 를 자신이 라이브러리에서 만든 무비클립으로 Linkage 시켜 주던가,

graphics 클래스를 이용해서 좀 더 이쁘게 꾸밀수 있습니다.

테스트를 해 보니 몇가지 버그가 있어서 수정 합니다. 초기에 Mouse Over 했을때 Tooltip 이 발생안하는 것은 Tooltip 자체가 초기화가 안되어 있어서 (오브젝트를 Tooltip 으로 넘기고 바로 addEventListener 로 이벤트들을 걸어 주기 때문에 이벤트 발생 순서 상에 문제가 발생하게 됩니다. 그래서 강제로 초기화를 해 줘야 하는데 방법은 간단합니다.

위와 같이 Over 이벤트를 밖에 초기화 코드를 입력해 주시면 됩니다.


Posted by Flash 동강
Actionscript3.02008.12.11 15:20

embededFonts 를 사용한 TextField , TextArea , TextInput  폰트 관리 하는 방법 입니다.  

 
  1. var hyfont:Font = new HYKANG();            // 할 필요 없음
  2.  
  3. var format:TextFormat = new TextFormat();
  4. format.font = hyfont.fontName;                 // format.font = "폰트이름"; 으로 대체 가능
  5. format.bold = true;
  6. format.size = 15;
  7.  
  8. atxt.text = "플래시 액션스크립트 카페, 정기 스터디 모임, 우왕 굿";       // TextArea
  9. atxt.setStyle("antiAliasType", AntiAliasType.ADVANCED);
  10. atxt.setStyle("embedFonts", true);
  11. atxt.setStyle("textFormat",format);
  12.  
  13. itxt.text = "플래시 액션스크립트 카페, 정기 스터디 모임, 우왕 굿";       // TextInput
  14. itxt.setStyle("antiAliasType", AntiAliasType.ADVANCED);
  15. itxt.setStyle("embedFonts", true);
  16. itxt.setStyle("textFormat",format);
  17.  
  18. dtxt.text = "플래시액션스크립트 카페, 정기 스터디 모임, 우왕 굿";       // TextField
  19. dtxt.antiAliasType = AntiAliasType.ADVANCED;
  20. dtxt.embedFonts = true;
  21. dtxt.setTextFormat(format);
  22.  

 

보통 한글 폰트를 embed 없이 사용하면 깨짐 현상이 발생하는데 그 현상을 없애주는 방법 입니다. 

라이브러리 - > New Font - >

Name : 자신이 확인가능한 이름

Fonts : embed 하고 싶은 폰트  

이렇게 라이브 러리에 새로운 폰트를 만든후에 그 해당 폰트를 적용 시켜 주면 깨짐이 없이 컴파일이 됨니다.

Properties 창에 있는 Embed... 버튼으로 적용해 줄수 있지만, 동적으로 TextField 나 TextArea , TextInput 을 생성했을때는 위와 같은 방법으로 사용하여야 합니다.  

Posted by Flash 동강