캠핑과 개발


1. 현재 설치된 flash player 버전 확인하기
(http://www.adobe.com/software/flash/about/)


2. 플래시 플레이어 삭제 프로그램 다운

http://download.macromedia.com/pub/flashplayer/current/uninstall_flash_player.exe


3. flash 설치

9버전

http://download.macromedia.com/pub/flashplayer/updaters/9/flashplayer_9_ax_debug.exe 

※ 설치 에러시 레지스트리 삭제

HKEY_LOCAL_MACHINE\SOFTWARE\Macromedia\FlashPlayer\SafeVersions
(안에 버전별 내용 모두 삭제)

  • Papervision3D - 간단한 큐브같은 도형부터 복잡한 3d모델과 재질까지 지원하는 3D엔진. 가장 유명한 플래시 3D엔진이며 아직 베타버전이지만 실제로 사용된 많은 사례가 존재한다.

  • Away3D - 또다른 플래시 3D엔진. 페이퍼비젼보단 인기가 덜하지만 정식릴리즈 되어있다. 그리고 페이퍼비전 코드를 토대로 만들어진 엔진이다. 데모보기

  • WOW Engine - AS3 3D 물리엔진. Papervision3D나 Away3D와 같이 사용하면 금상첨화.

  • FIVe3D - AS2와 AS3를 지원하는 3D 에니메이션 엔진

  • Ribbit - 마이크를 사용해서 웹상에서 전화를 걸 수 있는 대단한 기술임. 플래시를 사용해서 전화를 받을 수 있도록 하였고 컴포넌트로 만들어져있기 때문에 사용하기 간편함.

  • WiiFlash - 닌텐도 Wii 컨트롤러를 플래시에서 사용할 수 있게 한 라이브러리. 

  • APE (Actionscript Physics Engine) - 플래시용 물리엔진. 아직은 좀 부족하다.

  • AMFPHP - 데이터베이스와 플래시를 연동하기 위해 가장 추천하는 라이브러리. PHP기반이기 때문에 속도도 빠르고 사용하기도 쉽다.

  • Flickr Library - 플리커 서비스의 API를 래핑한 라이브러리

  • RSS Library - RSS 피드를 플래시에서 핸들링 하기 위한 라이브러리 

  • YouTube - 마찬가지로 YouTube의 API를 래핑한 라이브러리

  • FZip - 서버사이드의 도움없이 압축파일을 풀거나 압축할 수 있는 라이브러리

  • AS3SoundEditorLib - mp3파일의 스펙트럼 을 보여주거나 큐포인트를 보여주고 네비게이션 할 수 있게 하는 라이브러리

  • Facebook-AS3 - 페이스북 플랫폼의 REST API를 AS3로 래핑한 라이브러리 (와우!!!)

  • AS3Crypto - 여러가지 압축알고리즘을 제공하는 라이브러리

  • AlivePDF - 오픈소스 라이브러리로 PDF파일을 서버사이드 도움없이 컨트롤 할 수 있음

  • ASSQL - 액션스크립트에서 MySQL로 직접 통신하는 라이브러리(웹서버 거치지 않고)

  • Yahoo! Maps Communication Kit - GeoRSS 피드나, 커스텀 마커 등 야후 맵에서 제공하는 여러기능들을 사용할 수 있음.

  • AS3CoreLib - 이 라이브러리는 어도비에서 제공하는 것으로 여러가지 유틸리티 클래스들을 담고 있음(MD5, SHA-1, 이미지 인코더, JSON 라이브러리...)


// 무비클립을 탄력적으로 움직이게 하는 메서드

// a는 -2부터 2사이의 실수 (-2<a<2)

// b는 -1부터 0사이의 실수(-1<b<0)

// a*a+4b는 -4부터 0사이의 실수(-4<a*a+4b<0)

// b가 -1에 가까울수록 진동폭이 큼

// a가 -2에 가까울수록(작을수록) 속도가 빠름

// tx와 ty는 이동할 최종 위치


MovieClip.prototype.elasticMove = function(a, b, tx, ty){

     var tempx = this._x;

     var tempy = this._y;

     this._x = a*(this._x - tx) + b*(this.prevx - tx) + tx;

     this._y = a*(this._y - ty) + b*(this.prevy - ty) + ty;

     this.prevx = tempx;

     this.prevy = tempy;

};


[출처] http://blog.naver.com/sync6324/110033835026

// (x1, y1)에서 (x2, y2)까지의 거리를 구해서 정수값을 반환하는 함수

function distance(x1, y1, x2, y2) {

    var diffX = x2-x1;

    var diffY = y2-y1;

    var r = Math.sqrt(diffX*diffX+diffY*diffY);

    return r;

}


[출처] http://blog.naver.com/sync6324/110033835026

// 무비클립을 (targetx, targety)로 회전시키는 함수

MovieClip.prototype.rotateTo = function(targetx, targety){

    var diffX = targetx - this._x;

    var diffY = targety - this._y;

    this._rotation = Math.atan2(diffY, diffX)*180/Math.PI;

};


_root.무비클립인스턴스.rotateTo(this._xmouse, this._ymouse);



[출처] http://blog.naver.com/sync6324/110033835026

<?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/mx">
    
    <fx:Style>
        .backgroundImage {
            color: #808080;
            fontWeight: bold;
            fontSize: 18;
            fontStyle: italic;
            contentBackgroundColor: #FFFFFF ;
            backgroundImage: Embed(pattern_143.gif);
            backgroundImageFillMode: repeat;
            
        }
        
    </fx:Style>
    
    <s:BorderContainer width="100%" height="600" styleName="backgroundImage">
        <s:Label text="hai hai hai" />
    </s:BorderContainer>
    
</s:Application> 





     <s:BorderContainer width="100%" height="100%"
      backgroundImage="images/bkg/grey_grid.gif"
      backgroundImageFillMode="repeat"  > 

flex 3.x

html
<object id="paramTest" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="300" height="120">
    <param name="movie" value="Example.swf" />
    <param name="flashVars" value="
type=typevar&name=namevar" />
        <object type="application/x-shockwave-flash"
                data="Example.swf" width="300" height="120"
                flashVars="type=typevar&name=namevar">
        </object>



flex
creationComplete="init()"
 

private function init():void{
    var type:String = Application.application.parameters.type as String;
    var name : String = Application.application.parameters.name as String;
}



flex 4.x 

html

var flashvars = {};

flashvars.type = "타입변수";
flashvars.name = "이름변수";


flex
creationComplete="init()"
 

private function init():void{
    var type:String = parameters.type as String;
   
var name : String = parameters.name as String;
}



flex 4.5

html

var flashvars = {};

flashvars.type = "타입변수";
flashvars.name = "이름변수";


flex
creationComplete="init()"
 

private function init():void{
    var type:String = FlexGlobals.topLevelApplication.parameters.type as String;
    var name : String = FlexGlobals.topLevelApplication.parameters.name as String;
}


 


플래시 빌더 4.5를 설치하고 이클립스 플러그인을 설치하면서 플러그인을 통한 이클립스가 한글로 나오는 경우가 있다.
어도비사이트에 가면 분명히 언어를 선택하라는 항목이 단계에는 포함이 되어 있지만 이런 단계 없이 설치가 되었다..
물론 스탠다드 버전은 영문으로 설치를 했다..
근데 왠걸 한글로 메뉴가 나온다..
영어를 못하는데도 워낙 눈으로 많이 익혀서 한글로 메뉴가 나오니 더 모르겠다라..
아무래도 몰라도 영어로 바꿔야 겠다...
아래와 같이 -nl en_US 으로 추가해주면 다음부터 한글 메뉴가 영문으로 나오게 된다..
또 다른 방법은 eclipse.ini 파일 안에 -vmargs 상단에 해당 부분을 넣어주면 된다.

근데.. 맥은 어떻게 하지... 음..
[추가]
Mac은 eclipse.app 파일 열기에서 eclipse.ini 파일을 열고 해당 위에 내용처럼 하면 된다. 




참고 : http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc.user%2Ftasks%2Frunning_eclipse.htm


로컬자원을 서버에 전송하기 위해 우리는 FileReference Class를 사용하면 된다.
FileReference로 파일을 서버에 전송하는 방법은 많이 공개가 되어 있다.
알다시피 FileReference의 browse()함수를 호출한 뒤, select 이벤트가 발생시 upload() 함수를 이용하여 선택한 로컬자원을 서버로 보낸다.

서버에서는 아주 단순하게 서버 임시 저장소에 저장된 파일을 원하는 곳에 복사하기만 하면 된다.
php의 경우 move_uploaded_file() 메소드를 사용하면 되겠다.

그럼 Flex 시행도중 캡쳐한 화면을 저장하는 경우에도 위와 같은 방법으로 저장이 가능할까?

답은 "된다"


나는 예전에 ImageSnapshot 클래스를 이용해 base64로 변환해서 서버로 전송한 뒤에 base64를 decode하여 저장하는 방법에 대해서 언급한적이 있다. (http://blog.jidolstar.com/301 참고)
이 방법의 단점은 이미지가 큰 경우 base64로 encode, decode 하는 과정에서 서버성능 및 클라이언트 성능에 따라 속도 및 부하에 영향을 준다. 그러므로 이 방법으로는 PNGEncoder 및 JPGEncoder로 PNG, JPG 파일 형식에 맞는 데이타를 만들었다고 해도, FileReference와 같이 데이타를 전송을 할 수 없었다.

하지만 Google을 열심히 돌아다녔다니 이 문제점에 대한 해결의 실마리를 찾을 수 있었다.
(역시 Google!!!)

간단히 방법을 요약하자면
화면을 BitmapData로 만들어 PNGEncoder나 JPGEncoder를 이용하여 encode한 다음, 그 결과값인 byteArray값을 서버에 전송한다. 전송된 데이타는 FileReference에서 upload()을 이용해 보낸 파일을 저장할때와 동일하게 저장하면 되겠다.

1. BitmapData로 캡쳐해라.

아래 target은 캡쳐할 UIComponent와 같은 DisplayObject 객체이다.

BitmapData로 캡쳐
var bitmapData:BitmapData = new BitmapData(target.width, target.height, true, 0xFFFFFF);
var drawingRectangle:Rectanglenew Rectangle(0, 0, target.width, target.height);
bitmapData.draw(target, new Matrix(), null, null, drawingRectangle, false);

단, BitmapData를 이용해서 화면을 캡쳐할 대상이 외부 동영상이나 사진같은 거라면 crossdomain.xml 에 대한 check가 있어야 한다. 컨텐츠 로드시 checkPolicyFile 속성을  true로 설정할 필요가 있겠다.
그리고 2880px 이상의 크기는 BitmapData로 만들 수 없다.



2. JPG나 PNG로 Encode 하여 ByteArray를 얻는다.


Flex 3 SDK에는 mx.graphics.codec 패키지에 JPGEncoder와 PNGEncoder가 있다. 인터넷을 뒤져보면 GIFEncoder등도 있을것이다. Flex 2 환경에서 작업한다면 Google code에 Adobe AS3 Corelib에 이들이 제공된다. 만약 JPGEncoder를 사용한다면 다음과 같이 하면 되겠다.

JPGEncoder를 이용하여  JPG  ByteArray값 만들기
import mx.graphics.codec.JPGEncoder;

var byteArray:ByteArray = new JPGEncoder().encode(bitmapData);


Flex 3 SDK는 이러한 Encoder가 IImageEncoder로 구현되었다. 필요하다면 언제 어디서나 Encoder를 바꿔야 하는 경우 IImageEncoder를 사용하는 것이 좋을 수 있겠다.
가령 아래 예제처럼 말이다.

다양한 Image Encoder 사용하기
import mx.graphics.codec.*;

var imageType:String = "jpg";
var imageEncoder:IImageEncoder;
if( imageType.toUpperCase() == "JPG" ) imageEncoder= new JPEGEncoder();
else if( imageType.toUpperCase() == "PNG" ) imageEncoder= new PNGEncoder();
var byteArray:ByteArray = imageEncoder.encode(bitmapData);



 

3. 서버에 ByteArray를 전송한다.

데이타를 전송할때는 FileReference를 사용하지 않는다.
바로 URLLoader와 URLRequest만 이용해서 전송이 가능하다. 참고 데이타는 POST방식으로 URLVariable을 이용해서 보낼 수 있다.

Flex/AIR 데이터 전송 방법
//assumed variable declarations
//var byteArray:ByteArray = 2번째 단계에서 JPG 데이타를 얻었다.
//var fileName:String = "desiredfilename.jpg" //저장할 파일 이름이다. 아무거나 적자!
//var uploadPath:String = "저장할 때 사용되는 서버측 script 경로"
//var parameters:URLVariables = 이미지 이외에 다른 보낼 다른 데이타가 있다면 이것을 이용한다.
//function onComplete(eventObj:Event):void {  성공적으로 데이타를 전송했을때 핸들러 함수 정의
//function onError(eventObj:ErrorEvent):void {  이미지 전송을 실패했을때 핸들러 함수 정의

var urlRequest:URLRequest = new URLRequest();
urlRequest.url = uploadPath;
//urlRequest.contentType = 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary();
urlRequest.method = URLRequestMethod.POST;
urlRequest.data = UploadPostHelper.getPostData(file, byteArray, parameters);
urlRequest.requestHeaders.push( new URLRequestHeader( 'Cache-Control', 'no-cache' ) );
urlRequest.requestHeaders.push( new URLRequestHeader( 'Content-Type', 'multipart/form-data; boundary=' +UploadPostHelper.getBoundary()) );

var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.addEventListener(Event.COMPLETE, onComplete);
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onError);
urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
urlLoader.load(urlRequest);


위에 진한 부분에 대한 클래스는 아래에 정의되어 있다. 당신은 이 클래스가 어떻게 구성되었는가 열심히 공부할 필요가 없다.(원한다면 해도 된다. 말리지 않음 ^^)

UploadPostHelper Class (Language : java)
package {

    import flash.events.*;
    import flash.net.*;
    import flash.utils.ByteArray;
    import flash.utils.Endian;

    /**
     * Take a fileName, byteArray, and parameters object as input and return ByteArray post data suitable for a UrlRequest as output
     *
     * @see http://marstonstudio.com/?p=36
     * @see http://www.w3.org/TR/html4/interact/forms.html
     * @see http://www.jooce.com/blog/?p=143
     * @see http://www.jooce.com/blog/wp%2Dcontent/uploads/2007/06/uploadFile.txt
     * @see http://blog.je2050.de/2006/05/01/save-bytearray-to-file-with-php/
     *
     * @author Jonathan Marston
     * @version 2007.08.19
     *
     * This work is licensed under a Creative Commons Attribution NonCommercial ShareAlike 3.0 License.
     * @see http://creativecommons.org/licenses/by-nc-sa/3.0/
     *
     */

    public class UploadPostHelper {

        /**
         * Boundary used to break up different parts of the http POST body
         */

        private static var _boundary:String = "";

        /**
         * Get the boundary for the post.
         * Must be passed as part of the contentType of the UrlRequest
         */

        public static function getBoundary():String {

            if(_boundary.length == 0) {
                for (var i:int = 0; i < 0x20; i++ ) {
                    _boundary += String.fromCharCode( int( 97 + Math.random() * 25 ) );
                }
            }

            return _boundary;
        }

        /**
         * Create post data to send in a UrlRequest
         */

        public static function getPostData(fileName:String, byteArray:ByteArray, parameters:Object = null):ByteArray {

            var i: int;
            var bytes:String;

            var postData:ByteArray = new ByteArray();
            postData.endian = Endian.BIG_ENDIAN;

            //add Filename to parameters
            if(parameters == null) {
                parameters = new Object();
            }
            parameters.Filename = fileName;

            //add parameters to postData
            for(var name:String in parameters) {
                postData = BOUNDARY(postData);
                postData = LINEBREAK(postData);
                bytes = 'Content-Disposition: form-data; name="' + name + '"';
                for ( i = 0; i < bytes.length; i++ ) {
                    postData.writeByte( bytes.charCodeAt(i) );
                }
                postData = LINEBREAK(postData);
                postData = LINEBREAK(postData);
                postData.writeUTFBytes(parameters[name]);
                postData = LINEBREAK(postData);
            }

            //add Filedata to postData
            postData = BOUNDARY(postData);
            postData = LINEBREAK(postData);
            bytes = 'Content-Disposition: form-data; name="Filedata"; filename="';
            for ( i = 0; i < bytes.length; i++ ) {
                postData.writeByte( bytes.charCodeAt(i) );
            }
            postData.writeUTFBytes(fileName);
            postData = QUOTATIONMARK(postData);
            postData = LINEBREAK(postData);
            bytes = 'Content-Type: application/octet-stream';
            for ( i = 0; i < bytes.length; i++ ) {
                postData.writeByte( bytes.charCodeAt(i) );
            }
            postData = LINEBREAK(postData);
            postData = LINEBREAK(postData);
            postData.writeBytes(byteArray, 0, byteArray.length);
            postData = LINEBREAK(postData);

            //add upload filed to postData
            postData = LINEBREAK(postData);
            postData = BOUNDARY(postData);
            postData = LINEBREAK(postData);
            bytes = 'Content-Disposition: form-data; name="Upload"';
            for ( i = 0; i < bytes.length; i++ ) {
                postData.writeByte( bytes.charCodeAt(i) );
            }
            postData = LINEBREAK(postData);
            postData = LINEBREAK(postData);
            bytes = 'Submit Query';
            for ( i = 0; i < bytes.length; i++ ) {
                postData.writeByte( bytes.charCodeAt(i) );
            }
            postData = LINEBREAK(postData);

            //closing boundary
            postData = BOUNDARY(postData);
            postData = DOUBLEDASH(postData);

            return postData;
        }

        /**
         * Add a boundary to the PostData with leading doubledash
         */

        private static function BOUNDARY(p:ByteArray):ByteArray {
            var l:int = UploadPostHelper.getBoundary().length;

            p = DOUBLEDASH(p);
            for (var i:int = 0; i < l; i++ ) {
                p.writeByte( _boundary.charCodeAt( i ) );
            }
            return p;
        }

        /**
         * Add one linebreak
         */

        private static function LINEBREAK(p:ByteArray):ByteArray {
            p.writeShort(0x0d0a);
            return p;
        }

        /**
         * Add quotation mark
         */

        private static function QUOTATIONMARK(p:ByteArray):ByteArray {
            p.writeByte(0x22);
            return p;
        }

        /**
         * Add Double Dash
         */

        private static function DOUBLEDASH(p:ByteArray):ByteArray {
            p.writeShort(0x2d2d);
            return p;
        }

    }
}



한가지 중요한 정보를 언급하겠다.
URLLoader를 이용해 서버에 전송할때, 프로그램이 같은 도메인상에 있는 경우에는 보안문제가 없다. 하지만 다른 도메인에 위치한 서버로 이미지를 전송할때는 반드시 crossdomain.xml을 check해야한다.

1. Security.loadPolicyFile(http://다른도메인/crossdomain.xml); 를 URLLoader의 load()함수를 호출하기 전에 호출한다.

2. Flash Player 9.0.124.0 버전부터는 HTTP Header 보안취약점을 해결하기 위해서 cross domain 정책이 변경되었는데.... 서버측에 있는 crossdomain.xml에 allow-http-request-headers-from가 추가되어져야 한다. 이것은 HTTP 헤더 전송을 허용할지 결정해준다.

crossdomain.xml (Language : xml)
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
      <allow-access-from domain="*.jidolstar.com" />
      <allow-http-request-headers-from domain="*.jidolstar.com" headers="*"/>
</cross-domain-policy>

위 처럼 서버측 crossdomain.xml에 allow-http-request-headers-from을 추가함으로 다른 도메인간에 HTTP 헤더 전송을 허용할 수 있다.

서로 다른 도메인에 SWF와 서버측 코드가 배치되어 있다면 반드시 이 사실을 숙지하길 바란다.


3. Flash Player 10에서는 사용자 인터렉션이 반드시 필요하다.

다음글을 참고하세요.

http://blog.jidolstar.com/411 


 

4. 서버측 코드 작성

만약 위 3번 코드에서 var parameters:URLVariables를 아래와 같이 작성했다고 하자.

URLVariables 설정 (Language : java)
var parameters:URLVariables = new URLVariables();
parameters.method = "id";
parameters.userId = "2000321";


그럼 PHP 코드로 아래와 같은 방법처럼 만들면 되겠다.(테스트는 안해봤음)

PHP 코드 예제 (Language : php)
<?php
$method = $_POST['method'];
$userId = $_POST['userId'];
$file_temp = $_FILES['Filedata']['tmp_name'];
$file_name = $_FILES['Filedata']['name'];
$file_size = $_FILES['Filedata']['size'];

if( $method == "id" )
{
  $movePath = "/home/myPath/images/$userId_$file_name";
}
else
{
  $movePath = "/home/myPath/images/time_".time()."_".$file_name;
}

move_uploaded_file($file_temp,$movePath);

echo "save Complete";
?>


마지막 save Comple 메시지를 받기 위해서는 Flex의 Complete 이벤트 발생시 아래와 같은 방법으로 받으면 되겠다. 이것을 알아내는데도 많이 힘들었다. 일종의 팁이다. ^^;

데이타 받기 (Language : java)
var loader:URLLoader = URLLoader(event.target);
var bytedata:ByteArray = loader.data;
var strData:String = bytedata.toString();
trace( strData)


실제 업무에도 잘 이용하고 있다.
이미지 에디터 등을 만들때 아주아주 유용한 자료가 될 것이다.

누가 예제 프로그램 만들어서 트랙백 걸어 주시면 고맙겠다.


자료 출처 
http://marstonstudio.com/2007/08/19/how-to-take-a-snapshot-of-a-flash-movie-and-automatically-upload-the-jpg-to-a-server-in-three-easy-steps/


지돌스타 블로그내 참고자료
 - ImageSnapshot 클래스에 대해 : http://blog.jidolstar.com/301
 - FileReference의 UploadCompleteData 이벤트 : http://blog.jidolstar.com/324
 - 동영상 캡쳐 방법 : http://blog.jidolstar.com/215


 

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

//DB 생성 파일 위치
    var dbFile : File = File.desktopDirectory.resolvePath("application.db");
    
    //table생성
    var conn:SQLConnection = new SQLConnection(); //DB를 연결합니다..
    conn.open(dbFile);    
    var syntax:String = "CREATE TABLE IF NOT EXISTS testTable (" +
   "no INTEGER PRIMARY KEY AUTOINCREMENT," +
   "title TEXT," +
   "url TEXT" +
   ")";
  sendQuery(conn, syntax);
  
  //스키마 정보 확인
  try {
   conn.loadSchema();
   var schemaResult:SQLSchemaResult = conn.getSchemaResult();
   if (schemaResult) {
    for(var obj:String in schemaResult.tables){
     var table:SQLTableSchema = schemaResult.tables[obj] as SQLTableSchema;
     log("[" + table.name + "] 스키마(Schema)");
     for(var prop:String in table.columns){
      var column:SQLColumnSchema = table.columns[prop] as SQLColumnSchema;
      log("name:" + column.name + ",dataType:" + column.dataType + ",primaryKey:" + column.primaryKey + ",allowNull:" + column.allowNull + ",autoIncrement:" + column.autoIncrement + ",defaultCollationType:" + column.defaultCollationType);
     }
    }
   }
  } catch(e:Error) {
   log("테이블이 없습니다.");
  }
  
  //등록
  syntax = "INSERT INTO testTable (title, url) VALUES ('Adobe AIR Devpia.', 'http://airdev.tistory.com/')"; //no는 자동으로 증가
  sendQuery(conn, syntax);
  syntax = "INSERT INTO testTable (title, url) VALUES ('아폴로케이션[Apollocation]', 'http://cafe.naver.com/apollocation')"; //no는 자동으로 증가
  sendQuery(conn, syntax);
  
  //조회
  var syntax:String = "SELECT * FROM testTable";
  var responder:Responder = new Responder(
   function(e:SQLResult):void {
    var result:Array = e.data;
    var numRows:int = result.length;
    for(var i:int = 0; i < numRows; i++){
     log("필드 번호 :" + i);
     for(var columnName:String in result[i]){
      log(columnName + " :" + result[i][columnName]);
     }
    }
   }
  );
  sendQuery(conn, syntax, -1, responder);
  
  //DB 삭제
  syntax = "DROP TABLE testTable";
  sendQuery(conn, syntax);


private function sendQuery(conn:SQLConnection, syntax:String, prefetch:int=-1, responder:Responder=null):void { //쿼리 실행
  var stm:SQLStatement = new SQLStatement();
  stm.sqlConnection = conn;
  stm.text = syntax;
  stm.execute(prefetch, responder); //prefetch : 가져올 데이터 개수(-1이면 모두), responder : 결과, 상태 Responder
 }