페이스북 스파르탄 프로젝트의 비밀병기 Bolt.JS

[출처 : kth 웹어플리케이션팀, 2011년11월10일]

웹 서비스와 어플리케이션 개발을 위해 대부분의 경우 jQuery를 사용한다. 가볍고 훌륭한 이 프레임웍은 전 세계 개발자의 열기에 힘입어 거의 웹개발을 위한 표준 프레임웍이 되었다. jQuery 외에도 jQueryMobile과 Sencha Touch, jQTouch 등 몇가지 프레임웍이 더 있고 계속해서 새로운 종류가 등장하고 있다. 그만큼 프론트엔드 개발분야가 다양하다는 것을 시사하지만 프레임워크마다 좋은 점을 내세우고 개발의 편의성과 효율성을 자랑하는 가운데 정작 프레임워크 간에는 어떤 상호 연결성도 없으며 각각의 프레임워크를 위해 제작된 플러그인이나 라이브러리를 목적에 맞게 조절하지 않고는 그냥 가져다 쓸 수 없다. 이런 점 때문에 개발자는 프로젝트에 프레임워크별로 의존성이 생기는 것을 꺼리게 되고 프로젝트마다 저마다의 고유한 라이브러리나 프레임워크를 제작하려는 경향을 보였다.

이런 문제의 근본 원인은 자바스크립트가 중/대형 규모의 어플리케이션 제작이나 재 사용성 확보에 있어 반드시 제공해야하는 ‘모듈화 프로그래밍 구조’에 무게를 두고 설계된 언어가 아니기 때문이다. YUI와 PrototypeJS 에 이어 jQuery를 활용하는 시기가 지나는동안 개발자들은 모듈화 프로그래밍 문제를 해결하기 위해 자체적으로 꾸준한 시도를 해왔으나 폭넓은 사용자 층을 얻지 못하였다. 그러던중, 2009년 1월에 Kevin Dangoor에 의해서 “ServerJS”라는 이름의 프로젝트가 시작되었다. 곧 “CommonJS”로 변경된 이 프로젝트는 웹 브라우저 밖의 환경을 위한 자바스크립트 ecosystem 을 기술하는 것을 목적으로 하고 자바스크립트의 가장 취약한 부분중에 하나였던 ‘모듈화 개발을 위한 API 표준’을 제시하여 중/대형 규모의 어플리케이션 제작에 물꼬를 트게 하였다.

바로 이 CommonJS API 규격을 바탕으로 Facebook에 의해 제작된 Bolt.JS는 공개되자마자 전 세계 개발자의 상당한 관심을 끌었으나 돌연 GitHub등에서 소스가 삭제되고 어떠한 추가 공지도 없이 제대로 작성되지 않은 홈페이지 문서만 제공될 뿐이다. 홈페이지 문서와 관련된 기사를 훝어보던 중, 단순한 UI 프레임워크가 아님을 직감하였고 여러 경로를 뒤진후에 얻은 소스를 분석하였다. 예상대로 공식문서에서 보이는 것보다 훨씬 잠재력이 있다는 것과 웹 어플리케이션 제작에 있어 상당 부분에 영향을 줄 수 있다는 것을 이 리뷰를 통해 기술하고자 한다.

개요:
BoltJS는 오직 HTML5와 자바스크립트만을 사용하여 환상적인 모바일 웹 어플리케이션을 제작하는 것을 도와주는 UI 프레임웍이다. 서버사이드 처리 과정이 필요없으며 자바스크립트로만 작성되어 브라우저에서 동작하는 BoltJS는 현재 모바일 WebKit 기반 브라우저에 맞춰져 있다. 현재 Facebook의 Spartan 프로젝트가 모바일 WebKit에 초점을 맞추고 있기 때문이다.

구조 및 내장 기능:
Bolt.JS는 공개된 베타버전에서만 13,496 라인에 이르는 코드로 작성되어 있으며 다음과 같은 주요 패키지를 CommonJS 규격에 맞추어 자체적으로 포함하고 있다.

도식 1. Bolt.JS 구조

iScroll v4는 모바일용 HTML5 어플리케이션에 스크롤 관련 필수 기능을 제공하며 tokenizerTypeahead는 유용한 입력기능을, underscore.js 는 functional programming에서 쓰이는 고차함수 (higher-order function) 라이브러리로써 모듈성과 템플릿 기능을 제공한다. 이중에 눈여겨 봐야 할 것은 Javelin.JS 인데, 이벤트 처리를 모바일 웹 어플리케이션 제작에 최적화 시킨 프레임웍이다. Javelin.JS는 또 하나의 주제가 되므로 본 리뷰에서는 제외하였다.
또한, 모바일 웹 어플리케이션 제작에 있어 핵심적인 레이아웃과 ‘View’ 라 명명되는 내장 UI가 상당수 제공된다:

