사람들이 Ajax와 웹 2.0을 생각할 때 대개는 사용자 경험의 시각적인 요소를 기억한다. Ajax 특유의 매력은 페이지 새로고침(refresh) 없이 제자리에서 동작하는 것처럼 느껴지는 것인데, 이는 완전히 왜곡된 것은 아니다. 전통적인 HTML 응용 프로그램의 페이지 새로고침은 가장 빠른 연결하에서도 시각적으로 문맥 변화를 나타내는 깜빡거림과 새로고침을 유발한다.
이 기사에서는 Ajax를 사용하거나 하지 않고 사용자 경험 설계를 위한 문맥 변화에 자유로운 접근 방법을 보여주는 몇 가지 방법을 알아본다. Ajax 사용자 경험의 가장 단순한 예제인 탭 윈도부터 시작하자.
탭은 상대적으로 작은 영역에 많은 데이터를 표시하는 가장 쉬운 방법이다. 환상적인 Prototype.js 자바스크립트 라이브러리를 사용하면 DHTML로 Ajax를 사용한 탭 윈도를 정말 쉽게 만들 수 있다(Listing 1). Prototype 라이브러리를 다운로드하고 사용하는 법을 포함한 더 자세한 내용은 참고자료에서 찾을 수 있다.
Listing 1. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<a href="javascript:void loadTab( 'tab1.html' )">Tab 1</a> |
<a href="javascript:void loadTab( 'tab2.html' )">Tab 2</a> |
<a href="javascript:void loadTab( 'tab3.html' )">Tab 3</a>
<div id="content" style="padding:5px;border:2px solid black;">
</div>
<script>
function loadTab( tab ) {
new Ajax.Updater( 'content', tab, { method: 'get' } );
}
loadTab( 'tab1.html' );
</script>
</body>
</html>
|
파일의 처음에서 모든 Ajax 작업을 처리할 Prototype.js 라이브러리를 포함하고 있다. 각 탭 페이지로의 링크들이 있는데, 각각은 탭 페이지의 내용을 갱신하기 위해 loadTab을 호출한다. ID가 content인 <div>는 내용을 위한 영역이다. loadTab 함수는 Ajax.Updater를 호출해 이 <div>를 지정한 HTML 파일로 갱신한다.
Listing 2는 첫 번째 탭에 들어갈 HTML 파일이다. 다른 파일들도 비슷하다.
Listing 2. tab1.html
Tab 1
|
브라우저로 파일을 열어보면 그림 1과 비슷한 화면을 볼 수 있다.
그림 1. 탭 페이지 시작 화면
여기에서 두 번째 탭을 클릭하면, 그림 2처럼 해당 내용이 표시된다.
그림 2. 두 번째 탭을 클릭한 후 화면
내용을 미리 포함한 <div> 태그를 숨겨두고, 표시 여부를 전환하는 방식으로 이 기능을 구현할 수도 있다. Ajax를 사용함으로써 얻는 이점은 내용이 필요할 때만 만들어지고 불러온다는 점이다. 그래서 페이지를 표시하기 위한 계산 시간도 줄어 들고, 사용자가 페이지를 보지 않는다면 아예 계산 시간이 필요 없다.
계속해서, Ajax(또는 Ajax와 비슷하게 보이는)를 사용하여 테이블을 다루는 방법을 세 개의 예제를 통해 알아본다.
Ajax로 테이블을 구축하는 첫 번째 예제는 Ajax를 통해 서버에 XML을 요청하는 것이다. 이 기술은 두 가지 측면에서 가치가 있다. 첫째, 필요할 때 데이터를 요청하고 제자리에 갱신하므로 쾌적한 사용자 경험을 제공한다. 둘째, XML 데이터 소스를 사용하므로 Ajax뿐만 아니라 어떤 클라이언트라도 XML을 통해 데이터를 사용할 수 있다.
Listing 3이 XML 기반 테이블 예제 코드다.
Listing 3. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<table id="books">
</table>
<script>
new Ajax.Request( 'books.xml', {
method: 'get',
onSuccess: function( transport ) {
var bookTags = transport.responseXML.getElementsByTagName( 'book' );
for( var b = 0; b < bookTags.length; b++ ) {
var author = bookTags[b].getElementsByTagName('author')[0].firstChild.nodeValue;
var title = bookTags[b].getElementsByTagName('title')[0].firstChild.nodeValue;
var publisher =
bookTags[b].getElementsByTagName('publisher')[0].firstChild.nodeValue;
var elTR = $('books').insertRow( -1 );
var elTD1 = elTR.insertCell( -1 );
elTD1.innerHTML = author;
var elTD2 = elTR.insertCell( -1 );
elTD2.innerHTML = title;
var elTD3 = elTR.insertCell( -1 );
elTD3.innerHTML = publisher;
}
}
} );
</script>
</body>
</html>
|
Ajax.Request 호출의 onSuccess 핸들러가 XML 데이터에서 각 book 요소를 가져오고 그 안에서 author,
title, publisher 값을 가져온 다음 insertRow와 insertCell을 사용하여 테이블에 데이터를 추가한다.
이 예제를 위한 XML 파일이 Listing 4에 나와 있다.
Listing 4. books.xml
<books>
<book>
<author>Jack Herrington</author>
<title>Code Generation In Action</title>
<publisher>O'Reilly</publisher>
</book>
<book>
<author>Jack Herrington</author>
<title>Podcasting Hacks</title>
<publisher>O'Reilly</publisher>
</book>
<book>
<author>Jack Herrington</author>
<title>PHP Hacks</title>
<publisher>O'Reilly</publisher>
</book>
</books>
|
결과로 그림 3과 같은 DHTML 파일이 만들어진다.
그림 3. XML 기반 테이블 화면
이 예제는 결과 세트가 작을 때는 유용하지만 더 큰 데이터를 다룰 때는 어떨까?
Ajax로 다중 페이지 테이블을 만들려면 조금 다른 방법이 필요하다. 위의 XML 기술을 쉽게 확장할 수도 있겠지만, 이 기사에서는 독자가 필요에 따라 적절하게 선택해 쓸 수 있도록 다양한 방법을 보여주고자 한다.
이 예제에서는 테이블의 각 페이지를 위한 HTML 조각을 제공하는 PHP 데이터 소스를 사용했다. HTML 파일이 Listing 5에 나와 있다.
Listing 5. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<div>
<a href="javascript:void updateTable(0);">1</a> |
<a href="javascript:void updateTable(1);">2</a> |
<a href="javascript:void updateTable(2);">3</a> |
<a href="javascript:void updateTable(3);">4</a> |
<a href="javascript:void updateTable(4);">5</a> |
<a href="javascript:void updateTable(5);">6</a>
</div>
<div id="states">
</div>
<script>
function updateTable( start ) {
new Ajax.Updater( 'states', 'stats.php?start='+(start*10)+'&count=10',
{ method: 'get' } );
}
updateTable( 0 );
</script>
</body>
</html>
|
이 파일의 핵심은 테이블의 각 페이지를 위한 링크들이다. ID가 states인 states <div> 태그는 stats.php 페이지에서 테이블의 내용을 받아온다.
다중 페이지 테이블을 실행하기 위해 더 큰 데이터가 필요한데, 필자는 미국의 인구 통계를 찾아 여러 해에 걸쳐 주와 그 주의 인구를 배열로 반환하는 getdata라는 PHP 함수를 만들었다. 함수의 일부가 Listing 6에 나와 있다.
Listing 6. data.php
<?php
function getdata()
{
$population = array();
$population []=
array( 'Alabama',4447100,4527166,4596330,4663111,4728915,4800092,4874243 );
$population []= array( 'Alaska',626932,661110,694109,732544,774421,820881,867674 );
...
$population []= array( 'Wyoming',493782,507268,519886,528005,530948,529031,522979 );
return $population;
}
?>
|
다음으로 데이터의 특정 범위를 얻기 위해 stats.php 페이지를 만들었다. 이 페이지는 시작과 끝 인덱스를 주면 데이터의 해당 범위를 HTML 테이블로 반환한다. 이 파일이 Listing 7에 나와 있다.
Listing 7. stats.php
<table>
<?php
require 'data.php';
$data = getdata();
$start = 0;
$count = count( $data );
if ( array_key_exists( 'start', $_GET ) ) $start = $_GET['start'];
if ( array_key_exists( 'count', $_GET ) ) $count = $_GET['count'];
$index = 0;
foreach( $data as $state ) {
if ( $index >= $start && $index < $start + $count ) {
?>
<tr>
<?php
foreach( $state as $item ) {
?>
<td><?php echo($item); ?></td>
<?php
}
?>
</tr>
<?php
}
$index += 1;
}
?>
</table>
|
브라우저로 열어보면 그림 4와 비슷한 화면을 볼 수 있는데, 첫 번째 페이지를 자동으로 불러왔다.
그림 4. 다중 페이지 테이블 화면
테이블 상단의 각 페이지 링크를 클릭하면 stats.php로부터 동적으로 불러온다. 그림 5는 두 번째 페이지를 클릭했을 때 화면이다.
그림 5. 다중 페이지 테이블의 두 번째 페이지 화면
이 방법은 탭 윈도에서 사용한 것과 비슷하다. Ajax를 통해 HTML을 전송하는 것은 종종 XML만큼이나 효과적이다. 브라우저 상에서는 XML을 파싱하고 다시 HTML로 변환할 필요가 없으므로 더 쉽다.
세 번째 테이블 구축 방법은 Ajax를 사용하지 않고 동적으로 테이블을 구축하는 가장 쉬운 방법이다.
Listing 8은 Ajax를 사용하지 않고 다중 페이지 테이블을 만드는 간단한 방법을 보여준다.
Listing 8. index.php
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<div>
<?php
require( 'data.php' );
$data = getdata();
$states = count( $data ) / 10;
for( $s = 0; $s < $states; $s++ ) {
?>
<?php echo( ( ( $s == 0 ) ? '' : '| ' ) ); ?>
<a href="javascript:void updateTable(<?php echo( $s ) ?>);">
<?php echo( $s + 1 ) ?>
</a>
<?php
}
?>
</div>
<?php
$index = 0;
foreach( $data as $state ) {
?>
<?php
if ( $index % 10 == 0 ) {
?>
<?php if ( $index > 0 ) { ?></table></div><?php } ?>
<div id="states<?php echo( $index / 10 ) ?>" style="display:none;">
<table>
<?php
}
?>
<tr>
<?php
foreach( $state as $item ) {
?>
<td><?php echo($item); ?></td>
<?php
}
?>
</tr>
<?php
$index += 1;
}
?>
</table>
</div>
<script>
function updateTable( id )
{
var elStateDivs = [];
<?php
for( $s = 0; $s < $states; $s++ ) {
?>
elStateDivs.push( $( 'states<?php echo( $s ) ?>' ) );
<?php
}
?>
for( var i = 0; i < elStateDivs.length; i++ ) {
if ( i == id ) elStateDivs[i].show();
else elStateDivs[i].hide();
}
}
updateTable( 0 );
</script>
</body>
</html>
|
이 예제에서는 테이블의 각 페이지마다 <div> 태그를 하나씩 만드는 PHP 코드를 사용했다. 기본적으로 첫 번째 <div>만 보이고 나머지는 숨겨져 있다. updateTable 함수가 선택한 페이지에 따라 테이블의 특정 범위를 보이거나 숨긴다.
Ajax를 사용하지 않지만 여전히 Prototype.js 라이브러리를 포함하고 있는데 라이브러리가 제공하는 $(), show, hide 메서드를 사용해 각 <div> 태그를 쉽게 다룰 수 있다.
이렇게 만들어진 페이지가 그림 6에 나와 있다.
그림 6. 숨겨진 페이지 테이블
마지막 Ajax 예제는 글라이더 컨트롤이다. 글라이더(glider)는 페이지를 변경할 때 동적으로 왼쪽/오른쪽 움직임을 제공하는 새로운 형태의 화면이다.
글라이더 효과를 사용하려면 몇 가지 라이브러리가 더 필요하다. 첫 번째는 Prototype.js 라이브러리를 기반으로 만들어진 Scriptaculous 라이브러리인데, 글라이더 라이브러리가 사용하는 시각 효과를 제공한다. 두 번째는 글라이더 라이브러리다.
글라이더 예제가 Listing 9에 나와 있다.
Listing 9. index.html
<html><head>
<link rel="stylesheet" href="stylesheets/glider.css" type="text/css">
<script src="javascripts/prototype.js"></script>
<script src="javascripts/effects.js"></script>
<script src="javascripts/glider.js"></script>
</head><body>
<div id="glider"><div class="controls">
<a href="#tab1">Tab 1</a> |
<a href="#tab2">Tab 2</a> |
<a href="#tab3">Tab 3</a> |
<a href="#tab4">Tab 4</a></div>
<div class="scroller"><div class="content">
<div class="section" id="tab1">Tab 1</div>
<div class="section" id="tab2">Tab 2</div>
<div class="section" id="tab3">Tab 3</div>
<div class="section" id="tab4">Tab 4</div>
</div></div></div>
<script>
new Glider( 'glider', { duration:0.5 } );
</script>
</body></html>
|
파일의 맨 앞에서 여러 가지 스크립트 라이브러리를 포함하고 있다. 그 아래에 글라이더를 위한 <div> 태그들이 있다. 먼저 controls라는 <div> 태그는 각 탭을 위한 앵커 태그들을 포함하고 있다. 그 다음으로, scroller라고 불리는 <div> 태그는 각 탭을 위한 내용을 포함하고 있다. 그 아래에 있는 스크립트는 글라이더 <div> 태그의 ID로 Glider 객체를 만들고 있다.
브라우저로 이 페이지를 열어보면 그림 7과 비슷한 화면을 볼 수 있다.
그림 7. 글라이더 예제 실행 화면
이 화면에서 다른 탭을 클릭하면 말 그대로 미끄러지듯 내용이 나타난다.
Ajax, PHP, Prototype.js 라이브러리로 구축할 수 있는 몇 가지 다른 유형의 인터페이스 요소들을 살펴보았다. 이 아이디어들을 웹 응용 프로그램을 구축하는 데 활용할 수 있기를 바란다. 이 기술들은 충분히 쉬우며 Prototype.js 라이브러리와 함께라면 Ajax를 꽉 잡을 수 있다. 함께 나누고 싶은 성공 사례가 있다면 developerWorks Ajax 포럼에 알려주기 바란다.
교육
-
PHP 홈 페이지: PHP 프로그래머들을 위한 최고의 참고 자료
-
Prototype 라이브러리: 동적인 웹 애플리케이션을 더 쉽게 개발하기 위한 자바스크립트 프레임워크
-
Scriptaculous 자바스크립트 라이브러리: 웹 사이트가 날아다니게 만드는 화면 효과를 제공하는 Prototype 기반 프레임워크
-
Prototype.js 문서 페이지: 공식 Prototype 블로그와 많은 다른 참고 자료들에 대한 링크와 Prototype 자바스크립트 라이브러리에 대한 더 자세한 정보를 얻을 수 있다.
-
jQuery: Prototype.js와 비슷한 기능을 제공하는 또 다른 자바스크립트 라이브러리
-
Yahoo! 사용자 인터페이스 라이브러리: Yahoo!의 Ajax 툴킷
-
글라이더 컨트롤: 탭 스타일 인터랙션에 멋진 변형
-
IBM XML 인증: XML과 관련 기술에 대한 IBM 인증 개발자가 되는 방법을 찾을 수 있다.
-
XML 기술 자료: 한국 developerWorks XML 존에서 광범위한 기술 기사와 팁, 튜토리얼, 표준과 IBM Redbook을 볼 수 있다.
-
developerWorks 기술 행사 및 웹 캐스트: 이 세션들을 통해 현재의 기술적 흐름을 이해할 수 있다.
-
기술 서점: 이 주제 또는 다른 기술적인 주제에 대한 책들을 찾아보자.
제품 및 기술 얻기
-
IBM 시험판 소프트웨어: 한국 developerWorks를 통해 직접 다운로드할 수 있는 시험판 소프트웨어로 차세대 개발 프로젝트를 구축해보자.
토론
- 포럼에 참여하기.
-
XML 포럼: XML 관련 토론에 참여하기
-
developerWorks XML zone: Share your thoughts: 이 기사를 읽은 후 독자들의 생각이나 의견 올려보라.
-
developerWorks 블로그와 한국 developerWorks 커뮤니티에 참여하기
-
Ajax 토론 포럼: Jack Herrington이 관리하는 Ajax 포럼에 참여하기
Jack D. Herrington은 20년 경력의 소프트웨어 엔지니어이다. Code Generation in Action, Podcasting Hacks, PHP Hacks(출간 예정)의 저자이기도 하다. 30개 이상의 기술자료도 집필했다. (jack_d_herrington@codegeneration.net)