이전 글 CodeIgniter 라이브러리에 ZendAMF 추가하기를 마치셨다면 이번에는 Flex와 연동하는 것을 시작하겠습니다.
대부분은 글은 머드초보님의 글을 바탕으로 진행할 예정입니다.(출처: [Flex/PHP] Zend AMF를 이용한 PHP와 FLEX의 연동삽질후기)

①. 먼저 DB를 생성하고 데이터입력입니다

DROP TABLE IF EXISTS `sosi`.`sosi`; 
CREATE TABLE  `sosi`.`sosi` ( 
  `idx` int(10) unsigned NOT NULL AUTO_INCREMENT, 
  `sosiname` varchar(45) NOT NULL, 
  `height` int(10) unsigned NOT NULL, 
  `blood` varchar(45) NOT NULL, 
  PRIMARY KEY (`idx`) 
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8; 
 
INSERT INTO `sosi` (`idx`,`sosiname`,`height`,`blood`) VALUES  
 (1,'윤아',166,'B'), 
 (2,'수영',170,'O'), 
 (3,'효연',160,'AB'), 
 (4,'유리',167,'AB'), 
 (5,'태연',162,'O'), 
 (6,'제시카',163,'B'), 
 (7,'티파니',162,'O'), 
 (8,'써니',158,'B'), 
 (9,'서현',168,'A');

 

②. Flex Project 'ZendAmfTest'를 만듭니다. 머드초보님은 Application server type을 php으로 하셨는데 저는 서버가 외부에 있어서 None/Other로 하였습니다. 로컬이라면 php를 선택하신 다음에 아파치나 iis가 돌아가는 폴더를 지정하면 됩니다. 지정하게 되면 SWF가 서버로 바로 위치하게 되므로 테스트하기 편합니다.

③. 그런 다음 system>application>libraries에 sosimember.php라는 파일을 만듭니다. CI특성상 파일명은 소문자로 만드셔야합니다.


 

④. 다음은 DB에서 데이터를 가져오고 반환하는 모델을 만듭니다. system>application>models에 sosimodel.php를 생성하시고 아래 코드입력합니다.
load->library("SosiMember");
    	
        $query = $this->db->query('SELECT idx, sosiname, height, blood FROM sosi;');
        
        $ret = array();
        foreach ($query->result() as $row){        
            $tmp = new SosiMember(); 
            $tmp->idx = $row->idx; 
            $tmp->sosiname = $row->sosiname; 
            $tmp->height = $row->height; 
            $tmp->blood = $row->blood; 
            $ret[] = $tmp; 
        } 
        return $ret; 
    }
}  
?>

⑤. 다음은 controllers를 만듭니다. 여기에 ZendPHP가 들어갑니다. system>application>controllers에 remote.php를 생성하시고 아래 코드입력합니다.
load->model('SosiModel');    
    }
    
    public function index()
    {
        $this->load->library("Apps");
        $this->apps->load("Zend/Amf/Server");
        $server = new Zend_Amf_Server();
        $server->setClass("SosiModel"); 
		$server->setClassMap("SosiMember", "SosiMember"); 
		echo($server -> handle()); 
        
    }
}  
?>

⑥. 이제 Flex에게 PHP를 연결할 설정을 역할을 하는 service-config.xml을 만듭니다.
 
  
      
         
             
                    
              
             
                  
                    *  
                     
                
          
      
      
          
             
          
     

⑦. Flex파일 ZendAmfTest.mxmlf에 아래 코드를 입력합니다.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml
    layout="vertical"
    creationComplete="creationCompleteHandler()">
 <mx:Script>
  <![CDATA[
   import mx.controls.Alert;
   import mx.rpc.events.ResultEvent;
   import mx.rpc.events.FaultEvent;
   
   private function creationCompleteHandler():void
   {
    roSosi.getData();
   }
   
   private function faultHandler(event:FaultEvent):void
   {
    Alert.show(event.message.toString());
   }
   
   private function resultGetDataHandler(event:ResultEvent):void
   {
    dgSosi.dataProvider = event.result as Array;
   }
  ]]>
 </mx:Script>
 
 <mx:RemoteObject id="roSosi" fault="faultHandler(event)" destination="zend" source="SosiModel">
  <mx:method name="getData" result="resultGetDataHandler(event)" />
 </mx:RemoteObject>
 
 <mx:DataGrid id="dgSosi" width="100%" height="100%">
  <mx:columns>
   <mx:DataGridColumn headerText="아이디" dataField="idx"/>
   <mx:DataGridColumn headerText="소녀시대이름" dataField="sosiname"/>
   <mx:DataGridColumn headerText="신장" dataField="height" />
   <mx:DataGridColumn headerText="혈액형" dataField="blood" />
  </mx:columns>
 </mx:DataGrid>  
