난이도 : 중급
Brett McLaughlin, Author and Editor, O'Reilly Media Inc.
2007 년 1 월 02 일
지난 시리즈에서는, Ajax 애플리케이션인 서버로 가는 요청을 XML로 포맷팅 하는 방법을 설명했습니다. 그리고 대부분의 경우, 이것이 좋은 방법이 아닌지를 설명했습니다. 이번에는, 좋은 방법을 소개합니다. XML 응답을 클라이언트로 리턴하는 방법을 설명합니다.
여러분이 해서는 안될 일에 대한 글을 쓰는 것을 별로 좋아하지 않는다. 그것은 매우 바보 같은 일이다. 지금까지 어떤 것을 설명하는데 할애한 시간만큼, 나머지는 그 동안 배웠던 그 기술을 사용하는 것이 왜 좋은 생각이 아닌지를 설명하는데도 시간을 할애하곤 한다. 바로 지난달 지난 달 기술자료(참고자료)가 그 경우이다. Ajax 애플리케이션 요청에 데이터 포맷으로서 XML을 사용하는 방법을 설명했다.
모쪼록 이 글이, XML 요청에 대해 배우느라 여러분이 보냈던 시간을 보상해 주기를 바란다. Ajax 애플리케이션에서, 송신 데이터 포맷으로서 XML을 사용하는 경우는 드물지만, 서버에서 XML을 클라이언트로 보내야 하는 이유는 충분하다. 따라서, 지난 글에서 여러분이 XML에 대해 배웠던 모든 것이 이번 글에서 비로서 가치를 지니기 시작했다.
서버에서 XML 응답을 받는 것에 대한 기술적인 상세를 보기 전에, 서버가 요청에 대한 응답으로 XML을 보내는 것이 좋은 것인지를 이해해야 한다. (그리고 클라이언트가 요청을 XML로 보내는 것과는 어떻게 다른지도 이해해야 한다.)
클라이언트는 대부분의 경우에 XML을 사용할 필요가 없다. 이름값 쌍을 사용하여 요청을 보낼 수 있기 때문이다. 따라서, 다음과 같이 이름을 보내게 된다: name=jennifer
. 또한 이어지는 이름값 쌍들은 앰퍼샌드(&
)를 사용하여 추가할 수 있다: name=jennifer&job=president
. 간단한 텍스트와 이러한 이름값 쌍을 사용하면, 클라이언트는 여러 값을 가진 요청을 서버로 쉽게 보낼 수 있다. XML이 제공하는 추가 구조(오버헤드)가 필요 없다.
사실, XML을 서버로 보내야 하는 대부분의 이유들이 다음 두 개의 범주로 나뉠 수 있다.
이름값 쌍을 보낼 때, 요청을 보내는 웹 브라우저와 요청에 응답하고 서버 프로그램을 호스팅 하는 플랫폼은 이런 이름값 쌍들을 서버 프로그램이 쉽게 작업할 수 있는 데이터로 변환한다. 실제로, 모든 서버 측 기술 -- Java™ servlets, PHP, Perl, Ruby on Rails- 덕택에 다양한 메소드를 호출하여 이름에 기반한 값들을 얻을 수 있다. 따라서 name
애트리뷰트를 얻는 것은 간단하다.
서버가 name=jennifer&job=president
스트링으로 애플리케이션에 응답한다면, 클라이언트는 두 개의 이름값 쌍을 나누고, 각 쌍을 이름과 값으로 나눌 표준화 된 쉬운 방법이 없다. 리턴된 데이터를 직접 파싱해야 할 것이다. 서버가 이름값 쌍으로 구성된 응답을 리턴하면, 응답은 세미콜론, 파이프 심볼, 기타 비표준 포맷팅 문자로 구분된 엘리먼트를 가진 응답만큼이나 해석하기 어렵다.
|
응답에 플레인 텍스트를 사용하고, 적어도 응답에 여러 값이 포함되어 있을 때, 클라이언트가 그 응답을 받아서 표준 방식으로 인터프리팅 해야 하는 쉽지 않은 방식이다. 서버가 넘버 42를 보냈다면, 플레인 텍스트로도 충분하다. 하지만, TV 쇼 Lost, Alias,, Six Degrees,의 최근 시청률을 보냈다면? 여러분은 플레인 텍스트를 사용하여 이 응답을 보낼 많은 방법들을 선택할 수 있지만(Listing 1), 클라이언트에 의한 작업 없이는 쉬운 인터프리팅 방법이 없고, 표준화된 방법도 없다.
show=Alias&ratings=6.5|show=Lost&ratings=14.2|show=Six%20Degrees&ratings=9.1 Alias=6.5&Lost=14.2&Six%20Degrees=9.1 Alias|6.5|Lost|14.2|Six%20Degrees|9.1 |
이러한 응답 스트링들을 나누는 방법을 알아내는 것이 어려운 일은 아니지만, 클라이언트는 세미콜론, 등가 표시, 파이프, 앰퍼샌드에 따라 스트링을 파싱하고 나누어야 한다. 이는 다른 개발자들이 쉽게 이해하고 관리할 수 있는 강력한 코딩 방법이 아니다.
이름값 쌍으로 서버가 클라이언트에 응답하는 표준 방법이 없다는 것을 깨달았다면, XML을 사용해야 하는 이유가 분명해진다. 데이터를 서버로 보낼 때, 이름값 쌍은 최상의 선택이다. 서버와 서버 측 언어는 그 쌍들을 쉽게 인터프리팅 할 수 있기 때문에다. 마찬가지로, 데이터를 클라이언트로 리턴할 때 XML을 사용하면 일이 쉬워진다. 이전 기술자료들에서 XML을 파싱할 때 DOM을 사용하는 것에 대해 다루었고, 앞으로의 기술자료에서는 JSON이 XML을 파싱하는 옵션을 어떻게 제공하는지를 설명할 것이다. 무엇보다도, 여러분은 XML을 플레인 텍스트로서 취급할 수 있고, 이러한 방식으로 값을 얻어낼 수 있다. 따라서, 서버에서 XML 응답을 얻을 수 있는 여러 가지 방식이 있고, 매우 표준적인 방식으로 클라이언트에 있는 데이터를 가져다가 사용할 수 있다.
게다가 XML은 이해하기도 쉽다. 프로그래밍을 하는 사람이라면 Listing 2의 데이터를 이해할 수 있을 것이다.
<ratings> <show> <title>Alias</title> <rating>6.5</rating> </show> <show> <title>Lost</title> <rating>14.2</rating> </show> <show> <title>Six Degrees</title> <rating>9.1</rating> </show> </ratings> |
Listing 2의 코드는 특정 세미콜론이나 어포스트로피 때문에 생기는 혼란이 없다.
|
이 시리즈의 초점은 Ajax의 클라이언트 측에 맞춰져 있기 때문에, 서버 측 프로그램이 XML로 응답을 생성하는 방법에 대해서는 자세히 들어가지 않겠다. 하지만, 클라이언트가 XML을 받을 때 몇 가지 특별한 고려 사항이 있다.
서버에서 오는 XML 응답을 두 가지 기본 방식으로 취급할 수 있다.
Document
객체로 나타나는, XML 문서 서버에서 오는 간단한 응답 XML을 보자. Listing 3은 위와 똑 같은 TV 리스팅을 보여주고 있다. (Listing 2와 같은 XML이지만, 여러분의 편의를 돕고자 다시 기재한다.)
<ratings> <show> <title>Alias</title> <rating>6.5</rating> </show> <show> <title>Lost</title> <rating>14.2</rating> </show> <show> <title>Six Degrees</title> <rating>9.1</rating> </show> </ratings> |
새로운 프로그래밍 기술을 배우는 관점에서 볼 때, XML을 다루는 가장 쉬운 옵션은 서버로부터 리턴된 텍스트 조각처럼 다루는 것이다. 다시 말해서, 데이터 포맷은 기본적으로 무시하고, 서버에서 응답만 취하면 된다.
이러한 상황에서, 마치, 서버가 비 XML 응답을 보낼 때처럼, 요청 객체의 responseText
속성을 사용한다. (Listing 4).
function updatePage() { if (request.readyState == 4) { if (request.status == 200) { var response = request.responseText; // response has the XML response from the server alert(response); } } } |
|
이 코드에서, updatePage()
는 콜백이고, request
는 XMLHttpRequest
객체이다. 모든 것이 response
변수 안에 이어진 XML 응답이 될 것이다. 이 변수를 프린트하면, Listing 5와 같이 된다. (Listing 5의 코드는 하나의 연속적인 라인이다. 여기에서는 디스플레이를 위해서 여러 줄로 표현했다.)
<ratings><show><title>Alias</title><rating>6.5</rating> </show><show><title>Lost</title><rating>14.2</rating></show><show> <title>Six Degrees</title><rating>9.1</rating></show></ratings> |
가장 중요한 것은 XML이 모두 함께 실행된다는 것이다. 대부분의 경우, 서버는 스페이스와 캐리지 리턴으로 XML을 포맷팅 하지 않는다. 단지 하나로 연결할 뿐이다. (Listing 5) 물론, 애플리케이션은 스페이싱(spacing)에 대해서 신경 쓰지 않는다. 다만 읽기가 힘들어질 뿐이다.
이때, JavaScript split
함수를 사용하여 데이터를 나누고, 기본 스트링 조작을 통해서 엘리먼트 이름과 값을 얻을 수 있다. 물론, 이것은 엄청난 작업이고, 이전 시리즈에서 다루었던 DOM(Document Object Model)을 보는데 많은 시간을 보내야 한다. 따라서, 나는 여러분에게 responseText
를 사용하여 서버의 XML 응답을 사용 및 출력할 것을 권하고 싶지만, 그 코드 모두를 보여줄 수는 없다. DOM을 사용할 수 있다면, 이러한 방식을 사용하여 XML 데이터를 얻어서는 안된다.
서버의 XML 포맷 응답을 다른 텍스트 응답처럼 취급할 수 있지만, 이것은 좋은 방법이 아니다. 우선, 이 시리즈를 잘 읽어보았다면, XML을 조작할 수 있는, JavaScript 친화적인 API인 DOM을 사용하는 방법을 익혔을 것이다. JavaScript와 XMLHttpRequest
객체는 서버의 XML 응답을 완벽하게 얻고 이것을 DOM Document
객체 폼으로 얻을 수 있는 속성을 제공한다.
Listing 6을 보자. 이 코드는 Listing 4와 비슷하지만, responseText
속성을 사용하기 보다는, 콜백이 responseXML
속성을 사용한다. XMLHttpRequest
에 사용할 수 있는 이 속성은 DOM 문서의 형태로 서버 응답을 리턴한다.
function updatePage() { if (request.readyState == 4) { if (request.status == 200) { var xmlDoc = request.responseXML; // work with xmlDoc using the DOM } } } |
DOM Document
가 생겼으니, 다른 XML처럼 작업할 수 있다. 예를 들어, Listing 7에서처럼, 모든 show
엘리먼트를 얻을 수 있다.
function updatePage() {
if (request.readyState == 4) {
if (request.status == 200) {
var xmlDoc = request.responseXML;
var showElements = xmlDoc.getElementsByTagName("show");
}
}
}
|
여러분이 DOM에 익숙하다면, 이것도 익숙해야 한다. 이미 배웠던 모든 DOM 메소드를 사용할 수 있고, 서버에서 받은 XML을 쉽게 조작할 수 있다.
물론, 정상적인 JavaScript 코드로 혼합할 수도 있다. 예를 들어, 모든 show
엘리먼트들을 통해 반복할 수 있다. (Listing 8)
function updatePage() { if (request.readyState == 4) { if (request.status == 200) { var xmlDoc = request.responseXML; var showElements = xmlDoc.getElementsByTagName("show"); for (var x=0; x<showElements.length; x++) { // We know that the first child of show is title, and the second is rating var title = showElements[x].childNodes[0].value; var rating = showElements[x].childNodes[1].value; // Now do whatever you want with the show title and ratings } } } } |
비교적 간단한 코드를 사용하여, XML 응답을 XML로 취급할 수 있고, 약간의 DOM과 단순한 JavaScript를 사용하여 서버 응답을 다룰 수 있다. 더 중요한 것은, 콤마로 분리된 값이나 파이프로 구분된 이름값 쌍 대신, 표준화된 포맷인 XML로 작업했다는 점이다. 다시 말해서, 서버로 요청을 보내는 것 같은, 합법적인 곳에서 XML을 사용할 수 있었다는 점이다.
서버에서 XML을 생성하는 방법에 대해 많이 설명하지는 않았지만, 많은 설명 필요 없이, 간단한 예제를 보면서 이러한 상황을 다루는 방법에 대해 알아보자. Listing 9는 요청에 대한 응답으로 XML을 출력하는 PHP 스크립트이다. 비동기식 클라이언트에서 온 것이다.
이것은 과격한 접근 방식이다. PHP 스크립트는 실제로 XML 아웃풋을 직접 작성하고 있다. PHP와 XML 응답을 만들 수 있는 서버 측 언어를 위한 다양한 툴킷과 API들이 있다. XML로 응답을 생성 및 보내는 서버 측 스크립트가 어떤 모습인지를 파악할 수 있다.
<?php // Connect to a MySQL database $conn = @mysql_connect("mysql.myhost.com", "username", "secret-password"); if (!conn) die("Error connecting to database: " . mysql_error()); if (!mysql_select_db("television", $conn)) die("Error selecting TV database: " . mysql_error()); // Get ratings for all TV shows in database $select = 'SELECT title, rating'; $from = ' FROM ratings'; $queryResult = @mysql_query($select . $from); if (!$queryResult) die("Error retrieving ratings for TV shows.'); // Let the client know we're sending back XML header("Content-Type: text/xml"); echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>"; echo "<ratings>"; while ($row = mysql_fetch_array($queryResult)) { $title = $row['title']; $rating = $row['rating']; echo "<show> echo "<title>" . $title . "</title>"; echo "<rating>" . $rating . "</rating>"; echo "</show>"; } echo "</ratings>"; mysql_close($conn); ?> |
각자가 선호하는 서버 측 언어를 사용하여, XML을 만들 수 있다. IBM developerWorks의 많은 기술자료들에서 서버 측 언어를 사용하여 XML 문서를 만드는 방법을 설명하고 있다. (참고자료)
|
XML을 다루는 한 가지 매우 일반적인 옵션들은, 포맷팅 되지 않은 텍스트로서 취급하는 것 또는 DOM을 사용하는 것 이상으로 중요하다. 이것이 바로 JSON, (JavaScript Object Notation)이고, JavaScript에 포함된 무료 텍스트 포맷이다. 향후 시리즈에서는 JSON을 다루도록 하겠다.
일반적으로, JSON을 사용하여 할 수 있는 모든 것은, DOM을 사용해서도 할 수 있다. 그 반대의 경우도 마찬가지다. 이것은 선호도의 문제이고, 특정 애플리케이션에 알맞은 방식을 선택하는 문제이다. 지금까지는 DOM을 설명했고, 서버의 응답을 받는 상황에서 이를 사용하는 방법을 익혔다. 앞으로 남은 두 건의 기술자료에서는 JSON에 대해 설명할 것이다. 두 가지 중에서 한 가지를 선택할 준비를 해야 할 것이다. 다음 기술자료를 기다려주기 바란다.
|
|
지난 번 기술자료부터, 지금까지 거의 논스톱으로 XML에 대해 설명했다. 하지만 Ajax에 기여하는 XML의 빙산의 일각을 다루었을 뿐이다. 다음 기술자료에서는, XML을 보내는 특수한 상황에 대해 자세히 설명하겠다. (XML을 받는 상황에 대해서도 설명하겠다.) 특히, 사용 웹 서비스와 Google 같은 API 등 Ajax 인터랙션 관점으로, 웹 서비스에 대해서도 설명하겠다.
가장 중요한 것은 XML이 자신의 애플리케이션에 잘 맞는지를 생각하는 것이다. 많은 경우, 애플리케이션이 잘 작동한다면, XML은 그냥 유행어에 지나지 않고, XML을 사용해야 할 것 같은 유혹과 싸워야 한다.
서버가 보내는 데이터가 제한되어 있거나, 이상한 콤마 또는 파이프로 구분된 포맷으로 되어있다면, XML이 확실히 도움이 될 것이다. 서버 측 컴포넌트로 작업하거나 이를 변경하는 것을 고려하여, XML을 사용하여, XML만큼 강력하지 않은 상용 포맷을 사용하는 것 보다는, 표준 방식으로 응답을 리턴할 수 있다.
Ajax와 관련한 기술을 배우면 배울수록, 여러분의 결정에 신중을 더욱 기해야 한다. Web 2.0 애플리케이션을 작성하는 것은 재미있는 일이지만, 친구의 관심을 끌 요량으로 웹 페이지를 실행할 때 기술을 포기하지 않도록 조심해야 한다. 여러분이 좋은 애플리케이션을 작성할 것임을 믿고 있다. 다 만들고 나서 다음 글을 기대해주기 바란다.