메인 컨텐츠로 가기

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

jQuery와 ZK, Java 코드를 결합하여 Ajax 개발 강화하기

서버측 프로그래밍과 클라이언트측 프로그래밍의 이점을 신속하게 활용하기

Lance Lu, Technology Evangelist, Potix Corp.
Photo of Lance Lu
Lance Lu は ZK フレームワークの技術エバンジェリストです。彼は ZK に参加する以前、台湾にある 32 ビット・マイクロプロセッサーの設計企業の上級技術者でした。また、カナダの医療機器メーカーの製品マネージャーであったこともあります。彼はカナダのビクトリア大学 (University of Victoria) で数学の学位を取得しています。彼は学術領域として、物理学、哲学、心理学、数学、コンピューター・サイエンスなどに関心を持っています。
Sachin K Mahajan , Software Developer, IBM  
Sachin graduated with a Masters degree from the University of Utah, Salt Lake City, U.S. He has worked in both small and large companies in the United States and India performing various technical and managerial roles. Sachin currently works in IBM Software Group's Lotus division.

요약:  jQuery를 사용하여 서버측 Java™ 애플리케이션과 통신하기는 간단합니다. 그렇지만 엔터프라이즈 웹 애플리케이션을 개발할 경우에는 코드가 복잡해지며 jQuery를 사용하여 서버와 클라이언트 간에 보안 통신을 하게 되면 시간이 많이 소비되고 오류가 발생하기 쉽습니다. 전체 애플리케이션을 순수한 Java 코드로 구현할 수 있으면 그것이 훨씬 더 쉽습니다. 비즈니스 로직을 제어하고 클라이언트측 제어의 모든 이점을 활용하고 싶습니까? 이 기사에서는 ZK 도구와 Java EE(Java Platform Enterprise Edition) 기술을 사용하여 클라이언트측 기능을 포기하지 않고도 Ajax(Asynchronous JavaScript and XML) 애플리케이션 개발을 강화할 수 있는 방법을 살펴봅니다.

원문 게재일:  2010 년 10 월 19 일 번역 게재일:   2011 년 1 월 25 일
난이도:  중급 원문:  보기 PDF:  A4 and Letter (134KB | 17 pages)Get Adobe® Reader®
페이지뷰:  3684 회
의견:  


소개

jQuery 덕택에 CSS(Cascading Style Sheet) 구문에서 선택기를 사용하여 DOM(Document Object Model) 요소를 검색하고 이 요소에 조작을 적용하는 것이 일반화되었다. jQuery를 사용하면 복잡한 DOM 트리를 순회하기 위해 Javascript를 사용하지 않아도 된다는 이점이 생긴다.

jQuery는 웹 애플리케이션과 웹 페이지를 쉽게 빌드할 수 있게 도와주는 빠르고 간결한 크로스 브라우저 Javascript 라이브러리이다. jQuery를 이용하면 애니메이션 작성, 서버로의 통신 요청, 문서 순회 및 이벤트 핸들링을 단순화할 수 있다.

ZK는 Java EE 기술과의 통합 및 Java 프로그래밍에 필요한 이벤트 중심의 컴포넌트 기반 Ajax 프레임워크이다. 이 프레임워크를 이용하면 데스크탑 애플리케이션을 프로그래밍하는 것처럼 Ajax 애플리케이션을 프로그래밍할 수 있다. HTML을 많이 사용하는 경우에는 마크업과 EL(Expression Language)을 사용하여 ZK UI를 조합할 수 있다.

이 기사에서는 서버측 Java 코드를 결합하는 방법과 jQuery를 통해 엔터프라이즈 Ajax 애플리케이션 개발의 과제를 다루는 방법을 탐구한다. jQuery와 ZK를 이용하면 다양한 기술을 통합하여 응답 속도가 빠른 리치 UI 경험을 쉽고 효과적으로 제공할 수 있다.

