2006년 9월 8일 금요일

AHAH - AJAX의 보완.

여기저기 어디서나 AJAX 타령. 개나 소나 AJAX를 이용해 서비스를 만들고 있는데, 솔직히 말하자면 아이들에게 칼들려 놓는 것처럼 위태위태하다. 그러다보니 이런 만행도 일어나고.
실제로 웹서비스 개발 중에 AJAX를 사용해보면 그닥 만만한 작업은 아니다.

1) XML 스키마를 정의하고 개발중에 관리하는 것은 꽤나 귀찮은 일이다.
2) 서버사이드에서 XML로 인코딩하고, 클라이언트사이드에서 XML을 파싱한다. 단지 화면에 약간의 HTML 컨텐트를 보여주기 위해 들어야 하는 품이 제법 많다.
3) 서버사이드에 XML을 만들고 발송하는 서버프로그램을 별도로 제작해야한다.
4) 접근성을 위한 대체텍스트 혹은 대체페이지를 개발하기 위한 품이 별도로 들어간다.
5) 잘 아시다시피 클라이언트사이드에서 JavaScript 디버깅하는 것은 매우 골치아픈 일이다.

고작 HTML 조금 동적으로 보여주기 위해 AJAX를 써야 하는가?
여기 대체재 AHAH가 있다.

AJAX는 Asynchronous JavaScript and XML을 가리킨다. 그럼 AHAH는?
Asychronous HTML and HTTP를 말한다.

언제 나온 새 기술인가 하고 의아해하는 분들이 있다면 조금 실망할지도 모른다. 실은 XMLHttpRequest 객체를 활용하는 또다른 방법일 뿐이다.

이미 AJAX를 많이 다뤄본 분들은 XMLHttpRequest.responseXML 대신 XMLHttpRequest.responseText가 편하다는 것을 깨달은 분들이 있을 것이다.
맞다, 그것이 AHAH이다. responseXML대신 responseText를 쓰면 AJAX라고 부르지 말고 AHAH라고 불러주자. 그간, responseText를 쓰면서 XML도 아닌데 AJAX라고 불러도 되나 찜찜하셨던 분들이라면 기꺼워 할 것이다. (나는 그랬다.)

?? 둘 사이에 무슨 차이가 있길래?

AHAH와 AJAX의 가장 큰 차이는, AHAH는 (x)HTML을 이용한다는 점이다. 주의할 점은, Text가 아닌 HTML이라는 점. responseText를 쓰되 그 전달값으로 HTML 서브셋을 쓴다는 소리다.

XHTML역시 XML의 일종이므로 XMLHttpRequest를 이용할 수 있다.

다음은 클라이언트사이드에서 AHAH를 이용하는 JavaScript 함수의 예제이다.
[javascript]
function SendAHAH(url,target) {
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = function() {
ReceiveAHAH(target);
};
req.open("GET", url, true);
req.send(null);
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange = function() {
ReceiveAHAH(target);
};
req.open("GET", url, true);
req.send();
}
}
}

function ReceiveAHAH(target) {
if (req.readyState == 4) {
if (req.status == 200 || req.status == 304) {
result = req.responseText;
document.getElementById(target).innerHTML = result;
} else {
document.getElementById(target).innerHTML="AHAH error:\n" +
req.statusText;
}
}
}
[/javascript]

코드를 보면 AJAX랑 별 다를 것도 없다. 실제로 이미 이와 비슷하게 코딩해서 작업하는 분도 많을 것이다.

그럼 왜 AHAH인가?

1. 파싱이 필요없다.
데이터를 XML로 바꾸고, 다시 그 XML을 파싱해서 필요한 정보를 뽑고... 그것을 다시 DOM을 구성하는 AJAX의 과정이 필요없어진다.
document.getElementById(target).innerHTML = result;
이것으로 만사해결. 아예 처음부터 HTML로 보내고 받은 HTML을 target에 채워넣어주기만 하면 된다.
DOM과 JavaScript에 익숙하지 않은 개발자라면 기뻐할 일이다.

2. 웹접근성이 깔끔히 해결된다.
AJAX를 사용하는 종래의 DHTML은 접근성 면에 문제가 많았다. 동등한 정보를 제공하는 대체텍스트나 대체페이지를 제공해야하는데 그러기 위해서는 XML외에도 따로 똑같은 내용을 담은 HTML을 만들고 연결해야 한다. 당연히, 이 과정을 무시하는 개발자들이 대부분이고(심지어는 왜 대체페이지를 제공해야 하는지 모르는 개발자가 더 많겠지만.), 따라서 근래의 AJAX를 사용한 서비스들은 대부분 접근성에서 많은 문제가 있었다.
비록 접근성을 중요하게 생각하는 개발자라 하여도, XML데이터 외에 별도의 HTML데이터를 만들어야 한다는 것은 부담스러운 일이다.
그러나 AHAH를 사용하면 아예 처음부터 HTML을 되돌려주므로 접근성을 완벽히 보장할 수 있다.
다음 코드를 보자.

[html]
...

...

...

title="카테고리 목록">
카테고리 목록 바로가기

[/html]

getCategoryList.php가 이 페이지의 카테고리 목록을 다음처럼 보여준다고 하자.
[html]

[/html]

여기, 세가지의 접근성을 고려한 기법이 들어갔다.

