달력

11

« 2024/11 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

Ajax 클라이언트/서버 통신이 복잡한 문제가 될 수 있다.

developerWorks

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.



난이도 : 중급

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을 서버로 보내야 하는 대부분의 이유들이 다음 두 개의 범주로 나뉠 수 있다.

  • 서버는 XML 요청을 수락하기만 한다. 이 경우, 선택권이 없다. 지난 달 기술자료에서, 이러한 유형의 요청들을 보낼 때 필요한 모든 툴을 제공했다.
  • XML 요청이나 SOAP 요청만 수락하는 원격 API를 호출할 경우. 이것은 매우 특별한 케이스이지만, 짚고 넘어가야 한다. 비동기식 요청에서 Google이나 Amazon에서 API를 사용할 경우, 특별히 고려해야 할 것이 있다. 다음 달 기술자료에서 API로 요청하는 문제를 예제를 통해 설명하겠다.

서버는 (표준 방식으로) 이름값 쌍을 보낼 수 없다.

이름값 쌍을 보낼 때, 요청을 보내는 웹 브라우저와 요청에 응답하고 서버 프로그램을 호스팅 하는 플랫폼은 이런 이름값 쌍들을 서버 프로그램이 쉽게 작업할 수 있는 데이터로 변환한다. 실제로, 모든 서버 측 기술 -- Java™ servlets, PHP, Perl, Ruby on Rails- 덕택에 다양한 메소드를 호출하여 이름에 기반한 값들을 얻을 수 있다. 따라서 name 애트리뷰트를 얻는 것은 간단하다.

서버가 name=jennifer&job=president 스트링으로 애플리케이션에 응답한다면, 클라이언트는 두 개의 이름값 쌍을 나누고, 각 쌍을 이름과 값으로 나눌 표준화 된 쉬운 방법이 없다. 리턴된 데이터를 직접 파싱해야 할 것이다. 서버가 이름값 쌍으로 구성된 응답을 리턴하면, 응답은 세미콜론, 파이프 심볼, 기타 비표준 포맷팅 문자로 구분된 엘리먼트를 가진 응답만큼이나 해석하기 어렵다.

싱글 스페이스(single space)!

대부분의 HTTP 요청에서, %20은 싱글 스페이스를 나타내는데 사용된다. 따라서 "Live Together, Die Alone"이라는 텍스트는 Live%20Together,%20Die%20Alone 형태로 HTTP로 보내진다.

응답에 플레인 텍스트를 사용하고, 적어도 응답에 여러 값이 포함되어 있을 때, 클라이언트가 그 응답을 받아서 표준 방식으로 인터프리팅 해야 하는 쉽지 않은 방식이다. 서버가 넘버 42를 보냈다면, 플레인 텍스트로도 충분하다. 하지만, TV 쇼 Lost, Alias,, Six Degrees,의 최근 시청률을 보냈다면? 여러분은 플레인 텍스트를 사용하여 이 응답을 보낼 많은 방법들을 선택할 수 있지만(Listing 1), 클라이언트에 의한 작업 없이는 쉬운 인터프리팅 방법이 없고, 표준화된 방법도 없다.



Listing 1. TV 시청률에 대한 서버 응답 (다양한 버전)
				
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을 사용하면 일이 쉬워진다. 이전 기술자료들에서 XML을 파싱할 때 DOM을 사용하는 것에 대해 다루었고, 앞으로의 기술자료에서는 JSON이 XML을 파싱하는 옵션을 어떻게 제공하는지를 설명할 것이다. 무엇보다도, 여러분은 XML을 플레인 텍스트로서 취급할 수 있고, 이러한 방식으로 값을 얻어낼 수 있다. 따라서, 서버에서 XML 응답을 얻을 수 있는 여러 가지 방식이 있고, 매우 표준적인 방식으로 클라이언트에 있는 데이터를 가져다가 사용할 수 있다.

게다가 XML은 이해하기도 쉽다. 프로그래밍을 하는 사람이라면 Listing 2의 데이터를 이해할 수 있을 것이다.