</mx:Application>

SyntaxHighlighter가 Flex를 지원하지 않네요ㅠ
만약 다른 서비스를 추가하게 된다면, <mx:RemoteObject>에서 endpoint를 다른 url로 잡아주면 됩니다.
<mx:RemoteObject id="roAnother" fault="faultHandler(event)"  
       
destination="zend" source="AnothorService"  
       
endpoint="http://localhost/ZendAmfTest-debug/another_amf.php">


그렇게 Flex를 컴파일 하게 되면 아래와 같이 출력됩니다.


이상입니다. 혹시 에러나 잘못된 점은 지적해주시기 바랍니다.

참고사이트:

http://corlan.org/2008/11/13/flex-and-php-remoting-with-zend-amf/ 
http://mudchobo.tomeii.com/tt/398

Posted by Finebe
,


RIA에서 Data Loading은 중요한 요소입니다. 대부분이 서버와 데이터연동을 통하기 때문입니다.
어떤 Data Format이 좋을까 고민할 수도 있습니다. HTTP, SOAP, XML, Dojo, JSON, AMF3등 중에서도 자주 쓰이는 방식은  HTTP, XML,  JSON, AMF3등이 있습니다. 지금 알아볼려고 하는 벤치마크도 이 4개의 데이터포멧을 가지고 진행될 예정입니다.
브라우저별로 렌더링엔진, 스크립트엔진이 틀리기때문에 벤치마크에 대한 결과도 틀립니다.
그래서 제가 자주 사용하는 브라우저 3개만 벤치마크해보았습니다.

벤치마크에 사용될 브라우저와 대상 데이터포멧
 Benchmarks Browser  Internet Explorer8,Firefox 3.6.8, Chrome
 Benchmarks Data Format  HTTP, XML, JSON, AMF3

벤치마크방법:
  1. 모든 브라우저, 실행프로그램들을 꺼둔 상태(메모리, CPU할당량 최소화)
  2. 벤츠마크 사이트: http://www.jamesward.com/census/
  3. IE8->Firefox->Chrome으로 진행


벤치마크 결과:

-Internet Explorer8
Data 500Rows 보냈을때

Data 5,000Rows 보냈을때


-Firefox 3.6.8
 Data 500Rows 보냈을때

Data 5,000Rows 보냈을때


-Chrome
Data 500Rows 보냈을때

Data 5,000Rows 보냈을때


-벤치마크를 마치며
 벤치마크프로그램 시간내서 만들 생각을 하고 있었는데 마침 Server Exec Time, Transfer Time, ParseTime, RenderTime까지 나오는 친절한 벤치마크를 발견했습니다. 위 그림을 보시면 한눈에 브라우저 별로 데이터처리속도가 틀린것을 알 수 있습니다. 특히 IE8은 타브라우저보다 훨씬 느립니다.ㅎㄷㄷ.

 데이터 처리건수  500건  5,000건
 데이터 처리속도  XML>AMF3>JSON>HTML  AMF3>>XML>JSON>HTML
 데이터 크기(작은순)  AMF3>JSON>XML>HTML  AMF3>>>JSON>XML>HTML

IE8에서는 데이터크기가 커지니 XML ParseTime이 매우 늘어나 느려지는 것을 확인할 수 있습니다. 데이터 처리건수가 커질 수록 AMF3는 XML보다 월등한 처리속도를 보여줍니다(XML의 ParseTime은 처리건수에 비례). 또한 AMF3 데이터크기는 JSON의 1/10정도밖에 되질 않는 것도 확인이 되었습니다. 이러한 벤치마크결과들이 제 고민을 해결해주었습니다.

'Application Programming > Flex & Flash' 카테고리의 다른 글

Actionscript Vector 초기화(initialization)  (6) 2011.02.16
Flash AMF 의 개요  (0) 2010.03.08
Flex Builder 3에 JSON적용하기  (2) 2010.01.13
Posted by Finebe
,



AMF(Action Message Format
)이란?

-한마디로 말해서 서버와 SWF(플래시)의 통신이 AMF라고 불리는 Binary형식의 프로토콜을 사용하여 이루어지며 서버상에 있는 원격지 객체를 호출합니다.