도식 2. Bolt.JS UI components

특징: LDAP 처럼 CommonJS 스펙을 구현하였다는 점이다.
서버사이드 자바스크립팅 환경인 NodeJS 역시 CommonJS 스펙에 기반하여 API를 작성하였기에 안정버전이 0.6 이지만 사용가능 모듈수는 2011년 11월 8일 현재 4870개에 달하며 다양한 서버측 요구조건에 맞는 모듈을 쉽게 찾을 수 있다. 2010년 초반에 소개된 NodeJS 가 불과 2년이 되지 않은 시점에서 이렇게 발전할 수 있었던 것은 저마다 제각각의 API를 가졌던 jQuery, ExtJS, YUI는 달리 CommonJS API에 기반하여 모듈을 제작할수 밖에 없는 구조 때문이다. Bolt.JS 역시 표준화된 API 덕분에 어플리케이션 개발자는 서로의 모듈을 손쉽게 가져다 사용할 수 있으며 통합개발환경 (Facebook이 제작한다는 루머가 있지만 확인하지 못하였다) 의 도움을 받아 고수준의 어플리케이션을 손쉽게 만들 수도 있는 것이다.

예제 코드:
전통적인 ‘HelloWorld’를 표시하는 예제를 통해 Bolt.JS의 활용을 살펴보자. 우선, 기존 웹 어플리케이션과는 달리 ‘패키지’ 개념이 있다는 점이 틀리다. 패키지는 .html 파일과 .js, .css 등으로 구성되며 package.json 파일에 JSON 포맷으로 기술되야 한다. 이 역시 CommonJS 요구사항이다.

package.json:

{
“bolt_build_manifest” : [{ “sources”: [ “css”, [“”, “js”]],
“package_target”: “pkg”, // 이름이 ‘pkg’인 폴더를 가리킨다
“package_name”: “helloworld”}] }

– View를 정의하는 helloworld.js:

require.define({‘helloworld’: function(require, exports, module) {

var core = require(‘javelin/core’);
var View = require(‘view’).View;

var HelloView = core.createClass({
extend: View,

declare: function(options) {
return{
content: “Hello World!”
}}
})

exports.init = function() {
require(‘builder’).build({
view: HelloView
}).placeIn(document.body);
}

}});

– Control 을 담당하는 helloworld.js (위의 것과 이름이 같지만 다른 폴더에 있다):

var core = require(‘javelin/core’);
var View = require(‘view’).View;

var HelloView = core.createClass({
extend: View,
declare: function(options) { return{ content: “Hello World!” }}
});

exports.init = function() {
require(‘builder’).build({ view: HelloView }).placeIn(document.body);
}

– 마지막으로, helloworld.html이다 (helloworld.css 파일은 생략):

<html>
<head>
<title>Hello World Application</title>
<meta name=”apple-mobile-web-app-capable” content=”yes”>
<meta http-equiv=”content-type” content=”text/html; charset=utf-8″>
<meta name = “viewport” content=”initial-scale=1,maximum-scale=1,user-scalable=no,width=device-width,target-densityDpi=device-dpi” />
<link rel=”stylesheet” href=”lib/bolt.css” type=”text/css” media=”screen” charset=”utf-8″>
<link rel=”stylesheet” href=”pkg/helloworld.css” type=”text/css” media=”screen” charset=”utf-8″>
<script src=”lib/bolt.js”></script>
<!– HelloWorld JS –>
<script type=”text/javascript” charset=”utf-8″ src=”pkg/helloworld.js”></script>
</head>
<body>
<script type=”text/javascript” charset=”utf-8″>
var helloworld = require(‘helloworld’);
helloworld.init();
</script>
</body>
</html>

단순한 예제여서 Bolt.JS의 특징을 한번에 파악할 수는 없지만, 모듈 기반의 개발방식을 한눈에 알 수 있다. CommonJS 규약을 지키는 Node.JS 모듈을 Bolt.JS의 모듈로써 사용할 수도 있을 것이다. 성공적인 중/대형 규모의 어플리케이션의 특징가운데 하나는 모듈화에 있으므로 Bolt.JS의 API 표준화 정책은 많은 개발자의 참여를 불러일으킬 것이라 예측할 수 있다.

활용:
지정된 프레임워크가 없는 사내 개발환경에 CommonJS 규약에 의한 개발방식은 언뜻 생각해도 몇몇 부분에서 시너지 효과를 가져올 것이라 쉽게 예측할 수 있다:

– 각 부서별/팀별로 중복으로 제작할 필요가 없고, 부서별로 모듈을 유지보수하는 비용이 줄어들 것이다.
– 사내에서 개발하는 것 자체가 글로벌에 적용될 수 있다.

