최근에 AIR 애플리케이션을 개발하면서 publisher ID이 누락되는 문제에 대한 글을 적은 적이 있었다.

Adobe AIR 애플리케이션 배포후 publisher ID 파일이 누락되는 문제

나는 이 문제를 단순히 설정이 틀어진다던가 버그라고만 생각했다. AIR 1.5 라이브 문서를 보면 다음과 같이 명백하게 밝히고 있다.

As of AIR 1.5.3, publisher IDs are deprecated. New applications (originally published with AIR 1.5.3 or later) do not need and should not specify a publisher ID.


AIR 1.5.3 릴리즈 노트를 살펴보면 PublisherID문제를 해결하기 위해 기존 버전의 AIR에서 어떻게 AIR 1.5.3으로 마이그레이션을 할 수 있을까 적어두었다.

Changes in AIR 1.5.3 

정리하자면 이렇다. AIR 1.5.3으로 처음 애플리케이션을 개발하는 사람은 그대로 개발하면 된다. 어짜피 AIR 애플리케이션이 배포되고 그 상태에서 업데이트 하는데는 문제가 없기 때문이다. 하지만 PublisherID가 필요한 경우가 있거나(그런 경우는 없는게 좋다) 기존 버전을 AIR 1.5.3으로 갈아타고 싶을 때는 AIR의 디스크립터 파일에 <publisherID></publisherID>를 삽입하여 컴파일 해줘서 기존버전과의 호환을 유지할 수 있게 된다. 이는 AIR 1.5.3 뿐 아니라 앞으로 배포될 AIR 2.0에도 해당하는 것으로 보인다.

아마도 이렇게 된데에는 중간에 인증서(certificate) 관련 파일이 변경되더라도 애플리케이션 배포에 문제가 없도록 한다는 취지가 있는 것이 아닐까 판단한다. 가령, 자기발급인증서 사용하다가 공인인증서로 바꿔도 배포에 문제가 없게 된 것이다. 그 반대의 경우도 마찬가지이고. 그렇다면 오히려 더 좋은거 아닌가?

이 AIR 애플리케이션이 고유하다는 것을 명시적으로 알려주는 것은 Publisher ID와 Application ID 였는데... 이제부터 그 고유성은 Publisher ID는 선택사항이고 Application ID가 증명해주게 되었다. 이렇게 되면 다른 사람이 제작한 Application ID가 중복되는 경우도 있는데... 그런 경우에는 com.jidolstar.air.myapp 형태로 해주면 어느정도 중복을 방지할 수 있다. 하지만 완벽히 피해갈 수는 없게 되었다.

앞으로 AIR 애플리케이션을 개발할 때 꼭 참고하자.

문제를 발견해주시고 알려주신 leigh님께 감사한다.

참고글
AIR: Migrating Expired Certificates using AIR 1.5.3
Changes in AIR 1.5.3
Packaging an AIR installation file using the AIR Developer Tool (ADT)

