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의 이해
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 를 통해 객체를 생성하여 사용 합니다.
잘못된 내용이나 개발 중 고민하고 있는 부분들은 댓글을 통해 공유 주세요~
'Actionscript3.0' 카테고리의 다른 글
Flash Platform에서 OAuth 사용하여 인증 (0) | 2012.01.08 |
---|---|
[AS3] Flash 로 오디오 플레이어 만들기 (4) | 2011.03.05 |
[AS3] TLF( Text Layout Framework ) 사용시 FlashVars 접근 문제 (2) | 2011.02.18 |