결론:
Apple AppStore에 휘말리지 않겠다는 의지를 보인 Facebook의 행보는 HTML5 어플리케이션 개발의 흐름에 한번더 큰 변화를 가져다 줄 것이며 글로벌 사업을 향하는 여러 업체의 사업방향에도 영향을 줄 것이다. 따라서, Bolt.JS 와 CommonJS 표준화 개발방식을 검토할 필요가 있다는 것을 강조한다.

flashplayer

페이지안의 특정컨텐츠가 브라우저화면에 노출될 경우, 재생되는 영상플레이어

HTML상에 정의되어야할 Javascript함수입니다.

이는 “jquery-1.3.2.min.js”파일을 import하여 사용하는 것을 전제로 합니다.

HTML상에서 Object Embed태그

플래시 내부의 클래스정의

ExternalInterface가 가능한 시점, 그리고 HTML내부의 js파일이 로드과 완료되어서 준비가 되었는지, 플래시파일이 초기화가 되어서
Javascript에서 플래시내부함수를 호출할때 그 이벤트를 받아들일 준비가 되었는지,
여러가지 상황을 체크해서 통신을 하도록 해주는 것이 좋습니다.
그렇지 않으면 항상 객체의 함수가 정의되어있지않다는둥, null객체라는둥 수많은 js에러메세지를 경험하실수 있을겁니다.

사용자 삽입 이미지사용자 삽입 이미지
이러한 에러들이 발생하는 모든 이유는 서로의 객체가 준비되지 않았는데, CallBack명령들이 실행되서입니다.
HTML페이지 내에서는 현재 페이지가 로드가 완료된 시점에서 브라우저scroll이벤트를 발생하고, 플래시객체에
접근하는 것이 좋습니다. (좋은것이 아니라 반드시 그렇게 해야합니다 ^^)
그 시점을 찾아주는 것이 jQuery에서  $(“document”).ready 부분입니다.
브라우저의 스크롤로 인한 페이지의 scrollTop값의 변화값은 HTML상에서 처리해야할 부분입니다.
그러나 영상재생을 켜고,끄는 부분은 플래시가 내부적으로 처리해야할 부분이지요.
Javascript와 플래시간의 함수호출방법에 대해 간단하게 알아보겠습니다.
<플래시에서 Javascript함수호출>
이는 간단하게 플래시에서 ExternalInterface를 사용하면 됩니다.
<Javascript에서 플래시의 함수호출>
Javascript에서 플래시내부의 함수에 접근을 하기 위해서는, 플래시에서 미리 정의가 필요합니다.
ExternalInterface.addCallBack 메서드를 사용하며, 쌍방간의 사용할 ID를 정의합니다.
큰 그림은 이렇게 됩니다. 혹시 질문이 있는분은 댓글부탁드립니다.

플래시 자체 Javascript 팝업 소스

버튼액션이 들어갈 타임라인상의 프레임에 :

