Actionscript3.02012.01.08 20:05


요즘 OAuth 인증 때문에 고생좀 했습니다. 머리속에 있는 개념을 정리도 할겸 제가 사용해본 OAuth 라이브러리에 대해 소개 합니다. 


OAuth 란?


 OAuth가 사용되기 전에는 인증방식의 표준이 없었기 때문에 기존의 기본인증인 아이디과 비밀번호를 사용하였는데, 이는 보안상 취약한 구조이다.

기본인증이 아닐 경우는 각 애플리케이션들이 각자의 개발한 회사의 방법대로 사용자를 확인하였다. 예를 들면 구글의 AuthSub, AOL의 OpenAuth, 야후의 BBAuth, 아마존의 웹서비스 API 등이 있다.

OAuth는 이렇게 제각각인 인증방식을 표준화한 인증방식이다. OAuth를 이용하면 이 인증을 공유하는 애플리케이션끼리는 별도의 인증이 필요없다. 따라서 여러 애플리케이션을 통합하여 사용하는 것이 가능하게 된다.


(출처 : http://ko.wikipedia.org/wiki/OAuth )


실 서비스 외부에서 API 를 사용할 때 이 OAuth 를 이용하여 인증을 하게 됩니다. 요즘 많이 사용하는 Twitter, facebook, Dropbox에서 제공 하는 API 모두 이 OAuth 를 지원하고 있고 지원하는 버전은 대부분 1.0 입니다. API 를 제공하는 곳에 따라서 2.0 을 제공하는 곳도 있습니다.  저 자세한 내용은 아래 링크에 자세히 설명 되어 있으니 생략하고 Flash 에서 OAuth 를 사용하는 방법에 대해 다뤄 보겠습니다.


 OAuth 인증 방식 이해 하기 : http://dev.springnote.com/pages/1083036



Actionscript3.0 으로 구현 된 OAuth 라이브러리


OAuth인증을 하기 위해서는 서비스 프로바이더와 몇번의 통신을 해야 하고 결과적으로 accessToken 과 accessTokenSecret 을 발급 받게 됩니다. 일종의 로그인을 위한 허락 키를 발급 받는 거지요. 이 키와 몇가지 OAuth 에서 원하는 값들을 조합해서 리퀘스트를 날릴때 Header 나 리퀘스트 URL 에 포함 시켜서 보내게 되면 서비스 프로바이더는 해당 리퀘스트를 분석하여 제대로된 인증을 가지고 있을 경우에만 결과 값을 내려 주는 구조로 되어 있습니다. 


OAuth 인증을 거치는 과정이 accessToken 과 accessTokenSecret을 발급 받는 과정이지만, 인증이 끝나고 나서 이 값들만 포함 시켜서 리퀘스트를 날리는건 아님니다. OAuth 에서 원하는 값들이 많이 있는데요. 이 값들을 http://oauth.net/ 에 구현 된데로 개인적으로 만들어서 사용해도 되지만, 이미 많은 라이브러리가 구현 되어 사용 되고 있기 때문에 기존 라이브러리를 사용 하는 걸 추천 합니다. (OAuth 인증 절차상 인증이 잘못된 경우 어디서 무엇이 잘못된건지 디버깅 하기가 어렵습니다.)


oauth-as3



oauth-as3은 actionscript3.0으로 구현된 oauth 라이브러리 입니다. 기본적인 기능들만 구현 되어 있어서 바로 사용하기 보다는 이 라이브러리를 이용하여 따로 구현해 줘야 할 것들이 많습니다. 그럼 인증을 받는 순서대로 라이브러리를 사용해 보겠습니다.

사용하기 전에 알아 두면 좋은 이론은 라이브러리에 포함 되어 있는 OAuthRequest 는 실제로 서비스프로바이더와 통신을 하기 위해 리퀘스트를 만드는 클래스 이고, 이 클래스에서 OAuth 인증을 할때 필요한 oauth_nonce, oauth_timestamp, oauth_signature 등을 생성하게 됩니다. 서비스 프로바이더와의 통신은(인증할때) URLLoader 를 사용하지만 이 URLLoader의 값을 세팅할때 참조 해야 하는 클래스가 인증에 대한 정보를 가지고 있는 OAuthRequest 클래스 입니다. 그럼 requestToken을 받는걸로 시작해서 코드를 작성해 보겠습니다. Twitter(https://dev.twitter.com/docs/api) 인증을 예를 들겠습니다.


1. 서비스 프로바이더에서 requestToken 을 받는다.


우선 인증을 시작하기에 앞서 인증을 해야 하는 대상 어플리케이션이 존재 합니다. Twitter 등의 서비스 프로바이더에서 어플리케이션을 생성하면 해당 어플리케이션이 갖게 되는 고유의 consumerKey 와 consumerSecretKey 을 알 수 있습니다. 이 값들을 이용해서 OAuthRequest를 생성 합니다. 



var twitter = {
  consumerKey : "",
  consumerSecret : "",
  requestTokenURL : "https://api.twitter.com/oauth/request_token",
  authorizeURL : "https://api.twitter.com/oauth/authorize",
  accessTokenURL : "https://api.twitter.com/oauth/access_token",
  callbackURL : ""
}


var oauthRequest:OAuthRequest = new OAuthRequest(OAuthRequest.HTTP_MEHTOD_POST, twitter.requestTokenURL, nullnew OAuthConsumer(consumerKey, consumerSecret));

var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, oauthLoadHandler);

var request:URLRequest = new URLRequest();

request.method = URLRequestMethod.POST

request.url = oauthRequest.buildRequest(new OAuthSignatureMethod_HMAC_SHA1(), OAuthRequest.RESULT_TYPE_URL_STRING);      

loader.load(request);

private function oauthLoadHandler(event:Event):void {
    
  //oauth_token=&oauth_token_secret=&oauth_callback_confirmed=
  //위의 값을 oauthRequest 에 저장
  
  var token:OAuthToken = new OAuthToken();
  token.key = oauth_token값;
  token.secret = oauth_token_secret값;
  oauthRequest.token = token;
}

 



그리고 Twitter의 경우 requestToken 을 발급 받는 api 가 post 를 사용하므로 셋팅을 해주고 oauthRequest에 인증에 필요한 모든 값들이 들어 있기 때문에 buildRequest 메소드를 이용해서 OAuth인증 값들이 포함 되어 있는 url 을 리턴 받아서 서비스프로바이더에서 리퀘스트를 날리게 됩니다.


buildRequest 에 들어가는 첫번째 파라미터는 oauth_signature_method 값이고 두번째 인자는 OAuth 인증 리퀘스트 값을 어떤 방식으로 받을 것이냐 선택 하는 것 입니다. 파라미터에 따라 URLRequestHeader값 또는 String 으로 받을수 있습니다.


2. requestToken 을 이용하여 서비스 프로바이더에게 접근 한다.


1번에 대한 response 값으로 oauth_token을 받게 되는데요. 이 값을 이용해서 또 다시 서비스 프로바이더에게 인증을 요청해야 합니다. 이번에 요청하는 인증은 URLLoader 를 이용한 인증이 아니라, 직접 URL로 이동하여 사용자가 아이디와 비번을 입력하여자신의 권한을 해당 어플리케이션에 수락 시키는 절차 입니다.





 https://api.twitter.com/oauth/authorize?oauth_token=REQUEST_TOKEN입력


위의 URL로 Desktop AIR의 경우 HTMLLoader 를, Mobile AIR의 경우 StageWebView를 이용해서 해당 사이트로 이동하면 위와 같이 인증 화면이 뜨게 됩니다. 


 

웹용 Flash Player에서는 서버를 (Proxy) 사용하지 않고 인증 할 수 없습니다. 웹상에서 클라이언트를 Flash 로 만들경우에는 (javascript 도 마찬가지 입니다) 서버에서 위의 인증 과정을 모두 대리로 수행 해야 합니다. 



사용자가 아이디와 비번을 입력하고 인증을 마무리 하게 되면 Twitter의 경우 어플리케이션을 등록할때 지정 했던 callback URL 로 이용하게 되는데요. 이동할때 URL 뒤로 추가적으로 필요한 정보들을 전달 받게 됩니다. 이 인증 절차를 통해 OAuthRequest가 가지고 있는 token 값은 이제 accessToken 을 접근 할 수 있는 인증권한을 갖게 됩니다.  


 http://www.ddongkang.com?oauth_token=&oauth_verifier=


위의 callback URL 로 전달 되는 oauth_token값은 요청할때 전달했던 값과 같습니다. oauth_verifier값은 이 예제에서는 사용되지 않습니다. 다음 링크를 참조 하세요. 


3. 서비스 프로바이더에서 accessToken 을 받는다.


이제 인증의 마지막 절차 입니다. accessToken 을 받는 방법은 requestToken 을 받을때와 같습니다. 



oauthRequest.requestURL = twitter.accessTokenURL;

oauthRequest.httpMethod = OAuthRequest.HTTP_MEHTOD_POST;
      
request.url = _oauthRequest.buildRequest(new OAuthSignatureMethod_HMAC_SHA1(), OAuthRequest.RESULT_TYPE_URL_STRING);

loader.load(request);

private function oauthLoadHandler(event:Event):void {
  
 // request token 리퀘스트일때
 //oauth_token=&oauth_token_secret=&oauth_callback_confirmed=true
 // access token 리퀘스트일때
 //oauth_token=&oauth_token_secret=&user_id=&screen_name=
 //위의 값을 oauthRequest 에 저장
 

  var token:OAuthToken = new OAuthToken();
 token.key = oauth_token값;
 token.secret = oauth_token_secret값;
 oauthRequest.token = token;

}




4. 인증 끝. 


위의 과정을 통해 accessToken 과 accessTokenSecret을 갖게 되어 인증이 끝났습니다. 이제 oauthRequest값에 인증 값들이 모두 포함 되어 있기 때문에 이를 이용해서 api 호출을 하면 됩니다.



oauthRequest.requestURL = Resource URL
oauthRequest.httpMethod = Request Method
    
var api_loader:URLoader = new URLLoader();

var api_request:URLRequest = new URLRequest();    
api_request.url = oauthRequest.buildRequest(new OAuthSignatureMethod_HMAC_SHA1(), OAuthRequest.RESULT_TYPE_URL_STRING);

api_loader.load(api_request);

 



OAuth를 이용한 인증은 개념을 파악하면 간단하지만 처음 개념 없이 무작정 사용하기엔 어렵습니다. 서비스 프로바이더에 따라 OAuth 인증 실패 이유를 제대로 반환해 주는 곳도 있지만 한번 꼬이기 시작하면 어디서 잘못된건지 찾기도 힘든게 OAuth 인증 같습니다. 


웹상에서 Flash 로 Twitter 나 Dropbox 같이 OAuth를 제공하는 서비스를 사용하고 싶으면 서버에 Proxy를 만들어서 서버를 통해서 인증을 받아야 합니다. 클라이언트 단에서 인증이 가능한 서비스 제공 업체도 있겠지만, 대부분은 서버를 통해서 인증을 받아야 보안 제약을 받지 않습니다. 그래서 FLash 를 이용한 방법은 주로 AIR(Desktop, Mobile)에서 사용 가능 합니다. 


많이 사용 되는 Twitter API 는 tweetr (http://wiki.swfjunkie.com/tweetr)는 있지만, 인증에 문제가 있는지 잘못 쓴건지 제대로 동작을 하지 않아 따로 만들어 사용하고 있습니다. 검색을 해 보니 github에 Twitter API를 구현한 소스가 올라와 있는데요. 아직 구현중인걸로 보이네요; 


조만간 사용하고 있는 라이브러리도 정리 해서 공유해 보겠습니다. 

잘못된 점이나 궁금한 점이 있으면 댓글로 문의 주세요~



Posted by Flash 동강
i'T news2011.12.03 11:54

Google Analytics


서비스를 만들어 보면 페이지뷰가 얼마나 발생하나 실 사용자는 얼마나 되나 같은 분석이 필요 합니다. 하지만 이런 분석 시스템을 구축 하기란 여간 힘든 작업이 아닐수가 없지요. 이 문서에서 소개 해 드릴 서비스는 Google Analytics 입니다. 구글이 내놓은 분석 서비스 입니다.




http://www.google.com/intl/ko/analytics/ 


위 주소로 들어 가서 계정을 만들면 바로 사용 할 수 있습니다. 로그인을 완료 하게 되면 계정 홈으로 들어가지는데요. 오른쪽 상단에 위치한 설정 아이콘을 클릭해서 들어 가면 분석을 할 대상을 추가 할 수 있습니다.




계정을 만드는 절차를 진행하면 등록된 서비스의 고유한 ID를 부여 받게 되고, 웹 서비스에 추가 할 수 있는 스크립트를 볼수 있습니다. 


웹 속성 ID : UA-XXXXXXXX-X 


<script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type =
 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ?
 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0];
 s.parentNode.insertBefore(ga, s);
  })();