다운로드 섹션에서 이 기사에서 사용한 샘플 코드를 다운로드할 수 있다.


Ajax 애플리케이션 개발 과제

엔터프라이즈급 Ajax 애플리케이션 개발자들이 직면해 있는 일반적인 과제는 다음과 같다.

복잡도
Ajax는 복잡하다. Ajax 통신 패턴을 사용하면 DOM 요소를 개별적으로 업데이트하는 경우에 웹 페이지를 전체적으로 새로 고치지 않아도 된다.

엔터프라이즈 애플리케이션에서는 서버에서 클라이언트에 이르는 복잡한 비즈니스 로직을 마샬링하고 각 Ajax 호출을 수동으로 처리하는 데 상당한 노력이 들어간다.

서버측 프로그래밍
서버측 Ajax 솔루션은 클라이언트에 있는 자원을 활용하여 응답 속도가 더욱 빠른 사용자 경험이나 오프라인 기능, 클라이언트 데이터 저장소 및 분산 컴퓨팅을 구현할 수가 없다.

서버측 Ajax 솔루션으로 인해 서버의 메모리 용량이 줄어들지는 않으므로 애플리케이션의 확장 가능성이 증가한다.

클라이언트측 프로그래밍
클라이언트측 프로그래밍에서는 보안 문제와 개발 비용을 자세하게 소개한다. 비즈니스 로직과 민감한 데이터가 브라우저에서 공개된 상태로 남아있게 되면 애플리케이션이 공격에 취약하게 된다.

클라이언트측 프로그래밍을 하는 경우에는 대규모로 Javascript 코드를 구현해야 하며, Java EE 기술을 사용하여 애플리케이션을 개발하는 데 익숙한 경우에는 이러한 작업이 문제가 될 수 있다.

대용량 데이터
UI 티어에서 뷰에 많은 데이터를 표시해야 하는 경우에는 일반적으로 또 다른 문제가 발생한다. 예를 들어, 보통의 HTML 테이블을 생각해 보자. 데이터 소스의 용량이 커지면 다음과 같은 작업 중 하나를 수행해야 한다.
  • 대용량 데이터 세트를 미리 로드하여 브라우저 캐시 오버로딩과 트래픽 감축을 수행한다.
  • 사용자가 요청을 할 때마다 뷰에서 사용 가능한 관심 데이터 서브세트를 작성하는 메커니즘을 수동으로 서버에 구현한다.

이러한 문제를 제거하려면 클라이언트와 서버의 상태가 자동으로 동기화되는 프레임워크를 사용해야 한다. 클라이언트측 계산을 사용하여 응답 속도와 UI 제어를 개선하면서 서버측에서 안전한 Java EE 기술을 모두 활용할 수 있다.


서버측 기술과 클라이언트측 기술이 결합된 ZK 아키텍처

ZK의 혁신적인 아키텍처는 서버와 클라이언트에서 사용 가능한 모든 기술을 완전히 최대화할 수 있는 수단을 제공한다. 원한다면 클라이언트측 위젯을 직접 액세스할 수 있다. 이 섹션에서는 서버측 기술과 클라이언트측 기술이 결합된 ZK 아키텍처의 몇 가지 이점을 개략적으로 살펴본다.

ZK Loader 및 ZK AU Engine

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 요청과 URL 및 HTML 페이지와 ZK 응답을 리턴하는 서버가 표시된 다이어그램

Ajax 복잡도 해결하기

ZK의 Client Engine과 AU Engine은 각각 투수와 포수 역할을 하며 ZK의 이벤트 큐는 처리할 이벤트를 파이프라인으로 보낸다. 결과적으로 비동기 이벤트 핸들링이 데스크탑 프로그래밍처럼 단순해진다.

서버측 기술 활용하기

