IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  웹 개발 | 자바 | 오픈 소스  >

Dojo 1.x로 위젯 개발하기

developerWorks
문서 옵션
PDF format - Fits A4 and Letter

PDF - Fits A4 and Letter
227KB (21 pages)

Get Adobe® Reader®

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

영어원문

영어원문


제안 및 의견
피드백

난이도 : 초급

Marco Lerro, Staff Engineer, IBM
Roberto Longobardi, Advisory Software Engineer, IBM
Gianluca Perreca, Staff Engineer, IBM
Alessandro Scotti, Advisory Software Engineer, IBM

원문 게재일 : 2009 년 4 월 28 일
번역 게재일 : 2009 년 7 월 21 일

Dojo JavaScript 툴킷을 사용하여 HTML 위젯을 개발하는 기본적인 방법을 설명하는 이 기사에서는 이 툴킷을 소개한 후 여러 예제를 통해 샘플 위젯부터 단계적으로 복잡한 위젯을 살펴보면서 개발 단계에서 발생할 수 있는 일반적인 문제를 찾아보고 해결합니다.

소개

이 기사에서는 Dojo JavaScript 툴킷(버전 1.0부터)을 사용하여 HTML 위젯을 개발하는 기본적인 방법에 대해 설명한다. 또한 여러 예제를 통해 간단한 위젯부터 단계적으로 복잡한 위젯을 살펴보면서 위젯을 개발하는 과정에서 발생할 수 있는 일반적인 문제점을 해결한다.




위로


Dojo 툴킷이란?

Dojo는 동적 HTML 웹 애플리케이션을 개발하기 위한 JavaScript 기반의 오픈 소스 툴킷이다. 이 툴킷을 사용하면 표준 HTML 위젯보다 복잡한 위젯을 빠르게 개발할 수 있다. Dojo에서 제공하는 구성 요소를 통해 편의성, 응답성 및 기능성이 강화된 웹 사용자 인터페이스를 만들 수 있다. Dojo에서 제공하는 하위 레벨 API 및 호환성 계층은 여러 브라우저에서 호환되는 애플리케이션을 작성하는 데 도움이 된다.




위로


시작하기 전에

시작하기 전에 먼저 개발 환경을 설정해야 한다. 그렇게 하려면 다음을 수행한다.

  1. Dojo 프로젝트 사이트에서 최신 버전의 Dojo 툴킷(dojo-release-1.x.x-src.zip 또는 dojo-release-1.x.x-src.tar.gz)을 다운로드한다. (참고자료에서 링크를 볼 수 있다.)
  2. 아카이브의 컨텐츠를 폴더에 압축 풀기한다. 이 경우 압축이 풀린 dojo.js 파일의 위치에 주의를 기울여야 한다. dojo.js가 페이지에 로드되면 패키지 시스템이 모든 모듈에 대한 로드 작업을 관리한다.

완료된 후에는 그림 1과 같은 폴더 구조가 생성된다.


그림 1. 펼쳐진 dojo 파일의 폴더 구조
루트, 루트의 서브폴더인 dojo1.x.x, dojo1.x.x의 서브폴더인 dijit, dojo, dojox 및 util을 보여 주는 폴더 구조

Dijit은 dojo의 상위 계층에 있는 위젯 시스템이다. 고유 테마인 tundra를 통해 모든 위젯에 공통된 디자인 및 색상 스키마를 제공한다. Dojox는 Dojo 툴킷의 확장 기능을 제공하는 개발 패키지로 공통 콜렉션에 없는 기능을 원하는 개발자에게 필요하다.




위로


Dojo 위젯

웹 사이트를 검색하다 보면 화면에서 수백 개의 위젯을 보게 된다. 웹 브라우저에 있는 단추 하나하나가 위젯이며 텍스트 입력 상자도 위젯이다. 표준 HTML은 입력 상자, 단추 및 하이퍼링크와 같은 제한된 위젯 세트만을 제공한다.

Dojo 위젯은 텍스트 입력 상자와 같은 항목을 받아서 날짜를 선택할 수 있는 그래픽 달력과 같이 사용자에게 좀 더 친숙한 기능을 추가한다. 이 위젯은 원래 항목에 영향을 주지 않고 새 기능을 추가할 수 있다.

Dojo 위젯은 쉽게 다시 사용할 수 있도록 시각적 웹 구성 요소를 캡슐화하며 다음 세 파일을 이용해서 정의된다.

  • 위젯 논리가 있는 JavaScript 파일
  • 위젯에 사용할 HTML 형태의 템플리트를 제공하는 선택적 HTML 파일
  • 일반적으로 모든 위젯(테마)에 공통되며 위젯의 HTML 템플리트에 적용될 시각적 양식을 가지고 있는 CSS 파일

Dojo 툴킷 가져오기

Listing 2에서는 일반적인 웹 페이지에서 위젯을 가져오는 데 사용할 수 있는 기본적인 HTML 기본 폼을 보여 준다.