</script>


위 스크립트를 블로그나 서비스에 추가 하면 설정을 끝납니다. 다시 정리 해 보면 절차는 다음과 같습니다.



1. http://www.google.com/intl/ko/analytics/ 접속
2. 웹 로그 분석 액세스 클릭
3. 계정 홈 - 설정 클릭
4. 새 계정을 추가 해서 사용하거나, 기존에 만들어져 있는 계정에 새 웹 속성을 등록해서 사용
5. 웹 페이지 컨텐츠일 경우 추적 코드를 페이지가 추가



gaforflash


그럼 플래시로 만들어진 컨텐츠는 어떻게 하느냐? 위의 스크립트를 통해 분석을 하는 방법도 있지만, 더 쉬운 방법으로 Actionscript Library가 있습니다.



http://code.google.com/p/gaforflash/  


import com.google.analytics.GATracker;

import com.google.analytics.AnalyticsTracker;

var tracker:AnalyticsTracker;

tracker = new GATracker(this, "UA-XXXXXXX-X", "AS3", true);
// ex) tracker.trackPageview("admin/change");
tracker.trackPageview("페이지이름");


이 라이브러리를 사용해서 이벤트에 따라서 페이지뷰를 날리는 방법으로 특정 이벤트에 대해 분석을 할 수 있습니다. 더 자세한 설명은 Google Code 페이지에 되어 있습니다.