-가장 작은 패킷 크기에 데이터 통신에 필요한 거의 모든 옵션을 넣을 수 있는 바이너리 메세징 프로토콜

-HTTP(80포트), HTTPS(443)를 통해 통신하기 때문에 방화벽을 무시할 수 있습니다.

-AMF는 플래시 플레이어가 인식 가능한 기본 메세징 포맷이므로 클라이언트에서 데이터 직렬화와 역직렬화가 자동으로 처리되며 속도도 빠릅니다.

-게이트웨이는 HTTP(80포트), HTTPS(443)를 통해 AMF패킷 송수신, AMF직렬화/역직렬화, 적절한 서비스에 요청위임 등을 수행할 수 있는 게이트웨이 라이브러리가 필요합니다. 이러한 게이트웨이 라이브러리 여러 종류 중에 우리는 여기서 ZendAMF라는 것을 사용할 것입니다.


AMF의 구조 :
 http://wiki.gnashdev.org/AMF


Actionscript & PHP Type Mapping

   

PHP to ActionScript mapping

  

PHP

ActionScript

null

null

boolean

boolean

string

string

DomDocument

xml

DateTime

date

float

number

integer

number

Associative Array w/ mix of keys

Object

Associative Array w/ Numeric index of keys

Array

object

object

RemoteClass Zend_Amf_Value_TypedObject

typed object

Zend_Amf_Value_ByteArray

flash.utils.ByteArray

Zend_Amf_Value_ArrayCollection

  

 

원본 위치 <http://framework.zend.com/wiki/display/ZFPROP/Zend_Amf+-+Wade+Arnold>


ZendAMF란?

-Remoting Gateway Library로써 Adobe가 공식지원하여 Zend 프레임워크에서 만들었습니다. AMF3 스펙를 사용하여 AMF0스펙를 사용한 AMFPHP보다 뛰어난 성능을 발휘합니다.    

----------------------------------------------------------------------------------------------------------------------

   