Listing 1. 위젯을 웹 페이지로 가져오는 HTML 코드
<html>
   <head>
      <title>Dojo Toolkit Test Page</title>    
      
      <style type="text/css">
         /* CSS style code */    
      </style>    
    
 <script type="text/javascript" src="js/dojo1.2/dojo/dojo.js"
 djConfig="parseOnLoad:true, isDebug:true"></script>
      
      <script type="text/javascript">
         /* Javascript code */
      </script>
   </head>
   <body>
      /* Widgets definition code */
   </body>
</html>
            

첫 번째 스크립트 태그는 간단히 dojo.js 부트스트랩 파일을 로드하여 Dojo 툴킷을 초기화한다. djConfig 오브젝트의 parseOnLoadisDebug 특성은 Dojo가 런타임에 검사하는 가장 일반적인 두 가지 구성 옵션이다. parseOnLoad는 로드 타임에 실행되는 마크업 구문 분석을 토글하고 isDebug는 디버깅 메시지를 활성화 또는 비활성화한다. djConfig 오브젝트는 다음과 같이 dojo.js 파일이 로드되기 전에 전역 변수로 설정될 수도 있다.


Listing 2. djConfig를 사용하여 전역 변수를 설정하는 코드
<script type="text/javascript">
   var djConfig = {
      isDebug:true, parseOnLoad:true
   };
</script>
<script type="text/javascript" src="js/dojo1.2/dojo/dojo.js"></script>
            

Dojo 패키지 시스템

Dojo에는 dojo.require 함수를 통해 파일에 있는 애플리케이션 클래스를 구조화하고 로드하는 패키지 시스템이 있다. 이 함수는 기본 dojo.js에서 아직 제공하지 않는 Dojo 툴킷의 일부를 로드할 수 있다.

위젯을 작성하려면 Listing 3의 코드를 추가하여 위젯 선언을 가져와야 한다.


Listing 3. 위젯 선언을 가져오는 코드
<script type="text/javascript">
   dojo.require("widgets.Button");
</script>
             

이제 다음과 같은 코드는 본문 섹션에 삽입할 수 있다.

<body>
   <div dojoType="widgets.Button">My Button</div>
</body>
            

dojoType 속성을 지정하면 Dojo 툴킷이 태그를 특별한 방법으로 관리하게 된다. 페이지 로드 타임에 Dojo 구문 분석기는 dojoType 속성에 지정된 위젯 선언을 검사하고 위젯을 인스턴스화한 후 가져온 위젯 DOM 노드로 태그를 대체한다.

위젯 선언하기

이제 TextBox 위젯 예제를 살펴보자. 이 예제에서는 JavaScript 파일, 템플리트 파일 및 CSS 양식 파일을 정의한다.

먼저 위젯의 정의와 논리가 들어 있는 JavaScript 파일인 TextBox.js를 작성해야 한다(Listing 4 참조).


Listing 4. JavaScript 파일 TextBox.js의 컨텐츠
dojo.provide("widgets.TextBox");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.declare(
    "widgets.TextBox",
    [dijit._Widget, dijit._Templated],
    {
        /** the template path */
        templatePath: dojo.moduleUrl("widgets", "templates/TextBox.html"),
        /** the input DOM node */
        inputNode: null,       
        /** the label */      
        label: "", 
        
        /** onkeyup handler */
        onKeyUp: function() {
            // give a chance to the browser to update the DOM
            setTimeout(dojo.hitch(this, this.validate), 0);
        },
        
        /** validate function */
        validate: function() {
            if ( this.inputNode.value === "Ok" ) {
                // the text is correct
                dojo.addClass(this.inputNode, "inputOk");
                dojo.removeClass(this.inputNode, "inputError");
            } else {
                 // the text is incorrect       
                 dojo.removeClass(this.inputNode, "inputOk");
                 dojo.addClass(this.inputNode, "inputError");
              }
           }
      }
);
               

dojo.provide()는 새 위젯의 이름을 정의하고 클래스 선언을 등록한다. 다음 사항에 주의한다.

  • dijit._Widgetdijit._Templated는 TextBox 위젯의 수퍼클래스이다.
  • templatePath, inputNodelabel은 위젯의 속성이다.
  • onKeyUp()validate()은 위젯의 논리를 정의한 함수이다.

이제 Listing 5와 같은 템플리트 파일 TextBox.html을 정의할 수 있다.


Listing 5. TextBox.html의 컨텐츠
<span class="textBox"> 
   ${label}: 
   <input 
       type="text"
       class="inputOk"
       dojoAttachPoint="inputNode"
       dojoAttachEvent="onkeyup: onKeyUp">
   </input>
</span>
            

${label}은 위젯 인스턴스의 label 특성으로 대체된다.

dojoAttachPoint 선언으로 인해 inputNode 위젯의 특성은 input 태그에 해당하는 DOM 노드로 설정된다.