http://code.google.com/apis/analytics/docs/tracking/flashTrackingIntro.html 


Google Analytics는 정말 여러가지의 분석을 해 줍니다. 자주 보는것 위주로 정리를 하면 다음과 같습니다.


주요 기능


1. 지역별 방문자 

2. 페이지 뷰 

3. 사용자 유입량

4. 실 사용자 유입량

5. 사용자 접속 환경 ( 브라우저, 플래시 버전 등등 )

6. 실시간 방문 현황 (베타)

7. 사이트 속도

8. 방문자 흐름

9. 방문 형태 (신규 방문, 재방문)

10. 광고 분석


생각 나는 것만 정리해 본 내용이니 실제로 사용할 수 있는 데이터는 엄청 많습니다. 

저는 이 블로그크롬 웹스토어에 올린 Daum Equation EditorDaum Paper 에 적용해서 사용하고 있는데요. 데이터 질적인 면에서 서비스를 분석하는데 상당히 많이 도움이 되고 있습니다. 


무료 서비스와 전문적인 서비스 지원 두가지로 제공 되니 사용해 보세요.


Posted by Flash 동강
Actionscript3.02010.01.14 11:03

작년에 썼던 Javascript vs Actionscript 라는 글에서는 비교 관련 자료가 06년도의 Flash player 9 와 그때 당시의 브라우져를 대상으로 테스트한 것인데요. jacksondunstan.com 블로그에서 최근에 AS3 기반의 Flash player 10과 최근 브라우져의 Javascript 와 Performance 테스트를 한 포스팅이 있었네요. 아래는 테스트 한 결과 입니다.