글쓴이 : 지돌스타(http://blog.jidolstar.com/655)




지난 22일에 Adobe Labs에서 Adobe Stratus 2에 대한 소개가 있었습니다.

http://labs.adobe.com/technologies/stratus/

Stratus는 RTMFP(Real Time Message FlowProtocal)이라 불리우는 통신프로토콜을 이용해 Flash Player 10이 설치된 클라이언트 까지 P2P(Peer to Peer)가 가능하게한 기술입니다. TCP가 아닌 UDP기반으로 동작하고요.

이번 Stratus 2는 Adobe Flash Player 10.1 beta, Adobe AIR 2 Beta에서 동작하도록 만들어졌습니다. 재미있게도 이번 버전에서는 애플리케이션 수준에서 멀티케스트와 소스 공급자의 로드를 줄여주는 구조를 지원하게 되었습니다. 맨 위의 그림에서 좌측 그림은 기존 Flash Player끼리 통신하기 위해 서버를 항상 거쳐야만 했었습니다. 서버입장에서는 완전 부담이죠. 그런데 중간 그림에서 볼 수 있듯이 Stratus가 나오면서 서버와는 한번의 접속으로 하고 Flash Player끼리 통신이 되었습니다. 이것도 소스 공급자인 Flash Player 입장에서는 로드가 심할 수 있습니다. 이를 Flash Player 단위에서 분산시키도록 한 것이 이번 배포의 핵심인 것 같네요.

물론 Stratus 2는 아직 베타버전인 Flash Player 10.1과 AIR 2.0에서만 동작하므로 바로 실무에 사용할 수는 없습니다. 그러나 조만간 이 기술을 사용할 수 있게 되겠죠.

Stratus 1.0에 대한 많은 실험이 국내에도 있었습니다. 저도 조금 테스트 해봤었고요.
http://blog.jidolstar.com/498 

다른 분들의 글들입니다.
플래시 P2P RTMFP에 대해(예제 파일 첨부)
[Flex] Stratus를 이용한 P2P방식의 Flash간에 1:1 다이다이 오목게임-_-
Flash로 p2p를 만들어보자 - Stratus 라이브러리
Flash로 채팅을 구현해보자.


하지만 방화벽, 공유기를 통해 접근 문제가 해결되었는지는 미지수네요.(테스트 안해봤음)
이 문제만 해결되면 정말 멋진 애플리케이션이 많이 나올거라 생각됩니다. ^^

글쓴이: 지돌스타(http://blog.jidolstar.com/651)




지난 2009년 11월 어도비(Adobe)에서는 AIR 2.0 Beta를 새롭게 발표하면서 퍼포먼스 향상과 더 많은 OS의 자원을 사용할 수 있는 API 기능을 추가해서 발표했다. Flash Player 10.1 Prerelease와 함께 발표된 Adobe AIR 2.0의 새로운 기능 및 추가/개선 사항에 대해서 정리해보았다.

참고로 이 글은 Elad Elrom의 AIR 2 Enhancements Complete Overview  와 AIR 2 Rerelease Note를 참고해서 정리한 것이다.




  1. 새로운 기능 (이번 페이지에서 다룸)
    - File Promises
    - Screen reader
    - Native Processes
    - New networking support
    - Global Error Handling
    - Packaging an AIR application in a native installer
  2. 기존 API에 대한 추가된 기능 (다음 편에 다룸)
    - Max Size of NativeWindow
    - Idle time-out
    - Mac Vector Printing
    - Database Transaction Savepoints
    - Microphone Access API
    - Open file with Default Application
  3. 플랫폼 인식 관련 API (다음 편에 다룸)
    - Multi-touch functionality
    - Mass Storage Device Detection
  4. 퍼포먼스 향상 (다음 편에 다룸)


출처 : http://tinyurl.com/ydxevnu




Flash Builder 4 beta 2에서 Adobe AIR 2.0로 개발 환경 만들기 

여기에서 보여지는 예제는 모두 Flash Builder 4 beta 2에 기본으로 설치된 Flex 4 SDK를 이용한다. 하지만 AIR 2.0로 테스트해보기 위해서는 AIR 2.0 SDK를 따로 받아 다음과 같은 과정이 필요하다.

Windows 환경이라면 다음과 같이 하면 되겠다.

  • 만약 Flash Builder를 설치 안했다면 다음 링크를 통해 받는다.
    1. AIR 2.0 SDK와 Runtime을 다운로드 받는다.
    2. 다운받은 Runtime을 실행해 설치한다.
    3. Flash builder가 설치된 sdks/4.0.0과 sdks/3.4.1 폴더를 복사해서 sdks 폴더안에 붙인뒤 4.0.0_AIR2.0, 3.4.1_AIR2.0을 만든다. 이렇게 되면 sdks 폴더안에는 3.4.1, 4.0.0, 3.4.1_AIR2.0, 4.0.0_AIR2.0 이름을 가진 4개의 SDK가 만들어진다.
      본인의 경우는 C:/Program Files/Adobe/Adobe Flash Builder Plug-in Beta 2/sdks 내에 있다. 
    4. AIR 2.0 SDK는 압축을 풀고 그안에 있는 내용을 방금 만든 4.0.0_AIR2.0, 3.4.1_AIR2.0 폴더에 복사한다.
    5. Flash Builder를 실행한다.
    6. 메뉴에서 Window > Preference 로 들어간다.
    7. 창이 뜨면 왼쪽 메뉴에서 Flash builder > Installed Flex SDKs를 선택한다.
    8. 우측에 Add버튼을 눌러 위에서 새로 만든 AIR 2.0을 위한 SDKs들을 선택한다.  
      Flex SDK Name은 각각 Flex 3.4 AIR 2.0, Flex 4.0 AIR 2.0 등으로 이름을 바꿔도 된다.
      본인의 경우 아래 경로가 되겠다.
      C:/Program Files/Adobe/Adobe Flash Builder Plug-in Beta 2/sdks/3.4.1_AIR2.0/
      C:/Program Files/Adobe/Adobe Flash Builder Plug-in Beta 2/sdks/4.0.0_AIR2.0/
      아래처럼 Flex 4.0으로 체크되어 있다면 AIR 2.0기반의 Flex 4.0 SDK를 디폴트로 바꾸자.
    9. 이제 모든 개발환경이 완료되었다. 자신의 프로젝트 생성시에 원하는 SDK를 선택하면 되겠다.  물론 아래에서 소개하는 예시를 따르려면 Flex 3든 Flex 4든 AIR 2.0 SDK를 선택해야겠다.


    Mac 환경이라면 다음과 같이 하면 되겠다.

    Mac에서 AIR 2.0 Beta 개발환경 만들기 - Flash Builder 4 Beta 2 기반

    참고로 Flash CS4나 CS3, 드림위버나 기타 다른 IDE에서 개발하시는 분들에게는 본인의 경험이 없어 정보를 줄 수 없다.

  •  
    1. Adobe AIR 2.0 새로운 기능

    1.1 IPv6 지원
    AIR 2.0은 모든 Network API에 대해서 IPv6를 지원하게 되었다. 현재 인터넷에서 주로 사용하고 있는 IP 주소의 버전은 IPv4로서 무려 20년이 넘도록 사용하고 있다. IPv4는 32비트 주소체계를 가지며 4,294,967,296개의 제한된 갯수의 주소를 가진다. IPv6는 이 부족함을 해소하기 위해 만들어진 IP 주소 체계이다. IPv6는 128비트 주소체계를 가진다. IPv6가 일반적으로 사용되고 있는 것은 아니지만  가까운 미래에 IPv6가 범용적으로 도입되어 네트워크 IP 주소체계가 더욱 확장될 수 있으므로 미리 지원될 수 있도록 한 것으로 여겨진다. IPv6에 대한 자세한 내용은 아래 링크를 참고한다.




    1.2  UDP(User Datagram Protocol) 소켓, Server 소켓, TLS/SSL 소켓 지원
    AIR 2.0에서는 더욱 다양한 소켓 통신 관련 클래스들이 추가되었다. 이전버전까지 반쪽짜리 였다면 이제 어느정도 구색을 갖춘듯 하다. 

    AIR 2.0에서 지원하는 네트워크에 관련된 내용은 다음 링크를 참고한다.


    서버 소켓 : ServerSocket 클래스 
    기존 AIR 버전에서는 반쪽 소켓통신만 지원되었다. 즉, 클라이언트는 만들 수 있었지만 서버측을 만들지 못했다. 이번 AIR 2.0에서 서버 소켓이 지원됨에 따라 이를 이용한 다양한 네트워크 애플리케이션을 만들 수 있을 것으로 보인다.

    서버 소켓은 TCP(Transmissin Control Protocal)을 기반으로 한다. TCP는 연결지향 통신 규약으로 인터넷 상의 컴퓨터들 사이에 데이터를 통신하기 위해 IP와 함께 사용된다. TCP는 데이터의 통신 중간에 데이터가 유실되더라도 신뢰도를  체크해서 완벽한 데이터를 통신할 수 있는 신뢰형 기반의 데이터 통신시 사용된다. 일반적인 웹브라우져를 이용한 통신데이터는 모두 TCP를 근간으로 한다.



    AIR 2.0에서 지원하는 서버 Socket는 ServerSocket 클래스에서 관장한다.



    UDP 소켓 : DatagramSocket 클래스
    UDP는 User Datagram Protocal의 약어로 IP를 사용해 네트워크내에서 컴퓨터들간에 데이타 통신하기 위해 제한된 서비스만 제공하는 통신 규칙이다. TCP의 대안이기도 하며 IP와 함께 사용하면 UDP/IP라고 표현하기도 한다. UDP는 정확한 데이터를 전송할 의무가 주어지지 않은 비연결지향성을 가져 데이터의 흐름에 신뢰를 할 수 없는 것이 특징이다. TCP처럼 통신을 하기전 상대방을 확인하는 절차가 없기 때문에 데이터 정확도는 떨어질 수 있지만 빠른 데이타 전송에 유리하다. 그래서 음악 및 비디오 실시간 스트리밍 서비스에 잘 사용하는 프로토콜이다.



    AIR 2.0에서는 UDP 통신을 DatagramSocket 클래스와 DatagramSocketDataEvent 클래스를 지원하고 있다. 더욱 자세한 내용은 아래 링크를 참고한다.



    Secure 클라이언트 소켓 : SecureSocket 클래스 
    소켓서버에 접속하기 위해 SSLv4(Secure Socket Layer version 4) 또는 TLSv1(Transport Layer Security version 1) 기반으로 하는 프로토콜을 이용하여 SecureSocket 클래스로 접속할 수 있다. Secure 소켓을 이용하면 암호화된 데이터 전송으로 서버인증(server authentication), 데이터 무결성(data integrity), 메시지 기밀성(message confidentiality)등의 장점을 가진다. 




    1.3 네트워크 정보 
    AIR 2.0의 API로 네트워크 정보를 얻어낼 수 있는 클래스인 NetworkInfo가 추가되었다. 이 클래스를 이용하면 사용자의 기기의 Mac Address, IP정보 등의 네트워크 정보를 얻어올 수 있다.


    Adobe 문서에서 보여지는 예제에서는 var networkInfo:NetworkInfo = new NetworkInfo() 처럼 생성해서 사용하도록 되어 있는데 잘못된 것이다. var networkInfo:NetworkInfo = NetworkInfo.networkInfo; 처럼 static 속성으로 접근해야한다.
    그리고 NetworkInterface에 networkInterfaceDefault 속성 또한 존재하지 않는다.  
    package { 
    	import flash.display.Sprite; 
    	import flash.net.InterfaceAddress; 
    	import flash.net.NetworkInfo; 
    	import flash.net.NetworkInterface; 
    	
    	public class NetworkInformationExample extends Sprite 
    	{ 
    		public function NetworkInformationExample() 
    		{ 
    			var networkInfo:NetworkInfo.<NetworkInterface> = NetworkInfo.networkInfo;
    			var interfaces:Vector.<NetworkInterface> = networkInfo.findInterfaces(); 
    			
    			if( interfaces != null ) 
    			{ 
    				trace( "Interface count: " + interfaces.length ); 
    				for each ( var interfaceObj:NetworkInterface in interfaces ) 
    				{ 
    					trace( "\nname: "             + interfaceObj.name ); 
    					trace( "display name: "     + interfaceObj.displayName ); 
    					trace( "mtu: "                 + interfaceObj.mtu ); 
    					trace( "active?: "             + interfaceObj.active ); 
    					//trace( "default?: "         + interfaceObj.networkInterfaceDefault ); 
    					trace( "parent interface: " + interfaceObj.parent ); 
    					trace( "hardware address: " + interfaceObj.hardwareAddress ); 
    					if( interfaceObj.subInterfaces != null ) 
    					{ 
    						trace( "# subinterfaces: " + interfaceObj.subInterfaces.length ); 
    					} 
    					trace("# addresses: "     + interfaceObj.addresses.length ); 
    					for each ( var address:InterfaceAddress in interfaceObj.addresses ) 
    					{ 
    						trace( "  type: "           + address.ipVersion ); 
    						trace( "  address: "         + address.address ); 
    						trace( "  broadcast: "         + address.broadcast ); 
    						trace( "  prefix length: "     + address.prefixLength ); 
    					} 
    				}             
    			} 
    		}     
    	} 
    }
    

     
    위 프로그램은 NetworkInfo를 사용하는 아주 간단한 예시이다. Flash Builder 4 에서 이 예시를 테스트해볼때는 AIR 프로젝트 생성시 마지막에 mxml대신 as로 확장자를 두고 생성해서 테스트 하면 되겠다.


    1.4 DNS lookup
    AIR 2.0에서부터 DNSResolver 클래스를 제공하여 DNS(Domain Name System) 정보를 찾을 수 있게 되었다. 정보를 찾게되면 DNSResolverEvent가 발생한다. 

    DNS는 각 도메인 이름(가령 examples.com)을 IP주소로 가리킨다. 일반적으로 사람은 111.123.431.11와 같은 IP주소보다 examples.com처럼 도메인 이름과 같은 단어조합을 더욱 인지하기 쉽다. 이러한 이유로 실제로는 도메인 이름을 사용하면 DNS를 걸쳐 이에 해당하는 IP주소로 연결시켜 관련 서버로 접속하게 한다. AIR 2.0에서 제공하는 DNSResolver 클래스를 이용하면 이러한 관계를 조사해볼 수 있게 된다. 

    IP주소는 IPv4(32비트) 또는 IPv6(128비트)를 사용할 수 있다. 

    DNSResolver 클래스의 lookup() 함수를 통해 host이름과 레코드 형태(record type)을 넘겨주면 DNSResolverEvent.LOOK_UP 이벤트를 발생하여 관련 레코드 타입에 대한 정보를 반환해준다. 
     



     다음은 예제이다.
    package
    {
    	import flash.desktop.NativeApplication;
    	import flash.display.Sprite;
    	import flash.events.DNSResolverEvent;
    	import flash.events.ErrorEvent;
    	import flash.net.dns.AAAARecord;
    	import flash.net.dns.ARecord;
    	import flash.net.dns.DNSResolver;
    	import flash.net.dns.MXRecord;
    	import flash.net.dns.PTRRecord;
    	import flash.net.dns.SRVRecord;
    	import flash.utils.getQualifiedClassName;
    	
    	public class DNSResolverExample extends Sprite
    	{
    		private var lookupCount:int = 0;
    		public function DNSResolverExample()
    		{
    			//Create the resolver object
    			var resolver:DNSResolver = new DNSResolver();
    			resolver.addEventListener( DNSResolverEvent.LOOKUP, lookupComplete );
    			resolver.addEventListener( ErrorEvent.ERROR, lookupError );
    			
    			//Look up records
    			resolver.lookup( "yahoo.com", ARecord );
    			resolver.lookup( "yahoo.com", AAAARecord );
    			resolver.lookup( "yahoo.com", MXRecord );
    			resolver.lookup( "209.191.93.53", PTRRecord );
    			resolver.lookup( "_sip._tcp.yahoo.com.", SRVRecord );
    		}
    		
    		private function lookupComplete( event:DNSResolverEvent ):void
    		{
    			trace("-------------------------------------");
    			trace( "Query string: " + event.host );
    			trace( "Record type: " +  flash.utils.getQualifiedClassName( event.resourceRecords[0] ) + 
    				", count: " + event.resourceRecords.length );
    			for each( var record:* in event.resourceRecords )
    			{
    				if( record is ARecord ) trace( record.name + " : " + record.address );
    				if( record is AAAARecord ) trace( record.name + " : " + record.address );
    				if( record is MXRecord ) trace( record.name + " : " + record.exchange + ", " + record.preference );
    				if( record is PTRRecord ) trace( record.name + " : " + record.ptrdName );
    				if( record is SRVRecord ) trace( record.name + " : " + record.target + ", " + record.port +
    					", " + record.priority + ", " + record.weight );
    			}    
    			if( ++lookupCount == 5 )
    			{
    				NativeApplication.nativeApplication.exit();
    			}
    		}
    		
    		private function lookupError( error:ErrorEvent ):void
    		{
    			trace("-------------------------------------");
    			trace("Error: " + error.text );
    			if( ++lookupCount == 5 )
    			{
    				NativeApplication.nativeApplication.exit();
    			}
    		}
    	}
    }
    



    1.5 스크린 리더 지원(Screen Reader Support)

    AIR 2.0은 스크린 리더를 지원하기 위한 Accessibility 클래스가 추가되었다. 스크린 리더는 시각 장애 사용자들을 위한 보조 기술로서 화면 내용을 오디오 버전으로 제공하는 것이다. 이 클래스는 현재 Windows 환경에서만 제공된다. 이것이 지원되는지 확인하려면 Capabilities.hasAccessibility 정적속성이 true이어야 한다. 버튼, 무비클립, 텍스트필드와 같은 객체에 액세스 가능한 속성을 얻고 설정하기 위해 DisplayObject.accessibilityProperties 속성을 사용하며 이 값이 바뀌었다는 것을 알려주기 위해 Accessibility.updateProperties() 정적메소드를 이용한다.

    이 기능을 사용하기 위해 프로젝트의 컴파일 옵션을 추가해야한다. Flash builder 4에서 해당 프로젝트를 선택후 메뉴의 Project > Properties를 선택한다. 새창이 나오면 Flex Compiler를 선택후 컴파일 옵션에 Generate accessible SWF file을 선택후 OK 버튼을 누른다.


    package {
    	import flash.accessibility.Accessibility;
    	import flash.desktop.NativeApplication;
    	import flash.display.Sprite;
    	import flash.display.StageAlign;
    	import flash.display.StageScaleMode;
    	import flash.utils.setTimeout;
    	
    	public class AccessibilityExample extends Sprite {
    		public static const BUTTON_WIDTH:uint = 90;
    		public static const BUTTON_HEIGHT:uint = 20;
    		
    		private var gutter:uint = 5;
    		private var menuLabels:Array = new Array("PROJECTS", "PORTFOLIO", "CONTACT");
    		private var menuDescriptions:Array = new Array("Learn more about our projects"
    			, "See our portfolio"
    			, "Get in touch with our team");
    		
    		public function AccessibilityExample() {
    			configureAssets();
    			NativeApplication.nativeApplication.autoExit = true;
    			stage.align = StageAlign.TOP_LEFT;
    			stage.scaleMode = StageScaleMode.NO_SCALE;
    			stage.nativeWindow.activate();
    			setTimeout(updateAccessibility, 2000); 
    		}
    		
    		private function updateAccessibility():void {
    			trace("Accessibility.active: " + Accessibility.active);
    			if(Accessibility.active) {
    				Accessibility.updateProperties();
    			}
    		}
    		
    		private function configureAssets():void {
    			var child:CustomAccessibleButton;
    			for(var i:uint; i < menuLabels.length; i++) {
    				child = new CustomAccessibleButton();
    				child.y = (numChildren * (BUTTON_HEIGHT + gutter));
    				child.setLabel(menuLabels[i]);
    				child.setDescription(menuDescriptions[i]);
    				addChild(child);
    			}
    		}
    	}
    }
    
    import flash.accessibility.AccessibilityProperties;
    import flash.display.Shape;
    import flash.display.SimpleButton;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.text.TextFormat;
    import flash.text.TextFormatAlign;
    import flash.text.TextField;
    
    class CustomAccessibleButton extends Sprite {
    	private var button:SimpleButton;
    	private var label:TextField;
    	private var description:String;
    	private var _name:String;
    	
    	public function CustomAccessibleButton(_width:uint = 0, _height:uint = 0) {
    		_width = (_width == 0) ? AccessibilityExample.BUTTON_WIDTH : _width;
    		_height = (_height == 0) ? AccessibilityExample.BUTTON_HEIGHT : _height;
    		
    		button = buildButton(_width, _height);
    		label = buildLabel(_width, _height);
    		
    		addEventListener(Event.ADDED, addedHandler);
    	}
    	
    	private function addedHandler(event:Event):void {
    		trace("addedHandler: " + this._name);
    		var accessProps:AccessibilityProperties = new AccessibilityProperties();
    		accessProps.name = this._name;
    		accessProps.description = description;
    		accessibilityProperties = accessProps;
    		removeEventListener(Event.ADDED, addedHandler);
    	}
    	
    	private function buildButton(_width:uint, _height:uint):SimpleButton {
    		var child:SimpleButton = new CustomSimpleButton(_width, _height);
    		addChild(child);
    		return child;
    	}
    	
    	private function buildLabel(_width:uint, _height:uint):TextField {
    		var format:TextFormat = new TextFormat();
    		format.font = "Verdana";
    		format.size = 11;
    		format.color = 0xFFFFFF;
    		format.align = TextFormatAlign.CENTER;
    		format.bold = true;
    		
    		var child:TextField = new TextField();
    		child.y = 1;
    		child.width = _width;
    		child.height = _height;
    		child.selectable = false;
    		child.defaultTextFormat = format;
    		child.mouseEnabled = false;
    		
    		addChild(child);
    		return child;
    	}
    	
    	public function setLabel(text:String):void {
    		label.text = text;
    		this._name = text;
    	}
    	
    	public function setDescription(text:String):void {
    		description = text;
    	}
    }
    
    class CustomSimpleButton extends SimpleButton {
    	private var upColor:uint = 0xFFCC00;
    	private var overColor:uint = 0xCCFF00;
    	private var downColor:uint = 0x00CCFF;
    	
    	public function CustomSimpleButton(_width:uint, _height:uint) {
    		downState = new ButtonDisplayState(downColor, _width, _height);
    		overState = new ButtonDisplayState(overColor, _width, _height);
    		upState = new ButtonDisplayState(upColor, _width, _height);
    		hitTestState = new ButtonDisplayState(upColor, _width, _height);
    		useHandCursor = true;
    	}        
    }
    
    class ButtonDisplayState extends Shape {
    	private var bgColor:uint;
    	private var _width:uint;
    	private var _height:uint;
    	
    	public function ButtonDisplayState(bgColor:uint, _width:uint, _height:uint) {
    		this.bgColor = bgColor;
    		this._width = _width;
    		this._height = _height;
    		draw();
    	}
    	
    	private function draw():void {
    		graphics.beginFill(bgColor);
    		graphics.drawRect(0, 0, _width, _height);
    		graphics.endFill();
    	}
    }
    


    1.6 네이티브 프로세스의 직접 실행과 상호 작용( Launching and Interacting with Native Processes )
    네이티브 프로세스에 대해서 본인도 처음 접하는 용어라 해석하기 어려웠는데, 이해한바 각 운영체제에 실행될 수 있는 코드라고 생각하면 될 것 같다. 가령, 윈도우에서는 exe, dll, ocx등이겠고 맥이라면 dmg, app 등이 아닐까 생각한다.

    AIR 2.0부터 기존의 애플리케이션을 실행해 AIR 애플리케이션과 표준입출력을 통한 상호작용할 수 있는 기능이 추가되었다. 가령, C언어로 만든 프로그램을 자신의 AIR 애플리케이션과 함께 배포했다고 하자. AIR 애플리케이션이 이 C언어로 만든 프로그램을 실행하고 표준입출력을 이용해 통신이 가능해진다. 또는 이미 설치된 Editplus에 File을 넘겨서 실행하고 종료시점도 알 수 있다.

    자세한 내용은 다음을 참고한다.

    이 기능을 수행하려면 반드시 AIR 디스크립터 파일에 다음 코드를 꼭 넣어야 한다.


    <supportedProfiles>extendedDesktop</supportedProfiles>
    


    아래는 Editplus를 이용해 Text파일을 열고 Editplus가 닫힐 때 감지하는 간단한 Flex 4를 이용한 AIR 2.0 애플리케이션 코드이다. NativeProcess와 NativeProcessStartupInfo 클래스의 용도를 잘 살펴보자.
    <?xml version="1.0" encoding="utf-8"?>
    <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
    					   xmlns:s="library://ns.adobe.com/flex/spark" 
    					   xmlns:mx="library://ns.adobe.com/flex/halo">
    	<fx:Script>
    		<![CDATA[
    			import flash.events.NativeProcessExitEvent;
    			
    			public function executeNativeProcess():void 
    			{
    				var executable:File = new File("C:/Program Files/EditPlus 3/editplus.exe"); //c:/Windows/System32/notepad.exe
    				var workingDirectory:File = new File("c:/");
    				
    				var nativeProcess:NativeProcess = new NativeProcess();
    				
    				if (NativeProcess.isSupported) 
    				{
    					trace("Native Process Supported");
    				}
    				
    				var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
    				nativeProcessStartupInfo.executable = executable;
    				nativeProcessStartupInfo.workingDirectory = workingDirectory;
    				
    				var args:Vector.<String> = new Vector.<String>();   
    				args.push("c:/LAN.log"); // open file that was given with the executable application 
    				nativeProcessStartupInfo.arguments = args;
    				
    				nativeProcess.addEventListener( NativeProcessExitEvent.EXIT, onExitError );
    				
    				try {
    					nativeProcess.start(nativeProcessStartupInfo);
    				} catch (error:IllegalOperationError) {
    					trace("Illegal Operation: "+error.toString());
    				} catch (error:ArgumentError) {
    					trace("Argument Error: "+error.toString());
    				} catch (error:Error) {
    					trace ("Error: "+error.toString());
    				}
    				
    				if (nativeProcess.running) 
    				{
    					trace ("Native Process Support");
    				}       
    			}
    			
    			public function onExitError(event:NativeProcessExitEvent):void 
    			{
    				trace( "Native Process Exit code: "+event.exitCode );
    			}            
    			
    		]]>
    	</fx:Script>
    	
    	<s:Button id="button"
    			  label="Open File foobar.txt with text editor"
    			  click="executeNativeProcess();"
    			  width="250" />
    	
    </s:WindowedApplication>
    

    Mac인 경우 Mac에 설치되어 기본으로 설치되어 있는 텍스트 에디터를 실행할 수도 있다. 이것도 별다른 설정없이 같은 방법으로 실행할 수 있다. new File()에는 "/Applications/TextEdit/TextEdit.app/Contents/MacOS/TextEdit"와 "/" 로 대체하고 args.push()부분은 foobar.txt가 데스크톱에 있을때 "/User/사용자계정/Desktop/foobar.txt"로 대체해서 실행하면 된다. 

    NativeProcess 클래스는 단순히 실행과 종료만 담당하지 않는다. AIR 애플리케이션과 Native 실행 소스간에 통신도 가능하다. 다음 링크는 HTML/Javascript, Flex, Flash 개발자들을 위한 예제이다. AIR코드 뿐 아니라 C코드도 있으니 꼭 다운받아 실행해보길 바란다.

    다음과 같이 Flex 4 코드로 변경해봤다.


    <?xml version="1.0" encoding="utf-8"?>
    <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
    					   xmlns:s="library://ns.adobe.com/flex/spark" 
    					   xmlns:mx="library://ns.adobe.com/flex/halo" 
    					   width="350" height="150"
    					   applicationComplete="windowedapplication1_applicationCompleteHandler(event)">
    	<fx:Script>
    		<![CDATA[
    			import flash.events.ProgressEvent;
    			import flash.system.Capabilities;
    			import flash.utils.IDataInput;
    			
    			import mx.controls.Alert;
    			import mx.events.FlexEvent;
    			
    			private var process:NativeProcess;
    			
    			private function windowedapplication1_applicationCompleteHandler(event:FlexEvent):void {
    				//Native Process가 지원되는지 확인. 
    				//지원되려면 반드시 디스크립터에  <supportedProfiles>extendedDesktop</supportedProfiles>을 추가해야한다.
    				if( NativeProcess.isSupported ) {
    					launchEchoTest();
    				} else {
    					Alert.show("NativeProcess not supported.","Error");
    				}
    			}			
    			private function launchEchoTest():void {
    				//실행할 Native 애플리케이션 선택
    				var file:File = File.applicationDirectory;
    				file = file.resolvePath("NativeApps");
    				if( Capabilities.os.toLocaleLowerCase().indexOf("win") > -1 ) {
    					file = file.resolvePath("Windows/bin/echoTestWin.exe");
    				} else {
    					file = file.resolvePath("Mac/bin/echoTestMac");
    				}
    				
    				//Native Process를 진행하기 위한 정보 설정 
    				var info:NativeProcessStartupInfo = new NativeProcessStartupInfo();
    				info.executable = file;
    				
    				//Native Process생성
    				process = new NativeProcess();
    				
    				//보내고 받을때 발생하는 이벤트에 대한 처리 
    				process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, function(event:ProgressEvent):void {
    					var date:Date = new Date();
    					var bytes:IDataInput = process.standardOutput;
    					textReceived.text = bytes.readUTFBytes( bytes.bytesAvailable );
    					launchEchoTest();
    					lbDateStamp.text = date.toString();
    				} );
    				process.addEventListener(ProgressEvent.STANDARD_INPUT_PROGRESS, function(event:ProgressEvent):void {
    					process.closeInput();
    				} );
    				//Native Process 시작 
    				process.start( info );
    			}
    			private function writeData():void {
    				process.standardInput.writeUTFBytes( textToSend.text + "\n" );
    			}
    		]]>
    	</fx:Script>
    	<fx:Declarations>
    		<!-- Place non-visual elements (e.g., services, value objects) here -->
    	</fx:Declarations>
    	<s:VGroup paddingLeft="10" paddingRight="10" paddingTop="10" paddingBottom="10">
    		<mx:Form>
    			<mx:FormItem label="Text to send" direction="horizontal">
    				<s:TextInput id="textToSend"/>	
    				<s:Button label="writeData()" click="writeData()"/>
    			</mx:FormItem>
    			<mx:FormItem label="Text received">
    				<s:TextInput id="textReceived" editable="false"/>
    			</mx:FormItem>
    		</mx:Form>
    		<s:Label id="lbDateStamp"/>
    	</s:VGroup>
    </s:WindowedApplication>
    
    


    아래 코드는 AIR 애플리케이션과 통신할 C코드(Mac용)이다.
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    #define BUFFER_SIZE 8192
    
    int main(int argc, char** argv)
    {
    	char buf[BUFFER_SIZE];
    	int  cnt;
    	
    	while ( !feof(stdin) )
    	{
    		cnt = read(STDIN_FILENO, buf, sizeof buf); 
    		if (-1 == cnt) 
    		{
    			perror("read");
    			exit(1);
    		}
    		if (0 == cnt)
    		{
    			// eof reached...
    			exit(0);
    		}
    
    		write(STDOUT_FILENO, buf, cnt ); 
    	}
    	
    	return 0;
    }
    
    




    NativeProcess의 standardInput과 standardOutput 속성은 각각 IDataOutput, IDataInput을 입력과 출력값으로 받고 있다. 그러므로 이 속성을 이용해 표준입출력(standard input/output)을 이용해 서로 통신하게 된다.

    매우 다양한 형태로 응용이 가능할 것이라 판단한다.


    1.7 File Promise 지원

    AIR 2.0부터 FilePromise 클래스가 새로 추가되어 드래그&드롭 형태로 리모트 파일을 AIR 애플리케이션 외부로 다운로드 받을 수 있게 되었다. URLFilePromise 클래스를 이용해 이 작업을 할 수 있다.

    이 기능은 Windows와 Mac에서만 지원되며(Clipboard.supportsFilePromise로 확인) 반드시 AIR 애플리케이션 외부로 드롭하는 경우만 해당한다. 일반적인 클립보드 복사&붙이기 기능으로는 할 수 없다.

    다음 코드는 예시이다.

     

    <?xml version="1.0" encoding="utf-8"?>
    <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
    					   xmlns:s="library://ns.adobe.com/flex/spark" 
    					   xmlns:mx="library://ns.adobe.com/flex/halo"
    					   applicationComplete="windowedapplication1_applicationCompleteHandler(event)">
    	<fx:Script>
    		<![CDATA[
    			import mx.controls.Alert;
    			import mx.events.DragEvent;
    			import mx.events.FlexEvent;
    			
    			private var clipboard:Clipboard;
    			private function windowedapplication1_applicationCompleteHandler(event:FlexEvent):void {
    				clipboard = new Clipboard();
    				if( !clipboard.supportsFilePromise ) {
    					Alert.show( "File Promise를 지원하지 않습니다." );
    				}
    			}
    			private function onDragOut(event:DragEvent):void {
    				trace( event.target, event.type );
    				var items:Array = fileData.selectedItems;
    				var promises:Array = new Array();
    				for each (var item:Object in items) {
    					var filePromise:URLFilePromise = new URLFilePromise();
    					var request:URLRequest = new URLRequest(item.url);
    					filePromise.request = request;
    					filePromise.relativePath = item.name;
    					promises.push(filePromise);
    				}
    				clipboard.setData(ClipboardFormats.FILE_PROMISE_LIST_FORMAT, promises);
    				NativeDragManager.doDrag(fileData, clipboard);     
    			}
    			private function onDragOutComplete(event:NativeDragEvent):void {
    				trace( "Drag out complete");
    				clipboard = new Clipboard();
    			}            
    		]]>
    	</fx:Script>
    	
    	<fx:Declarations>
    		<mx:ArrayCollection id="arrColl">
    			<mx:source>
    				<fx:Array>
    					<fx:Object name="rhall.jpg" url="http://a1.twimg.com/profile_images/57117466/robert_m_hall_bio_photo_big_normal.jpg" />
    					<fx:Object name="bobjim.jpg" url="http://a1.twimg.com/profile_images/51723308/ryancampbell3_normal.jpg"/>
    					<fx:Object name="jenschr.jpg" url="http://a1.twimg.com/profile_images/43222252/jenschr_mugshot3_normal.jpg"/>
    					<fx:Object name="adamflater.jpg" url="http://a1.twimg.com/profile_images/21503622/Photo_8_normal.jpg"/>
    					<fx:Object name="reboog711.jpg" url="http://a1.twimg.com/profile_images/16984682/DSCF0044_normal.jpg"/>
    				</fx:Array>
    			</mx:source>
    		</mx:ArrayCollection>
    	</fx:Declarations>
    	
    	<mx:DataGrid id="fileData" dragEnabled="true"
    				 dataProvider="{arrColl}" 
    				 dragStart="onDragOut(event)"
    				 nativeDragComplete="onDragOutComplete(event)" width="100%">
    		<mx:columns>
    			<mx:DataGridColumn dataField="name" width="100"/>
    			<mx:DataGridColumn dataField="url"/>
    		</mx:columns>
    	</mx:DataGrid>
    	
    </s:WindowedApplication>
    




    1.8 Global Error Handling

    AIR 애플리케이션이 런타임 도중에 에러가 발생할 때 국부적 Error 처리는 이미 가능했다. 하지만 개발자가 애플리케이션의 어느 부분에서 Error가 발생할지 또는 문제가 발생할지 찾기 힘든 것이 현실이다. 국부적으로 일어나는 에러를 처지하지 못하는 경우 애플리케이션이 동작중에 어떤 부분에서 에러가 발생하든지 대처할 수 있도록 Global Error를 처리할 수 있는 기능이 AIR 2.0과 Flash Player 10.1에 추가가 되었다. 다음 글을 참고하자.

    Global Error를 처리하는데 UncaughtErrorEvent 클래스를 이용한다. 이름에서도 볼 수 있듯이 기존의 try..catch문으로 처리하지 못한 Error가 발생할 때 발생함을 알 수 있다.

    발생하는 UncaughtErrorEvent를 처리하기 위해 LoaderInfo 객체의 uncaughtErrorEvents 속성에 이벤트 처리를 위한 함수를 등록하면 된다.

    loaderInfo.uncaughtErrorEvents.addEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, handler );

    단, 로드된 SWF 객체의 경우에는 Loader의 uncaughtErrorEvents 속성에 이벤트 처리 함수를 등록한다.

    loader.uncaughtErrorEvents.addEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, handler );


    하나의 SWF가 다른 SWF에 로드되는 경우 UncaughtErrorEvent 이벤트 전파에 대한 처리가 필요하다.  A.swf가 B.swf를 Loader를 이용해 로드했다면 다음과 같은 순서로 LoaderInfo와 Loader 객체에 UncaughtErrorEvent 가 전파된다.

    1. (Capture phase) A.swf의 LoaderInfo
    2. (Capture phase) A.swf내의 Loader 
    3. (Target phase) B.swf의 LoaderInfo
    4. (Bubble phase) A.swf의 Loader
    5. (Bubble phase) A.swf의 LoaderInfo

    Loader객체의 uncaughtErrorEvents 속성은 결코 이벤트 전파시 target phase가 발생하지 않음에 주목하자. 그리고 이렇게 이벤트가 전파되는데는 디스플레이 리스트에 등록되어 있어야만 한다. 즉 addChild()된 객체어야한 한다. 중간에 이벤트 전파를 중단하려면 stopPropagation()이나 stopImmediatePropagation() 메소드를 이용하면 되겠다. 또한 ADL 기반나 디버그용 Flash Player에서 구동 경우 에러표시 다이얼로그가 뜨는 것을 방지하기 위해 UncaughtErrorEvent 이벤트 발생시 preventDefault() 메소드를 사용해 안뜨도록 할 수 있다.

    아래는 AIR 2.0 예제이다.

    package {
    	import flash.desktop.*;
    	import flash.display.*;
    	import flash.events.*;
    	public class UncaughtErrorEventExample extends Sprite {
    		public function UncaughtErrorEventExample()
    		{
    			var options:NativeWindowInitOptions = new NativeWindowInitOptions();
    			options.type = NativeWindowType.UTILITY;
    			
    			var window:NativeWindow = new NativeWindow(options);
    			window.width = 200;
    			window.height = 200;
    			window.title = "UncaughtErrorEventExample";
    			
    			window.stage.scaleMode = StageScaleMode.NO_SCALE;
    			window.stage.align = StageAlign.TOP_LEFT;
    			
    			window.activate();
    			window.addEventListener(Event.CLOSING, function($event:Event):void {
    				NativeApplication.nativeApplication.exit();
    			});			
    
    			var btn:Sprite = new Sprite();
    			btn.useHandCursor = true;
    			btn.buttonMode = true;
    			btn.graphics.clear();
    			btn.graphics.beginFill(0xFFCC00);
    			btn.graphics.drawRect(0, 0, 100, 50);
    			btn.graphics.endFill();
    			btn.addEventListener(MouseEvent.CLICK, clickHandler);			
    			window.stage.addChild(btn);
    			
    			loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, uncaughtErrorHandler);
    		}
    		private function uncaughtErrorHandler(e:UncaughtErrorEvent):void {
    			if (e.error is Error) {
    				var error:Error = e.error as Error;
    				// do something with the error
    				trace(error.errorID, error.name, error.message);
    			} else if (e.error is ErrorEvent) {
    					var errorEvent:ErrorEvent = e.error as ErrorEvent;
    					// do something with the error
    					trace(errorEvent.errorID);
    			} else {
    				// a non-Error, non-ErrorEvent type was thrown and uncaught
    				trace( " a non-Error, non-ErrorEvent type was thrown and uncaught " );
    			}
    			e.preventDefault();
    		}
    		private function clickHandler(event:MouseEvent):void
    		{
    			throw new Error("Gak!");
    		}
    	}
    }
    


    위 예제에서 볼 수 있듯이 AIR 애플리케이션의 노란 부분을 클릭하면 강제로 에러를 발생시킨다. 이때 이 에러를 처리하기 위한 try...catch문이 없으므로 UncaughtErrorEvent가 발생하고 그것을 처리하고 있다. 마지막에 e.preventDefault()를 둬서 에러표시 다이얼로그가 뜨는 것을 방지한다.


    1.9 Packaging an AIR application in a native installer

    AIR 2.0가 생소하게 다가오는 이유중에 하나는 바로 AIR 2.0을 설치할 때 과정이다. 뱃지(Badge)기능을 이용해 웹페이지에서 AIR 런타임 및 해당 AIR 애플리케이션을 다운로드 받을 수 있지만 그 과정이 일반 사용자에게 생소하게 다가올 수 있다. AIR 2.0에서는 이러한 생소함을 덜어주기 위해 각 OS별로 설치패키지를 따로 구성할 수 있도록 지원하고 있다. 가령, Windows는 exe, Mac은 dmg으로 설치 패키지를 구성할 수 있다는 말이다.

    AIR 2.0의 ADT의 옵션설정으로 설치 패키지를 만들 수 있다. 다음 링크를 참고한다.


    연관글






    정리하며 

    이번 글은 Adobe AIR 2.0 Overview 첫번째 글로 AIR 2.0에 추가된 새로운 기능에 대해서만 언급했다.  "기존 API에서 추가된 기능", "플랫폼 인식 관련 API", "퍼포먼스 향상"에 관련된 내용도 조만간 언급하겠다. 이 글을 읽고 AIR 2.0 기반으로 하는 다양한 애플리케이션 예제들이 많이 나왔으면 하는 바램이다.

    글쓴이 : 지돌스타(http://blog.jidolstar.com/629)
    처음 Flash Builder 4 beta 2를 설치하면 설치된 디렉토리에 sdks 디렉토리가 있고 이 안에 3.4.1, 4.0.0 의 두개의 디렉토리가 있다. 이 디렉토리는 SDK 두개의 버전을 말한다. 이는 윈도우(MS Windows)던 맥(Mac)이든 동일하다. 윈도우는 C:/Program Files/Adobe/Flash Builder 4 beta 2/sdks가 되겠고 맥이라면 /Application/Adobe Flash Builder 4 beta 2/sdks가 될 것이다.

    하지만 AIR 1.5개발을 위한 sdk들이며 새로운 AIR 2.0 Beta를 테스트해보기 위해서는 sdks를 변경해야한다. 윈도우에서는 Adobe Labs에서 AIR 2.0 Beta SDK를 다운로드 받아 해당 sdks안에 3.4.1, 4.0.0 디렉토리에 각각 복사하고 AIR 2.0 Runtime을 설치하는 것만으로 개발환경이 구축된다. (이미 윈도우환경에서 AIR 2.0 Beta를 Flash Builder 4에 적용하는 방법을 소개했었다. : http://blog.jidolstar.com/619)

    하지만 맥에서의 복사는  윈도우 운영체제에서 복사와 다른 개념을 가진다. 윈도우에서는 같은 디렉토리 이름의 경우 이전의 내용과 덮어쓰려는 내용을 합쳐버린다. 하지만 맥은 같은 이름의 디렉토리는 제거하고 복사할 디렉토리로 바꾼다. 이를 대치한다고 한다. 그래서 맥 사용자는 AIR 2.0 개발환경을 구축하기 위해 조금 복잡한 과정을 거쳐야한다.

    약간 복잡하더라도 리눅스를 조금만 다뤄봤다면 쉽게 이 문제를 해결할 수 있다.

    • 파인더에서 Application(응용 프로그램) > 유틸리티 에서 터미널을 실행한다. 
    • 만약 이전에 root 계정을 만든 적이 있다면 바로 su를 입력해 root권한으로 접근한다.
      아니면 sudo passwd root 를 입력해서 현재 계정의 암호를 입력하고 root암호를 설정후 성공적으로 입력하면 su로 접속해 방금 입력한 root암호로 접속한다. 참고로 root로 접속하면 명령 프롬프트가 $에서 #로 바뀐다.
    • 다운로드 받은 AIR 2.0 SDKs를 기존 sdks에 복사하기 위해 cp -rf orig_dir/* dest_dir를 이용한다.
      만약 AIR 2.0 SDKs를 자신의 홈에 복사해 두었다면 다음과 같이 터미널 창에 입력하여 강제 복사한다.
      cp -rf /Users/jidolstar/AIR2.0SDK/* /Applications/Adobe\ Flash\ Builder\ Beta\ 2/sdks/3.4.1/
      cp -rf /Users/jidolstar/AIR2.0SDK/* /Applications/Adobe\ Flash\ Builder\ Beta\ 2/sdks/4.0.0/

    윈도우와 맥의 디렉토리 복사에 대한 개념이 달라 본인도 몇시간 고민한 결과 찾아낸 방법이다. 좋은 정보가 되었으면 한다.


    추가사항 
    기존에 AIR 1.5 기반의 SDKs를 그대로 두면서 AIR 2.0도 필요할 때 개발하고 싶은 사람도 있을 것이다. 
    그런 경우에는 위의 설명에서 약간만 다르게 하면 되겠다. 위에서 설명한 2번째 내용에서 root로 접속하는 것까지는 같다. 

    1. Flash builder 4의 sdks 디렉토리에 있는 3.4.1과 4.0.0의 복사본을 만든다. 
      mkdir 3.4.1_AIR2.0
      mkdir 4.0.0_AIR2.0
      cp -R 3.4.1/* 3.4.1_AIR2.0
      cp -R 4.0.0/* 4.0.0_AIR2.0
    2. AIR 2.0 SDKs를 3.4.1_AIR2.0과 4.0.0_AIR2.0 폴더에 복사한다.
      cp -rf /Users/jidolstar/AIR2.0SDK/* /Applications/Adobe\ Flash\ Builder\ Beta\ 2/sdks/3.4.1_AIR2.0/
      cp -rf /Users/jidolstar/AIR2.0SDK/* /Applications/Adobe\ Flash\ Builder\ Beta\ 2/sdks/4.0.0_AIR2.0/
    3. Flash Builder 를 실행한다.
    4. 메뉴에서 Eclipse > Preference에 들어간다. (참고로 Window였다면 Window > Preference이다.)
    5. 창이 뜨면 왼쪽 메뉴에서 Flash builder > Installed Flex SDKs를 선택한다.
    6. 우측에 Add버튼을 눌러 위에서 새로 만든 AIR 2.0을 위한 SDKs들을 선택한다.  
      Flex SDK Name은 각각 Flex 3.4 AIR 2.0, Flex 4.0 AIR 2.0 등으로 이름을 바꿔도 된다.
      본인의 경우 아래 경로가 되겠다.
      /Applications/Adobe\ Flash\ Builder\ Beta\ 2/sdks/3.4.1_AIR2.0/
      /Applications/Adobe\ Flash\ Builder\ Beta\ 2/sdks/4.0.0_AIR2.0/
      본인은 아래처럼 AIR 2.0기반의 Flex 4.0 SDK를 디폴트로 잡았다.

    7. 이제 모든 개발환경이 완료되었다. 자신의 프로젝트 생성시에 원하는 SDK를 선택하면 되겠다. 
    8. 만약 프로젝트 중간에 AIR 1.5기반으로 만들다가 AIR 2.0기반으로 바꾸려면 해당프로젝트를 선택후 마우스 우클릭으로 Properties를 선택한다. 창이 뜨면 좌측 메뉴에서 Flex Compiler를 선택후 Flex SDK Version을 해당 SDK로 바꾸면 되겠다.



    Adobe AIR로 만든 아주아주 간단한 웹브라우져이다. Adobe AIR는 Webkit 엔진을 내장한 HTMLLoader라는 클래스가 있다. Webkit엔진은 사파리, 구글 크롬등에 사용하는 엔진이다. Flex 4에서는 이것을 HTML로 한번 랩핑해서 사용하고 있다. Adobe AIR에서 이 엔진을 사용하면 로드되는 페이지의 DOM에 직접 접근이 가능하며 DOM 이벤트 발생시 ActionScript 3.0 함수를 호출하게끔 하는 형태로도 변경이 가능해진다. 생각보다 활용도가 무궁무진하다. 게다가 AIR 2.0부터는 한글입력 문제가 해결되었다 . 또한 HTML5/CSS3를 지원하기 시작했다.

    아래 코드는 AIR 2.0, Flash Builder 4 Beta 2 환경에서 만들었다. 이 환경을 구축하는 방법은 다음과 같이 한다.

  • 만약 Flash Builder를 설치 안했다면 다음 링크를 통해 받는다.
  • AIR 2.0 SDK와 Runtime을 다운로드 받는다.
  • 다운받은 Runtime을 실행해 설치한다.
  • (MS Windows의 경우)SDK는 압축을 풀고 그안에 있는 내용을 Flash builder가 설치된 sdks/4.0.0과 sdks/3.4.1 폴더에 각각 덮어씌운다. 본인의 경우는 C:\Program Files\Adobe\Adobe Flash Builder Plug-in Beta 2\sdks\4.0.0
  • Flash Builder를 실행한다.
  • 메뉴에서 File > New > Flex Project를 선택한다.
  • 프로젝트 이름을 적고 Application Type은 AIR를 선택한다. Finish를 한다.
  • 다음 아래 코드를 메인 코드에 복사해서 덮어씌운다.




  • <?xml version="1.0" encoding="utf-8"?>
    <!--
    	간단한 Adobe AIR 웹브라우져
    	제작 : 지용호 
    -->
    <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
    					   xmlns:s="library://ns.adobe.com/flex/spark" 
    					   xmlns:mx="library://ns.adobe.com/flex/halo"
    					   backgroundFrameRate="0.01"
    					   windowComplete="windowedapplication1_windowCompleteHandler(event)">
    	<fx:Script>
    		<![CDATA[
    			import flash.events.Event;
    			import flash.net.URLRequest;
    			import flash.net.navigateToURL;
    			
    			import mx.events.AIREvent;
    
    			private function windowedapplication1_windowCompleteHandler(event:AIREvent):void {
    				nativeWindow.x = 0;
    				nativeWindow.y = 0;
    				width = 1280;
    				height = 900;
    				//browser.htmlLoader.navigateInSystemBrowser = true;
    			}
    			private function linkClickHandler(o:Object):void {
    				navigateToURL( new URLRequest(o.currentTarget.href), "blank" );
    			}
    			private function browser_locationChangeHandler(event:Event):void {
    				trace( "browser_locationChangeHandler" );
    				tiAddress.text = browser.location;
    				btnBack.enabled = browser.historyPosition==0?false:true;
    				btnNext.enabled= (browser.historyPosition < browser.historyLength-1)?true:false;
    			}
    			private function onGoHandler(event:Event):void {
    				browser.location = tiAddress.text;
    			}
    			private function browser_completeHandler(event:Event):void
    			{
    				trace( "browser_completeHandler" );
    				tiAddress.text = browser.location;
    				var dom:Object = HTML(event.currentTarget).domWindow.document;
    				var links:Object = dom.getElementsByTagName("a");
    				for( var i:Number = 0; i < links.length; i++ ) {
    					if( links[i].target.toLowerCase() == "_blank" || links[i].target.toLowerCase() == "_new" ) {
    						links[i].onclick = linkClickHandler;
    					}
    				}
    			}
    		]]>
    	</fx:Script>
    	<s:VGroup width="100%" height="100%">
    		<s:HGroup verticalAlign="middle" paddingLeft="10" paddingRight="10" paddingTop="5" paddingBottom="5">
    			<s:Button id="btnBack" label="뒤로" click="browser.historyBack()"/>
    			<s:Button id="btnNext" label="앞으로" click="browser.historyForward()"/>
    			<s:Button label="새로고침" click="browser.reload()"/>
    			<s:Label text="주소 : "/>
    			<s:TextInput id="tiAddress" width="400" enter="onGoHandler(event)"/>
    			<s:Button label="가기" click="onGoHandler(event)"/>
    		</s:HGroup>
    		<s:HGroup verticalAlign="middle" paddingLeft="10" paddingRight="10" paddingTop="5" paddingBottom="5">
    			<s:Button label="지돌스타 블로그" click="browser.location='http://blog.jidolstar.com'"/>
    			<s:Button label="위콘 블로그" click="browser.location='http://weconize.com'"/>
    			<s:Button label="천문노트" click="browser.location='http://astronote.org'"/>
    			<s:Button label="Adobe RIA" click="browser.location='http://adoberia.co.kr'"/>
    			<s:Button label="Adobe Labs" click="browser.location='http://labs.adobe.com'"/>
    			<s:Button label="Adobe Development Center" click="browser.location='http://www.adobe.com/devnet/'"/>
    		</s:HGroup>
    		<!-- http://labs.adobe.com/wiki/index.php/Apollo:Articles:Using_HTML_in_Flex-based_Apollo_Applications -->
    		<mx:HTML id="browser" width="100%" height="100%" 
    				 location="http://blog.jidolstar.com"
    				 complete="browser_completeHandler(event)"
    				 locationChange="browser_locationChangeHandler(event)"/>
    	</s:VGroup>
    </s:WindowedApplication>
    
    

    Ajax, ActionScript 3.0, Flex, Flash등을 이용하면 AIR 애플리케이션을 만들 수 있다. Flash를 몰라도 Ajax를 알면 만들 수 있기 때문에 웹개발자들이 데스크탑 영역으로의 개발이 가능해졌다. 실제로 Ajax로 만들어진 애플리케이션도 꽤 된다. Adobe AIR 세계에 많은 개발자가 동참하길 바란다.


    글쓴이 : 지돌스타( http://blog.jidolstar.com/621 )
    어제 Adobe AIR에서 CPU 사용을 줄이는 방법에 대해서 소개했다. 이 글에 Hika님과 찬익님이 그에 대해 댓글을 달아주시며 다른 정보를 공유해주셨다. 정말 감사드린다. 이런 것이 블로그의 매력일 것이다. 블로그를 내 완벽한 지식을 전달하기 위해 쓴다는 것은 다소 어폐가 있다. 완벽한 것은 없다. 블로그는 지식 소통의 도구로 잘 활용하면 좋은 정보 공유를 통한 더욱 완전해지는 지식습득이 가능하게 한다. 난 지난 몇년간 블로그를 하면서 정말 몸소 체험했다. 지금 이글을 보고 있는 분들도 꼭 블로그를 하길 권장한다.

    각설하고. 찬익님이 Flex 4 기반에서 AIR 애플리케이션을 만들때 FrameRate를 조절하는 방법으로 backgroundFrameRate를 소개해주었다. 이것은 Event.ACTIVATE와 Event.DEACTIVATE를 이용해서 이미 Flex 4의
    WindowedApplication 클래스에 적용되어 있다. 아래 코드는 WindowedApplication 클래스의 일부이다.

    /**
    *  Constructor.
    *  
    *  @langversion 3.0
    *  @playerversion AIR 1.5
    *  @productversion Flex 4
    */
    public function WindowedApplication()
    {
    	super();
    
    	addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
    	addEventListener(FlexEvent.PREINITIALIZE, preinitializeHandler);
    	addEventListener(FlexEvent.UPDATE_COMPLETE, updateComplete_handler);
    	addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
    
    	var nativeApplication:NativeApplication = NativeApplication.nativeApplication;
    	nativeApplication.addEventListener(Event.ACTIVATE, nativeApplication_activateHandler);
    	nativeApplication.addEventListener(Event.DEACTIVATE, nativeApplication_deactivateHandler);
    	nativeApplication.addEventListener(Event.NETWORK_CHANGE, dispatchEvent);
    
    	nativeApplication.addEventListener(InvokeEvent.INVOKE, nativeApplication_invokeHandler);
    	initialInvokes = new Array();
    
    	//Force DragManager to instantiate so that it can handle drags from
    	//outside the app.
    	DragManager.isDragging;
    }
    
    /**
    *  @private
    *  Storage for the backgroundFrameRate property.
    */
    private var _backgroundFrameRate:Number = 1;
    
    /**
    *  Specifies the frame rate to use when the application is inactive.
    *  When set to -1, no background frame rate throttling occurs.
    *
    *  @default 1
    *  
    *  @langversion 3.0
    *  @playerversion AIR 1.5
    *  @productversion Flex 4
    */
    public function get backgroundFrameRate():Number
    {
    	return _backgroundFrameRate;
    }
    
    /**
    *  @private
    */ 
    public function set backgroundFrameRate(frameRate:Number):void
    {
    	_backgroundFrameRate = frameRate;
    }
    
    /**
    *  @private
    */
    private function nativeApplication_activateHandler(event:Event):void
    {
    	dispatchEvent(new AIREvent(AIREvent.APPLICATION_ACTIVATE));
    
    	// Restore throttled framerate if appropriate when application is activated.
    	if (prevActiveFrameRate >= 0 && stage)
    	{
    	    stage.frameRate = prevActiveFrameRate;  
    	    prevActiveFrameRate = -1;
    	}
    }
    
    /**
    *  @private
    */
    private function nativeApplication_deactivateHandler(event:Event):void
    {
    	dispatchEvent(new AIREvent(AIREvent.APPLICATION_DEACTIVATE));
    
    	// Throttle framerate if appropriate when application is deactivated.
    	// Ensure we've received an updateComplete on the chance our layout
    	// manager is using phased instantiation (we don't wish to store a
    	// maxed out (1000fps) framerate).
    	if ((_backgroundFrameRate >= 0) && (ucCount > 0) && stage)
    	{
    	    prevActiveFrameRate = stage.frameRate;
    	    stage.frameRate = _backgroundFrameRate; 
    	}
    }
    


    이는 Flex 4를 이용해 AIR 애플리케이션을 만들때 별도의 조치없이 backgroundFrameRate 속성 설정만으로 frameRate를 조절할 수 있다. 이 값은 기본으로 1이다. 더 좋은 값은 0.01이라고 한다. 이는 거의 멈추게 하는 수준이다. 이 속성은 Flex 4에서 AIR를 위해 WindowedApplication 에만 적용되어 있다. Flash기반인 Application 클래스에는 이 속성이 없다.
    참고글
    Adobe AIR에서 CPU 사용을 줄이는 방법

    글쓴이 : 지돌스타(http://blog.jidolstar.com/624)

    Flash Platform 개발자 분들에게 반가운 소식이 있습니다. AIR 2.0 Beta와 Flash Player 10.1 Prelease 버전이 공개되었습니다. 이제 Adobe Labs(http://labs.adobe.com/)에서 직접 다운로드 받을 수 있습니다.


     

    Adobe AIR 2.0 beta

    AIR 2.0은 다음과 같은 새로운 feature들이 추가되었습니다.(영어 압박? 그럼 : http://blog.chanik.com/entry/AIR-20-Beta-릴리즈 )

    • Support for the detection of mass storage devices.
    • Advanced networking capabilities like secure sockets, UDP support, and the ability to listen on sockets.
    • Support for native code integration.
    • The ability to open a file with its default application.
    • Multi-touch and gesture support.
    • New APIs for access to raw microphone data.
    • Webkit update with HTML5/CSS3 support.
    • Global error handling.
    • Improved cross-platform printing
    • Improved security and support for enterprise and government standards.

    AIR 2.0에 대해서 자세한 설명 다음 글들을 참고하세요. 



    AIR 2.0으로 개발테스트 하시려면 다음과 같이 합니다. 윈도우, Flash Builder 4 beta 2 환경을 가정하고 설명드립니다.

    더 쉽게 환경을 구축하고 테스트 해보시겠다면 다음 링크를 참고하세요.
    http://blog.jidolstar.com/619 

     

    1. 만약 Flash Builder를 설치 안했다면 다음 링크를 통해 받으세요.
    2. SDK와 Runtime을 다운로드 받습니다.
    3. 다운받은 Runtime을 실행해 설치합니다.
    4. SDK는 압축을 풀고 그안에 있는 내용을 Flash builder가 설치된 sdks/4.0.0과 sdks/3.4.1 폴더에 각각 덮어씌웁니다. 제 경우는 C:\Program Files\Adobe\Adobe Flash Builder Plug-in Beta 2\sdks\4.0.0
    5. Flash Builder를 실행합니다.
      Windows>Preferences에 들어가 Flash Builder > Installed Flex SDKs를 확인해보세요.
    6. Learn to Use Adobe AIR 2 Beta에 들어가 관련 내용을 학습합니다.
    7. Adobe AIR 2 Sample Applications에 들어가 Sample을 받아보고 실제 Flash Builder에서 작업해봅시다. (해당작업화면을 이미지 캡쳐하고 이런거 너무 힘들어서요. 그냥 말로 주절주절 써봅니다.)
      저는 일단 수많은 예제들중에 Microphone 예제의 소스를 다운로드 받았습니다.
      Flash Builder에서 Flex Project를 생성합니다. 물론 Application Type은 Desktop으로 설정해야겠죠? 예제를 다운받아 사용하므로 프로젝트 이름은 예제 소스 압축을 풀어보면 메인소스의 이름을 선택해주면 됩니다. 저의 경우 MicrophoneExamples군요. 프로젝트를 생성했으면 그 다음으로 Flash Builder에서 방금 생성한 프로젝트를 선택한 상태에서 마우스 오른쪽 버튼을 눌러 Import로 들어갑니다. 창이 뜨면 General > Archive File을 선택하고 다음 버튼을 누릅니다. Browse...버튼을 눌러 다운받은 소스압축파일을 선택합니다. 그리고 Finish하세요. Overwrite할거냐 물으면 Yes To All 을 선택하시면 됩니다. 초반에 sdk 에러가 뜰겁니다. 원본 소스의 sdk 설정이 달라서 그러는데요. 이것을 해결하기 위해 프로젝트명을 선택한후 마우스오른쪽 버튼을 눌러 Properties로 들어가 Flex Compiler를 선택한 다음 Use a specific SDK를 Flex 3.4로 선택해주시면 됩니다. 4.0이 아닌 이유는 예제 소스가 mx:WindowedApplication으로 만든 것으로보아 Flex 3.4 기반으로 만들어졌기 때문입니다. 다른 예제가 s:WindowedApplication으로 만들어져 있다면 Flex 4.0을 선택하세요. 다 끝났습니다. 이제 실행해보세요.


      앗... 제 데톱에 마이크가 없군요... ㅡㅡ; 아무튼 이렇게 하면 됩니다. Sample에는 Flex뿐 아니라 Ajax, Flash용도 있으니 잘 활용하시면 학습하는데 도움이 될겁니다.

     

    Flash Player 10.1 Prelease

    Flash Player 10.1의 가장 큰 특징은 바로 모바일 지원입니다. 제 블로그에서 앞서 설명했지만 Flash Player 10.1은 오픈소스프로젝트를 통해 탄생된 결과물입니다. 데스크탑 뿐아니라 다양한 기기에서도 Adobe Flash Platform 기술이 적용될 수 있도록 Flash Player 10.1을 만든겁니다. 이는 모바일과 같이 저급(?) 하드웨어 기반에서 항상 이슈가 되어 왔던 메모리, 전력소비, 속도, 하드웨어가속등의 문제를 해결한 Flash Player를 만들었다는 것을 의미합니다. 이외에도 차세대 모바일에 걸맞는 몇가지 기능(멀티터치등)을 구현할 수 있는 API도 추가되었죠. 또한 H.264 비디오도 지원해줍니다.

    Flash Player 10.1에 대해서 더욱 자세히 알고 싶다면 Flash Player 10.1 Beta Release Notes를 참고하시면 될 것 같습니다.

    Flash Player 10.1 기반의 프로그램을 개발하고 싶다면 Flash Player 10.1 플러그인을 자신의 컴퓨터에 먼저 설치한뒤 Player Global SWC를 다운받아 개발하면 됩니다. 일련의 절차를 간단하게 설명드립니다.

    참고로 Flash Player 10.1은 정식 배포버전이 아닙니다. 테스트 목적으로 하시고 실제 배포는 하지 마세요.

    Flash Player 10.1 플러그인을 http://labs.adobe.com/downloads/flashplayer10.html 에서 다운로드 받습니다. 기존에 설치된 Flash Player는 삭제를 하시고 설치하세요. 윈도우의 경우 파이어폭스와 모질라 계열이라면 Download plug-in for Windows (EXE, 2.2 MB)를 받고 IE라면 Download active-x for Windows (EXE, 2.2 MB)를 다운로드 받으세요. 아쉽게도 개발자를 위한 디버그 버전은 아직 없는 것 같습니다.

    Flash Player 10.1 기반 개발을 위해 해당 API로 개발할 수 있도록 지원해주는 SWC를 다운로드를 같은 페이지에서 받을 수 있습니다. 다운받아 압축을 풀면 playerglobal.swc가 있습니다. 이것을 자신의 프로젝트에 포함하여 개발하면 됩니다. 함께 포함된 readme.txt파일을 보면 사용하는 방법이 잘 나와 있는데 여기서도 간단히 설명해 드리죠. (단, Flash Builder 4 beta 2 기준입니다.)

    1. 만약 Flash Builder를 설치 안했다면 다음 링크를 통해 받으세요.
    2. 새로운 애플리케이션 프로젝트를 만듭니다.
    3. playerglobal.swc를 playerglobal10.1.swf로 이름을 바꾸고 만들어진 프로젝트의 libs폴더에 복사합니다. libs폴더에 복사하면 자동으로 Referenced Libraries로 설정됩니다. (여기서 이름을 바꾼 이유는 다음 내용을 설정할 때 playerglobal.swc의 Link Type을 수정못하도록 Flash Builder가 만들어져 있기 때문입니다.)
    4. 프로젝트명을 선택후 마우스 오른쪽 버튼을 눌러 properties를 선택한 뒤 Flex Builder Path를 선택합니다. 그런 다음 Library path 탭을 선택한뒤 libs 폴더를 열어 Link Type을 External로 바꿉니다. 그런 다음 Flex 4.0 를 열어 기존 playerglobal.swc는 삭제합니다. Link type이 External이라는 것은 컴파일시 사용한 클래스를 빼놓는다는 뜻입니다. 어짜피 playerglobal.swc에 정의된 클래스는 이미 Flash player 10.1에서 지원해주기 때문에 굳이 swf안에 포함할 필요가 없기 때문이지요.
    5. Flash Player 10.1을 요구하는 HTML이 되도록 만들어주기 위해 Properties 창에서 Flex Compiler를 선택합니다. Adobe Flash Player options에서 Use a specific version을 10.1.0으로 바꾸거나 Additional compiler arguments에 -target-player=10.1.0 을 추가합니다.

    이로써 Flash Player 10.1 에서 돌아가는 Flash 애플리케이션을 만들때 환경 구축을 모두 완료했습니다.

    아래처럼 Flash Player 10.1 API인 TouchEvent, TransformGestureEvent 등을 사용할 수 있게 되었습니다.



    아래 링크를 통해 Flash Player 10.1에 대한 다양한 정보를 얻을 수 있습니다.


    앞으로 정식버전이 배포되고 Flash CS5도 나오게 되면 아이폰 및 다양한 기기에서 동작하는 재미있는 애플리케이션들을 만들 수 있게 될 것입니다. 

    Flash Platform 개발자들이여.. 향후 10년 밥벌이 벌었습니다. ㅋㅋㅋ


    글쓴이 : 지돌스타(http://blog.jidolstar.com/617)
     

    지난 2009년 10월 5일부터 7일까지 3일간 어도비(Adobe)에서 주최하는 컨퍼런스인 Adobe MAX 2009행사에 참여하기 위해 일주일간의 일정으로 미국 LA에 다녀왔다. ACC(Adobe Community Champion)의 구성원 중에 올해는 필자를 포함한 3명이 발탁되어 이번 행사에 행사참여비를 비롯한 모든 여행경비를 거의 전액 무료로 참여하게 되었다. Adobe MAX는 Adobe의 새로운 기술과 트렌드를 공개하는 큰 행사이다. Adobe Flash Platform에 관련된 기술에 항상 관심을 가지고 지켜본터라 이번 행사의 참여는 개인적으로 매우 즐겁고 흥미로운 경험이였다.

    행사 일정은 3일이였으나 전체 미국에서의 일정은 1주일이였기 때문에 행사 일정을 제외한 나머지 시간은 LA를 둘러보는 시간도 가질 수 있었다. 개인적으로 LA에 동서댁이 살고 있어서 행사끝나고 가족상봉도 이룰 수 있어서 정말 좋은 시간이였다. 

    3일간 열리는 이번 Adobe MAX 2009행사는 노키아 극장에서 열리는 2번의 키노트 행사와 LA 컨벤션 센터에서 주제별 세션이 있었다. 키노트는 한 장소에서 모든 행사 참여자가 경청할 수 있으며 전체 흐름과 주제를 파악하는데 필요한 거의 모든 내용을 다룬다. 키노트 행사에는 수천명의 사람들이 참여한다. 반면 주제별 세션은 많게는 100명 적게는 30~40명 정도 들을 수 있는 방에서 자신이 원하는 세부적인 내용을 들을 수 있는 자리이다. 세션은 제품군, 주제, 난이도 등으로 나눠서 입맛에 맞게 골라 경청하거나 실험해 보는 자리로 꾸며진다.

    Adobe MAX 행사 참여로 누구보다 가장 빠르게 Adobe 신기술을 접할 수 있으며 또한 미국 또는 세계에서 온 각계각층의 다양한 사람들이 이 행사에 참여하기 때문에 안목을 높힐 수 있는 계기를 만들어주었다고 생각한다.

    이 글은 이번 행사를 통해 필자가 알게된 Adobe의 신기술 및 트렌드를 소개하는 것을 목적으로 한다. 

    내용중에 필자의 주관적 진술이 많이 포함되어 있다. 즉 Adobe의 정책이나 방향을 말하고 있지만 그에 대한 전망에 대한 개인적인 의견이지 Adobe의 실질적인 정책은 아님을 미리 말해둔다.


    오픈 스크린 프로젝트 - 디지털 기기간에 장벽제거


    이번 Adobe MAX에서 Flash Platform에 관심이 있는 개발자라면 바로 Flash Player 10.1과 AIR 2.0에 대한 언급이 아니였을까 생각한다. 이들 기술은 더욱 다양하고 강력한 API를 제공할 수 있게 되었다. 그러나 이 기술 자체만 관심가지는 것보다 그 기술에 어째서 만들어졌는가? 더 나아가 Adobe는 왜 이런 기술을 만들어냈는가 관심을 가져야할 것이다.

    Flash Player 10.1과 AIR 2.0은 오픈 스크린 프로젝트(Open Screen Project)의 첫번째 결실이다. 오픈 스크린 프로젝트는 지금까지 데스크탑 컴퓨터 환경을 뛰어 넘어 텔레비전, PC, 모바일 장비, 각종 소비자 가전제품등의 디지털 기기간에 호환성을 보장해주고 다양한 사용자 경험을 선사하기 위한 프로젝트이다. 이 말을 쉽게 이야기 하자면 다양한 기기에 Flash 및 AIR 애플리케이션이 운용될 수 있도록 각종 디지털 기기 업체와 협력하는 프로젝트인 것이다. 애초부터 Adobe Flash Platform 기술은 웹에서 시작해 데스크탑으로 또 각종 운영체제(Windows, Mac, Linux 등)를 지원해왔다. 하나의 애플리케이션이 다양한 환경에서도 동작하게 하기 위한 전략을 세웠던 Adobe가 이를 더 확장하기 위한 정책으로 만든 프로젝트가 바로 오픈 스크린 프로젝트인 것이다.

    오픈 스크린 프로젝트에 참여한 기업은 한국의 삼성, LG를 비롯해 Nvidia, 노키아, 모토로라, 인텔등 다양한 기기 업체들을 포함한다. 또한 각종 컨텐츠 업체들도 참여했는데 대표적으로 구글이 있겠고 BBC, MTV Networks, NBCUniversal 등도 이 프로젝트에 참여했다.

    Adobe는 자사의 기술을 널리 활용될 수 있도록 다음과 같은 적극적인 오픈 정책을 실현해왔다.
    • SWF, FLV/F4V 스팩 사용 제한을 없앰.
    • 어도비 플래시 플레이어용 모바일 단말기 포팅 레이어(APIs)를 퍼블리싱.
    • 어도비 플래시 케스트 프로토콜 및 대용량 데이터 서비스용 AMF 프로토콜을 퍼블리싱.
    • 디바이스용 어도비 플래시 플레이어와 AIR 제품의 차기 버전의 라이센스를 무상 제공.

    오픈 스크린 프로젝트의 첫번째 결실이 Flash Player 10.1과 AIR 2.0 이라고 이미 언급했다. 그럼 어째서 이 기술이 이 프로젝트의 결실물이 되는 것인가? 가장 중요하게 보아야 할 것을 뽑는다면 기능, 메모리, 속도, 전력소비량이 아닌가 생각한다.

    기능적 측면으로 Flash Player 10.1는 멀터터치가 지원되고 AIR 2.0의 경우 다양한 USB 디바이스 지원, 소켓서버, UDP통신 다양한 설치 포멧(dmg, exe등)등을 지원하게 된다. 이러한 기능이 지원된데에는 기존의 부족한 기술을 업그레이드 시키는 것외에도 오픈 스크린 프로젝트와 연관되어 사용자에게 다양한 경험을 주기 위한 것이다. 가령 요즘 모바일에 멀티터치는 기본기능으로 들어간다. 이러한 기능을 Flash 애플리케이션으로 사용할 수 있도록 한것이다. 기능은 단순히 기술을 돋보이게 하는 것이 아니라 철저한 정책 바탕위에 만들어진다.

    다양한 기기에서 Flash 컨텐츠가 문제없이 돌아가야 하므로 메모리, 속도, 전력소비량을 생각하지 않을 수 없을 것이다. 특히나 모바일과 같은 기기에서는 메모리, 속도, 전력소비량을 어떻게 최적화 시키느냐가 관건이 된다. 이는 오픈 스크린 프로젝트를 실현하기 위한 중대한 기술적 이슈로 Adobe의 노력의 결실이 이번 Adobe MAX를 통해 공개된 것이다.

    메모리의 경우 매우 괄목할 만한 성장을 보였다고 할 수 있다. 아래 그림은 키노트 당시 화면으로 각종 애플리케이션에서 기존의 Flash Player 10과 새 Flash Player 10.1 간에 메모리 사용량을 비교하고 있다. 2~3배의 메모리 사용량을 줄였음을 볼 수 있다.

    다음으로 전력소비량이다. 전력소비량도 다음 키노트 영상에서 볼 수 있듯이 모바일 기기에서 운영되는 Flash 컨텐츠가 얼마나 전력을 소비하는가 절대적 수치로 보여주고 있다. 일반적인 동영상의 경우 3.4시간, 애니메이션이 들어간 컨텐츠의 경우 6.5시간, 마지막으로 저전력 모드에서 14.5시간까지 유지할 수 있다고 한다.

    마지막으로 빼놓을 수 없는 것이 속도이다. 다양한 기기들 중에 모바일에서 움직여야하는 컨텐츠의 경우에는 적은 CPU연산으로 속도를 빠르게 하거나 GPU 가속이 필요할 것이다. 오픈 스크린 프로젝트에 참여한 Nvidia가 그것을 실현하는데 결정적인 역할을 하게 되었다. 노트북, 넷북, 스마트폰, 스마트북 등 Nvidia 지포스와 아이온, 테그라 플랫폼 등에 쓰이는 Nvidia GPU의 지원으로 낮은 전력과 CPU점유율을 Flash Player 10.1부터 가능하게 해주었다. 이로써 모바일 기기에서도 HD급 영상을 부드럽게 재생할 수 있게 되었다. 다음 동영상은 이번 키노트를 통해 공개된 속도의 최적화를 단적으로 보여준 동영상이다.



    이처럼 Adobe는 오픈 스크린 프로젝트를 통해 Flash Player 10.1과 AIR 2.0을 탄생되었으며 이들 기술은 기능, 메모리, 전력소비량, 속도등의 개선에 큰 성과를 거두었다.

    세계 전 PC에 99%이상 Flash Player가 설치되었으며 이미 두터운 사용자 층을 다지고 있는 Flash Platform 기술이 이제 Flash 애플리케이션이 모바일, 텔레비전등에도 동작하게 하는 것은 Adobe가 오래전부터 바래왔던 RIA(Rich Internet Application)의 참모습을 보여주기 위한 것이 아닌가 생각된다.

    오픈 스크린 프로젝트의 가장 큰 성과는 바로 엄청난 수의 디자이너와 개발자들이 그들이 가진 자산과 자원을 그대로 사용할 수 있다는 것에 있다. 이로써 Flash Platform 기술을 이용하는 업체들에게 시간과 자본을 매우 줄이는 결정적인 역할을 하게 된 것이다. 이전에 모바일의 Flash 컨텐츠는 Flash Lite로 ActionScript 2.0 기반하에서만 개발할 수 밖에 없는 한계가 있었다. 그러나 이 한계를 기존 Flex, Flash, ActionScript 3.0 기술을 그대로 이용해 데스크탑 뿐 아니라 각종 다양한 기기에도 운영할 수 있는 애플리케이션을 만들 수 있도록 기술적, 정책적 문제를 오픈 스크린 프로젝트를 통해 해결한 것이다. Adobe는 이제 Cross OS, Cross Browser를 넘어 Cross Device를 실현하기 위한 디딤돌을 제대로 만든 셈이다.

    불행히도(?) Apple은 오픈 스크린 프로젝트에 참여하지 않았다. 하지만 Adobe는 Adobe Flash Professinal CS5 베타버전을 선보이며 ActionScript 3.0 기반으로 iPhone용 애플리케이션을 만들어 시연하는 모습을 보여줌으로써 Flash Player가 iPhone에 탑제되어야 한다는 문제를 말끔히 씻었다. Adobe Labs에서는 CS5에 대한 설명 및 이를 이용해 만든 iPhone 애플리케이션을 소개하고 있다.

    http://labs.adobe.com/technologies/flashcs5/



    더 자세한 내용은 오픈 스크린 프로젝트 공식 홈페이지에서 알 수 있으니 참고바란다.

    오픈 스크린 프로젝트 공식 홈페이지 : http://www.openscreenproject.org/


    플래시 플랫폼 서비스 - Adobe의 강력한 유통 채널


    Adobe가 오픈 스크린 프로젝트 프로젝트를 통해 다양한 기기, OS등에 지원하도록 하는 것은 단순히 Flash컨텐츠를 공급하여 자사의 컨텐츠 제작도구를 팔기 위한 것만은 아니라고 생각한다. 물론 지금까지 Adobe는 PhotoShop, CS4, Flex Builder, LCDS등의 다양한 제품을 팔아 이윤을 남겨 회사를 운영했다고 본다. 그런데 몇년전부터 Adobe는 자사의 핵심 기술을 무료로 공개하기 시작했다. 물론 그것이 컨텐츠 제작도구는 아니지만 제품 외에 다양한 기술을 아무 댓가가 없는 것 마냥 공개하기 시작한 것이다. 이미 실시간 메세지 전송 프로토콜인 RTMP과 데이터 통신의 핵심의 일부를 BlazeDS등를 제작해 오픈 소스로 공개하고 있다. 누구든지 오픈소스 홈페이지를 통해 Adobe에서 제작한 소스를 볼 수 있다.

    요즘은 공개가 주요 덕목이라고는 하지만 Adobe가 자사의 기술을 이렇게 공개하는 이유는 무엇일까? 또한 오픈 스크린 프로젝트를 통해 Flash 컨텐츠가 다양한 자원, 기기들을 지원할 수 있도록 한 배경은 무엇일까? 이 이유에 대한 답은 이외로 간단하다. 회사는 영리를 목적으로 한다. Adobe도 건실한 하나의 회사이므로 당연히 영리를 목적으로 한다. 영리를 취하기 위한 방편으로 Adobe가 생각한 것은 바로 유통이다.

    iPhone, iPod을 사용하는 사용자라면 Apple Store에 대해서는 너무도 잘 알것이다. iPhone이라는 매우 훌륭한 기기를 만든 것도 사실이지만 Apple은 더 앞서 이들 기기에 사용할 애플리케이션이 널리 보급되고 공개될 수 있는 유통 채널을 Apple Store를 통해 확보했다. 애플리케이션 개발업체 및 개인 개발자는 Apple Store를 통해 자신의 애플리케이션을 팔 수 있고 그 이윤의 일부를 Apple이 가진다. 얼마 안되는 액수이긴 하지만 이것이 쌓이면 엄청나다. 이런 유통 채널로 무수한 애플리케이션이 만들어졌고 미려한 iPhone의 디자인에 흠뻑 반한데다가 다양한 컨텐츠까지 접할 수 있는 고객입장에서는 iPhone을 선택하지 않을 수 없게 되었다. 어디 그뿐인가? 이것으로 Apple의 매출을 최고조를 이루고 있고 자사의 회사 이미지도 상승하여 다른 제품군들의 매출도 상승하게 되었다. 이 점에서 필자가 생각하는 Apple의 가장 큰 성공요인은 유통이라고 생각한다.

    Adobe는 Apple보다 늦었지만 분명 유통의 강점을 잘 알고 있었을 것이라 생각한다. 유통을 적절하게 해서 성공한 Apple의 사례는 Adobe에게 좋은 간접 경험이 되었으리라 판단한다. 그럼 구체적으로 Adobe는 어떻게 유통을 하겠다는 것인가?

    플래시 플랫폼 서비스(Flash Platform Services)는 Apple Store처럼 유통채널을 만들기 위한 첫단추라고 생각한다. 이번 Adobe MAX 2009 키노트에서는 이에 대해 많은 부분 소개하진 않았다. 하지만 이번에 Flash Platform Service을 공개함으로서 Adobe도 Flash 컨텐츠 유통 시스템을 만들고 있다는 것을 예상할 수 있게 되었다. 

    플래시 플랫폼 서비스는 배포(Distribution), 협업(Collaboration), 소셜(Social)이라는 3가지 키워드로 요약된다.

    배포 서비스는 말그대로 Flash Platform 애플리케이션이 배포될 수 있는 공간을 만들어 준다는 것이다.
    이 서비스는 만들어진 Flash애플리케이션을 마이스페이스나 페이스북과 같은 소셜 서비스와 모바일 기기, 데스크톱등에 배포하기 위한 일련의 복잡한 절차를 해소 시켜주고 각종 프로모션 및 광고를 쉽게 해주고 각종 통계까지 내준다. 배포 서비스에 대해 더욱 자세히 알기 위해 다음 링크와 동영상을 참고한다.

    Flash Platform Distribution Service : http://www.adobe.com/flashplatform/services/distribution/

    협업 서비스는 Adobe가 Adobe자체 기술을 지원해준다는 말이다. 가령, 채팅, 오디오, 비디오 서비스등은 일반 개발자뿐 아니라 회사에게 자체 서버가 있어야하는 기술적, 자금적 부담감이 존재한다. 이런 어려운 부분을 Adobe에서 지원해준다는 이야기이다. 다음 링크로 부터 이 협업 시스템의 형태와 Showcase를 볼 수 있겠다.
     
    Flash Platform Collaboration Service : http://www.adobe.com/flashplatform/services/collaboration/
    Flash Platform Collaboration Service Showcase : http://www.adobe.com/devnet/flashplatform/services/collaboration/showcase/

    소셜 서비스은 페이스 북과 마이 스페이스와 같은 소셜 네트워크와 통합해서 이를 가지고 개발할 수 있도록 하는 서비스이다. 하지만 현재 공개되어 있지 않다. 이미 Open API를 통해 매쉬업 애플리케이션들이 만들어져 있고 그 중요성 또한 높아지고 있다. 이것을 더욱 쉽고 강력하게 할 수 있도록 소셜 서비스를 통해 지원해준 다는 것을 의미한다. 

    위에서 언급한  3가지 키워드를 바탕으로 플래시 플랫폼 서비스로 하여금 유통채널을 만들어 가겠다는 의미로 필자는 받아 들였다. 아직 많은 부분 완성되지 않았지만 앞으로 Flash Player 10.1 및 AIR 2.0 배포되고 이를 지원하는 다양한 디지털 기기들이 판매되며 또한 플래시 플랫폼 서비스의 3가지 키워드가 완성이 된다면 새로운 Flash 컨텐츠 유통채널이 만들어져서 기존 Flash Platform 개발자의 유입이 증대될 것이고 더불어 관련 애플리케이션도 많아져 결국 사용자의 경험을 극대화 시키는 효과와 함께 이것을 수용한 기술 및 제품이 잘 팔리게 되는 효과를 기대할 수 있을 것이라 생각한다. 결국 자사 만족, 개발자만족, 고객만족을 위한 Adobe의 정책이라 할 수 있다.

    이미 두텁케 형성된 Flash 컨텐츠 개발자들은 플래시 플랫폼 서비스를 통해 기존 기술을 맘껏 이용해 개발과 배포를 쉽게 할 수 있다. 그리고 각종 기기 및 기술적 어려운 부분은 오픈 스크린 프로젝트를 통해 그 문제를 해결한다. 이들 모두가 결국 Flash 컨텐츠의 유통을 실현하기 위한 정책의 일환임을 알 수 있다.

    Flash Platform Services 공식 사이트 : http://www.adobe.com/flashplatform/services/
    Flash Platform Services 개발자 센터 : http://www.adobe.com/devnet/flashplatform/services/


    정리하며
    Adobe MAX 2009 행사는 개인적으로 어떤 기술적인 답변을 얻었다것 외에 Adobe가 지향하는 정책에 대한 로드맵을 더욱 이해하는데 도움이 된 자리였다고 생각한다. 어짜피 기술은 계속 발전한다. 기술이 기술자체로 끝나는 것이 아니라 그 방향성이 더 중요하고 결국 사용자에게 감동을 주어야 그 기술이 빛을 발할 것이라 생각한다.

    Adobe가 Flash Platform의 확산을 위해 오픈 스크린 프로젝트(Open Screen Project)와 플래시 플랫폼 서비스(Flash Platform Services)라는 여러가지 대안을 마련하여 이에 기술이 뒷받침 되도록 방향성을 맞추어가고 있다는 것을 염두한다면 Flash Platform 관련 기술 적용에 더욱 도움이 될 것이라 생각한다.

    글쓴이 : 지돌스타(http//blog.jidolstar.com/610)

    + Recent posts