jQuery 덕택에 CSS(Cascading Style Sheet) 구문에서 선택기를 사용하여 DOM(Document Object Model) 요소를 검색하고 이 요소에 조작을 적용하는 것이 일반화되었다. jQuery를 사용하면 복잡한 DOM 트리를 순회하기 위해 Javascript를 사용하지 않아도 된다는 이점이 생긴다.
ZK는 Java EE 기술과의 통합 및 Java 프로그래밍에 필요한 이벤트 중심의 컴포넌트 기반 Ajax 프레임워크이다. 이 프레임워크를 이용하면 데스크탑 애플리케이션을 프로그래밍하는 것처럼 Ajax 애플리케이션을 프로그래밍할 수 있다. HTML을 많이 사용하는 경우에는 마크업과 EL(Expression Language)을 사용하여 ZK UI를 조합할 수 있다.
이 기사에서는 서버측 Java 코드를 결합하는 방법과 jQuery를 통해 엔터프라이즈 Ajax 애플리케이션 개발의 과제를 다루는 방법을 탐구한다. jQuery와 ZK를 이용하면 다양한 기술을 통합하여 응답 속도가 빠른 리치 UI 경험을 쉽고 효과적으로 제공할 수 있다.
다운로드 섹션에서 이 기사에서 사용한 샘플 코드를 다운로드할 수 있다.
엔터프라이즈급 Ajax 애플리케이션 개발자들이 직면해 있는 일반적인 과제는 다음과 같다.
- 복잡도
- Ajax는 복잡하다. Ajax 통신 패턴을 사용하면 DOM 요소를 개별적으로 업데이트하는 경우에 웹 페이지를 전체적으로 새로 고치지 않아도 된다.
엔터프라이즈 애플리케이션에서는 서버에서 클라이언트에 이르는 복잡한 비즈니스 로직을 마샬링하고 각 Ajax 호출을 수동으로 처리하는 데 상당한 노력이 들어간다.
- 서버측 프로그래밍
- 서버측 Ajax 솔루션은 클라이언트에 있는 자원을 활용하여 응답 속도가 더욱 빠른 사용자 경험이나 오프라인 기능, 클라이언트 데이터 저장소 및 분산 컴퓨팅을 구현할 수가 없다.
서버측 Ajax 솔루션으로 인해 서버의 메모리 용량이 줄어들지는 않으므로 애플리케이션의 확장 가능성이 증가한다.
- 클라이언트측 프로그래밍
- 클라이언트측 프로그래밍에서는 보안 문제와 개발 비용을 자세하게 소개한다. 비즈니스 로직과 민감한 데이터가 브라우저에서 공개된 상태로 남아있게 되면 애플리케이션이 공격에 취약하게 된다.
클라이언트측 프로그래밍을 하는 경우에는 대규모로 Javascript 코드를 구현해야 하며, Java EE 기술을 사용하여 애플리케이션을 개발하는 데 익숙한 경우에는 이러한 작업이 문제가 될 수 있다.
- 대용량 데이터
- UI 티어에서 뷰에 많은 데이터를 표시해야 하는 경우에는 일반적으로 또 다른 문제가 발생한다. 예를 들어, 보통의 HTML 테이블을 생각해 보자. 데이터 소스의 용량이
커지면 다음과 같은 작업 중 하나를 수행해야 한다.
- 대용량 데이터 세트를 미리 로드하여 브라우저 캐시 오버로딩과 트래픽 감축을 수행한다.
- 사용자가 요청을 할 때마다 뷰에서 사용 가능한 관심 데이터 서브세트를 작성하는 메커니즘을 수동으로 서버에 구현한다.
이러한 문제를 제거하려면 클라이언트와 서버의 상태가 자동으로 동기화되는 프레임워크를 사용해야 한다. 클라이언트측 계산을 사용하여 응답 속도와 UI 제어를 개선하면서 서버측에서 안전한 Java EE 기술을 모두 활용할 수 있다.
서버측 기술과 클라이언트측 기술이 결합된 ZK 아키텍처
ZK의 혁신적인 아키텍처는 서버와 클라이언트에서 사용 가능한 모든 기술을 완전히 최대화할 수 있는 수단을 제공한다. 원한다면 클라이언트측 위젯을 직접 액세스할 수 있다. 이 섹션에서는 서버측 기술과 클라이언트측 기술이 결합된 ZK 아키텍처의 몇 가지 이점을 개략적으로 살펴본다.
ZK Loader는 다음과 같은 경우에 수행되는 URL 요청을 처리한다.
- 요청된 페이지에서 UI 컴포넌트 작성
- 컴포넌트에 필요한 데이터 로딩
- 데이터를 HTML 페이지에 렌더링
- ZK의 Client Engine과 함께 HTML 페이지를 클라이언트로 다시 전송
ZK AU(Asynchronous Update) Engine과 Client Engine은 개발자가 Ajax 호출을 처리하는 데 따른 복잡한 과정을 단순화할 수 있게 Ajax 호출을 처리한다. 그림 1에는 ZK Loader, ZK AU Engine 및 ZK Client Engine이 표시되어 있다.
그림 1. ZK 퓨전 아키텍처 개요
ZK의 Client Engine과 AU Engine은 각각 투수와 포수 역할을 하며 ZK의 이벤트 큐는 처리할 이벤트를 파이프라인으로 보낸다. 결과적으로 비동기 이벤트 핸들링이 데스크탑 프로그래밍처럼 단순해진다.
서버는 ZK 컴포넌트 세트(브라우저에서 Javascript 오브젝트로 존재하는 ZK 위젯 세트)를 JVM에서 유지하기 때문에 페이지의 상태가 서버 및 클라이언트측에서 동기화된 상태로 유지된다. 비즈니스 로직이나 민감한 데이터를 처리하는 모든 이벤트 핸들링은 서버측에서 유지된다. 결과적으로 서버에서 ZK 컴포넌트의 상태가 변경되면 이벤트 처리가 완료되는 경우에만 클라이언트측 ZK 위젯에 변경된 내용이 다시 반영된다. 클라이언트측에서는 비즈니스 로직이 전혀 노출되지 않는다.
ZK 위젯은 jQuery로 작성된 클라이언트측 Javascript 오브젝트이므로 이 위젯에는 jQuery와 같은 특성이 있다. 완전하게 표현된 컴포넌트와 컴포넌트의 상태가 클라이언트와 서버측 모두에 존재하므로 개발자는 서버나 클라이언트 애플리케이션을 선택해서 프로그래밍할 수 있다. 그림 2에는 이와 관련된 예제가 표시되어 있다.
그림 2. ZK 클라이언트측 기술
때로는 클라이언트측에서 대용량 데이터를 처리하는 문제를 해결해야 한다. 데이터 레코드를 표시하는 데 사용하는 ZK의 그리드, 목록 상자 및 트리 컴포넌트에는 온 디맨드 로드 기능이 있어서 뷰에서 데이터를 필요로 하는 경우에만 브라우저에 데이터가 렌더링된다. 또한, 다수의 페이지로 대용량 데이터를 분배할 수 있는 페이징 기능도 있다. 이러한 기능을 이용하면 대용량 데이터를 표현하는 복잡한 과정이 매우 단순화된다.
서버측 기술과 클라이언트측 기술이 결합된 ZK 아키텍처를 탐구하려면 두 가지 방법 즉, 순수한 서버 중심 솔루션을 참조로 사용하거나 이벤트 핸들링을 서버와 클라이언트로 분배하는 과정을 통해 샘플 개념 증명 주식 뷰어 애플리케이션을 살펴보아야 한다.
주식 뷰어 애플리케이션은 히스토리 주식 레코드를 XML로 읽어서 테이블 형식과 선 그래프로 데이터를 표시한다. 또한, 이 애플리케이션에는 Google Suggest와 같이 검색을 자동 완성하는 검색 상자가 포함된다. 그림 3에는 이 애플리케이션이 표시되어 있다.
그림 3. 주식 뷰어 애플리케이션
서버 중심 방식의 샘플에서는 ZK의 MVC(Model-View-Controller) 방식을 채택하고 있다.
- 모델
- 모델은 세 개의 Java 클래스로 구성되며 두 개는 데이터 오브젝트용이고 하나는 DAO 오브젝트용이다.
Stock오브젝트는 다수의Price오브젝트에 해당한다.public class Stock { private int _id; private String _name; private List<Price> _priceItems = new ArrayList<Price>(); .... //getter and setter methods } public class Price { private String _date; private double _open; private double _high; private double _low; private double _close; private int _volumn; .... //getter and setter methods }
StockDAO클래스는 data.xml에 있는 히스토리 주식 데이터를 구문 분석하여 메모리에Stock과Price오브젝트를 작성한다. 각Stock오브젝트는 연결 목록 "stocks"에 추가된다.public class StockDAO { private List<Stock> stocks = new LinkedList<Stock>(); public List findAll() {...} // returns all stock items in data.xml public Stock getStock(int id) {...} } - 뷰
- 뷰는 ZK의 마크업 언어를 사용하여 구현한다. 기본 프리젠테이션 페이지인 index.zul은 경계 레이아웃을 사용하여 파티션된다. 서쪽 부분에서는 검색 상자와 주식 이름 목록을 호스트하고
중심 부분에는 price.zul의 플레이스홀더 역할을 하는
include요소가 포함된다. price.zul에서는 그리드 컴포넌트로 각 주식의 데이터 레코드를 표시하고 차트 컴포넌트로 그래프를 작성한다.목록 1에 있는 index.zul에 대한 설명
- 1행에서는
init태그를 사용하여 ZK Loader가 ZK의 Data Binding Manager를 초기화하도록 하여 데이터 소스가 UI 컴포넌트 또는 UI 컴포넌트가 데이터 소스에 자동으로 바인드될 수 있게 한다. - 2행의
apply="StockController"속성은 기본 페이지의StockController클래스가borderlayout컴포넌트의 제어기 역할을 한다는 점을 나타낸다. - 12행의
model="@{main$composer.stocks}"속성은StockController클래스의getStocks()메소드에서 얻은 데이터 모델을 사용하여listbox설정을 변환한다. - 14행에서 16행까지의
listitem컴포넌트는 각 stock 오브젝트를 처리하기 위해 작성되며 오브젝트의 이름이listcell의 레이블에 지정된다.
목록 1. index.zul1. <?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?> 2. <borderlayout id="main" apply="StockController"> 3. <west title="ZK Finance" size="250px" flex="true" 4. splittable="true" minsize="210" maxsize="500" collapsible="true"> 5. <panel> 6. <toolbar> 7. <label value="Search:" /> 8. <textbox id="searchBox" ctrlKeys="#down#up" 9. focus="true" sclass="demo-search-inp" /> 10. </toolbar> 11. <panelchildren> 12. <listbox id="itemList" model="@{main$composer.stocks}" 13. fixedLayout="true" vflex="true"> 14. <listitem self="@{each='stock'}" value="@{stock}"> 15. <listcell label="@{stock.name}" /> 16. </listitem> 17. </listbox> 18. </panelchildren> 19. </panel> 20. </west> 21. <center> 22. <include id="detail"/> 23. </center> 24. </borderlayout>
목록 2에 있는 price.zul에 대한 설명
- 앞서와 마찬가지로 1행에서는 ZK의 Data Binding Manager가 초기화된다.
- 2행의
apply="PriceController"속성은 기본 페이지의PriceController클래스가 window 컴포넌트의 제어기로 역할을 한다는 점을 나타낸다. - 3행의
model="@{main2$PriceController.prices}"속성은PriceController클래스의getPrices()메소드에서 얻은 데이터 모델을 사용하여 그리드 설정을 변환한다. - 13행에서 20행까지의 row 컴포넌트는 각
price오브젝트를 처리하기 위해 작성되며 오브젝트의 값이 레이블에 지정된다.
목록 2. price.zul1. <?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?> 2. <window id="main2" apply="PriceController"> 3. <grid id="history" model="@{main2$PriceController.prices}" > 4. <columns menupopup="auto"> 5. <column label="Date" /> 6. <column label="Open" /> 7. <column label="High" /> 8. <column label="Low" /> 9. <column label="Close" /> 10. <column label="Volumn" /> 11. </columns> 12. <rows> 13. <row self="@{each='price'}"> 14. <label value="@{price.date}"/> 15. <label value="@{price.open}"/> 16. <label value="@{price.high}"/> 17. <label value="@{price.low}"/> 18. <label value="@{price.close}"/> 19. <label value="@{price.volumn}"/> 20. </row> 21. </rows> 22. </grid> 23. <chart id="line" width="500" height="250" type="line" 24. fgAlpha="128" model="@{main2$PriceController.cateModel}"/> 25. </window>
- 1행에서는
- 제어기
- 제어기는 데이터 오브젝트와 UI 컴포넌트를 자동으로 연결하는 ZK의
rg.zkoss.zk.ui.util.GenericForwardComposer에서 확장된 클래스이다.StockController클래스에서는 index.zul에 있는borderlayout컴포넌트의 뷰를 제어한다.- 8행에서는
onCreate이벤트 리스너를 사용하여 id가main인borderlayout을 등록하며 이렇게 하면 기본 주식 항목이 해당 뷰에 표시되도록 설정된다. - 13행에서는
onSelect이벤트 리스너를 사용하여 id가itemList인 목록 상자를 등록하며 이렇게 하면listbox에서listitem이 선택되고 id가detail인 include 컴포넌트(주식 데이터와 선 그래프를 표시하기 위한 페이지 소스)가 설정된다. - 18행에서는
onChanging이벤트 리스너를 사용하여 id가searchBox인 텍스트 상자를 등록하며 이렇게 하면 주식 항목 전체를 반복하여 텍스트 상자의 값이 변경될 때마다 사용자 입력과 일치하는 주식 목록이 리턴된다. 인수로 사용한 이벤트는org.zkoss.zk.ui.event.InputEvent로 캐스트되어 사용자 입력이 문자열key에 지정될 수 있게 한다. - 34행의
getStocks()메소드는 data.xml에 나열된 모든 주식 항목을 리턴한다.
목록 3. StockController.java1. public class StockController extends GenericForwardComposer { 2. Textbox searchBox; 3. Listbox itemList; 4. Include detail; 5. StockDAO dao = new StockDAO(); 6. private static String DETAIL_URL = "price.zul"; 7. 8. public void onCreate$main(){ 9. itemList.setSelectedIndex(0); 10. Events.postEvent(new Event(Events.ON_SELECT, itemList)); 11. } 12. 13. public void onSelect$itemList(){ 14. int id = ((Stock)itemList.getSelectedItem().getValue()).getId(); 15. detail.setSrc(DETAIL_URL + "?id=" + id); 16. } 17. 18. public void onChanging$searchBox(InputEvent event) { 19. String key = event.getValue(); 20. LinkedList item = new LinkedList(); 21. List items = dao.findAll(); 22. 23. if (key.trim().length() != 0) { 24. for (Iterator iterator = items.iterator(); iterator.hasNext();) { 25. Stock st = (Stock) iterator.next(); 26. if (st.getName().toLowerCase() 27. .indexOf(key.toLowerCase()) != -1) 28. item.add(st); 29. } 30. itemList.setModel(new ListModelList(item)); 31. } else itemList.setModel(new ListModelList(items)); 32. } 33. 34. public List getStocks(){ 35. return dao.findAll(); 36. } 37. }
PriceController클래스에서는 price.zul에 있는 그리드와 차트 컴포넌트의 뷰를 제어한다.- 14행에서는 price.zul을 위해 요청에 추가된
id매개변수를 페치한다.org.zkoss.zk.ui.Executions클래스는 비Ajax 요청을 처리하기 위한 랩퍼이다. - 21행에서는 선형 차트 모델의 값이 설정된다.
- 25행에서는
getPrices()메소드를 선언하여 price.zul에 있는 그리드 컴포넌트의 EL을 통해 호출할 수 있게 한다. 이렇게 하는 이유는PriceController클래스가 UI 컴포넌트와 데이터 오브젝트를 연결하는org.zkoss.zk.ui.util.GenericAutowireComposer를 확장하기 때문이다.
Lisitng 4. PriceController1. public class PriceController extends GenericAutowireComposer { 2. 3. private StockDAO dao = new StockDAO(); 4. private CategoryModel cateModel; 5. private List items; 6. 7. public PriceController() { 8. init(); 9. } 10. 11. public void init() { 12. //get stock id 13. int id = Integer.parseInt((String) 14. Executions.getCurrent().getParameter("id")); 15. Stock stock = dao.getStock(id); 16. items = stock.getPriceItems(); 17. //create category model for chart 18. cateModel = new SimpleCategoryModel(); 19. for (Iterator iterator = items.iterator(); iterator.hasNext();) { 20. Price price = (Price) iterator.next(); 21. cateModel.setValue(stock.getName(), price.getDate(), 22. Price.getClose()); 23. } 24. } 25. public List getPrices(){ 26. return items; 27. } 28. public CategoryModel getCateModel() { 29. return cateModel; 30. } 31. } - 8행에서는
이 예제에서는 표와 차트에서 동적으로 데이터를 업데이트하는 기능과 검색 상자 기능을 구현하기 위해 여러 곳에서 비동기 호출을 사용해야 했으며 이러한 비동기 호출을 ZK의 Client Engine과 AU Engine을 사용하여 전체적으로 처리했다. 명령어는 서버에서 실행되며 클라이언트는 UI 컴포넌트와 데이터 모델의 업데이트만 수신한다.
서버+클라이언트 퓨전 방법론을 사용하는 동일한 애플리케이션을 살펴보자. 검색 상자는 분명히 클라이언트측에서 구현해야 할 대상이고 여기서는 응답 속도가
가장 중요하며 주식 항목의 데이터 대신 이름만 구문 분석하여 표시하면 된다. 이러한 경우에는 검색 상자의 이벤트 처리 기능을 클라이언트에서만 구현하기 때문에
StockController 클래스가 더 이상 필요하지 않다. 예제에서는 index.zul을 수정하고 그 이름을 hybrid.zul로 변경한다.
아래에 있는 hybrid.zul에서는 다음과 같은 ZK 구문에 주목한다.
- 다음과 같이 ZK의 클라이언트 네임스페이스를 선언해야 한다.
<zk xmlns:w="http://www.zkoss.org/2005/zk/client">
(위젯을 위한 네임스페이스 w는 ZK의 규약이다.) - 주식 이름을 나타내는 목록 상자와 검색 상자는 클라이언트에서 직접 업데이트되므로 2행에서는
borderlayout에서apply="StockController"속성을 제거한다. - 8행에서는
w:어노테이션이 있는 클라이언트에서 처리되도록textbox의onChanging이벤트를 선언한다. - 9행에서는
listbox를 가져오고update()메소드를 호출한다.this.$f(‘list')표현식은 Java에서의inp.getFellow("list")표현식과 동일하며id가 "list"인listbox컴포넌트를 가져온다. - 13행에서는 zk.Widget 클래스의
bind_ callback메소드가update()메소드를 실행하도록 오버라이드되며listbox가 DOM 트리에 바인드되고 나면 첫 번째 목록 항목을 선택 항목으로 설정한다. - 28행에 있는
zUtl.parseXML()메소드는 XML 문서를 구문 분석하는 데 필요한 유틸리티 메소드이다.jq()메소드는 jQuery의$()표기법을 가능할 때마다 계속 사용할 수 있도록 ZK의 jQuery 선택기에 맞는 표기법을 작성한다. - 38행에서는 각 주식 항목의 ID 세트와 레이블 값을 이용하여 새로운
listitem위젯을 작성하고 이 위젯을listbox의 하위 위젯으로 listbox에 추가한다. - 56행에서 70행까지는 서버에서 비동기 요청을 하는 데 필요한 서비스 메소드를 구현하여
listbox의onSelect이벤트를 직접 처리한다. 예제에서는 선택될listitem의uuid를 검색하여 주식 데이터와 선형 차트를 표시하는 price.zul 페이지의 요청에 추가한다.
목록 5. hybrid.zul
1. <zk xmlns:w="http://www.zkoss.org/2005/zk/client">
2. <borderlayout id="main">
3. <west title="ZK Finance" size="250px" flex="true"
4. splittable="true" minsize="210" maxsize="500" collapsible="true">
5. <panel>
6. <panelchildren>
7. <textbox id="inp">
8. <attribute w:name="onChanging">
9. this.$f('list').update(event.data.value);
10. </attribute>
11. </textbox>
12. <listbox id="list" onSelect="" rows="10" width="300px">
13. <attribute w:name="bind_">
14. function (desktop, skipper, after) {
15. this.$bind_.apply(this, arguments);
16. var self = this;
17. after.push(function () {
18. self.update();
19. self.firstChild.setSelected(true);
20. });
21. }
22. </attribute>
23. <attribute w:name="update"><![CDATA[
24.
25. (function () {
26. var data;
27. function loadData(w) {
28. var xmlDoc = zk.xml.Utl.parseXML(jq(w).html().replace(/<!--|-->/g,'').trim()),
29. ids = xmlDoc.getElementsByTagName("id"),
30. labels = xmlDoc.getElementsByTagName("name");
31. data = [];
32. jq(ids).each(function (i) {
33. data.push({id: this.firstChild.nodeValue, label:
34. labels[i].firstChild.nodeValue});
35. });
36. }
37.
38. function createItems (listbox, data) {
39. if (!data.length) return;
40. jq(data).each(function () {
41. listbox.appendChild(new zul.sel.Listitem({label: this.label, uuid: this.id}));
42. });
43. }
44. return function (txt) {
45. txt = txt || '';
46. if (!data) loadData(this.$f('data'));
47. this.clear();
48. createItems(this, jq.grep(data, function (item) {
49. return item.label.toLowerCase().indexOf(txt.toLowerCase()) != -1;
50. }));
51. this.stripe();
52. };
53. })()
54. ]]></attribute>
55. </listbox>
56. <zscript>
57. public class MyService implements org.zkoss.zk.au.AuService {
58. public boolean service(org.zkoss.zk.au.AuRequest request, boolean everError) {
59. final String cmd = request.getCommand();
60. if (cmd.equals(Events.ON_SELECT)) {
61. String uuid = ((List)request.getData().get("items")).get(0);
62. System.out.println("selected:" + uuid);
63. content.setSrc("price.zul?id=" + uuid);
64. return true;
65. }
66. return false;
67. }
68. }
69. list.setAuService(new MyService());
70. </zscript>
71. <include id="data" src="data.xml" comment="true"/>
72. </panelchildren>
73. </panel>
74. </west>
75. <center>
76. <include id="content" src="price.zul?id=1"/>
77. </center>
78. </borderlayout>
79. </zk>
|
샘플 코드를 다운로드할 수 있다. 검색 상자의 응답 속도가 개선되었다는 점에 주목하기 바란다.
이 기사에서는 서버측 프로그래밍과 클라이언트측 프로그래밍의 장점을 활용하여 ZK로 Ajax 개발을 개선하는 방법을 탐구했다. ZK는 애플리케이션의 상태를 서버측과 클라이언트측에서 자동으로 동기화한다. 개발자는 Java EE 애플리케이션 기술의 생산성을 활용하면서 계속해서 클라이언트측 기능을 구현할 수 있다. 여기서 살펴본 구현 방법은 개발 프레임워크의 장점이나 제한조건에 의존하는 것이 아니라 개발자가 빌드하는 엔터프라이즈 애플리케이션의 요구사항에 의존하게 된다.
| 설명 | 이름 | 크기 | 다운로드 방식 |
|---|---|---|---|
| Sample code for this article | zk5Client_ServerFusion.zip | 9018KB | HTTP |
교육
- "Rich Internet applications using ZK"(developerWorks, 2010년 1월): 이 기사에서는 ZK를 소개하면서 ZK를 사용하는 실제 예제를 통해 애플리케이션을 Apache Tomcat에서
실행하는 방법과 MySQL 데이터베이스에 연결하는 방법을 설명한다.
- ZK 5.0 and jQuery와 ZK 5.0 and jQuery part 2를 읽어보고 ZK 및 jQuery에 대한 소개와 데모를 확인하고 ZK 제어를 구현하는 방법과 예제를 구성하는 방법 등을 살펴보자.
- 클라이언트 네임스페이스와 클라이언트 프로그래밍을 배우자.
- 모든 위젯 클래스의 상위 클래스인 ZK 위젯에 관해 알아보자.
- ZK MVC Made Easy에서는 MVC(Model-View-Controller) 패턴의 애플리케이션을 쉽게 작성할 수 있게 도와주는,
ZK에서 제공하는 세 가지 유틸리티 클래스와 세 가지 헬퍼 메소드를 세부적으로 논의한다.
- UI 컴포넌트와 데이터 소스 간의 데이터 복사 Plumbing Code를 자동화하는 메커니즘인 ZK 데이터 바인딩과 데이터 바인딩 관리자에 관해 배우자.
제품 및 기술 얻기
- 무료로 ZK를 다운로드하자.
- IBM 제품 평가판을 다운로드하거나 IBM
SOA Sandbox의 온라인 시험판을 살펴보고 DB2®, Lotus®,
Rational®, Tivoli® 및 WebSphere® 애플리케이션 개발 도구와 미들웨어 제품을 사용해 볼 수 있다.
토론
- developerWorks 블로그를 통해 developerWorks 커뮤니티에 참여할 수 있다.
- 지금 My developerWorks 프로파일을 작성하고 Ajax 대한 관심 목록을 설정하자.
My developerWorks에서 최신 정보를 자주 확인하자.
- 웹 개발에 관심이 있는 다른 developerWorks 구성원을 찾아보자.
- 자신의 지식을 공유하자. 웹 주제를 다루는 developerWorks 그룹에 참여하자.
- Roland Barcia는 자신의 블로그에서
Web 2.0 및 미들웨어에 대해 설명했다.
- developerWorks 멤버의 shared bookmarks on Web topics를 따라가 보자.
- 빠른 해답: Web 2.0 Apps forum을 방문하십시오.
- 빠른 해답: Ajax forum을 방문하십시오.