function JSOpen( url, winName, winW, winH, tools, menu, scroll, resize, status, directory, location){
        javacode = “javascript:window.open(‘” add url add “‘,'” add winName add “‘,’width=” add winW add “,height=” add winH add “,top=’+((screen.height/2)-(” add winH/2 add “))+’,left=’+((screen.width/2)-(” add winW/2 add “))+’,toolbar=” add tools add “,scrollbars=” add scroll add “,resizable=” add resize add “,menubar=” add menu add “,status=” add status add “,directories=” add directory add “,location=” add location add “‘); void(0);”
        return javacode;
}

버튼에 들어갈 액션:

getURL( JSOpen(“URL”,”NAME”,300,200,0,0,0,0,0,0,0) );

첫번째는 열고자 하는 유알엘, 두번째는 윈도우 이름이고 다음부터 순서대로,
가로크기, 세로크기, 도구모음, 메뉴, 스크롤여부, 리사이즈가능, 상태바, 디렉토리, 주소창 입니다

IE Tester (IE브라우저 버젼별 테스트)

IETester is a free WebBrowser that allows you to have the rendering and javascript engines of IE8, IE7 IE 6 and IE5.5 on Vista and XP, as well as the installed IE in the same process.
New in v0.3.2 : IE8 final version !


This is an alpha release, so feel free to post comments/bugs on the IETester forum or contact me directly.
Minimum requirement : Windows Vista or Windows XP with IE7 (Windows XP/IE6 config has some problems and IE8 instance do not work under XP without IE7)


Download IETester v0.3.2 (24MB)
(IETester v0.3.2 zipped intaller for people unable to download .exe files due to proxy limitations)


Known problems and limitations :



  • The Previous/Next buttons are not working properly

  • Focus is not working properly

  • Java applets are not working

  • Flash is not working on IE6 instance in user mode : A solution is to launch IETester as admin user and Flash will work.

  • CSS Filters are not working correctly in user mode : A solution is to launch IETester as admin user and CSS Filters will work.



    http://www.my-debugbar.com/wiki/IETester/HomePage

현재 브라우저의 URL을 FLEX로 받아오는 방법

ExternalInterface를 사용하여 eval을 호출하는 방법으로 URL을 받아올 수 있다.
ExternalInterface.call(“eval”, “window.location.href”);

private var currentURL:String = ExternalInterface.call(“eval”, “window.location.href”);
private var encodedCurrentURI:String = escape(currentURL); // &를 포함할 경우 escape처리

FLEX에 Embed된 Flash SWF파일과의 통신

FLEX에서 SWFLoader를 이용하여 플래시SWF파일을 Embed시킬 경우에
간단하게 변수를 전달하는 것이 안되더군요. (SWFLoader.params = 어쩌고 이런 방식이 안됨;;)

이를 위해서는 이전부터 존재했던 LocalConnection을 사용하여야 통신이 가능합니다.

Javascript, AJAX를 사용하여도 되지만, 독립적인 실행이 가능하게 하려는 취지에는 맞지않지요.


이와 같은 방법으로 FLEX의 송신부에서 localConnection 객체를 생성해주고 StatusEvent리스너를 달아줍니다.

FLASH의 수신부에는 아래의 코드를 입력해줍니다.


수신부에서는 이처럼 세팅합니다. 이런 방식으로 FLEX에서 플래시로 데이터를 전달할수 있고, 플래시에서 다시 FLEX로 데이터를 전달할때는 이 방식도 가능하겠지만, Event를 디스패치 시켜서 받는 방식도 가능합니다

FLEX FileUpload with ASP .NET

[FLEX PART]


<mx:Script>
  <![CDATA[
    var imageTypes:FileFilter = new FileFilter(“Images (*.jpg, *.jpeg, *.gif, *.png)”, “*.jpg; *.jpeg; *.gif; *.png”);
    var textTypes:FileFilter = new FileFilter(“Text Files (*.txt, *.rtf)”, “*.txt; *.rtf”);
    var allTypes:Array = new Array(imageTypes, textTypes);
    var fileRef:FileReference = new FileReference();
 
   private function doFileSelect():void{
   try {
    fileRef.addEventListener(Event.SELECT, selectHandler);
    fileRef.addEventListener(Event.COMPLETE, completeHandler);  
       var success:Boolean = fileRef.browse(allTypes);
    } catch (error:Error) {
       trace(“Unable to browse for files.”);
    }
   }
   
   private function selectHandler(event:Event):void {
       var request:URLRequest = new URLRequest(“http://localhost/FlexService/fileupload.aspx“)
       try {
           fileRef.upload(request);
       } catch (error:Error) {
           trace(“Unable to upload file.”);
       }
   }
   private function completeHandler(event:Event):void {
       trace(“uploaded”);
   }


  ]]>


< ?xml:namespace prefix = mx />—————————————————————————————————-

[.NET – fileupload.aspx – C#]

protected void Page_Load(object sender, EventArgs e)
    {


            if (Request.Files.Count > 0)
            {
                HttpPostedFile htpFile = Request.Files[0];
                htpFile.SaveAs(this.MapPath(“”) + “\\test\\” + Request.Params[“FileName”]);
            }


     }

출처 : http://cafe.naver.com/flexcomponent/3564

Embed SWF의 cross-browsing 문제해결

Internet Explorer에서는 문제가 없으나, Firefox, Safari, Chrome에서는 마우스 휠이 작동하지않는
문제점이 있습니다. 이를 해결하기 위한 한가지 방법을 공유합니다.

일단 <swfobject>라는 js파일을 이용하여 HTML등에 Embed하는 방식입니다.

Source 다운로드 : http://swfobject.googlecode.com/files/swfobject_2_1.zip

===============================================================================================

1. HTML코드에 js파일을 로드합니다.

<script type=“text/javascript” src=“swfobject.js”></script>

2. 아래와 같이 swfobject.registerObject 를 사용하여 Embed합니다

swfobject.embedSWF(swfUrl, id, width, height, version, expressInstallSwfurl, flashvars, params, attributes)

<
script type=“text/javascript”>

var flashvars= {
  name1
: “hello”,
  name2
: “world”,
  name3
: “foobar”
};
var params= {
  menu
: “false”
};
var attributes= {
  id
: “myDynamicContent”,
  name
: “myDynamicContent”
};

swfobject
.embedSWF(“myContent.swf”, “myContent”, “300”, “120”, “9.0.0”,“expressInstall.swf”, flashvars, params, attributes);

</script>


이런 방식으로 변수를 전달할수 있다.

참고사이트 : http://blog.pixelbreaker.com/flash/as30-mousewheel-on-mac-os-x/
Google Code : http://code.google.com/p/swfobject/