1) head안의 link에 AHAH 서버페이지를 적어준다. 검색엔진봇이나 텍스트 브라우저, 텍스트리더기들은 이 link에 기술된 URL에 들어있는 HTML 정보에 문제없이 접근가능하다.
2) target 엘리먼트에 longdesc 속성으로 해당 AHAH 서버페이지를 적어준다. 여기에서는 div에 걸었으므로 엄밀하게 말해서는 맞는 방법이 아니지만, 만약 target 엘리먼트가 img라면 매우 좋은 방법이 될 수 있다.
3) target 엘리먼트안에, AHAH로 대치되기전까지 사용될 대체텍스트를 넣어둔다. 만약 JavaScript가 disabled되어있거나 지원하지 않거나 혹은 기타등등 에러가 발생해서 컨텐트를 동적으로 받아올 수 없다면 이 대체텍스트가 화면에 뿌려질 것이다. 사용자도 JavaScript가 안되어서 텅빈 화면을 멍하니 바라보는 것이 아니라, 대체텍스트나 수고스럽긴 해도 클릭 한번이면 대체페이지가 보이게 되는 것이다.

이 기능들을 AJAX로 구현하려고 하면 혀가 빠진다. MVC 프레임워크를 쓴다 하여도 XML데이터를 별도의 HTML로 재가공하는 View 기능을 만들어야 하기 때문이다. 그러나 AHAH를 쓰면 이렇게 간단히 해결된다. Hurrrah!

3. 동적 스크립팅이 쉬워진다.
AJAX의 단점중에 하나는, 서버사이드에서는 데이터를 전달할 뿐이고, 그에 대한 처리는 클라이언트사이드에서 담당해야 한다는 것이었다. 미리 정의된 데이터를 정의된 방식으로 처리할 수 밖에 없다. 데이터의 형식이 바뀌거나 처리방법이 바뀐다면 클라이언트사이드의 페이지를 열어서 일일이 수정해야 한다.

그러나 AHAH를 쓰면 동적 스크립팅이 쉬워진다. 클라이언트사이드의 수정없이 서버사이드에서의 변경만으로 얼마든지 브라우저에서 JavaScript 실행을 컨트롤할 수 있다.

위에서 소개한 ReceiveAHAH()를 조금 변형시켜보자.
[javascript]
var bSaf = (navigator.userAgent.indexOf('Safari') != -1);
var bOpera = (navigator.userAgent.indexOf('Opera') != -1);
var bMoz = (navigator.appName == 'Netscape');
function ReceiveAHAH(target) {
if (req.readyState == 4) {
if (req.status == 200 || req.status == 304) {
result = req.responseText;
document.getElementById(target).innerHTML = result;
execJS(result);
} else {
document.getElementById(target).innerHTML="AHAH error:\n" +
req.statusText;
}
}
}

function execJS(node) {
var st = node.getElementsByTagName('SCRIPT');
var strExec;
for(var i=0;i
if (bSaf) {
strExec = st[i].innerHTML;
}
else if (bOpera) {
strExec = st[i].text;
}
else if (bMoz) {
strExec = st[i].textContent;
}
else {
strExec = st[i].text;
}
try {
eval(strExec);
} catch(e) {
alert(e);
}
}
}
[/javascript]

전달받은 HTML중에 <SCRIPT>를 찾아 실행시켜준다. 즉, 클라이언트쪽에서 JavaScript를 준비하지 않아도, 서버사이드에서 필요한 JavaScript를 만들어서 넘겨주면 얼마든지 실행된다는 소리다. 물론 AJAX로도 비슷한 기능을 구현할 수 있다. 허나 저거보다 짧고 쉽게 할 수는 없다.
(IE는 내부적으로 HTML태그를 대문자로 유지하므로 실제로 응용할 때에는 String.upperCase 메쏘드를 이용해서 브라우저별로 SCRIPT 와 script를 분리해서 찾도록 할 필요가 있다. 또 주석의 형태와 세미콜론 사용에 유의해야 한다.)

IE에서만 통용되었던 비호환방식의 dynamic scripting이 AHAH를 씀으로써 아주 간단히 크로스브라우징상에서 구현가능하다.

물론 AJAX가 DOM 컨트롤이라든가 JavaScript 제어를 세밀하게 할 수 있는 장점이 있지만, 장담하건데, 여러분이 AJAX로 시도하려는 작업의 95%는 AHAH만으로도 충분하다. 공연히 몸에 맞지 않는 옷입고 비틀거리지 말고, 쉽고 간단한 AHAH를 써서 효율 좀 올려보자. 물론 내 욕심은 AHAH를 사용하면 접근성 고려가 매우매우 간단해지므로 덤으로 접근성도 좀 신경써달라는 것이다.

AHAH는 Kevin Marks가 2005년 5월, JAH(Just Asynchronous HTML) 라는 이름으로 처음 기법을 고안했고,
Ernest Prabhakar가 2005년 웹 2.0 컨퍼런스에서 처음 AHAH라는 용어를 사용했다. 결국 현재에는 REX(REST-Enabled XHTML) microformat의 일부로 채택이 되었다. 어디 이상한 사이비 기법 아니니 안심하고 쓰시길.

관련 URL
JAH : http://epeus.blogspot.com/2005_05_01_epeus_archive.html#111588374981985824
REX : http://www.opendarwin.org/~drernie/talk/rest-enabled-xhtml-20051019.html

댓글 없음:

댓글 쓰기