서버는 ZK 컴포넌트 세트(브라우저에서 Javascript 오브젝트로 존재하는 ZK 위젯 세트)를 JVM에서 유지하기 때문에 페이지의 상태가 서버 및 클라이언트측에서 동기화된 상태로 유지된다. 비즈니스 로직이나 민감한 데이터를 처리하는 모든 이벤트 핸들링은 서버측에서 유지된다. 결과적으로 서버에서 ZK 컴포넌트의 상태가 변경되면 이벤트 처리가 완료되는 경우에만 클라이언트측 ZK 위젯에 변경된 내용이 다시 반영된다. 클라이언트측에서는 비즈니스 로직이 전혀 노출되지 않는다.

클라이언트측 기술 활용하기

ZK 위젯은 jQuery로 작성된 클라이언트측 Javascript 오브젝트이므로 이 위젯에는 jQuery와 같은 특성이 있다. 완전하게 표현된 컴포넌트와 컴포넌트의 상태가 클라이언트와 서버측 모두에 존재하므로 개발자는 서버나 클라이언트 애플리케이션을 선택해서 프로그래밍할 수 있다. 그림 2에는 이와 관련된 예제가 표시되어 있다.


그림 2. ZK 클라이언트측 기술
DOM, ZK Ajax 위젯, 선택사항인 클라이언트 애플리케이션 및 ZK 클라이언트 엔진 간의 관계가 화살표로 표시된 다이어그램

대용량 데이터 처리하기

때로는 클라이언트측에서 대용량 데이터를 처리하는 문제를 해결해야 한다. 데이터 레코드를 표시하는 데 사용하는 ZK의 그리드, 목록 상자 및 트리 컴포넌트에는 온 디맨드 로드 기능이 있어서 뷰에서 데이터를 필요로 하는 경우에만 브라우저에 데이터가 렌더링된다. 또한, 다수의 페이지로 대용량 데이터를 분배할 수 있는 페이징 기능도 있다. 이러한 기능을 이용하면 대용량 데이터를 표현하는 복잡한 과정이 매우 단순화된다.


ZK를 사용하는 솔루션

서버측 기술과 클라이언트측 기술이 결합된 ZK 아키텍처를 탐구하려면 두 가지 방법 즉, 순수한 서버 중심 솔루션을 참조로 사용하거나 이벤트 핸들링을 서버와 클라이언트로 분배하는 과정을 통해 샘플 개념 증명 주식 뷰어 애플리케이션을 살펴보아야 한다.

주식 뷰어 애플리케이션은 히스토리 주식 레코드를 XML로 읽어서 테이블 형식과 선 그래프로 데이터를 표시한다. 또한, 이 애플리케이션에는 Google Suggest와 같이 검색을 자동 완성하는 검색 상자가 포함된다. 그림 3에는 이 애플리케이션이 표시되어 있다.


그림 3. 주식 뷰어 애플리케이션
여러 개의 주식과, 고가, 시초가, 저가, 종가 및 거래량이 표시된 화면

ZK MVC를 사용하는 서버측 솔루션

서버 중심 방식의 샘플에서는 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에 있는 히스토리 주식 데이터를 구문 분석하여 메모리에 StockPrice 오브젝트를 작성한다. 각 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.zul
                
1. <?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.zul
                
1. <?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>
            

제어기
제어기는 데이터 오브젝트와 UI 컴포넌트를 자동으로 연결하는 ZK의 rg.zkoss.zk.ui.util.GenericForwardComposer에서 확장된 클래스이다.

StockController 클래스에서는 index.zul에 있는 borderlayout 컴포넌트의 뷰를 제어한다.

  • 8행에서는 onCreate 이벤트 리스너를 사용하여 id가 mainborderlayout을 등록하며 이렇게 하면 기본 주식 항목이 해당 뷰에 표시되도록 설정된다.
  • 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.java
                          
1. 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. PriceController
                 
1. 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. }
               