Listing 2. TV 시청률에 대한 서버 응답 (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>

Listing 2의 코드는 특정 세미콜론이나 어포스트로피 때문에 생기는 혼란이 없다.




위로


서버에서 XML 받기

이 시리즈의 초점은 Ajax의 클라이언트 측에 맞춰져 있기 때문에, 서버 측 프로그램이 XML로 응답을 생성하는 방법에 대해서는 자세히 들어가지 않겠다. 하지만, 클라이언트가 XML을 받을 때 몇 가지 특별한 고려 사항이 있다.

서버에서 오는 XML 응답을 두 가지 기본 방식으로 취급할 수 있다.

  • XML로 포맷팅 되는 플레인 텍스트
  • DOM Document 객체로 나타나는, XML 문서

서버에서 오는 간단한 응답 XML을 보자. Listing 3은 위와 똑 같은 TV 리스팅을 보여주고 있다. (Listing 2와 같은 XML이지만, 여러분의 편의를 돕고자 다시 기재한다.)



Listing 3. XML-포맷 TV 시청률 예제
				

<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을 다루는 가장 쉬운 옵션은 서버로부터 리턴된 텍스트 조각처럼 다루는 것이다. 다시 말해서, 데이터 포맷은 기본적으로 무시하고, 서버에서 응답만 취하면 된다.

이러한 상황에서, 마치, 서버가 비 XML 응답을 보낼 때처럼, 요청 객체의 responseText 속성을 사용한다. (Listing 4).



Listing 4. XML을 정상적인 서버 응답으로서 처리하기
				
function updatePage() {
  if (request.readyState == 4) {
    if (request.status == 200) {
      var response = request.responseText;

      // response has the XML response from the server
      alert(response);
    }
  }
}

이전 기술자료 리뷰

코드 중복을 피하기 위해, 후반 기술자료에서는 논의되는 주제와 관련된 코드 부분만 제시하겠다. 따라서, Listing 4에서는 Ajax 클라이언트 코드의 콜백 메소드만 보인다. 비동기식 애플리케이션에 이 부분이 어떻게 적용되는지 잘 모르겠다면, 본 시리즈의 기술자료들을 복습하기 바란다. 참고자료 섹션에 이전 기술자료 링크가 제공된다.

이 코드에서, updatePage()는 콜백이고, requestXMLHttpRequest 객체이다. 모든 것이 response 변수 안에 이어진 XML 응답이 될 것이다. 이 변수를 프린트하면, Listing 5와 같이 된다. (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로 취급하기

서버의 XML 포맷 응답을 다른 텍스트 응답처럼 취급할 수 있지만, 이것은 좋은 방법이 아니다. 우선, 이 시리즈를 잘 읽어보았다면, XML을 조작할 수 있는, JavaScript 친화적인 API인 DOM을 사용하는 방법을 익혔을 것이다. JavaScript와 XMLHttpRequest 객체는 서버의 XML 응답을 완벽하게 얻고 이것을 DOM Document 객체 폼으로 얻을 수 있는 속성을 제공한다.

Listing 6을 보자. 이 코드는 Listing 4와 비슷하지만, responseText 속성을 사용하기 보다는, 콜백이 responseXML 속성을 사용한다. XMLHttpRequest에 사용할 수 있는 이 속성은 DOM 문서의 형태로 서버 응답을 리턴한다.



Listing 6. XML을 XML로 취급하기
				
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 엘리먼트를 얻을 수 있다.



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)



Listing 8. 모든 show 엘리먼트들을 통해 반복하기
				
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: 간단한 예제

서버에서 XML을 생성하는 방법에 대해 많이 설명하지는 않았지만, 많은 설명 필요 없이, 간단한 예제를 보면서 이러한 상황을 다루는 방법에 대해 알아보자. Listing 9는 요청에 대한 응답으로 XML을 출력하는 PHP 스크립트이다. 비동기식 클라이언트에서 온 것이다.

이것은 과격한 접근 방식이다. PHP 스크립트는 실제로 XML 아웃풋을 직접 작성하고 있다. PHP와 XML 응답을 만들 수 있는 서버 측 언어를 위한 다양한 툴킷과 API들이 있다. XML로 응답을 생성 및 보내는 서버 측 스크립트가 어떤 모습인지를 파악할 수 있다.



Listing 8. XML을 리턴하는 PHP 스크립트
				
<?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을 인터프리팅 하는 기타 옵션

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 애플리케이션을 작성하는 것은 재미있는 일이지만, 친구의 관심을 끌 요량으로 웹 페이지를 실행할 때 기술을 포기하지 않도록 조심해야 한다. 여러분이 좋은 애플리케이션을 작성할 것임을 믿고 있다. 다 만들고 나서 다음 글을 기대해주기 바란다.

기사의 원문보기



참고자료

교육

제품 및 기술 얻기

토론


필자소개

Photo of Brett McLaughlin

Nextel Communications에서는 복잡한 엔터프라이즈 시스템을 구현했고, Lutris Technologies에서는 애플리케이션 서버를 개발했다. O'Reilly Media에서는 기고 및 편집 활동을 하고 있다. 베스트 셀러 작가인 Eric과 Beth Freeman과 공동 집필한 Head Rush Ajax는 Ajax에 혁신적인 Head First 방식을 취하고 있다. 그의 신간 Java 1.5 Tiger: A Developer's Notebook은 최신 자바 버전을 다룬 첫 번째 책이며, 그의 고전 Java and XML은 자바 언어에서 XML을 사용하는 방법에 대한 바이블로 통하고 있다.

:
Posted by 뽀기