참고 자료 :  AS3 vs Javascript Performance Test

                AS3 vs Javascript Performance Test Followup

                


Posted by Flash 동강
Diary2009.12.20 16:49

 안녕하세요. 그 동안 정신이 없어서 한참 동안 블로그 질도 못하고 살았네요. 이제 바쁜것도 마무리 되었고, 뒷 전이었던 Flash 공부도 다시 하고 2010 을 위해 재충전 하는 시간을 가지고 있습니다. 반년 가까이 매달려 있었던, "다음가계부" 가 별탈 없이 오픈을 해서 아주 다행이라는 생각이 드네요. 




 이제 한해가 끝나가네요. 올해는 직장에 들어 와서 정말 정신 없는 한해를 보낸거 같은데요. 쉬는 동안 한해를 마무리 하고 내년을 알차게 계획 하고 목표를 세울 생각 입니다. 그동안 일이 바쁘다는 핑계로 못한 공부나 문서 작업들도 하고, 작년에 사서 썪히고 있는 사진기로 사진도 많이 찍으러 다니려고요. 그리고 요즘 플래시 액션 스크립트 카페에서 언노운 이 하고 있는 결정적 비밀 22 for AS3 을 보니 다시 제대로된 강좌를 써보고 싶다는 욕심도 생기네요. 그리고 무엇 보다도, 우선은 올해 뒷전으로 밀려 있던 Flash 관련 책 집필 계획을 내년에는 계획을 잘 세워서 마무리 할 생각 입니다. 



사진 출처http://me2day.net/saladin )



이 블로그에 오시는 모든 분들 새해 잘 마무리 하시고, 건강 하세요.


'Diary' 카테고리의 다른 글

요즘 들어 하는 이런 저런 생각.  (7) 2010.06.06
잘 살고 있습니다.  (14) 2009.12.20
최근 근황, - me2day에서 가져온 글  (0) 2009.03.15
스티브 잡스  (0) 2008.12.11
Posted by Flash 동강
Review2009.09.09 00:11

 

브라우져 별로 Javascript 와 Actionscript 의 스크립팅 퍼포먼스를 비교한 자료 입니다. 06년라고 나와 있는걸 보니 상당히 오래된 테스트 네요. 하지만 아직 까지 IE6, IE7 사용자가 압도적인 우리 나라 웹 환경에서는 여전히 적용되는 비교 자료 인것 같습니다..

 

 현재 98% 이상 설치 되어 있는 Flash player 9에서의 Actionscript 퍼포먼스와 파폭, 오페라, IE 에서의 Javascript 퍼포먼스를 테스트 한 것인데, 방법의 차이는 있겠지만 Actionscript가 압도적으로 빠르게 나왔네요. 물론 최근에 나온 파폭이나, 오페라 크롬에 탑재 되어 있는 자바스크립트 엔진과 비교를 하지 않은 거라서 언어 적으로 두 언어의 퍼포먼스를 비교 하기는 쉽지 않을것 같습니다. Flashplayer 도 10 버젼에서 굉장한 퍼포먼스 항상을 가져 왔으니, 자바스크립트 엔진Flashplayer 의 퍼포먼스 비교라고 해도 될 정도로 환경의 영향을 많이 받습니다.

 

Javascript 나 Actionscript 나 모두 휼륭한 스크립트 입니다. 두 언어 모두 다른 것과 대체 하기 힘들 정도로 해당 분야에서 가장 많이 사용되는 방법이기도 합니다. 하지만 Javascript(Ajax 컨텐츠) 로 만들어야 하는 것과 Actionscript(Flash 컨텐츠) 로 만들어야 하는 것은 엄연히 차이가 있습니다. 서비스를 기획하기에 앞서, 서비스가 어떤 방향으로 나가는 것인지 여러 상황을 고려 하여 판단하여 프로젝트에 적용해야 합니다.

 

