오랜만에 Adobe Labs를 가봤는데 마침 Flash Builder 4, ColdFusion Builder, Flex 4 SDK가 베타 딱지를 떼고 정식으로 배포되기 시작했네요.

  • Adobe ColdFusion Builder
  • Adobe Flash Builder™ 4
  • Adobe Flex® 4 SDK

    위 링크를 통해 자세한 정보를 볼 수 있습니다.
  • 추가사항 1
    정영훈님께서 유용한 댓글을 달아주셨습니다. 이클립스에 Flash Builder를 Plug-in 형태로 설치할 때 멈추는 현상이 있는데 아래 내용으로 문제를 해결할 수 있습니다.

    설치할때 우선 압축을 풀게 되는데 그 경로를 지정할 수가 있습니다.
    그 압축을 푸는 경로에 하글이 섞여 있으면 설치가 안됩니다.

    xp에서는 바탕화면 에 압축을 풀게 딜포트 설정으로 나옵니다
    그 경로를 한글이 없는 경로로 수정하면 설치가 가능합니다.


     

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



    ACC의 오창훈님과 이문국님이 직접 제작한 Adobe Flash Platform 탐구생활 동영상입니다.

    동영상의 좌측 상단을 누르시면 Flash Builder와 Flash Catalyst의 베타버전을 무료로 다운로드 받을 수 있습니다. ^^

    Flash Builder 100배 즐기기



    Flash Catalyst 100배 즐기기


    출처 : http://www.adoberia.co.kr/trial_down/main.html

    지난 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로 바꾸면 되겠다.


    Flash Builder 4 Plugin을 설치후 기존 프로젝트로 열었을때 황당한 문제에 봉착했다. 아래 그림처럼 툴바에 Run, Debug 버튼이 없어진 것이다.


    한번도 이런적이 없어서 몇시간 당황했는데, 해결방법은 이외로 간단했다.

    먼저 툴바위에 마우스 오른쪽 버튼을 눌러 Customize Perspective 를 선택한다. 또는 메뉴에서 Window > Customize Perspective 를 선택하면 되겠다. 그럼 다음과 같은 창이 나온다. 여기서 Command 탭을 선택한다.

    위 그림과 같이 왼쪽 Available command groups에 Launch를 체크한뒤 OK버튼을 누른다.



    휴~ 이거 하나 알아낼려고 엄청 힘들었다. 별것도 아닌것이... ㅎㅎㅎ

    Flash Builder 는 언제든지 다운받을 수 있다. 다음 링크를 참고바란다.
    http://www.adoberia.co.kr/pds/down.html?src=text&kw=000026 

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

    독립형 FB4(Flash Builder 4)를 사용하지 않고 굳이 Eclipse에 FB4 plugin을 설치하는 이유는 독립형 FB4는 기능의 제약점이 있기 때문이다. 물론 FB4로도 충분히 개발이 가능하지만 Eclipse와 연동하는 것은 이 편이 실무에 더욱 적합하다. 그 이유는 hika님의 글 Flex Builder는 반드시 Plug in 으로 설치 글을 읽어보면 알 수 있다.

    하지만 이러한 설치법은 처음 해보는 사람에게는 단순하지 않다. 한방에 설치하는 독립형 FB4에 비해 이것저것 고려할 것이 많은 것 같은 생각이 들기 때문이다. 이 글을 쓰는 목적은 FB4 plugin을 설치를 하는데 있어서 다소 어려움을 쉽게 극복하기 위한 방법을 소개하기 위함이다.

    설치하는 대략적인 순서는 hika님이 매우 잘 설명해 주었다.
    Flex Builder는 반드시 Plug in 으로 설치

    그러나 더욱 자세한 방법은 Chocodonut님의 글대로 하면 되겠다.
    Flex Builder 3 Professional Eclipse plug-in 설치

    FB4도 위 글과 거의 동일한 방법으로 설치하지만 아래와 같은 몇가지 체크할 사항이 있다. (단, 본인은 Window XP환경에서 테스트 했음을 언급한다. Mac이나 Linux의 경우 아래에서 지적한 문제가 있을지는 테스트해보지 않았다.)

    1. Eclipse는 Ganymede를 설치한다.
    먼저, Eclipse버전은 Ganymede RC2 버전을 이용하기 바란다. 최신 버전인 Galileo는 제대로 설치되지 않는다.
    http://www.eclipse.org/downloads/
    에서 화면 오른쪽에 Older Versions를 선택한 뒤 Eclipse Ganymede SR2 Packages로 들어간다. 여기서 Eclipse IDE for Java EE Developers를 다운로드 받으면 되겠다. 아래 링크로 직접가도 되겠다.
    http://www.eclipse.org/downloads/packages/release/ganymede/sr2

    다운받은뒤 설치를 원하는 곳에 압축을 풀면 설치가 완료이다. 설치완료후 반드시 한번이상 실행해준다.

    만약 Galileo버전을 사용하고 싶다면 굳이 말리지 않는다. ^^
    다음 글을 참고한다.
    http://blog.naver.com/joycestudy/100090900907


    2. Eclipse실행시 JVM terminated. Exit code=-1 에러가 발생하는 경우
    Eclipse 설치폴더에 eclipse.ini를 열어 다음과 같이 수정한다.
    -showsplash
    org.eclipse.platform
    --launcher.XXMaxPermSize
    256M
    -vm
    C:\Program Files\Java\jdk1.6.0_07\bin\javaw.exe
    -Dosgi.requiredJavaVersion=1.5
    -vmargs
    -Xms40m
    -Xmx512m

    원래 eclipse.ini에서 수정된 부분은 -vmargs의 위치가 -Xms40m 바로 위로 이동된 것이며 추가된 부분은 -vm 부분이 들어간 것이다. 이때 javaw.exe 경로는 각자 jdk또는 jre 설치 경로를 따라 설정하면 되겠다. 이렇게 해도 같은 에러가 난다면 검색을 통해 다른 방법을 찾길 바란다.


    3. Flash Builder 4 plug in을 설치시 반드시 Eclipse 설치경로를 지정해줄것!
    FB4 plug in을 설치하면 중간에 Eclipse설치 경로를 지정하는 순서가 있다. 이 부분을 잊지 말고 Eclipse 경로를 지정하기 바란다.


    4. FB4를 실행할때는 Eclise를 실행하거나 FB4에 설치된 Run FB Plug-in with alternate Eclipse를 실행한다.
    FB4 plug-in에서 Run FB plug-in 을 실행하면 eclipse-host-distro의 Eclipse가 실행되므로 이것을 사용하지 말자.

    5. 바로가기를 FB4 아이콘으로 바꾸기
    일반적으로 Eclipse를 실행하기 위해 바탕화면에 바로가기를 만들거나 빠른실행아이콘으로 등록해서 사용할 것이다. 하지만 이 바로가기는 기본 아이콘이 이클립스이다. 그러므로 기존에 사용하는 이클립스 아이콘이 있다면 무엇이 Flash Builder이고 무엇이 Eclipse인지 잘 분간이 안갈터...

    바로가기의 아이콘을 Flash Builder 아이콘으로 바꿔보자.
    1. Flash Builder Plug-in이 설치된 폴더로 가서 eclipse-host-distro 폴더에 가면 Eclipse.ico 파일이 있다. 이것을 복사해서 Eclipse 설치 폴더에 복사한다.
    2. 다음으로 바탕화면 또는 빠른실행아이콘을 선택해 마우스 오른쪽 버튼을 눌러 속성을 선택한다.
    3. 아이콘 변경 버튼을 눌러 Eclipse 설치 폴더에 복사한 Eclipse.ico로 바꿔준다.

    이제 근사하게 Flash Builder 아이콘을 가진 바로가기를 만들 수 있게 되었다.


    6. 이전 워크스페이스를 열때 만약 Run, Debug 버튼이 사라진다면!
    다음 글을 참고한다.
    Flash Builder/Flex Builder의 툴바에서 Run, Debug Launch 버튼이 없어진 경우 해결법


    7. 이전 워크스페이스의 SDK경로는 따로 빼자!
    Flash Builder의 SDK가 아닌 기존에 원래 사용하던 SDK를 참조할 필요가 있는 경우가 있다. 이런 문제를 해결하기 위한 방법은 여러가지가 있겠지만 본인은 C나 D 드라이브로 SDK폴더를 따로 만들어 FB가 이 SDK를 참조하도록 하고 있다.

    다음과 같이 진행한다.

    1. C나 D 드라이브등에 사용할 SDK를 복사한다.(새 FB의 설치경로에 sdks에 있는 파일을 복사할 수 있다.)
    2. FB를 실행한다.
    2. 메뉴에서 Window > Preference를 선택한다.
    3. 창이 뜨면 좌측에 Flash Builder를 열어 Installed Flex SDKs를 선택한다.
    4. 우측에 Flex 3.4, Flex 4.0이 이전 FB버전의 경로를 참고하고 있을 것이다. 이를 C나 D드라이브에 복사한 SDK를 참조하도록 한다.


    8. 기본 플러그인 설치는 기본!
    독립형 FB4에는 설치되지 않는 플러그인이 Eclipse에는 언제든지 설치가 가능하다. 주로 협업이 이뤄지므로 SVN등을 설치해야하고 다양한 배포 경로를 확보하기 위해 ANT관련 설정이 필요할 것이다. C/C++개발을 위한 CDT, PHP개발을 위한 PDT등 플러그인을 제한없이 설치할 수 있으니 Eclipse의 FB4 plugin을 설치하는 편이 훨씬 득이라는 것을 느낄 수 있을 것이다.

    다음글들을 참고하면 좋겠다.
    Flex Builder 에서 Subversion(SVN) 사용하기
    Flex Builder 3에서 ANT 사용하기
    Maven 시작하기


    정리하며
    사실 위에 제시한 사항들은 개인적으로 사용하는 방법이다. 꼭 그렇게 따라할 필요 없으며 필요시 참조하면 무난할 것이라 판단한다.

    실무에 종업하시는 분들은 왠만하면 FB4 플러그인을 사용하고 있다. hika님의 블로그에 실무를 통해 자주 사용하는 설정정보를 정리해두었으니 참고 바란다.

    플래시를 위한 이클립스 기본 설정

    다음 글들은 이외에 개발에 큰 도움이 되는 글이니 참고 바랍니다.
    플래시 어플리케이션 개발하기
    플래시 프로젝트 생성하기


    다운로드
    Flash Builder 및 갖가지 Adobe 제품군을 다운로드 받으려면 다음 링크를 참고하세요.
    http://www.adoberia.co.kr/pds/down.html?src=text&kw=000026

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


    어제 무사히 Flex 기술세미나를 마쳤습니다.

    (비트기술세미나라고 명칭되어 있었네요. 그게 좀 전달이 안된 것 같네요.)

     

    무려 200개의 자리를 꽉 채울 정도로 많은 분들이 밤 늦은 시간까지 경청하시고 가셨습니다. 정말 수고 많으셨어요. ^^

     

    세미나에서 옥상훈님께서는 UX(User Experience)에 대해서 매우 자세히 잘 말씀해주셨습니다. UX에 대해 다시 한번 생각해보는 계기가 되었구요. 또 배준균님께서 BlazeDS에 대해 현업에서 어떻게 쓰일지에 대해서 자세히 말씀해 주셨습니다. 아쉽게도 인터넷이 잘 안되어서 난감해 하셨는데... 알고보니 그거 유동IP가 아니라 고정IP였다는... ^^

     

    저는 Flex 4에 대해 설명드렸습니다. 사실 저도 Flex 4를 공부한다는 마음을 가지고 이번 세미나 주제로 다룬겁니다. 덕분에 저도 열심히 공부할 수 있었고 많은 분들에게 Flex 4에 대해서 처음으로 소개할 수 있게 되어서 기분도 좋았답니다. 하지만 시간이 촉박해서 마지막에 질의시간을 가지지 못한 것 죄송합니다.

     

    Flex 4에 대해 잠깐 언급했고 Flex 4를 이용해서 개발하는 툴인 Flash Builder 4와 Flash Catalyst에 대해서 소개했습니다. CSS, FXG, Namespace, State, Data Binding, Effect, None Visual Component 다루는 법, Spark Component와 Spark Layout 등에 대해서 약간 맛배기 정도로 다뤘습니다. 사실 소개드린 하나하나가 무거운 주제로 다루어도 몇시간씩은 해야하는 것들입니다. 그러므로 더 깊이 있는 공부를 위해서 관련 내용을 프리젠테이션에 있는 링크를 보시고 습득하시길 바래요.


    아래 파일은 어제 발표했던 프리젠테이션 파일입니다.


     

    아래 파일들은 어제 다뤘던 예제입니다.

     

    invalid-file

    출처 : http://evtimmy.com/2009/06/wheellayout-source-and-quick-mashup/

     

    아래 두개는 시간이 없어서 소개하지 못한것인데 Flex 4를 이용해 컴포넌트를 만든 예제입니다. (제가 만든거 아닙니다. ^^)

    invalid-file

    출처 : http://www.hulstkamp.com/2009/07/09/custom-popup-rating-component-in-spark-flex-4-gumbo/464

    invalid-file

    참고 : http://blog.jidolstar.com/570

     

    위 예제를 실험하기 위해서는 Flash Builder 4를 다운 받아야겠지요?
    http://www.adoberia.co.kr/pds/down.html?src=text&kw=000026 

    위의 예제는 Flash Builder 4에서 import 해서 사용할 수 있는데 다음과 같이 해보세요.

    1. Flash Builder 4를 실행
    2. File > New > Flex Project를 통해 Project를 생성
    3. File > Import > Other 선택
    4. 새창이 뜨면 General > Archive File 선택 후 Next 버튼 클릭
    5. "From archive file"에서 Browse 버튼을 클릭하여 위 Zip파일중 하나를 선택
    6. "Into folder" 에서 Browse 버튼을 눌러 새로 생성한 프로젝트를 선택후 Finish 버튼 클릭 (진행도중 Overwrite 경고 뜨면 모두 Overwrite합니다.)
    7. src 폴더에 들어간 mxml파일은 모두 Application입니다. 이중 하나를 열고 Run 메뉴에서 실행하거나 Ctrl+F11로 실행하면 되겠습니다.

     

    다른 분의 자료는 http://okgosu.net 에서 제공이 될겁니다.

     

    개인적인 소망이 있습니다. 많은 분들이 제 블로그를 통해 Flex 관련자료를 접하고 계신것 잘 알고 있습니다. 하지만 저도 다른 사람들을 통해서 많이 배우고 싶은 사람입니다. 서로 소통이 되어야 진정으로 정보공유라고 생각하고 바람직한 방향이라고 생각해요. 앞으로 Flex 4든 Flash Platform에 대한 어떤 자료든지 아시는 것있다면 함께 공유해서 함께 커갔으면 합니다. 어짜피 기술이라는 것은 시간이 지나면 또 바뀌고 사라질 수도 있잖아요? 자기만 알고 있다고 해서 다 좋은 것은 아니라는 겁니다. Flex 5, Flex 6가 나올때도 한국에서 한국 블로거 또는 카페등을 통해 매일 피상적인 정보만 얻어가는 정도나 질문에만 답해야하는 그런 상황이 반복된다면 정말 암울할 것 같아요. 정보생산의 주체가 적어도 어제 참석한 분들의 수만 되도 한국의 IT 미래는 매우 밝아질 것입니다.

     

     

    012345

     

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

    토성(Saturn)

     

    Papervision3D나 Away3D 라이브러리를 이용하지 않고 Flash Player 10 3D API만을 이용해 태양계의 행성인 토성을 그려보았다. 토성을 그리기 위해 먼저 표면부분과 고리부분의 Texture를 구해야한다. 아래 사이트에서 다양한 행성의 Texture 그림을 구할 수 있다.

     

    http://planetpixelemporium.com/saturn.html

     

    토성의 고리 Texture

    토성의 표면 Texture

     

    Texture를 이용해 3D로 만들기 위한 아이디어는 아래 링크를 참고한다.

     

    [Flash 3D]우리 아가 회전시키기 2-Texture를 이용해 여러모양 만들기

    [Flash 3D]우리 아가 회전시키기-UV맵핑,원근투영 이용

     

     

    토성 그리기 : 표면과 고리가 겹치는 문제

     

    지구와 같은 행성과 다르게 토성의 경우에는 고리가 있다. 토성의 표면은 그냥 구형태로 Mesh데이타를 만들어 처리하면 된다. 하지만 고리의 경우는 다른 형태로 Mesh데이타를 만들어야 한다. 설명은 생략하겠다.

     

    아래는 아래 예시의 소스이다.

    invalid-file

    고리와 구가 겹치는 문제가 있는 소스

     

    토성을 모양을 만들기 위해 토성의 표면과 고리에 대한 Mesh데이타를 만들어야 한다. 아래코드는 고리(Ring) 부분의 Mesh데이타를 만드는 부분이다. 표면부분과 다르게 고리 Texture를 반복해서 그리는 데이타를 만든다.

    /**
     * 고리 Mesh 데이터 작성 
     * @param radius 고리 안쪽 반지름  
     * @param thickness 고리 두께
     * @param div 고리 조각수 
     * @return mesh 데이터 
     */
    function createRingMesh( radius:Number, thickness:Number, div:uint ):GraphicsTrianglePath
    {
        var vertices:Vector. = new Vector.( 0, false );
        var indices:Vector. = new Vector.( 0, false );
        var uvtData:Vector. = new Vector.( 0, false );
        var mesh:GraphicsTrianglePath = new GraphicsTrianglePath( vertices, indices, uvtData, TriangleCulling.NONE );
        var s:Number = 0;
        var x1:Number = radius;
        var x2:Number = radius + thickness;
        var y1:Number = 0;
        var y2:Number = 0;
        var z:Number = 0;          
        var cos:Number;
        var sin:Number;    
        var n:Number = 0;
        
        for( var i:uint = 0; i < div; i++ )
        {
            //Vertices
            mesh.vertices.push( 
                x1, y1, z, 
                x2, y2, z 
            );
            s = Math.PI * 2 * (i + 1) / div;
            cos = Math.cos( s );
            sin = Math.sin( s );
            x1 = radius * cos;
            x2 = (radius + thickness) * cos;
            y1 = radius * sin;
            y2 = (radius + thickness) * sin;
            mesh.vertices.push( 
                x1, y1, z, 
                x2, y2, z 
            );
            //UVT
            mesh.uvtData.push( 
                0,1,1, 
                1,1,1, 
                0,0,1, 
                1,0,1 
            );
            
            //Indices
            n = i * 4;
            mesh.indices.push( n, n+1, n+2, n+2, n+1, n+3 );             
        }    
        
        return mesh;
    }
    

     

    Enterfame시에 렌더링을 실시하는데 Utils3D.projectVectors(), graphics.beginBitmapFill(), graphics.drawTriangles() 메소드를 2번씩 호출한다. 즉, 토성의 구와 고리를 그리기 위해 투영, 렌더링을 2번씩 하는 것이다.

    private function onEnterFrame( event:Event ):void
    {
        world.identity(); //단위행렬로 전환 
        world.appendRotation( getTimer() * 0.0027, Vector3D.Z_AXIS );
        world.appendRotation( xRotation, Vector3D.X_AXIS );
        world.appendRotation( yRotation, Vector3D.Y_AXIS );
        world.appendTranslation(0, 0, viewPortZAxis); //이동 
        world.append(projection.toMatrix3D()); //투영 변환 적용 
        
        // mesh 데이터를  투영하여  projected 생성 
        // uvtData도 갱신된다. 갱신되는 데이터는 T값이다. 
        Utils3D.projectVectors( world, saturnFaceMesh.vertices, saturnFaceProjected, saturnFaceMesh.uvtData );
        Utils3D.projectVectors( world, saturnRingMesh.vertices, saturnRingProjected, saturnRingMesh.uvtData );    
        
        viewport.graphics.clear();
        // Triangle 라인을 그림 
        if( visibleTriangle )
        {
            viewport.graphics.lineStyle( 1, 0xff0000, 0.1 );
        }
        
        //Texture 입힌다.
        viewport.graphics.beginBitmapFill( saturnFaceTexture, null, false, true );
        viewport.graphics.drawTriangles( saturnFaceProjected, getSortedIndices(saturnFaceMesh), saturnFaceMesh.uvtData, saturnFaceMesh.culling );                
        viewport.graphics.beginBitmapFill( saturnRingTexture, null, false, true );
        viewport.graphics.drawTriangles( saturnRingProjected, getSortedIndices(saturnRingMesh), saturnRingMesh.uvtData, saturnRingMesh.culling );                
    }
    

     

    언뜻보면 이 코드는 문제가 없어보이지만 실제로 실행해보면 바로 문제가 있다는 것을 확인할 수 있다.

    아래는 이 프로그램을 실행한 것이다.

     

     

    마우스로 돌려보고 화살표키로 확대/축소도 할 수 있다. 또한 Space키 누르면 삼각형 부분이 보인다.

     

    실행한 결과를 보면 문제가 있다. 토성 표면 뒤에 고리가 보인다. 당연히 저렇게 그려지면 안된다. 이 문제는 위의 방법처럼 Texture와 Mesh데이타가 2개여서는 방법이 나오지 않는다. 왜냐하면 graphics.drawTriangles() 함수를 2번 그려주게 되면 먼저 그린 것은 항상 나중에 그린것에 의해 가려지기 때문이다.

     

     

    토성 그리기 : 고리 겹치지 않게 만들기

     

    invalid-file

    표면과 고리가 겹치지 않는 소스

     

    위처럼 고리가 토성표면에 겹치는 문제를 해결하기 위한 방법은 Texture를 하나로 통합하고 Mesh데이타도 하나로 만든다. 그리고 graphics.drawTriangles() 를 한번만 호출하도록 하면 된다.

     

    아래 함수는 고리, 표면 Texture를 1개의 텍스쳐로 만들어준다.

    /**
     * 텍스쳐 생성 
     * @param faceTexture 표면의 BitmapData
     * @param ringTexture 고리의 BitmapData 
     * @return TexturInfo의 객체 
     */ 
    function createTexture( faceTexture:BitmapData, ringTexture:BitmapData ):TextureInfo
    {
    	var texture:BitmapData;
    
    	texture = new BitmapData( 
    			Math.max( faceTexture.width, ringTexture.width ), 
    			faceTexture.height + ringTexture.height, 
    			true,
    			0xff000000 
    	);
    
    	faceTexture.lock();
    	ringTexture.lock();
    
    	var facePixels:ByteArray ;
    	var ringPixels:ByteArray;
    	facePixels = faceTexture.getPixels( new Rectangle( 0, 0, faceTexture.width, faceTexture.height ) );
    	ringPixels = ringTexture.getPixels( new Rectangle( 0, 0, ringTexture.width, ringTexture.height ) );
    	facePixels.position = 0;
    	ringPixels.position = 0;
    
    	texture.setPixels( 
    		new Rectangle( 0, 0, faceTexture.width, faceTexture.height ), 
    		facePixels 
    	);
    	texture.setPixels( 
    		new Rectangle( 0, faceTexture.height, ringTexture.width, ringTexture.height ), 
    		ringPixels 
    	);
    	
    	var faceRect:Rectangle = new Rectangle( 0, 0, faceTexture.width, faceTexture.height );
    	var ringRect:Rectangle = new Rectangle( 0, faceTexture.height+1, ringTexture.width, ringTexture.height );
    	
    	faceTexture.unlock();
    	ringTexture.unlock();
    	
    	return new TextureInfo( texture, faceRect, ringRect ); 
    }
    

     

    결국 아래 그림처럼 Texture BitmapData가 만들어진다.

     

    위 함수에 TextureInfo는 실제 texture Bitmap정보와 Texture상의 표면과 고리 부분에 대한 영역정보를 가지고 있다. 이 영역정보를 가지고 Mesh 데이타를 만들도록 한다.

     

    /**
     * 토성모양의 Mesh 데이타 
     * @param textureInfo 텍스쳐 정보 
     * @return Mesh 데이타 
     */ 
    function createMesh( textureInfo:TextureInfo ):GraphicsTrianglePath
    {
    	var width:Number = textureInfo.texture.width;
    	var height:Number =textureInfo.texture.height;
    	var faceRect:Rectangle = textureInfo.faceRect;
    	var ringRect:Rectangle = textureInfo.ringRect;
    
    	var minU:Number;
    	var maxU:Number;
    	var minV:Number;
    	var maxV:Number;
    	
    	//표면 Mesh 데이타 만들기 
    	minU = faceRect.x / width;
    	maxU = (faceRect.x + faceRect.width) / width;
    	minV = faceRect.y / height;
    	maxV = (faceRect.y + faceRect.height) / height;
    	var faceMesh:GraphicsTrianglePath = createSphereMesh( 50, 24, 24, minU, maxU, minV, maxV );
    	
    	//고리 Mesh 데이타 만들기 
    	minU = ringRect.x / width;
    	maxU = (ringRect.x + ringRect.width) / width;
    	minV = ringRect.y / height;
    	maxV = (ringRect.y + ringRect.height) / height;
    	var ringMesh:GraphicsTrianglePath = createRingMesh( 70, 20, 50, minU, maxU, minV, maxV );
    
    	//고리 Mesh 데이타에서 Index 부분 조정 
    	var deltaIndex:uint = faceMesh.vertices.length/3; //Vertex는 x,y,z 3개씩 묶이므로... ^^
    	var length:uint = ringMesh.indices.length;
    	for( var i:int = 0; i < length; i++ )
    	{
    		//아래와 같이 2개의 mesh가 합쳐지면 뒤에 붙는  ring부분의 index값이 변경되야한다.
    		ringMesh.indices[i] += deltaIndex; 
    	}
    	
    	//최종 Mesh 데이타 완성 
    	var mesh:GraphicsTrianglePath = new GraphicsTrianglePath();
    	mesh.vertices = faceMesh.vertices.concat( ringMesh.vertices );
    	mesh.uvtData = faceMesh.uvtData.concat( ringMesh.uvtData );
    	mesh.indices = faceMesh.indices.concat( ringMesh.indices );
    	mesh.culling = TriangleCulling.NONE;
    	return mesh;	
    }
    

     

    위 함수는 2개의 Mesh데이터를 이용해 1개의 Mesh데이타로 통합해준다. 이로써 이제는 투영, 렌더링을 한번만 하도록 한다.

     

    private function onEnterFrame( event:Event ):void
    {
    	world.identity(); //단위행렬로 전환 
    	world.appendRotation( getTimer() * 0.0027, Vector3D.Z_AXIS );
    	world.appendRotation( xRotation, Vector3D.X_AXIS );
    	world.appendRotation( yRotation, Vector3D.Y_AXIS );
    	world.appendTranslation(0, 0, viewPortZAxis); //이동 
    	world.append(projection.toMatrix3D()); //투영 변환 적용 
    	
    	// mesh 데이터를  투영하여  projected 생성 
    	// uvtData도 갱신된다. 갱신되는 데이터는 T값이다. 
    	Utils3D.projectVectors( world, mesh.vertices, projected, mesh.uvtData );
    	
    	viewport.graphics.clear();
    
    	// Triangle 라인을 그림 
    	if( visibleTriangle )
    	{
    		viewport.graphics.lineStyle( 1, 0xff0000, 0.1 );
    	}
    	
    	//Texture 입힌다.
    	viewport.graphics.beginBitmapFill( textureInfo.texture, null, false, true );
    	viewport.graphics.drawTriangles( projected, getSortedIndices(mesh), mesh.uvtData, mesh.culling );            	
    
    }
    

     

    위 함수처럼 1번만 투영/렌더링 처리하면 이제 토성의 표면과 고리는 아래처럼 자연스럽게 나오게 된다.

     

     

    하지만 완벽하지 않다. 이유는 렌더링시 Culling을 None으로 지정했기 때문이다. 이는 보이지 않는 표면까지 그린다는 의미이다. 고리의 경우 양쪽면이 다보여야한다. 그러므로 고리의 Mesh데이타는 None으로 지정한다. 하지만 토성 표면의 경우는 화면 앞쪽을 향하는 부분만 보이면 되므로 Culling을 Positive로 지정하면 된다. 첫번째 예제에서는 어짜피 Mesh 데이터가 2개이므로 상관없었지만 두번째의 경우에는 양면 다보여야하는 고리때문에 토성의 표면도 None처리 했다. 이는 보이지 않는 부분까지 렌더링하므로 그만큼 속도저하가 일어난다. 이를 해결하기 위해 Positive로 지정하되 고리를 앞뒤면으로 겹쳐서 그리면 된다. 하지만 이 방법밖에 없는지 의문이다.

     

     

    정리하기

     

    이런 작업은 신나는 일이다. ^^

     

    이 토성에 Light효과를 주어 Shading 예제도 만들어봐야 겠다.

     

    참고로 모든 작업은 Flash Builder 4에서 했으며 Flex 4 SDK를 이용했다. 결과물은 Flash Player 10이상 설치된 브라우져에서만 확인할 수 있다.

     

    위 코드는 아래 링크에서도 볼 수 있다.

     

    Saturn 3D, 토성, 고리 중첩 해결못한 것

    Saturn 3D, 토성, 고리 중첩 해결한 것

     

    참고사이트

    [Flash 3D]우리 아가 회전시키기 2-Texture를 이용해 여러모양 만들기

    [Flash 3D]우리 아가 회전시키기-UV맵핑,원근투영 이용

     

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

     

    기존 Flex Builder 3를 구입한 사람에게만 적용됩니다.

     

    Step 1. Adobe Labs에 접속합니다. (http://labs.adobe.com)

     

    Step 2. Adobe Flash Builder 4 Beta 다운로드 페이지로 이동합니다.

    https://www.adobe.com/cfusion/entitlement/index.cfm?e=labs%5Fflashbuilder4

    Adobe 회원이 아니라면 먼저 회원가입하세요.

     

    Step 3. 30-day Beta 부분에 request extension serial number 를 선택합니다.

    기존 Flex Builder 3를 고객만 해당되며 Flash Builder 4 다운로드 후 21일 후에 Flash Builder 4에 대한 Serial Number를 받을 수 있다고 명시되어 있습니다.

     

     

    Step 4. 자신의 이름과 전자우편주소, Flex Builder 3 Serial Number를 입력하고 Do you accept this term?를 check한다음에 Request Serial Number 버튼을 누릅니다.

    입력한 전자우편 주소로 Flash Builder 4 Serial Number가 전송되므로 정확하게 입력해야합니다.

     

    성공적으로 발송되면 다음과 같은 페이지가 나옵니다.

     

    Step 5. 입력한 전자우편 계정에서 Flash Builder 4 Serial Number를 확인합니다.

     

     

    Step 6. Flash Builder 4를 실행시키고 받은 Serial Number를 입력합니다.

     

     

    이제부터 Flash Builder 사용기간에 구애받지 말고 마음대로 쓰세요.

    Adobe Flash Builder 4 Beta가 배포되었습니다. 공식판은 아니고요. Flash Builder 4는 Flex Builder 3의 차기버전으로 Flex SDK 4(Flex Gumbo)를 기본 SDK로 설정되어 있습니다. Flex SDK 4로 만들어진 애플리케이션은 기본적으로 Flash Player 10 버전에서 동작이 가능합니다. 물론 기존 Flex SDK 3도 사용할 수 있습니다.

     

    아래 링크에서 언제든지 다운로드 받을 수 있습니다.(회원가입하셔야 합니다.) 윈도우, 맥 버전이 있으니 자신의 운영체제에 맞게 다운로드 받으시면 됩니다.

     

    http://www.adobe.com/cfusion/entitlement/index.cfm?e=labs%5Fflashbuilder4

     

     

    다음 글을 참고하세요.

     

    1. 설치하기

    위 링크에서 다운로드 받아 쉽게 설치할 수 있습니다.

     

    처음 설치화면입니다.

     

    C:/Program Files/Adobe/Flash Builder Beta 경로에 기본 설치되는군요.

     

    설치중인 화면입니다.

     

    이름도 Gumbo입니다. ㅎㅎ 아직 Beta라는 것이겠죠.

     

    실행해 보겠습니다.

     

    30일 Trial버전으로 사용해봅니다.

     

    첫 실행 화면입니다. FB 문자가 선명하네요. FB는 Flex Builder가 아니라 Flash Builder 입니다.

     

     

     

    2. 사용해보기

     

    메뉴 구성 변화

    FXP 임포트도 되고 Test Case Class, Test Suit Class도 만들 수 있도록 되어 있네요. Flex Builder로 테스트 주도형 제작이 가능해지겠군요.

     

    Data 메뉴가 상당히 직관적으로 바뀌었네요. 또한 더욱 많은 서비스도 지원하도록 만들어졌고요. 진정한 RIA를 구축하기 위한 서버측 기술 지원을 배려한 기능이군요.

     

     

    이전에 없었던 Data/Services, ASDoc, Network Monitor 등이 지원되네요.

     

    아래는 네트워크 모니터툴입니다. RPC 통신등을 할 때 서버와 통신이 어떻게 되는지 확인하는데 요긴하게 사용할 수 있을 것 같습니다. 이제 Http Watcher가 필요 없겠군요!!!!!

     

     

    Flex 코딩해보기

    Flex Project를 만들어보겠습니다. SDK를 Flex SDK 3.4와 Flex 4.0을 사용할 수 있도록 되어 있네요. Flex 4.0 기반에서 작업해 보겠습니다.

     

    FDT(Flash Development Tools)에서 보이는 구조와 비슷하네요. 프로젝트에 사용하고 있는 Flex 4.0 SDK 라이브러리들도 보이고 각각의 (+)버튼을 누르면 정의된 클래스도 한눈에 볼 수 있습니다. 이거 정말 편해졌군요. SWC도 못봤던 netmone.swc, sparksins.swc등이 있습니다.

     

    재미있는 것은 Flex Gumbo가 Fx이니셜로 컴포넌트가 만들어진 것으로 알고 있었는데 FxApplication이 아닌 그냥 Application입니다.

    그리고 몇가지 namespace(fx, s, mx)로 구분 되었네요. ComboBox가 DropDownList로 이름이 바뀐 것 같습니다.

     

    <?xml version="1.0" encoding="utf-8"?>
    <s:Application
        xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        xmlns:mx="library://ns.adobe.com/flex/halo"
        minWidth="1024" minHeight="768">
        <s:Panel x="14" y="44" width="250" height="200" title="타이틀입니다.">
            <s:Button x="15" y="12" label="버튼"/>
            <s:CheckBox x="15" y="46" label="체크박스"/>
            <mx:ColorPicker x="16" y="71"/>
            <s:DropDownList x="103" y="13"/>
            <s:RichEditableText x="92" y="50" width="147" height="39" text="RichEditableText 컴포넌트"/>
        </s:Panel>
    </s:Application>

     

    디자인 모드입니다. 스킨도 바뀌고 새로운 컴포넌트도 있네요.

     

    실행해볼까요?

    헛! 깔끔해진 실행화면!, Flex가 이젠 기본스킨도 이쁘게 나왔네요.

     

     

    Theme 선택 기능

    프로젝트의 Properties를 보면 Flex Theme가 추가되었습니다. 와우! 그런데 아직 기능이 완벽하지 못한 것 같습니다. 적용이 잘 안되네요 ㅡㅡ;

     

     

    Flash CS4 Component 연동

    디자인 모드에서 Components를 보시면 Custom에 New Flash Componet, New Flash Container가 있습니다. 즉 Flash CS4에서 만들어진 SWC와 연동이 가능해졌다는 것을 의미합니다.

     

    드래그 해서 디자인 뷰에 붙이면 아래처럼 화면에 보이고 선택하면 오른쪽 Properties에 Create in Adobe Flash 버튼이 보입니다.

     

     

    버튼을 누르면 Class를 선택할 수 있게 하고 SWC 파일을 선택합니다.

    Create 버튼을 누르면 Flash CS4가 실행되면서 컴포넌트를 만들 수 있게 되어 있네요.

     

     

    ASDoc 기능

    와우! Panel에 마우스를 올려보니 간단한 설명도 나오네요. Eclipse에서는 되던건데… ㅎㅎ

     

    앗… ASDoc View가 바로 이런 역할을 가지는 거였군요. 해당 컴포넌트를 선택하면 ASDoc View에 아래처럼 보입니다. 강력하군요.

     

     

    Getter/Setter 생성기능 / ASDoc Commnet 기능

     

    엄청난 기능(?)이 추가되었군요. Eclipse에서는 당연히 되던건데 왜 Flex Builder에서는 안되나 궁금했던 기능이 이제야 추가되었군요.

     

    properties를 만들고 해당 속성의 Getter/Setter 기능을 아래처럼 추가할 수 있습니다. 단축키는 없네요. ㅡㅡ;

    또한 Add ASDoc Commnent 기능도 추가 되었습니다. @author, @since 등을 자동으로 붙여줄 수 있으면 좋으련만… 아마 설정이 가능할겁니다. ^^

     

     

    이벤트 핸들러 및 Service Call 등록 기능

     

    코딩작업 없이 Event 핸들러 및 Service Call 기능을 추가할 수 있게 되었습니다.

     

     

    위 그림에서 처럼 버튼을 선택하고 Properties에서 On click에 Generate Event Handler 를 선택하면 아래처럼 이벤트 핸들러가 생성됩니다. 넘 좋군요. ^^

     

    버튼을 click하면 바로 아래 코드가 실행되는겁니다.

     

    그리고 Generate Service Call을 누르면 Data/Services를 생성해서 연결할 수 있습니다. 와우 RIA 개발툴 다운 면모가 보이는군요.

     

     

    File Templates 기능

    메뉴의 Windows의 Perferences에 들어가면 아래와 같은 창이 뜹니다.

    여기에서 Flash Builder > File Template 가 있습니다. 이를 선택하면 자신의 코딩방식을 설정할 수 있도록 되어 있습니다. 좋은 기능이네요.

     

     

    3. 정리하며

    이외에도 아직 제가 발견하지 못한 기능이 상당합니다.

     

    이제 FDT를 사용하지 않아도 Flash Builder로 충분히 예전에 지원되지 않았던 기능들을 사용할 수 있게 되었습니다. 몇가지 버그가 있는 것 같지만 그 버그만 잘 잡아준다면 훌륭합니다.

     

    제가 적지 않은 기능이 있다면 소개해주세요. 그리고 제 블로그에 트랙백(엮인글) 적극 환영합니다. ^^

    Flex, Flash, ActionScript, AIR....

    Adobe RIA 기술을 처음 접해본 이들에게 이 용어들의 구분은 매우 생소하다. 앞에 3개는 모두 Flash Player에서 돌아가는 SWF파일을 만들어주는 툴 및 언어이다. AIR는 이러한 것을 확장해서 데스크탑 영역까지 애플리케이션을 제작할 수 있는 기술이라고 할 수 있다.

     

    많이 헷갈리는 것중에 하나가 바로 Flex, Flash, ActionScript 의 구분이다. ActionScript는 Flex, Flash 애플리케이션을 개발하는 가장 핵심이면서 기반이 되는 언어이다. Flex는 ActionScript 3.0을 확장해 RIA를 지원하기 위한 일종의 프레임워크이다. Flash는 ActionScript 초기 시절부터 있는 일종의 툴로서 이펙트 및 다양한 효과를 제작하는데 적절하도록 구성된다. 결국 Flex, Flash의 태생은 ActionScript 이고 어떤 목적을 가지고 제작하느냐에 따라 Flex, Flash로 구분해서 개발한다. 물론 어떤 것을 선택하든지 결과물은 SWF이다.

     

    재미있는 사실은 Flash는 뭔가 디자인 중심적으로 느껴지는 반면, Flex는 개발적이고 기술적으로 여겨는 풍토가 있다. Flash 개발자라고 말하는 것보다 Flex 개발자라고 하면 연봉협상에도 유리할지 모른다. 하지만 Flash 개발이든 Flex 개발이든 어떤 애플리케이션을 만드냐에 따라 선택이 달라지는 것이지 개발의 질이 달라지는 것은 절대 아니다. 여기서 선택이라는 것은 가령 이렇다. 기업솔루션을 구축해야하는 상황이면 서버 구성 및 데이타 통신, 데이터 관리, 각종 컴포넌트를 아낌없이 지원해주는 Flex로 개발하는 것이 좋다. 하지만 Google Map과 같이 Flex 컴포넌트를 전혀 사용하지 않는다면 Flash 기반이나 순수 ActionScript 기반으로 개발하는 것이 맞다.

     

    Adobe에서 Flex Builder 3의 다음 버전을 Flex가 아닌 Flash Builder 4로 지정하기로 했다. Flash Builder 4는 현재 Flash CS4와 같은 툴이 아니라 지금의 Flex Builder와 같이 Eclipse기반으로 만들어진 툴이다. 또한 Flex 4 SDK(현 Flex Gumbo)를 기반으로 Flex 개발환경을 지원한다. 결국 그런거다. Adobe RIA기술의 핵심은 Flash다. 그리고 Flex도 결국 Flash다. 다만 Flex SDK를 기반으로 제작하면 Flex SDK로 만들어진 Flash 애플리케이션인 것이다.

     

    차기 버전이 Flex Builder 4 대신 Flash Builder 4로 지정한 것은 여러모로 바람직해 보인다. 일단 같은 SWF 결과물을 만들어 준다는 암시를 지니기 때문에 의미전달이 쉬워진다. 겉모습은 전부 Flash이지만 개발방법은 선택하기 나름인 것이다. Flex SDK를 사용하면 그 사람은 여전히 Flex 개발자인 것이다. 앞으로 디자이너와 개발자간에 협력 도구인 Flash Catalyst는 Flash Builder와 매우 자연스럽게 연동이 된다. 그런데 어떤것은 Flex, 어떤 것은 Flash, 이렇게 되면 뭔가 섞일 수 없는 느낌이 든다.

     

    2009년 6월 쯤에 1차 베타버전이 나오고 4분기면 정식 버전이 출시될 것이다. 아무튼 기존 보다 개발의 편의성을 극대화 시킬 수 있는 Flash Builder 4가 나오길 기대한다.

     

    이것만은 기억하자.

    이제 더 이상 Flex는 Flex Builder를 지칭하지 않는다. Flex는 Flex SDK를 지칭하며 그것을 이용해서 개발하는 툴은 Flash Builder 4인 것이다.

    Flash Builder 4는 다음 링크를 통해 다운받으세요.
    http://www.adoberia.co.kr/pds/down.html?src=text&kw=000026 

    + Recent posts