AMF3 스펙 기반으로 만들어진 ZendAMF 라이브러리를 가볍고 막강한 성능을 자랑하는 CI에 추가해보도록 하겠습니다.

   

  1. 준비물:
    1. CodeIgniter (http://codeigniter.com)
    2. ZendAMF (http://framework.zend.com/download/amf)
       
  2. CodeIgniter를 서버에 설치한 후 ZendAMF를 압축해제합니다. 그러면

    이 생성됩니다. 여기서 사용할 것은 library폴더에 들어있는 Zend라는 넘만 쓸 것입니다. Zend폴더를 복사하여
    system>application>libraries>Zend폴더에 넣습니다.

  3. CI의 config파일의 내용변경

    $config['enable_hooks'] = FALSE; --> $config['enable_hooks'] = TRUE;로 변경합니다.

  4. 후킹을 통한 프레임워크 코어확장
    코어파일을 해킹하지 않고도 내부작동방식을 변경하게 하는 기능인 후킹(설명)을 이용하여 컨트롤러가 호출되기 직전(pre-controller)에 실행하게 되게 추가합니다.

    위 hooks.php 파일에 아래 코드를 추가하시면 됩니다.

$hook['pre_controller'][] = array(

  'class' => 'App_hook',

  'function' => 'index',

  'filename' => 'app_hook.php',

  'filepath' => 'hooks'

);


5.    app_hook파일을 hooks폴더에 추가합니다.
 
app_hook.php 파일 안의 코드는

<?php 

if(!defined('BASEPATH')) exit('No direct script access allowed');

   

class App_hook

{

    function index()

    {

        ini_set('include_path',ini_get('include_path').PATH_SEPARATOR.BASEPATH.'application/libraries/');

    }

}

?>

이는 기존의 include_path의 값에 appliaction/libraries/를 추가한 것입니다.

6.    Zend 클래스와 다른 프레임워크 클래스를 이용하기 위해 하나의 사용자 라이브러리 파일을 만듭니다.

 

     그 파일 안의 코드는 다음과 같습니다.

<?php if (!defined('BASEPATH')) {exit('No direct script access allowed');}

   

class Apps

{

    function __construct($class NULL)

    {

        if(!empty($class) && is_array($class))

        {

            foreach($class as $item)

            {

                $this->load($item);

            }

        }

    }

      

    function load($class)

    {

        require_once (string) $class EXT;

    }

?>


7.    이제 ZendAMF 라이브러리를 사용할 준비는 끝났습니다. 테스트로 ZendAMF를 로드하는 Remoting Class를 만들어보겠습니다. 여기서 주의하실 점은 폴더명의 대소문자입니다. 이 글의 참고사이트에는 대문자로 되어있어서 그대로 하시면 오류가 생기십니다.
 
        파일을 만드신 후에 안에 코드는 아래와 같습니다.

<?php

class Remote extends Controller 

{

    function Remote()

    {

        parent::Controller();    

    }

      

    function index()

    {

        $this->load->library("Apps");

        $this->apps->load("Zend/Amf/Server"); //여기서 AMF가 아니라 Amf입니다. 각자 다를 수 있으니 확인하세요

          

        $server = new Zend_Amf_Server();

        $server->setClass($this);

        echo $server->handle();

    }

      

    function getData()

    {

        return array(1,2,3,4,5);

    }

?>


8.     Remote클래스를 호출합니다.
 
이라고 뜬다면 성공입니다. 그 외에 폴더명이 잘못되서 에러가 발생할 수 있습니다. 다시 한번 대소문자를 꼭 확인!! 

   

  
 
참고사이트

http://codeigniter.com/wiki/AMF_Flash_Remoting_with_Zend_and_CI/
http://www.cyworld.com/duck_info/3856801
http://framework.zend.com/wiki/display/ZFPROP/Zend_Amf+-+Wade+Arnold

Posted by Finebe
,



Action Message Format 이라불리우는 방식을 사용하게되면 객체를 그대로 전달하고 받을수있다.

서버로부터 객체를 전달받은후에 인코딩과정을 거치게되면 완전한 형식의 데이터가 뽑혀나온다.

근데 왜 이런짓(?)을 하는가.

xml로 그냥 보내면 될것을 말이지.....

일단 xml은 보안이 되지 않는다. 사람의 눈으로 그대로 보이니 보안관련 내용부분을 암호화 인코딩 한다하여도 노출되는것은 마찮가지다.

하지만 amf방식은 프로토콜이 전용이므로 보이지 않는다. 포트는 80포트를그대로 쓰기때문에 거의 왠만한 방화벽은 통과할수있다.

그뿐아니라 데이터 량이 많을경우 이진데이터로 변환해서 전송하기에 상당한 효율을 가져온다. 이것을 이용하면 파일 전송,채팅,게임까지도

플래시에서 구현하는데 많은 잇점이 생긴다.

플래시 플레이어에 이미 이 기능이내장되어있다. 플래시 8에서는 단지 이기능을쓰기위해 별도의 컴포넌트를 받아 플래시를 업데이트 해서 써야했다.

AMF 방식은 플래시 응용프로그램과 원격 서버간의 효율적인 통신을 한다. amf는 원격 프로시져 호출을 압축된 이진 표현으로 인코딩하여 플래시 미디어서버(Flash Media Server)에서 현재 사용되고있는 프로토콜(http,rtmp) 프로토콜형식으로 변환해서 전송한다. 그형식은 액션스크립트 객체와 데이터의 값을 이진형식으로 직렬화시키기 때문에 텍스트인 xml보다 엄청난 양을 압축할수있다.

xml을 압축전송한다고생각하면된다. 이방법을 썼을때 효율적인것은 바로 트래픽관리이다.

플래시로 제대로된 게시판이나 , 기타 대중화 어플리케이션이 상용화 되지 않는이유중 하나도 xml의 양날의 검때문이다.

개인사이트가아닌 상용사이트에서 xml로 구성된 데이터를 주고받는다면 일반 html로 만드는 어플리케이션보다 수배는 더많은 트래픽과 서버의 부하를 주게된다. 그러므로 이를 해결하기위해 장비를 늘리므로해서 더 많은 비용발생이되며 이것은 운영자에게는 별로 매력적이지 않은 부분이다. amf를 사용하면 그부분을 많이 줄일수있다. amf는 플래시가 쓸수있는 최상급의 리아 기술중 하나이다.

 

amf의 규격>

amf는 amf0과 amf3가 현재 사용되고있다.

플래시 8까지와 as2.0 까지는 amf0 이 지원되고

as3.0부턴 amf3를 쓸수있다.

amf3는 플래시9와 플렉스2 부터 지원한다.

--------AMF3   에서 추가된 사항 -------

1.int , uint 객체를 정식으로 지원해서 정수로 제대로인식할수있게됨.

2.ByteArray,XML,IExternalizable 의 데이터 유형을 그대로 인식함.

3.ByteArray, NetConnection, NetStream, SharedObject, Socket 및 URLStream 클래스에는 ObjectEncoding 클래스로부터 상수가 할당되는 objectEncoding 속성이 포함되어 있는데 objectEncoding 속성의 비헤이비어는 객체에 따라 달라진다.

----------------------------------------------

flash.net.ObjectEncoding 클래스의 부모는 Object이다.

 

 

활용>

그렇다면 이걸 어떻게 어디서 누가 쓰는것일까...

지난시간강좌중  new URLStream();

부분이 있었다.

amf가 사용되는곳은 SharedObject, Socket ,NetConnection ,URLStream , IDataInput ,IExternalizable , ByteArray ,IDataOutput , NetStatusEvent ..... 상당히 많이 쓰이고있다.

var test:URLStream=new URLStream();

을 해서 생성된 인스턴스 test는 objectEncoding의 속성이 있다. 이녀석은

public function set objectEncoding(value:uint):void  의 형식으로 선언되어있고

들어가야될 value값은 flash.net.ObjectEncoding 클래스에 상수값으로 아래와같이 규정되어있다.

AMF0 : uint = 0
[static] ActionScript 1.0 및 2.0용 AMF를 사용하여 객체를 직렬화하도록 지정
AMF3 : uint = 3
[static] ActionScript 3.0용 AMF를 사용하여 객체를 직렬화하도록 지정

DEFAULT : uint = 3

[static] 현재 플레이어의 기본(최신) 형식을 지정합니다.

3일경우는 현재까지는 플래시플레이어 9이므로 amf3가 자동지정된다.

 

웁쓰 그럼 또 NetStream은 어따쓰는거지? 지난번에 파일 읽어낼때 한번 본적이 있으나 구체적으로 살펴보면 아래와같다.

 

NetStream 클래스는 NetConnection 객체에 의해 설정된 연결을 통해 Adobe의 Macromedia Flash Media Server 2 (현재 3 까지 나왔음)또는 Adobe Flex 등의 서버와 Flash Player 사이, 또는 로컬 파일 시스템과 Flash Player 사이에 단방향 스트리밍 연결을 연다.

양방향이 아닌 단방향스트리밍이다.  이녀석의 속성과 메서드들은 플래시미디어서버,플렉스 서버등에 사용되도록 만들어져있다.

위에서  AMF가 이들용으로 http,rtmp 프로토콜을 사용해서 데이터를 주고받는다고언급했을때 이 netstream클래스가 해당 프로토콜을 제어하는것으로 마찬가지로 amf도 해당된다.

 

또한가지 살펴볼 녀석은 NetConnection이다. 이녀석은 주로 NetStream과 함께쓰이는데 서버에 존재하는 명령을 실행할때쓴다.

이객체를 만든다음 connect()메소드를 실행하게되면 서버와 연결되고 call()명령으로 서버의 펑션을 직접 실행하게된다.

그결과값도 받아올수있다. 이런역할을 하기위해서는 플래시미디어서버가 있어야했다.

플래시 미디어 서버의 가격을 알아봤다면 미디어를 컨트롤하지 않고 그장점을 사용하기위해 그 가격이 너무 비싸다고 생각했을것이다.(재벌 3세는 제외)

하지만 그것을위해 php에서 amf 프로토콜을 지원하는 프로젝트가 오래전부터 있어왔다.

바로 amfphp 이다.

 

비디오만 없지 채팅,데이터등은 아주 충실히 작동해준다.

만일 비디오스트리밍까지도 지원했다면 (red5 가 현재 오픈소스이다) 값싼 php에서 소형 미디어써버들이 대량생산되었을것이다.

항상 느끼는거지만 오픈소스의 더딤은 어쩔수없다. 실험정신에 신기술은 더 빠르지만 안정성과 업데이트는 상용에 밀릴수밖에 없다.

국내에서 amfphp를 쓴 프로젝트는 극히드믈다.

필자는 홈노트라는 사이트에서 2007년에 만든 플래시가계부중 스케쥴부분은 이 amfphp로 구현했다.

하지만 얼마나 더 속도가 빠른지에 대한 장점의 정밀한 테스트는 해보지 못했다.

그리고 그럴정도로 데이터량이 많은 서버에서 과연 php를 쓸것인가 하는점도 의문이다.

하지만 우리 플래시 오타쿠들은 실험정신에 입각하여 한번쯤은 해보는것도 좋을것이다.


출처: http://cafe.naver.com/amfphpsamo.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=175

Posted by Finebe
,