어떤 것을 "할 수 있다." 와 어떤 것을 "잘 한다." 는 엄연히 다른 의미니까요.

 

'Review' 카테고리의 다른 글

Introduce Daum Equation Editor and Daum Paper on Chrome Web Store  (0) 2011.11.14
Javascript Vs Actionscript  (4) 2009.09.09
OpenCast 와 블로거 뉴스  (4) 2008.12.16
대한 민국 플래시 人의 밤  (0) 2008.12.11
Posted by Flash 동강
Flash platform2009.09.08 00:12

 이런 말을 많이 듣습니다.



Flash로 만들면 느리지 않아요? 

Flash 로 만드면 유지 보수가 힘들지 않아요?

Flash 로 만들면 오래 걸리지 않아요?? 




예전에는 Flash를 맹신하여 위의 말들에 "욱" 했었지만, 지금은 반반 입니다. 하지만 확실한건 Flash 로 만든 컨텐츠는

느리지 않다 입니다. 그러면 왜 느린가?? 왜 느리다고 생각하는 건가요?


느리게 만들기 때문에 느린 것이다.

느리게 만들게 의도 하기 때문에 느린 것이다.



 저는 이 두가지 이유 때문이라 생각 합니다. 첫번째 이유는 생각 없이 심볼 생성하고, 퍼포먼스 고려 없이 트윈 남발하고
어느덧 라이브러리에는 쓸데 없는 심볼이 쌓여서 SWF 자체로 무거워 지고, 여러 가지 Flash player 과부화 요소를 생각하지 않고 빨리 빨리 작업 해야 한다는 압박 때문에 그냥 그냥 지나가고... 두번째 이유는 생각 없는 클라이언트, 기획자, 디자이너 만나서 화려 한게 좋아요. Flash 는 화려 한거 아니에요? 트윈 떡 칠한거 보고 역시 Flash 는 달라요. 좀 더 화려 하게 해 주세요. 이 요구에 마지못해 따라가는 개발 때문이라는 생각이 드네요. 

 Flash 컨텐츠는 보통 생각하는 화려한 UI 외에도 많은 것들을 할 수 있습니다. 단순히 UI만 만드는 도구가 아니라는 거죠. 
ActiveX 를 대체해서 채팅 솔루션을 개발하기도 하고, 파일 업로도와 같은 것, 뮤직 플레이어, 동영상 플레이어 최근에 오픈한 네이버의 N드라이브나 뉴스 아카이브 등등 할 수 있는게 무궁 무진 합니다. 

 느리다고 생각하는건 Flash 컨텐츠를 너무 맹신해서 그런것 아닐까요? Flash 로 만들었을때 느리면 다른 걸로 만들면 느리지 않을까요? 

한밤 중에 고뇌 하고 있습니다.....


Posted by Flash 동강
Actionscript3.02009.06.02 23:40

 Flash의 컴파일 결과물인 SWF는 그 자체로 UI 나 GAME 그리고 어플리케이션(AIR)이 될 수 있지만, 대부분은 브라우저에 Embeded 되어 사용됩니다. 배너와 같이 단순하게, 보여 주기 위해서 브라우저에 Embeded하는 경우도 있겠지만, UI 나 웹 어플리케이션을 구현할 때는 브라우져나, 서버사이드 언어와의 통신이 필요 하게 됩니다. AS3.0으로 거의 대부분의 Front-End 단의 개발작업을 모두 할 수 있긴 하지만, 퍼포먼스나 구현의 편의성을 위해 Javascript를 사용해야 하는 경우가 많습니다. 이 문서는 앞으로 몇개의 포스팅을 통해 다루게 될 AS3.0의 통신 방법에 대한 첫 문서로서 AS통신의 가장 기본이라 할 수 있는 브라우저와의 통신에 대해 다루고 있습니다.

 SWF와 브라우저와 통신 하는 방법은 크게 두가지로 구분할 수 있습니다.

첫번째, SWF 를 브라우저에 Embeded 시킬때 변수를 전달해 주는 방법
아래와 같이 main.swf 파일을 브라우저에 Embeded할때 "FlashVars" 변수를 SWF에서 접근 하는 방식입니다.

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
             id="FlashVar" width="500" height="375"
             codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
         <param name="movie" value="FlashVar.swf" />
         <param name="quality" value="high" />
         <param name="bgcolor" value="#869ca7" />
         <param name="allowScriptAccess" value="sameDomain" />
    <param name="FlashVars" value="data0=DongHyuk&data1=동혁&data2=http:www.ddongkang.com" />
         <embed src="FlashVar.swf" quality="high" bgcolor="#869ca7"
             width="500" height="375" name="FlashVar" align="middle"
             play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
             type="application/x-shockwave-flash"
             FlashVars="data0=DongHyuk&data1=동혁&data2=http:www.ddongkang.com"
             pluginspage="http://www.macromedia.com/go/getflashplayer">
         </embed>
 </object>


object 와 embed 를 함께 사용해야 하는 이유