dojoAttachEvent 선언으로 인해 입력 노드에서 발생한 onkeyup 이벤트가 onKeyUp 위젯의 메소드 호출을 트리거한다.

textBoxinputOk 클래스는 TextBox.css 파일에 정의된 CSS 클래스 이름을 참조한다(Listing 6 참조).


Listing 6. TextBox.css에 있는 CSS 클래스 이름
.ibm .textBox {
   margin: 5px;
   padding: 5px;
   background-color: #eee;
}

.ibm .inputOk {
   border: 1px solid green;
}

.ibm .inputError {
   border: 1px solid red;
}
            

클래스 이름은 프로젝트에서 고유해야 하므로 일반적으로 CSS 선택자(예제의 경우 ibm)를 가지고 있다.

마지막으로 Listing 7과 같이 HTML 페이지에서 위젯을 작성할 수 있다.


Listing 7. HTML 페이지에서 위젯을 작성하는 코드


<html>
   <head>
      <!-- page title -->
      <title>TextBox Widget</title>
      <!-- include the DOJO -->
      <script type="text/javascript" src="../dojo-1.0.0/dojo/dojo.js"
      		djConfig="isDebug: true, parseOnLoad: true">
      </script>

      <!-- import DOJO base CSS, DIJIT theme, and widget CSS -->
      <style type="text/css">
         @import "../dojo-1.0.0/dojo/resources/dojo.css";
         @import "../dojo-1.0.0/dijit/themes/tundra/tundra.css";
         @import "templates/TextBox.css";
      </style>
        
      <!-- import DOJO stuff -->
      <script type="text/javascript">
         dojo.require("dojo.parser");
         <!-- register our module path -->
         dojo.registerModulePath("widgets", "../../widget");
         <!-- import our stuff -->
         dojo.require("widgets.TextBox");
      </script>
   </head>

   <body class="tundra ibm" style="padding:5px">
   <br/>
      <!-- declare the DOJO widget -->
      <div 
         dojoType="widgets.TextBox" 
         label="Name">
      </div>
   </body>
</html>
            

그림 2에서는 TextBox 위젯을 보여 준다.


그림 2. TextBox 위젯
두 개의 작은 텍스트 상자 즉, 녹색으로 정상 상태임을 나타내는 상자와 빨간색으로 오류임을 나타내는 상자를 보여 주는 상자

선언적 방식과 프로그래밍 방식

Dojo는 두 가지 프로그래밍 모델 즉, 선언적 방식과 프로그래밍 방식을 지원한다. 필요한 경우 두 모델을 같은 페이지에서 사용할 수 있다. Listing 7에서는 선언적 방식 모델로 위젯을 작성한다.

<div dojoType="widgets.TextBox" label="Name"></div>

같은 모델을 Listing 8과 같이 프로그래밍 방식 모델로도 작성할 수 있다.


Listing 8. TextBox 위젯을 프로그래밍 방식으로 작성하기
<html>
   <head>
      <!-- page title -->
      <title>TextBox Widget</title>
      <!-- include the DOJO -->
      <script type="text/javascript" src="../dojo-1.0.0/dojo/dojo.js"
      		djConfig="isDebug: true, parseOnLoad: true">
      </script>

      <!-- import DOJO base CSS, DIJIT theme, and widget CSS -->
      <style type="text/css">
         @import "../dojo-1.0.0/dojo/resources/dojo.css";
         @import "../dojo-1.0.0/dijit/themes/tundra/tundra.css";
         @import "templates/TextBox.css";
      </style>
        
      <!-- import DOJO stuff -->
      <script type="text/javascript">
         dojo.require("dojo.parser");
         <!-- register our module path -->
         dojo.registerModulePath("widgets", "../../widget");
         <!-- import our stuff -->
         dojo.require("widgets.TextBox");
      </script>
	  
      <script type="text/javascript">
         function createWidget()
         {
            var widget = new widgets.TextBox();
            widget.label = "Name";
            widget.startup();
         }
      </script>
   </head>

   <body class="tundra ibm" style="padding:5px">
   <br/>
      <!-- declare the DOJO widget -->
      <script type="text/javascript">
         createWidget();
      </script>
   </body>
</html>
            




위로


Dojo 위젯에 대한 추가 설명

앞에서 언급한 대로 Dojo 위젯은 특수 클래스인 dijit._Widget 클래스에서 상속한 Dojo 클래스 선언이다. 이 클래스는 위젯의 기본 동작을 정의하고 모든 위젯 구현에서 공유하는 공통 함수를 제공한다. _Widget 클래스에 구현된 가장 중요한 작업은 다음과 같다.

  • create 메소드를 정의한다. 이 메소드는 위젯이 인스턴스화될 때 자동으로 호출되며 필수 작성 단계를 모두 실행한다.
  • 일부 template 메소드를 정의한다. 이러한 메소드는 위젯 구현자에 대한 특별한 후크를 제공하며 이를 통해 특정 작성 단계에서 특별한 초기화 작업을 구현할 수 있다.
  • destroy 메소드 세트를 정의한다. 이 메소드는 할당된 위젯의 리소스를 정리한다.
  • 이벤트 관리 메소드를 정의한다. 이러한 메소드는 위젯 메소드와 DOM 노드/메소드 호출 이벤트를 연결한다.

