모든 사람들은 특정 유형의 TO DO 리스트 시스템을 사용해 왔다. 그와 같은 시스템들은 일반적으로 빠르고 쉽게 사용할 수 있는 데이터의 작은 조각들로 구성된다. To Do 리스트는 Lotus Domino로 Asynchronous JavaScript and XML (Ajax)를 나타내는 완벽한 예제이기도 하다. Ajax 디자인 패턴을 사용하여 사용자에게 인스턴트 피드백과 태스크 업데이트를 제공하는 ToDo-list라고 하는 Lotus Notes 애플리케이션을 개발하는 방법을 설명한다.
이 글에서는 ToDo-list 애플리케이션의 생성 과정을 볼 수 있을 뿐만 아니라 샘플 애플리케이션도 다운로드 할 수 있다. 이 애플리케이션은 Domino 에이전트를 사용하여 Notes 문서를 만들고 업데이트 하는 등 웹 브라우저에서 보내진 Ajax 요청을 처리한다. 또한 Domino 뷰를 사용하여 이 애플리케이션에 사용되는 XML을 생성한다. 이 글은 JavaScript와 XML을 알고 있는 숙련된 Notes/Domino 애플리케이션 개발자를 위해 기획되었다.
Ajax에 대해 더 배우고 싶다면 아래 참고자료 섹션을 참조하라.
ToDo-list 애플리케이션은 To Do 아이템들의 기록을 관리한다. 각각에는 Subject와 Status 필드가 포함되어 있다. Subject 필드에는 각 아이템에 대한 정보가 있다.(그림 1) Status 필드에는 미해결 액션에는 0이 완료된 액션에는 1로 표시되어 있다.
그림 1. Ajax 기반의 ToDo-List 애플리케이션
Ajax 기반 애플리케이션은 웹 기반 애플리케이션의 가용성을 늘리고 Lotus Domino 서버는 리치 클라이언트 애플리케이션에 좋은 리파지토리를 제공한다. 강화된 보안과 목록화 된 뷰 덕택이다.
Lotus Domino가 제공하는 디자인 엘리먼트는 Domino 플랫폼 상에서 Ajax 솔루션을 개발한다. Ajax 포트를 핸들하는 세션 인식형(보안과 개인화를 위함) Domino 에이전트를 구현하기는 쉽다. 게다가 Domino 뷰를 설정하여 HTML, XML, 심지어 JavaScript Serialized Object Notation (JSON)을 제공할 수 있다. 성공적인 Ajax 구현에 필요한 모든 것이 여기에 다 있다.
현대적인 웹 브라우저와 성숙한 문서 객체 모델(DOM)은 리치 애플리케이션의 생성을 더욱 용이하게 한다. 예를 들어, 사용자가 제안을 받는 프로젝트에 type-ahead 또는 suggest field를 추가할 수 있다. 이름 검색을 위해 타이핑을 할 수 있다. 또 다른 프로젝트에서 작은 박스(<DIV>)로 포털 페이지를 로딩 했다. <DIV>는 Ajax 호출을 사용하여 백엔드로부터 파퓰레이트 된다. 몇몇 박스들은 30초 마다 자동으로 업데이트 되면서 Enterprise Resource Planning (ERP) 시스템으로부터 새로운 정보를 매니저에게 제공한다.
또 다른 예제로는 포탈 프로젝트이다. 이 경우 각 박스 헤더는 작은 "Add to my page" 아이콘을 갖고 있다. 사용자가 아이콘을 클릭하면 백그라운드에 있는 요청이 사용자가 원하는 박스가 무엇인지에 대한 정보와 함께 서버로 간다. 서버는 다음 두 개의 메시지들 중 한가지를 보낸다. "The box is now on your personal page" 또는 "You have that box already!"
이 모든 애플리케이션에서는 API를 우선 지정해야 했다. 잘못 지정된 API는 프로젝트를 망칠 수 있다.
ToDo-List 애플리케이션의 코딩을 시작하기 전에 클라이언트와 서버 간 보내지는 정보를 포맷팅 하는 방법을 결정해야 한다. 시스템 아키텍트는 어떤 포맷이라도 선택할 수 있지만 요즘은 일반적으로 XML, JSON 또는 간단한 텍스트를 선호한다.
두 개의 컴퓨터가 통신하는 경우 정의가 잘 된 규칙을 설정하여 송신자와 수신자 모두 모든 정보를 어떻게 다루어야 하는지를 알 수 있도록 해야 한다. 이러한 규칙들은 복잡하거나 장황할 수도 있고 유연하거나 간단할 수도 있다.
포맷 선택이 개방적이라면 가독성과 무결성에 우선순위를 둘 것을 권한다. 다음과 같은 포맷을 선택할 수 있다.(표 1 참조)
- XML. XML 포맷은 체계적이고 정의가 잘된 데이터에 가장 잘 맞다. 서버와 클라이언트 모두 데이터가 어떻게 보이는지를 정확히 알고 있다. 하지만 XML은 다소 장황하며 오래된 브라우저의 XML 구현은 다소 엉성하다. 다행히도 그러한 엉성함이 현대적인 Ajax 기반 예제에는 영향을 미치지 않는다.
- HTML. HTML은 서버에서 웹 브라우저로 직접 렌더링을 위해 데이터를 보내기에 적합하다. 클라이언트는 렌더링 하기 전에 콘텐트를 HTML로 변환해야 한다. 브라우저가 데이터를 분석하고 리액션을 취할 경우에는 사용하지 않는 것이 좋다.
- JSON. JSON은 가독성도 뛰어나고 오버헤드가 없다. JSON은 JavaScript 언어에 알맞지만 자바 서버 측에서는 추가 코딩이 필요하다.
- CSV. Comma-Separated Value (CSV)는 두 개의 시스템들 간 데이터를 교환할 때 가장 많이 사용되고 입증된 방식일 것이다. 이 뷰에 등록하지 않았는데도 읽기가 가능하다. 무결성 체크가 없지만 그렇다고 해서 오버헤드도 없다.
- Text. URL 같은 밸류 쌍 조합에서 순수 텍스트를 사용하여 정보를 교환할 수 있다.
표 1. 정보 교환을 위한 다양한 포맷
| XML | JSON | HTML | CSV | Text | |
| 오버헤드 | 많음 | 중간 | 많음 | 매우 적음 | 중간 |
| 무결성 체크 | 아주 좋음 | 약간 | 없음 | 없음 | 없음 |
| 가독성 | 좋음 | 중간 | 좋음 | 불가능 | 좋음 |
이 글의 예제에서는 백엔드 시스템으로의 요청에는 텍스트 포맷을 응답에는 XML을 사용한다. 시간을 들여 XML을 정의해야 한다. 순수 Lotus Notes 환경에서 추가 필드를 추가하기란 쉬운 일이 아니다.
이 글 후반에는 클라이언트가 서버로 보낼 수 있는 방식을 정의한다. 하지만 지금으로서는 어떤 XML 다이얼렉트를 사용하여 한 개 또는 여러 개의 To Do 아이템들을 정의할지를 결정해야 한다. ToDo-List 애플리케이션의 To Do아이템에는 세 개의 값-키, 주제, 상태-이 포함되어 있다. 키는 To Do 아이템을 갖고 있는 Lotus Notes 문서의 Universal ID (UID)이다. 주제는 사용자가 수행해야 하는 태스크 또는 액션이다. 상태는 미완 태스크에는 0을 완료 태스크에는 1을 사용한다.
이 예제에서 서버는 업데이트 된 아이템 리스트로 모든 호출에 응답한다. 실제 상황에서 응답은 서버가 수행했던 액션에 연결되어 있다. 이 예제의 다음 단계에서는 업데이트된 아이템 리스트를 보내고 클라이언트가 어떤 서버가 작업을 했는지를 알 수 있도록 상태 정보를 제공한다.
<response>
<response status></response status>
<document>
<key></key>
<subject></subject>
<status></status>
</document>
<document>
<key></key>
<subject></subject>
<status></status>
</document>
</response> |
API, 교환 포맷, XML 표준이 설정되면 서버측 기능을 개발한다. 그 후에 클라이언트 측 코드에 집중한다. 그 전에 문서에 대해 서버가 어떤 액션을 수행할 것인지를 결정해야 한다.
클라이언트에서 만들어진 모든 호출에는 액션 인자가 포함되어 있어서 서버가 무엇을 해야 할지를 알 수 있도록 한다. 가끔 아이템의 상태를 토글링하기 원한다면 추가 인자를 보내야 한다. 그 같은 경우 액션은 ToggleStatus이고 추가 인자에는 어떤 문서가 상태를 토글링 할 것인지에 대한 정보를 포함시켜야 한다. 그래야지만 Domino 서버가 정확한 문서에 대해 정확한 액션을 수행할 수 있다.
클라이언트에서 오는 모든 호출은 URL 인자와 HTTP GET 메소드를 사용하여 수행된다. 다음은 메소드와 키 인자 이름을 포함하고 있는 전체 URL이다.
http://host/ibm/ajaxdemo.nsf/AjaxHandler?open&method=deleteDocument&key=88877766fefe5678
웹 페이지는 API 안에서 다양한 메소드-예를 들어, createDocument, updateDocument, deleteDocument, getDocument, toggleStatus-를 사용한다. 각 메소드는 한 개 이상의 인자를 취한다. 상태 액션의 생성, 업데이트, 삭제, 토글링 이 모든 것이 데이터베이스 내의 정보를 바꾸고 그러한 변화는 웹 페이지 상의 To Do아이템 리스트에 반영된다. 이러한 변화를 반영하는 한 가지 방법은 클라이언트가 추가 요청을 수행하여 데이터베이스가 수정될 때 마다 아이템 리스트를 얻도록 하는 것이다. 더 나은 솔루션은 에이전트를 설정하여 에이전트가 호출될 때마다 업데이트 된 To Do리스트를 리턴하도록 하는 것이다. (이 글 후반에 자세히 설명하도록 하겠다.)
서버는 표 2에서 처럼 지정된 액션에 대해 반응해야 한다.
표 2. 지정된 엑션
| 메소드 | 목적 | 인자 | 리턴 |
| CreateDocument | 새로운 Lotus Notes 문서를 만들고 필드에 제공된 데이터로 파퓰레이트 한다. | 필드 리스트; 각 필드 인자에는 필드 이름, 유형, 값이 포함되어 있다. | 모든 아이템들을 포함하고 있는 XML 객체 |
| UpdateDocument | 문서 식별자, 필드 이름, 수정된 값을 제공하여 업데이트를 요청한다. | 문서 유니크 ID와 필드 인자: 필드 인자에는 필드 이름과 새로운 필드 값이 포함된다. | 모든 아이템들을 포함하고 있는 XML 객체 |
| DeleteDocument | 문서를 삭제한다. | 삭제될 문서의 유니크 아이디 | 모든 아이템들을 포함하고 있는 XML 객체 |
| GetDocument | 문서의 콘텐트를 리턴한다. | 검색될 문서의 유니크 아이디 | 요청된 아이템을 포함하고 있는 XML 객체 |
| ToggleStatus | 특정 To Do아이템의 상태를 토글링한다. | 상태가 토글링 되어야 할 문서의 유니크 아이디 | 모든 아이템들을 포함하고 있는 XML 객체 |
이 다섯 개의 액션들은 Domino 서버와 웹 브라우저 간 완벽한 API를 생성하는데 필요한 것들이다. 이제 서버측 에이전트 코드로 돌아가 보자.
Domino 서버는 모든 Ajax 요청들이 올바른 방식으로 처리되는지를 확인한다. 데이터 조작에 대한 호출을 하면 서버측의 지능-에이전트-에 의해 응답을 받는다. 정보를 단순히 요청하는 호출은 Lotus Notes 뷰에 의존한다. 이것은 훌륭한 XML 소스가 될 수 있다.
이 예제에서 설정된 Lotus Notes 뷰를 사용하여 XML을 디스플레이 한다. Lotus Domino가 고유의 HTML 코드를 추가하지 않도록 뷰를 설정하여 콘텐트를 HTML로서 나타낸다.
ToDo-List 애플리케이션에서 시스템에 각 To Do아이템용 XML 노드를 만들기 위해서는 이 뷰에는 단 한 개의 칼럼만 필요하다. 주제를 나열하는 첫 번째 칼럼은 숨겨지고 소팅 규칙을 설정하는데만 사용된다.(그림 2)
그림 2. XML 뷰를 보여주는 Lotus Domino Designer
이 뷰 외에도 뷰와 상관 관계가 있는 $$viewtemplate 폼이 필요하다. 이 폼에는 XML 래핑 코드가 포함되어 있다.(그림 3)
그림 3. $$viewtemplate 폼의 일부
기존 정보를 나타내는 것이 중요하다. 그림 3에 나타난 솔루션은 여러분의 필요에 정확히 맞는다. 이제 여러분의 요청에 응답할 Lotus Notes 에이전트를 만들어야 한다.
Ajax 패턴에 맞는 방식으로 Domino 백엔드 시스템에서 데이터를 이끌어 내는 방법을 알고 있다면 어떻게 Domino 에이전트를 사용하여 Ajax 호출을 받을 것인가?
우선 에이전트가 HTTP GET 메소드와 POST 메소드 중 어떤 것을 사용하여 호출될 것인지를 결정해야 한다. To Do아이템에는 적은 정보가 포함되어 있기 때문에 GET 메소드를 사용할 수 있다. 서버에 대한 모든 인자들은 다음과 같이 URL 스트링으로 보내진다.
/database.nsf/ajaxHandlerAgent?openagent&method=UpdateDocument&key=FFF&status=0
에이전트는 URL 스트링의 인자들을 파싱하여 메소드 인자에 있는 값에 기반하여 반응한다. 이 코드 리스팅은 ajaxHandlerAgent가 메소드 인자에 기반하여 어떻게 필요한 액션들을 취하는지를 보여주고 있다.
UrlArguments args = new UrlArguments(); (1) args.fromSession(session); |
주: 에이전트 코드 조각에서는 ToggleStatus 액션만 있다. 이 에이전트와 클라이언트용 전체 코드는 다운로드 섹션에서 다운로드 할 수 있다.
이 리스팅에서 다음 라인들에 주목하라. (1): UrlArguments 클래스는 URL 인자를 해시테이블 객체로 파싱하는 작은 유틸리티 클래스이다. (2): 이 라인에서 각 Lotus Notes 문서의 universalID 인자는 사용할 수 있다. (3): 이 라인에서 에러 핸들링은 제품 환경에서는 불충분하다. 필요할 경우 정정해야 한다.
뷰에 있는 데이터를 클라이언트로 보내기 위해 에이전트가 수행하는 리다이렉트를 이해할 수 있는가?
Ajax를 사용할 때의 큰 이점에는 사용자에게 즉각적인 실시간 정보를 서버에서 제공할 수 있다는 점이다. 따라서, 이 ToDo-List 애플리케이션에서 모든 서버 요청에 대한 응답으로서 새로운 아이템 리스트를 보낼 수 있다. 에이전트가 XML 뷰로의 서버측 리다이렉트를 수행하도록 하는 것이다. 웹 브라우저는 모든 호출에 대한 응답으로 XML 뷰의 콘텐트를 받는다.
pw.println("[" + "/" + thisDB.getFilePath() + "/XmlView?open]");
브라우저 상에서 Ajax 요청, 응답 정보용 플레이스홀더, 사용자가 인터랙팅 할 수 있는 한 개 이상의 핫스팟을 만들어야 한다. 인터랙션 포인트는 이벤트를 실행하는 어떤 객체라도 가능하다. 가장 잘 알려진 유형은 인풋 유형 버튼과 앵커 링크이다.(그림 4) 사용자가 목록 뷰에 익숙하다면 인터랙션 포인트가 어떻게 보일 지 알고 있다. Ajax는 이 구현에서도 뛰어나다. 사용자가 뷰를 확장하면 단 하나의 목록만 로딩하여 많은 오버헤드를 줄일 수 있고 사용자에게는 효과 만점이다.
그림 4. ToDo-list 애플리케이션의 인터랙션 포인트
그림 4에서 모든 가능한 핫스팟은 분홍색으로 강조했다. 다양한 핫스팟을 위한 HTML은 다양하다. REFRESH!와 Create new todo! 링크는 정적 코드인 반면, 상태 상징용 링크(빨간색 X와 녹색 체크 마크)와 아이템 주제는 즉시 렌더링 되어야 한다. 이 애플리케이션에서 헬퍼 기능을 설정하고 이 루틴은 Domino 서버가 제공하는 아이콘에 의존한다. HTML과 JavaScript 코드가 시각적 응답을 만드는데 필요하지만 서버에 대한 요청은 XMLHttpRequest 객체를 사용하여 같은 방식으로 설정된다.
실제 XMLHttpRequest 객체를 만들기는 매우 쉽다. 보다 복잡한 상황에서 일정 유형의 큐 핸들러가 더 흥미를 끌 수 있다. 하지만 지금으로서는 이 코드 리스팅에 나타난 코드를 사용할 수 있다.
var xmlHttp;
function createXMLHttpRequest() {
if (window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
} |
가독성 때문에 API의 각 메소드를 클라이언트 측의 메소드와 서버측에서 같은 이름을 가진 메소드로 매핑하는 것이 더 쉽다. 다음 코드 리스팅에 보이는 JavaScript 함수는 사용자가 상태 아이콘(녹색 체크 마크 또는 빨간색 X)을 클릭할 때 마다 호출된다. XmlHttp 객체가 상태 변화(12)를 받을 때 마다 실행되는 함수(02)를 선언하는 것으로 시작한다.
(10) 라인에서 글로벌 변수 Http가 파퓰레이트 되고 (11) 라인에서는 URL에 추가된 인자를 구현한다. (13) 라인에서 Ajax 객체가 (16) 라인으로 보내진다.
01 function toggleStatus(key) {
02 this.handleStateChange = function() {
03 if(xmlHttp.readyState == 4) {
04 if(xmlHttp.status == 200) {
05 refreshTodoList(xmlHttp.responseXML);
06 }
07 }
08 }
09
10 createXMLHttpRequest(); // build update string
11 var args='&method=ToggleStatus&key=' + key;
12 xmlHttp.onreadystatechange = this.handleStateChange;
13 xmlHttp.open("GET"
14 ,"./HandleAjaxRequests?open" + args
15 ,true);
16 SMLHTTP.send(null);
17 } |
(05) 라인에서 XML 파서에 응답을 취하기 전에 두 가지를 체크한다.
XMLHttpRequest(XHR) 구현은 요청이 다른 도메인에 의해 핸들되지 않도록 보안 제약을 두고 있다. 따라서 다중 서버가 개입되면 Ajax 솔루션을 사용하기가 더 힘들다. 이러한 제약을 어떻게 극복하고 또는 극복할 지의 여부를 따지지 않겠다. 대신 약간의 코딩이 필요한 대안 솔루션을 소개하도록 하겠다. 하지만 XMLHttpRequest 구현과 비슷한 사용자 경험을 제공한다.
- iframe 방식은 XMLHttpRequest 객체가 구현되기 전에 Ajax 기능을 얻을 수 있는 일반적인 방법이었다. 숨겨진 iframe 객체에서 콘텐트를 로딩하고 이것을 백그라운드에서 처리하여 XHR 솔루션과 비슷한 가능성을 경험할 수 있다.
- 프록시 방식은 XHR이 비 근원 서버를 호출할 때 최상의, 아마도 가장 일반적인 솔루션이다. 이 방식을 사용할 때 Ajax 페이지를 제공하는 서버상에서 프록시를 가져야 한다. 이 프록시는 모든 Ajax 호출을 받고 이들을 정확한 위치로 보낸다.
- 프록시 디자인 패턴은 캐싱과 콘텐트 밸리데이션을 추가할 수 있다. 모든 콘텐트가 같은 서버에서 로딩될 때 좋은 솔루션이 된다.
Ajax 디자인 패턴은 그들이 수행한 액션들에 대한 직접적인 응답을 받기 때문에 사용자에게는 참 좋은 패턴이다. 또한 통신 에러와 같은 경우 서버측 데이터를 완성하기에도 좋다. 하지만 Domino 개발자와 아키텍트가 Ajax 솔루션을 전개하기 전에 고려해야 할 사항도 있다.
우선 XMLHttpRequest 객체는 표준이 아니다. 또 다른 문제는 서버 퍼포먼스이다. Ajax 솔루션은 대역폭 요구를 늘릴 수 없지만 트랜잭션의 수라는 관점에서 Domino 서버에 압력을 준다. 세 번째로 웹 브라우저의 돌아가기(BACK) 버튼을 지원하지 않는 솔루션을 구현하지 않는 것이 좋다.
이러한 부정적인 측면과 잘 설계된 Ajax 솔루션이 제공하는 사용자 경험에 대해 충분히 고려를 해야 한다.
| 설명 | 이름 | 크기 | 다운로드 방식 |
|---|---|---|---|
| Sample AJAX-driven ToDo-list application | AjaxDemo_part1.nsf | 384 KB | HTTP |
교육
-
"Ajax 마스터, Part 1: Ajax 소개
-
"Considering Ajax, Part 1: Cut through the hype
-
"Ajax with Direct Web Remoting: Data serialization doesn't get any easier than this!"
-
AJAX Patterns Web site
-
The HttpRequest object reference page from the W3 Schools Web site
제품 및 기술 얻기
토론
Joachim Dagerot은 시스템 아키텍트이자 Strand Interconnect의 기술 리더이다. 1,300만 이상의 사용자들이 사용하는 월드와이드 인트라넷에 참여했다. 그는 현재 웹 개발에 집중하고 있다. 특히 가용성과 표준 순응 부분에 초점을 맞추고 있다. 여가 시간에는 웹 서비스와 블로그를 개발하고 있다.(jd@dagerot.com)