마이크로소프트의 Internet Explore(IE) 에서는 특정한 속성과 함께 <object>를 사용해야 하고, IE 외의 다른 브라우져에서는 이와 다른 속성을 설정한 <object>태그를 사용하거나, 아예 <embed>태그를 사용해야 하기 때문입니다. 모든 브라우저에서 크로스 브라우징을 하기 위함입니다.


object 태그를 사용하여 SWF 를 브라우져에 올릴때, FlashVars 값을 지정해서 넘겨 주는 방식 입니다. 위의 코드에서 볼드로 처리해 놓은 부분을 주의 깊게 보면, 두 부분에서 정의 하고 있는 변수들이 (data0,data1,data2)과 그 값들이 똑같아야 정상적으로 SWF에 넘어가게 됩니다.

AS3.0에서 FlashVars 변수를 통해 넘어 오는 값을 받는 방법은 다음과 같습니다.

package
{
    import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.text.TextField;
   

    public class FlashVarsExample extends Sprite
    {
        private var field:TextField;
        public function FlashVarsExample()
        {
            field = new TextField();
            field.autoSize = "left";
            addChild(field);
           
            var keyStr:String;
              var valueStr:String;
           
            var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters;
            for (keyStr in paramObj) {
                valueStr = String(paramObj[keyStr]);
                field.appendText("\t" + keyStr + ":\t" + valueStr + "\n");
            }
        }
       
    }
}

LoaderInfo(this.root.loaderInfo).parameters 는 위의 object 태그에서 넘겨 주는 FlashVars를 받아 오고 paramObj를 for..in 구문을 사용하여 그 안에 있는 변수들을 뽑아 오는 방법 입니다. SWF 가 브라우저 또는 다른 SWF에 로드 되었을때, 자신의 로드 정보를 LoaderInfo 객체에 담고 있기 때문에 사용할 수 있는 방법 입니다. 자세한건 LoaderInfo 클래스를 참고 하세요.

플래시에서 로드 하는 xml의 url이 유동적으로 바뀌거나, 상황에 따라 다른변수를 SWF에 전달해 주고 싶을때 간단하게 사용할 수 있는 방법 입니다. 예를들어 브라우저의 현재 위치를 SWF에 전달하여 네비게이션 Depth를 구현 하는 것도 이 방법을 사용하면 됩니다. 하지만, 비교적 작은 변수만 넘길 수 있다는 점과 변수 값이 그대로 외부에 노출 된다는 단점이 있습니다.

두번째, Flash API 의 ExternalInterface 객체를 사용하는 방법

ExternalInterface는 SWF와 Flash Player컨테이너(브라우져나 Flashplayer를 소유할 수 있는 모든 것들)간에 직접 통신 할 수 있도록 도움을 주는 클래스 입니다. Javascript와의 통신을 위한 중요한 기능을 제공하고 있으며 Adobe에서는 Javascript와의 통신에 ExternalInterface를 사용하도록 권장합니다.

통신은 양방향으로 모두 가능 합니다. SWF에서 Javascript의 함수나 변수에 접근할 수 있으며 변경도 가능합니다. 반대로 Javascript에서 SWF 안에 있는 Flash 객체들도 접근 가능 합니다. 하지만 ExternalInterface는 운영체제와 브라우저가 지원 하지 않으면 사용할 수 없습니다. 지원하는 OS와 브라우저들은 다음과 같습니다.

 브라우저  운영체제  운영체제
 Internet Explorer 5.0 이상
 Windows  
 Netscape 8.0 이상
 Windows  MacOS
 Mozilla 1.7.5 이상
 Windows  MacOS
 Firefox 1.0 이상
 Windows  MacOS
 Safari 1.3 이상
   MacOS

위와 같이 사용할 수 있는 환경이 존재 하기 때문에 사용전 체크를 해 줘야 합니다.