위젯 작성 단계

create 메소드는 위젯 초기화를 수행하는 동안 다음과 같은 기본 단계를 수행한다.

위젯의 고유 ID를 작성한다(제공되지 않은 경우).

모든 Dojo 위젯은 고유 ID로 식별되어야 한다. 위젯이 인스턴스화될 때 위젯 ID를 제공할 수 있다. 그렇지 않은 경우, Dojo가 다음과 같은 형식으로 ID를 작성한다.

packageName_className_number

예를 들어, 단추의 경우에는 dijit_form_Button_0이라는 ID가 자동으로 생성된다.

packageName은 마침표가 밑줄로 대체된 위젯 패키지(예: dijit_form)이며, number는 위젯 단위에서 단계별로 증가되는 숫자이다.

위젯을 전역 위젯 레지스트리에 등록한다.

위젯은 나중에 dijit.byId 메소드를 사용하여 검색할 수 있다. 이 메소드는 지정된 ID에 해당하는 위젯 오브젝트를 리턴한다. 레지스트리는 dijit.registry_hash의 전역 공간에 유지되는 오브젝트이다. FireBug(참고자료 참조)와 같은 디버깅 도구를 사용하여 이 레지스트리를 검사하면 유실된 위젯과 같은 유용한 추적 정보를 확인할 수 있다.

속성을 맵핑한다.

위젯 특성을 위젯 템플리트의 사용자 정의 노드에 다시 맵핑할 수 있다. 맵핑할 속성과 대상을 attributeMap 오브젝트에 나열할 수 있다. 이러한 오브젝트의 각 특성은 다음과 같은 방법으로 맵핑을 정의한다.

  1. 특성 이름은 설정할 값이 저장되어 있는 위치인 위젯 특성 이름을 식별한다.
  2. 특성 값은 대상 DOM 노드가 저장되어 있는 위치인 위젯 특성 이름을 식별한다. 빈 문자열이 지정된 경우에는 domNode가 사용된다.

Listing 9에서는 해당 예제를 보여 준다.