이 예제에서는 표와 차트에서 동적으로 데이터를 업데이트하는 기능과 검색 상자 기능을 구현하기 위해 여러 곳에서 비동기 호출을 사용해야 했으며 이러한 비동기 호출을 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: 어노테이션이 있는 클라이언트에서 처리되도록 textboxonChanging 이벤트를 선언한다.
  • 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행까지는 서버에서 비동기 요청을 하는 데 필요한 서비스 메소드를 구현하여 listboxonSelect 이벤트를 직접 처리한다. 예제에서는 선택될 listitemuuid를 검색하여 주식 데이터와 선형 차트를 표시하는 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 articlezk5Client_ServerFusion.zip9018KBHTTP

다운로드 방식에 대한 정보


참고자료

교육

  • "Rich Internet applications using ZK"(developerWorks, 2010년 1월): 이 기사에서는 ZK를 소개하면서 ZK를 사용하는 실제 예제를 통해 애플리케이션을 Apache Tomcat에서 실행하는 방법과 MySQL 데이터베이스에 연결하는 방법을 설명한다.

  • ZK 5.0 and jQueryZK 5.0 and jQuery part 2를 읽어보고 ZK 및 jQuery에 대한 소개와 데모를 확인하고 ZK 제어를 구현하는 방법과 예제를 구성하는 방법 등을 살펴보자.

  • 클라이언트 네임스페이스와 클라이언트 프로그래밍을 배우자.

  • 모든 위젯 클래스의 상위 클래스인 ZK 위젯에 관해 알아보자.

  • ZK MVC Made Easy에서는 MVC(Model-View-Controller) 패턴의 애플리케이션을 쉽게 작성할 수 있게 도와주는, ZK에서 제공하는 세 가지 유틸리티 클래스와 세 가지 헬퍼 메소드를 세부적으로 논의한다.

  • UI 컴포넌트와 데이터 소스 간의 데이터 복사 Plumbing Code를 자동화하는 메커니즘인 ZK 데이터 바인딩과 데이터 바인딩 관리자에 관해 배우자.

제품 및 기술 얻기

토론

필자소개

Photo of Lance Lu

Lance Lu は ZK フレームワークの技術エバンジェリストです。彼は ZK に参加する以前、台湾にある 32 ビット・マイクロプロセッサーの設計企業の上級技術者でした。また、カナダの医療機器メーカーの製品マネージャーであったこともあります。彼はカナダのビクトリア大学 (University of Victoria) で数学の学位を取得しています。彼は学術領域として、物理学、哲学、心理学、数学、コンピューター・サイエンスなどに関心を持っています。

Sachin graduated with a Masters degree from the University of Utah, Salt Lake City, U.S. He has worked in both small and large companies in the United States and India performing various technical and managerial roles. Sachin currently works in IBM Software Group's Lotus division.

잘못된 도움말 신고

부정사용 신고

감사합니다. 이 항목은 운영자가 관심을 표시했습니다.


잘못된 도움말 신고

부정사용 신고

제출실패 신고. 나중에 다시 실행해주세요.


디벨로퍼웍스 로그인


IBM ID가 필요하세요?
IBM ID를 잊으셨습니까?


비밀번호를 잊으셨습니까?
비밀번호 변경

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

화면상에 보여지는 닉네임을 정하세요.

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

3개의 &이나 대쉬를 포함해주시고 31글자내로 제한해주세요.


developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


아티클 순위

의견

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=20
Zone=웹 개발, 자바
ArticleID=618914
ArticleTitle=jQuery와 ZK, Java 코드를 결합하여 Ajax 개발 강화하기
publish-date=10192010
author1-email=lancelu@zkoss.org
author1-email-cc=
author2-email=sachin.mahajan@in.ibm.com
author2-email-cc=

태그

Help
검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오.

태그를 더 많이 보거나 적게 보기 위해 슬라이더 막대를 사용하십시오.

인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다.

내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.

검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오. 인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다. 내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.