ExternalInterface.available :Boolean = 이 값이 true를 반환하면 사용가능하고 false이면 사용 불가능 합니다.
if(ExternalInterface.available){// 통신 실행}

위와 같은 코드를 통해 사용 가능 여부를 체크 하고 사용해야만 합니다. ExternalInterface는 통신을 위한 두가지 메소드를 제공합니다.

ExternalInterface.call(functionName:String,...arguments):*
먼저 ExternalInterface.call은 SWF를 임베디드(소유)하고 있는 컨테이너의 메소드를 호출하는 함수 입니다.그함수를 수를 호출 할 수 있을 뿐만 아니라, 변수를 전달하여 실행 할 수 있습니다. 예를들어 다음과 같이 메소드를실행 하면 브라우져에서 alert()창을 띄웁니다. (여기서는 주로 사용되는 브라우저를 예를들어 설명하겠습니다.)

ExternalInterface.call("alert","alert function is called");

전달할 인수가 없을때는 빈공간으로 호출할 수 있고, 전달한 인수가 많아지면 그 갯수 만큼 arguments 자리에 넣어
주면 됩니다.

ExternalInterface.addCallback(functionName:String, closure:Function):void
addCallback의 첫번째 인수인 functionName은 Javascript에서 SWF안에 있는 Actionscript 함수를 호출할때 사용하는 이름이고, closure는 실제로 SWF 에서 호출 되는 함수명 입니다. 이 두가지 파라미터가 처음 사용할때 많이 헛깔리는 부분인데요.

예를 들어 SWF에서 addCallback 메소드를 아래와 같이 호출 하면

ExternalInterface.addCallback("sendToActionScript", receivedFromJavascript);

sendToActionScript는 Javascript에서 SWF 에 있는 receivedFromJavascript 함수를 호출 한다는 의미 입니다. 결국 sendToActionScript는 Javascript에서 사용하는 함수이고 receivedFromJavascript는 Actionscript에서 호출되는 함수 입니다. 예를 들어 보겠습니다. (Adobe 도움말에 있는 예제)

예제 샘플
if (ExternalInterface.available) {             
                output.appendText("Adding callback...\n");
                ExternalInterface.addCallback("sendToActionScript", receivedFromJavaScript);
                if (checkJavaScriptReady()) {
                    output.appendText("JavaScript is ready.\n");
                } else {
                    output.appendText("JavaScript is not ready, creating timer.\n");            
                }
               
            } else {
                output.appendText("External interface is not available for this container.");
            }
우선 ExternalInterface.available로 ExternalInterface 객체를 사용할 수 있는지 확인한 후에 addCallback 메소드를 실행 시켰습니다. addCallback 메소드를 등록 한 후에 checkJavaScriptReady() 메소드를 호출하여 javascript 호출이 가능한지 판단 합니다. 호출이 가능한지 체크 하는 이유는 브라우져가 모두 로드가 된 후에 Javascript 메소드를 호출 할 수 있기 때문 입니다. 그래서 Javascript안에 있는 isReady 메소드를 호출하여 반환 값이 true가 넘어 오면 준비가 된걸로 생각하고 스크립트가 진행 됩니다.

ExternalInterface.addCallback 을 등록했기 때문에, 해당 SWF를 임베디드한 브라우져의 Javascript에서 sendToActionScript 메소드를 호출하면 SWF 안에 있는 receivedFromJavaScript 메소드가 실행 됩니다.
private function receivedFromJavaScript(value:String):void {
            output.appendText("JavaScript says: " + value + "\n");
        }

ExternalInterface.call 메소드와 같이 Javascript에서도 SWF로 변수를 전달할 수 있기 때문에 전달된 value값을 받아서 Javascript에서 어떤 값이 넘어 왔는지, TextField에 뿌려 주는 메소드 입니다.

주의해야 할 점 브라우저에 SWF 를 object 태그나, embed 태그를 이용하여 삽입할때, name 값과 id 값을 설정해 줘야 해당 SWF에 접근 할 수 있습니다. 페이지 안에는 여러개의 SWF가 존재 할 수 있기 때문에, id 값이나 name 값을 통해 해당 SWF를 찾아 내서 그 안에 있는 메소드에 접근 할 수 있는 것 입니다. Javascript에서 SWF를 찾아 내는 메소드는 다음과 같습니다.
function thisMovie(movieName) {

         if (navigator.appName.indexOf("Microsoft") != -1) {

             return window[movieName];

         } else {

             return document[movieName];

         }

     }




navigator.appName.indexOf("Microsoft") 를 이용하여 브라우져의 종류를 판단하여, 종류에 따라 접근 방법을 다르게 하여 SWF 를 찾아 내는 메소드 입니다.

전체 브라우저 소스는 아래와 같습니다.

<!-- saved from url=(0014)about:internet -->

 <html lang="en">

 <head>

 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

 <title>ExternalInterfaceExample</title>

 <script language="JavaScript">

     var jsReady = false;

     function isReady() {

         return jsReady;

     }

     function pageInit() {

         jsReady = true;

         document.forms["form1"].output.value += "\n" + "JavaScript is ready.\n";

     }

     function thisMovie(movieName) {

         if (navigator.appName.indexOf("Microsoft") != -1) {

             return window[movieName];

         } else {

             return document[movieName];

         }

     }

     function sendToActionScript(value) {

         thisMovie("ExternalInterfaceExample").sendToActionScript(value);

     }

     function sendToJavaScript(value) {

         document.forms["form1"].output.value += "ActionScript says: " + value + "\n";

     }

 </script>

 </head>

 <body onload="pageInit();">

 

     <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"

             id="ExternalInterfaceExample" width="500" height="375"

             codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">

         <param name="movie" value="ExternalInterfaceExample.swf" />

         <param name="quality" value="high" />

         <param name="bgcolor" value="#869ca7" />

         <param name="allowScriptAccess" value="sameDomain" />

         <embed src="ExternalInterfaceExample.swf" quality="high" bgcolor="#869ca7"

             width="500" height="375" name="ExternalInterfaceExample" align="middle"

             play="true" loop="false" quality="high" allowScriptAccess="sameDomain"

             type="application/x-shockwave-flash"

             pluginspage="http://www.macromedia.com/go/getflashplayer">

         </embed>

     </object>

 

     <form name="form1" onsubmit="return false;">

         <input type="text" name="input" value="" />

         <input type="button" value="Send" onclick="sendToActionScript(this.form.input.value);" /><br />

         <textarea cols="60" rows="20" name="output" readonly="true">Initializing...</textarea>

     </form>
 </body>
 </html>


Javascript 소스를 위에서 부터 보면 Flash 에서 ExternalInterface.call 로 호출한 isReady 메소드가 정의 되어 있습니다.
<body onload="pageInit();"> 태그가 있기 때문에 페이지가 모두 로드 되면 jsReady 변수가 true가 되어 Flash 에서 Javascript를 호출할 준비가 완료 되었다는 것을 알게 됩니다. 그리고 sendToActionScript 메소드를 실행 하면 thisMovie 를 이용하여 해당 SWF를 찾아낸 후에 그 안에 있는 receivedFromJavaScript 메소드를 호출하는 것 입니다.

thisMovie("ExternalInterfaceExample").sendToActionScript(value); 를 호출했다고 해서 SWF안에 있는 sendToActionScript메소드를 호출한다고 생각하면 안됩니다. addCallback을 통해 Javascript에서 sendToActionScript를 호출하였을때 SWF에서는 receivedFromJavasript 메소드를 호출한다고 등록 했기 때문에 receivedFromJavascript 메소드가 호출 됩니다.

그리고 SWF 에서 ExternalInterface.call 메소드를 통해 Javascript의 sendToJavaScript를 호출하면 form태그에 있는 textarea에 그 값이 추가 되는 예제 입니다.

위와 같이 ExternalInterface를 이용하면, Javascript에 있는 함수나 SWF 안에 있는 함수나 쉽게 접근 할 수 있습니다. 다만,
ExternalInterface.call 이나, ExternalInterface.addCallback 으로 등록한 함수만 접근 할 수 있는 단점이 있습니다. 그리고 ExternalInterface에는 몇가지 단점이 존재 합니다.

ExternalInterface의 단점

- 액션스크립트와 자바스크립트 모두에서 별도 코드의 라이브러리를 작성하여, 플렉스 어플리케이션의기능을 자바스크립에서 사용하거나 그 반대의 경우에 대해서도, ExternalInterface 클래스가 있어야 한다.


 - ExternalInterface 클래스는 또한 제약이 있다. 기본 데이터 타입, 배열, 심플 오브젝트들은 전달할 수 있지만, 속성과 메소드를 가지는 사용자 정의 클래스를 전달하는 것은 문제가 있다.


그래서 Adobe에서는 Flex Ajax Bridge (FABridge) 라는 ExternalInterface의 단점을 보완한 Flex framework 기반의 오픈 소스 라이브러리를 제공 하고 있습니다. FABridge의 기능은 다음과 같습니다.

 

FABridge

- 리치 플렉스 컴포넌트를 에이젝트 어플리케이션 안에서 사용하고자 하지만 플렉스 코드를 엄청나게새로 쓰는 것은 원하지 않는 경우이다.  브릿지를 사용하는 일부 어플리케이션 내에 컴포넌트를 감싸려고 한다면, 자바스크립트로 전체를 스크립트할 수 있고, 이것은 서버에서 생성된 eval() 함수를 사용하는 형태의 자바스크립트를 이용한다.


 - 우리 팀에 플렉스를 하는 사람이 한 두 사람뿐인 경우이다. FABridge 라이브러리는 팀의 모든 사람이 한 두 명의 플렉스 전문가가 만든 결과물을 사용할 수 있게 해준다.


 - 플렉스와 에이젝스로 만들어진 부분을 모두 가지는 RIA를 만드는 경우이다. 우리는 ExternalInterface만을 이용하여 통합할 수도 있고, 남보다 앞서 FABridge를 사용하여 더 빠른 방법을 찾을 수도 있다.


공개된 라이브러리는 Flex 에 한정되어 만들어 졌지만, Flash platform에 모두 사용할 수 있도록 컨버팅이 가능한 구조로 되어 있습니다. 다음 문서에서는 FABridge가 어떻게 사용되며, FABridge를 기반으로한 새로운 Javascript 통신 객체에 대해 다룰 것 입니다.

관련 문서 : FABridge (Adobe Lab)

위의 예제에 대한 Actionscript 파일 전체 소스
package
{
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.external.ExternalInterface;
	import flash.text.TextField;	

	public class FlashVarsExample extends Sprite
	{
		private var field:TextField;
		public function FlashVarsExample()
		{
			field = new TextField();
			field.autoSize = "left";
			addChild(field);
			
			var keyStr:String;
  			var valueStr:String;
			
			var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters;
			for (keyStr in paramObj) {
				valueStr = String(paramObj[keyStr]);
				field.appendText("\t" + keyStr + ":\t" + valueStr + "\n");
			}			
		}		
	}
}


Posted by Flash 동강