Listing 9. dojo 위젯 선언하기
dojo.declare(
 "MyWidget", 
   dijit._Widget, 
 {
 // the attribute to map (name and value)
 title: "myTitle",

 // the DOM node to be used to set the 
 // title attribute to the "myTitle" value
 titleNode: null,

 // the attribute map 
 // the title attribute is mapped to the titleNode
      attributeMap: {title: "titleNode"},
// the template string
      templateString: "<div><span dojoAttachPoint=\"titleNode\"></span></div>",
            

결과 위젯 템플리트는 다음과 같다.

<div><span title="myTitle"></span></div>

base _Widget 클래스가 이미 일부 기본 HTML 속성(예: ID, 클래스, 양식)을 맵핑하고 있으므로 구현자가 attributeMap 특성을 재정의하면 안된다. 대신 기본 클래스 attributeMap 특성과 구현자의 값을 혼합해야 한다. Listing 10에서는 _FormWidget 클래스에서 가져온 예제를 보여 준다.


Listing 10. 기본 클래스 attributeMap 특성과 사용자 정의 값 혼합하기
attributeMap: 
 dojo.mixin(
 dojo.clone(dijit._Widget.prototype.attributeMap),
 {id:"focusNode", tabIndex:"focusNode", alt:"focusNode"}
),
            

템플리트 메소드

위젯 작성 단계 동안 특정 초기화 단계에서 구현자에게 일부 작업을 수행할 수 있는 기회를 제공하기 위해 몇 가지 메소드가 호출된다. 호출되는 메소드는 다음과 같다.

  1. postMixInProperties: 이 메소드는 모든 위젯 매개변수가 위젯 인스턴스 속성으로 설정(혼합)된 후 호출된다. 이 시점은 초기화에서 제공되는 특성을 기반으로 하는 경우 추가 특성 초기화를 수행하기에 적합한 시점이다.
  2. buildRendering: 이 메소드는 위젯에 대한 렌더링을 생성할 때 호출된다. 이 후크는 HTML 템플리트를 사용하여 기본 위젯을 확장하는 dijit._Templated 혼합 클래스에 의해 구현된다. 구현자는 고유한 구현을 제공하여 _Templated 클래스 작업을 구체화할 수 있다.
  3. postCreate: 이 메소드는 위젯의 DOM이 준비되어 페이지에 삽입된 후에 호출된다. 구현자는 이 시점에서 위젯의 DOM 구조에 대한 작업을 수행할 수 있다. 하위 위젯은 아직 시작되지 않았다.
  4. startup: 위젯에 대한 작업을 수행할 수 있는 마지막 기회이다. 이 시점에서 하위 위젯이 시작된다.
  5. uninitialize: 위젯이 제거될 때 호출된다. 구현자는 몇 가지 수동 정리 작업을 수행할 수 있다.

구현자가 템플리트 메소드를 제공할 수 있기는 하지만 이 경우 구현자는 수퍼클래스에 템플리트 메소드가 구현되어 있을 수도 있다는 점을 간과해서는 안된다. 체인에 속한 모든 클래스에 대한 초기화를 올바르게 수행하려면 구현자가 Listing 11과 같이 수퍼클래스 메소드 호출 코드를 직접 작성해야 한다.


Listing 11. 수퍼클래스 메소드 호출 예제
startup: function()
{
 // call the superclass' method
   this.inherited("startup", arguments);
 // your code here
}
            

일반적인 규칙에 따라 모든 작성 메소드(uninitialize를 제외한 모든 템플리트 메소드)의 경우에는 수퍼클래스의 항목에 대한 작업을 시작하기 전에 수퍼클래스의 메소드를 호출하여 해당 항목이 올바르게 초기화되었는지 확인해야 한다.

uninitialize 메소드의 경우에는 그 반대의 규칙을 따라야 한다.

마지막으로 startup 메소드를 사용할 때 주의해야 할 점이 있다. 위젯이 선언을 통해 작성되는 경우 dojo.parser.parse 메소드에 의해 startup 메소드가 자동으로 호출된다는 점을 명심해야 한다. 하지만 위젯이 프로그래밍 방식으로 작성될 때는 startup 메소드가 자동으로 호출되지 않으므로 다음 예제와 같이 수동으로 호출해야 한다.

var w = new MyWidget({});
w.startup();
            

위젯 제거 단계

위젯은 작성된 후 제거 요청이 명시적으로 실행될 때까지 유지된다. 따라서 구현자가 위젯 제거를 포함한 위젯의 전체 수명 주기를 관리해야 한다. 그렇지 않으면 전체 페이지 정리를 실행하기 전까지 유실된 위젯으로 남게 된다. 위젯에는 다음과 같은 4가지 제거 메소드가 있다.

  • destroyRendering: 이 메소드는 위젯의 렌더링 항목을 정리한다. 부분 정리가 필요하지 않는 한 이 메소드는 일반적으로 다른 제거 메소드에 의해 호출된다.
  • destroyDescendants: 모든 하위 위젯을 제거한다. 부분 정리가 필요하지 않는 한 이 메소드는 destroyRecursive 메소드에 의해 호출된다.
  • destroy: 위젯 항목(하위 위젯 제외)을 제거한다.
  • destroyRecursive: 위젯 항목과 하위 위젯을 제거한다. 위젯에 내부 위젯이 있는 경우 이 메소드를 호출해야 한다.

위젯에 내부 위젯이 있는 경우(예를 들어, 위젯의 템플리트에 들어 있는 위젯) 구현자는 호출할 제거 메소드를 위젯 사용자가 결정하지 않는 방식으로 하위 위젯을 트리거하여 제거해야 한다. Listing 12에서는 이를 수행하는 가능한 방법 중 하나를 보여 준다.


Listing 12. 위젯 제거를 트리거하는 예제
uninitialize: function()
{
 // destroy the descendants
 this.destroyDescendants();
 // call the superclass' method
   this.inherited("uninitialize", arguments);
}
            

이벤트 관리

Dojo 위젯은 DOM 노드 및 오브젝트에서 발생할 수 있는 외부 이벤트에 대응할 수 있다. 이러한 이벤트는 위젯의 connect 메소드를 사용하여 수동으로 연결할 수 있으며 이 메소드는 다음과 같은 시그니처(dojo.connect 메소드와 매우 유사한 시그니처)가 있다.

connect: function(/*Object|null*/ obj, /*String*/ event, /*String|Function*/ method);

또는 dojoAttachEvent 속성을 통해 템플리트에서 연결을 선언하여 자동으로 연결할 수도 있다. 두 경우 모두 위젯이 내부적으로 _connects 배열을 통해 연결을 추적한다. 모든 연결은 제거 시간에 자동으로 끊어진다. 이 방법으로 위젯과 DOM 노드 간의 참조도 끊어진다.

위젯의 수명 주기 동안 일부 연결이 더 이상 필요하지 않게 되면 이벤트 처리를 줄이기 위해 구현자가 disconnect 메소드를 호출하여 수동으로 연결을 끊을 수 있다.

위젯 템플리트

앞에서 본 것처럼 위젯은 Dojo 위젯의 기본 동작을 정의하고 제공하는 dijit._Widget 클래스를 상속해야 한다. 이 기본 클래스는 위젯 렌더링 요소를 빌드하는 buildRendering 메소드를 정의한다. 예를 들어, 위젯 구현자는 이 메소드에서 위젯 마크업을 작성한 후 위젯 DOM 노드에 설정할 수 있다. 또한 DOM API를 사용해서도 위젯 구조를 작성할 수 있다. 두 경우 모두 구현자가 buildRendering 메소드를 프로그래밍해야 한다.

Dojo는 위젯 렌더링 정의와 위젯 동작 구현을 구분하는 강력한 추상화 기능인 dijit­._Templated 혼합 클래스를 제공한다. 이와 같은 추상화를 이용하려는 구현자는 Listing 13처럼 _Templated 클래스를 상속해야 한다.


Listing 13. _Templated 클래스를 상속하는 코드
dojo.declare(
 "widgets.MyWidget", 
   dijit._Widget, dijit._Templated
 {
 templatePath: dojo.moduleUrl("widgets", "templates/MyWidget.html"),
 }
);
            

_Templated 클래스는 HTML 형태의 정의를 활용하는 고유한 buildRendering 구현을 제공한다. 이 정의는 서로 다른 두 장소에 있을 수 있다.

  1. 외부 파일. 이 경우에는 templatePath 특성을 통해 파일을 참조한다.
  2. 내부 문자열 특성. 이 경우에는 템플리트가 위젯의 templateString 특성에 직접 정의된다. templateString이 지정된 경우에는 templatePath가 지정되어 있더라도 무시된다.

첫 번째 방법은 위젯 소스 코드를 가장 깔끔하게 관리할 수 있는 방법이다. 왜냐하면 마크업을 다른 파일레 작성할 수 있을 뿐만 아니라 문자열 연결을 걱정할 필요 없이 손쉽게 형식을 지정할 수 있으며 문자열 구분 기호를 이스케이프하지 않아도 되기 때문이다. 이에 반해 두 번째 방법의 경우에는 브라우저에서 보조 파일을 로드하지 않아도 되기 때문에 성능이 향상된다. 하지만 Dojo에서 외부 템플리트를 위젯 소스 코드로 내부화하는 빌드 도구를 제공하므로 걱정하지 않아도 된다.

위젯 특성을 참조하여 템플리트를 매개변수화할 수 있다. 이 방법은 위젯이 마크업에 직접 영향을 미치는 일부 구성 매개변수를 노출하거나 외부 참조에 따라 마크업을 조건부로 생성해야 하는 경우에 유용하다. 위젯 특성은 ${propertyName} 형식의 구문을 통해 참조된다.

템플리트는 다른 위젯 선언을 포함할 수 있다. 하지만 이 경우에는 위젯 개발자가 widgetsInTemplate 특성을 true로 설정해야 한다는 점을 명심해야 한다. 왜냐하면 이 특성은 필요 없는 처리를 생략하기 위해 기본적으로 false로 설정되기 때문이다.

템플리트는 다음과 같은 두 가지 특별한 속성 선언을 포함할 수 있다.

  • dojoAttachPoint: 지정된 경우, 이 태그 속성은 위젯 특성 이름으로 설정해야 한다. 태그에 해당하는 DOM은 위젯 특성으로 설정된다. 템플리트의 여러 태그는 하나 이상의 연결 지점을 가질 수 있다.
  • dojoAttachEvent: 이 태그 속성은 DOM 이벤트가 트리거될 때 호출되어야 하는 위젯 메소드를 나열한다.

Listing 14에서는 템플리트 예제를 보여 준다.


Listing 14. 특별한 속성 선언을 보여 주는 템플리트 예제
<span 
 class="textInputDefault" 
 dojoAttachEvent="onclick:_onClick">
 <img 
 class="textInputIcon" 
 src="${constants.DEFAULT_ICON}" 
 dojoAttachPoint="_iconNode"/>
 <input 
 class="textInputNode"
 size="${size}"
 type="${type}"
 value=""
 dojoAttachPoint="_inputNode, _focusNode" 
 dojoAttachEvent="onkeyup:_onKeyUp, onkeypress:_onKeyPress, onchange:_onChange"
 />
 <span 
 class="textInputRight">&nbsp;
 </span>
</span>
            




위로


Tivoli Dynamic Workload Console 및 Dojo

TDWC(Tivoli Dynamic Workload Console)는 TWS(Tivoli Workload Scheduler)의 그래픽 사용자 인터페이스이다. 이 섹션에서는 TDWC v.8.5에서 Dojo 기능을 활용하는 방법에 대해 설명한다.

Tivoli Workload Scheduler 소개

TWS는 오늘날 복잡한 운영 환경의 워크로드를 관리하기 위해 설계된 프로덕션 자동화 솔루션이다. 기본 스케줄링 요소는 작업 및 작업 스트림이다. 작업은 실행 가능한 파일, 프로그램 또는 명령과 같은 태스크를 의미한다. 작업 스트림은 관련 작업에 대한 컨테이너이며 런타임, 시퀀싱, 동시성 제한 및 반복의 관점에서 작업을 관리한다. TWS는 작업의 실행 계획을 세우고 상호 의존성을 확인하며 각 작업을 시작 및 추적한다. 의존성이 충족되면 작업이 시작되므로 유휴 시간이 최소화되고 성능 또한 상당히 향상된다. 또한 작업 순서가 정상적으로 유지되며 작업이 실패할 경우 운영자가 거의 간여하지 않은 채로 TWS가 복구 프로세스를 처리한다.

Dojo 사용하기

TDWC v.8.5에는 Dojo 툴킷을 사용하여 완전히 JavaScript로 작성된 전체 기능을 제공하는 워크로드 편집기가 있다. 이와 같은 구현 방식은 브라우저 내에서 실행될 수 있는 코드를 최대한 많이 사용함으로써 "지능"적인 부분과 동작을 사용자측으로 이동시켜 준다.

TDWC에 표시된 TWS 작업 스트림의 특성 패널 예제를 살펴보자. 그림 3에서는 작업 스트림 PAYROLL에 대해 정의된 일반 특성의 웹 패널을 보여 준다.


그림 3. 작업 스트림 PAYROLL의 웹 패널
Name이 PAYROLL로 설정되어 있고 Workstation이 LAB132079_DM1_85로 지정되어 있는 PAYROLL 작업 스트림을 보여 주는 스크린샷. 팝아웃 달력을 사용하여 Valid from 날짜 필드를 편집 중이다. Valid to 및 Comments 필드는 비어 있다.

이전 기사인 "The Abstract User Interface Markup Language Web Toolkit: An AUIML renderer for JavaScript and Dojo"(참고자료 참조)에서 필자는 AUIML 툴킷을 사용하여 패널을 설계하는 방법과 AWT(AUIML Web Toolkit)를 사용하여 JavaScript로 논리 코드를 구현하는 방법을 설명했다. 그림 4에서는 AUIML 패널을 보여 준다.


그림 4. AUIML 패널
Name, Workstation, Valid From, Valid to, Description, Variable Table, Monitored, Draft 및 Commnents 등의 입력 필드가 비어 있는 AUIML 패널을 보여 주는 스크린샷

Valid from 필드를 살펴보자. 이 필드는 AUIML 편집기에서 Edit Box, Date로 정의되어 있다. AWT는 Listing 15와 같이 이 요소를 HTML 코드와 연결한다.


Listing 15. 요소를 연결하는 HTML 코드
<span type='text' dojoType='ajaxcommon.widgets.DateInputBox' id='validFrom'>
<script type='dojo/method'event='onValueChanged'>AWT.dispatchOnChange(this.id);</script>
</span>
            

Listing 16에는 ajaxcommon.widgets.DateInputBox 위젯이 정의되어 있다.


Listing 16. ajaxcommon.widgets.DateInputBox를 정의하는 코드
dojo.provide("ajaxcommon.widgets.DateInputBox"); 

dojo.require("ajaxcommon.resources.Images");
dojo.require("ajaxcommon.widgets._DateTimePicker");
dojo.require("ajaxcommon.widgets.picker.PickerInputBox");
dojo.require("ajaxcommon.widgets.picker.DatePicker");
dojo.declare(
   "ajaxcommon.widgets.DateInputBox",
     [ajaxcommon.widgets.picker.PickerInputBox, 
      ajaxcommon.widgets._DateTimePicker],
     {
      /** the picker icon */
      pickerIcon: ajaxcommon.resources.Images.get()["CALENDAR_ICON"],
      /** the picker disabled icon */
      pickerDisabledIcon: ajaxcommon.resources.Images.get()["DISABLED_CALENDAR_ICON"],
      /** the picker icon title */
      pickerIconTitle: ajaxcommon.resources.Labels.get()["PICK_DATE"],
      /** constraints */
      constraints: {selector: "date", formatLength: "short", wideYear: true},
      
      /**
       * Constructor.
       */
      constructor: function()
      {
         // even if the format length is short, ensure the wide year (yyyy)
         // by overriding the datePattern
         if (this.constraints.formatLength === "short" && this.constraints.wideYear) {
            this.constraints.datePattern = this._getWideDatePattern();
         }
         // set the regex for the text
         this.textRegExp = "^(" + dojo.date.locale.regexp(this.constraints) + “){0,1}$";
         // set the regex message for the text
         this.textRegExpMessage = 
            this._labels.format("DATE_INVALID_VALUE", {example: this._getExampleValue()});
         // set the picker class
         this.pickerClass = "ajaxcommon.widgets.picker.DatePicker";
      },
      
      /**
       * Returns the date pattern with the wide-year (yyyy)  
       */
      _getWideDatePattern: function()
      {
         // get the bundle
         var bundle = dojo.date.locale._getGregorianBundle();
         // get the pattern
           var pattern = bundle["dateFormat-short"];
           // replace the yy to yyyy if not yet yyyy
           if ( pattern.search(/yyyy/gi) === -1 ) {
              // the year is not in the wide form
              pattern = pattern.replace(/yy/gi, "yyyy");
           }
           return pattern;
      },
     /** 
       * Returns a string containing an example of accepted value. 
       */      
      _getExampleValue: function()
      {
         // get a sample date object (my birthday!!!)
         var d = new Date();
         d.setDate(15);
         d.setMonth(4);
         d.setYear(1971);
         // format the date in the current locale and return 
         return dojo.date.locale.format(d, this.constraints);
      }
   }      
);
         

생성자는 Listing 17에 정의되어 있는 수퍼클래스 위젯 ajaxcommon.widgets.picker.PickerInputBox에 선언된 위젯의 특성을 초기화한다.

Listing 18에서는 관련된 위젯 템플리트를 보여 준다.


Listing 18. ajaxcommon.widgets.picker.PickerInputbox의 위젯 템플리트
<span
    class="picker"
    ><span 
        tabindex="${tabindex}"
        dojoType="${_textBoxWidget}"
        dojoAttachPoint="_textNode,_focusNode"
        required="${required}"
        size="${size}"
        minLength="${textMinLength}"
        maxLength="${textMaxLength}"
        regExp="${textRegExp}"
        regExpReference="${textRegExpReference}"
        regExpMessage="${textRegExpMessage}"
        minWidth="${minWidth}"
    ></span
    ><span 
        dojoAttachPoint="_pickerButtonContainer">
        <img 
            tabindex="${tabindex}"
            src="${pickerIcon}"
            dojoAttachPoint="_pickerButtonNode"
            dojoAttachEvent="onclick:_onClick,onkeyup:_onKeyUp"
            class="pickerButton"
            title="${pickerIconTitle}"
    /></span>
</span>
            

그림 5에서는 위젯 논리를 브라우저측에 위임했을 때 얻을 수 있는 장점을 보여 준다. 값을 설정하는 동안 오류가 발생할 경우 관련된 오류 메시지를 표시하고 룩앤필을 변경하도록 위젯이 구현되었다.


그림 5. 브라우저측 위젯 논리를 보여 주는 패널
그림 3과 동일한 스크린샷. 이번에는 Valid from 필드가 May 15, 1971로 설정되어 있다.



위로


결론

이 기사에서는 Dojo JavaScript 툴킷(버전 1.0부터)을 사용하여 단순한 위젯부터 복잡한 위젯(예: TDWC v.8.5로 구현한 위젯)으로 단계를 높여 가면서 HTML 위젯을 개발하는 작업과 관련된 기본 개념을 설명했다. Dojo 툴킷의 장점에 대해서도 살펴보았다.

다음 기사에서는 기능이 풍부한 인터넷 애플리케이션을 개발하는 중에 발생할 수 있는 일반적인 성능 문제를 검토한 후 주로 Dojo 툴킷을 기반으로 하여 개발한 베스트 프랙티스를 통해 이러한 문제를 해결하는 방법을 소개한다.



참고자료



필자소개

Photo of Marco Lerro

Marco는 1999년부터 IBM Rome Tivoli Lab에서 Staff Engineer로 활동하고 있으며 현재는 TDWC 설계 및 개발 업무를 맡고 있다. Web 2.0 개발에 많은 관심을 가지고 있으며 특히, Dojo 기반 기술 및 사용자 환경 설계 패턴에 대한 관심이 매우 높다.


Photo of Roberto Longobardi

Roberto는 12년 동안 소프트웨어 개발 분야에서 활동하면서 개발자, 분석가, 웹 인터페이스 디자이너 및 상호 작용 디자이너 등의 여러 가지 역할에 대한 경험을 가지고 있다. 현재는 Tivoli 조직에서 Tivoli Workload Scheduler 및 Dynamic Workload Broker 제품을 위한 웹 사용자 인터페이스 디자이너로 활동하고 있다. 요구 사항 수집, 설계 검증 및 영업 교육과 같이 고객사를 대상으로 하는 업무도 수행한다. developerWorks에 여러 편의 기사를 게재하기도 했으며, IEEE 컨퍼런스에서 프리젠테이션을 발표하기도 하고 여러 학술 협업에도 참여하고 있다.


Gianluca Perreca's photo

Gianluca Perreca는 IBM Rome Tivoli Lab에서 Staff Engineer로 활동하고 있으며 Tivoli Workload Scheduler 개발 팀 소속으로 IBM Tivoli Workload Scheduler의 웹 인터페이스인 IBM Tivoli Dynamic Workload Console의 설계 및 구현에 적극적으로 참여하고 있다.


Photo of Alessandro Scotti

Alessandro Scotti는 AUIML Toolkit, AUIML 및 기타 Web 2.0 기술을 활용하는 IBM Tivoli Workload Scheduler의 웹 인터페이스인 IBM Tivoli Dynamic Workload Console의 Chief Dsigner이다. 주로 그래픽 사용자 인터페이스, 고성능 및 실시간 프로그래밍 분야와 관련된 다양한 오픈 소스 프로젝트에 대한 글을 쓰거나 기고했다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



 


 


 


이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us



developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의