IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  웹 개발  >

JSONP를 사용한 도메인 간 통신, Part 2: JSONP, jQuery 및 Yahoo! Query Language로 매시업 만들기

developerWorks
문서 옵션
PDF format - Fits A4 and Letter

PDF - Fits A4 and Letter
223KB (12 pages)

Get Adobe® Reader®

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

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

Seda Özses, IT Specialist, IBM
Salih Ergül, IT Architect, Independent Consultant

원문 게재일 : 2009 년 3 월 03 일
번역 게재일 : 2009 년 4 월 28 일

이 연재 기사의 이전 기사에서는 동일 출처 정책으로 인한 브라우저 제한을 극복하는 동시에 써드파티 소스의 데이터를 결합 및 제공할 수 있는 방법으로서 JSONP(JSON with Padding)을 소개했습니다. 이 기사에서는 이 프로세스를 계속 이어가면서 Yahoo!의 JSONP 서비스인 YQL(Yahoo! Query Language)을 사용하여 jQuery를 사용하는 매시업 웹 페이지를 빌드하는 방법에 대해 설명합니다.

소개

이 연재 기사의 Part 1에서는 JSONP를 현재 브라우저에 적용되는 동일 출처 정책 제한을 피할 수 있는 효과적인 도메인 간 통신 기술로 소개했다. jQuery의 네이티브 JSONP 지원을 사용하여 JSONP 서비스라고 부르는 써드파티 서비스에서 JSON 형식의 컨텐츠를 수집하는 방법을 살펴보았다. 이 기사에서는 YQL(Yahoo! Query Language)을 다양한 데이터 소스의 데이터에 대한 쿼리, 필터 및 결합 기능을 제공하는 단일 엔드포인트 JSONP 서비스로 소개한다.

또한 이 기사에서는 단일 웹 페이지에 표시할 주가 정보, The New York Times RSS 피드 및 일기 예보 데이터를 수집하는 매시업 애플리케이션에 사용할 jQuery 구현을 빌드하는 방법을 보여 준다.

데이터베이스로서의 웹

웹에는 다양한 웹 서비스 또는 API를 통해 개발자에게 노출되는 구조화된 데이터가 많이 있다. 이러한 서비스를 사용하려면 해당 서비스의 고유한 방식을 통해 서비스에 액세스하여 쿼리를 수행하고 결과를 구문 분석해야 한다. 각 서비스에는 액세스를 위한 고유 URL뿐 아니라 쿼리를 수행하고 결과를 이해하는 방법에 대해 설명하는 문서도 있다. YQL은 여러 URL에서 다양한 서비스를 통해 제공되는 데이터에 대한 쿼리 기능을 제공하는 통합 도구이다. YQL은 각 서비스의 고유 특성을 고려하지 않고도 웹 데이터를 쿼리, 필터링 및 결합할 수 있는 단일 엔드포인트 서비스를 제공한다.

YQL은 기본적으로 여러 서비스의 구조화된 데이터를 하나의 표준 방식으로 쿼리 및 검색할 수 있는 SQL 기반 쿼리 언어이다. 그러나 YQL은 Yahoo!에서 호스트하고 REST 엔드포인트를 통해 제공되는 쿼리 엔진이기도 하다. YQL은 우리에게 익숙한 테이블과 행으로 구성된 관계형 데이터베이스 모델을 사용한다. 그러나 내부적으로는 데이터를 XML로 해석하고 구조화한다. 기본 데이터 소스에서 XML 데이터를 제공하지 않을 경우에는 YQL이 변환을 수행한다. YQL은 XML 또는 JSON 형식으로(서비스를 호출할 때 사용자가 지정할 수 있음) 응답을 리턴할 수 있다. 또한 서비스에 JSON 데이터를 요청한 경우에는 콜백 함수를 지정할 수도 있다. 이렇게 하면 YQL 서비스를 JSONP 서비스로 만들 수 있으며, 결과적으로 많은 웹 서비스에게 JSONP 기능을 자동으로 지원할 수 있다.

YQL은 RSS, Atom, JSON, XML, CSV, HTML, Flickr, Yahoo! Finance, Weather 등의 데이터 소스를 인식하고 지원한다. YQL은 외부 데이터 소스(Yahoo!의 외부)도 지원하므로 매우 다양한 유형의 매시업 애플리케이션을 빌드할 수 있다. 즉, YQL은 단일 인터페이스에서 웹과 애플리케이션을 연결한다.


그림 1. 중재자 서비스로서의 YQL
YQL을 통해 웹과 애플리케이션이 연결되는 방법을 보여 주는 그래픽

앞에서 언급한 대로 YQL은 구조화된 웹 데이터를 쿼리하는 SQL 형태의 언어이다. 따라서 YQL 명령문에서도 SELECT가 주요 동사로 사용된다. 구문 또한 다음과 같이 SQL과 매우 유사하다.

SELECT fields FROM source_table WHERE filter ..

다음 Listing은 The New York Times RSS 피드에서 헤드라인 뉴스를 검색하는 간단한 쿼리를 보여 준다.

select title from rss where url="http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml"

다음 예제는 좀 더 세부적으로 뉴욕에 있는 채식 전문 음식점 3곳을 검색하는 YQL 쿼리를 보여 준다.

select Title, Address, City, Rating.AverageRating from local.search 
  where query="vegetarian" and location="New York, NY" limit 3

위 쿼리는 Listing 1과 같은 JSON 응답을 리턴한다(리턴된 쿼리 메타데이터 생략).


Listing 1. JSON 쿼리 응답
 "results": {
  "Result": [
    {
      "Title": "World of Vegetarian Incorporated",
      "Address": "24 Pell St",
      "City": "New York",
      "Rating": {
        "AverageRating": "5"
      }
    },
    {
      "Title": "Counter",
      "Address": "105 1st Ave",
      "City": "New York",
      "Rating": {
        "AverageRating": "4"
      }
    },
    {
      "Title": "Red Bamboo",
      "Address": "140 W 4th St",
      "City": "New York",
      "Rating": {
        "AverageRating": "4.5"
      }
    }
  ]
}

다음과 같이 YQL을 통해 웹에 대한 쿼리도 수행할 수 있다.

select title,abstract,url from search.web where query="Bart Simpson"

Yahoo!에서 제공하는 YQL 콘솔을 사용하면 YQL에 대한 정보를 얻고 이해도를 높일 수 있다. 이 콘솔은 http://developer.yahoo.com/yql/console/에서 다운로드할 수 있다(그림 2의 화면 캡처 참조).

이 기사에서 제공하는 YQL 명령문을 복사해서 YQL 콘솔에 붙여넣으면 결과 JSONP 응답을 확인할 수 있다. (이때 XML이 아닌 JSON 출력을 받도록 단일 선택 단추를 선택해야 한다.)


그림 2. YQL 콘솔
YQL 콘솔의 화면 캡처를 보여 주는 창



위로


jQuery로 YQL 쿼리하기

일반적인 YQL GET 요청의 형식은 다음과 같다.

http://query.yahooapis.com/v1/public?q=[command]&[query parameter]

여기서, command는 YQL 명령이고 query parameter는 서비스에 대한 선택적 매개변수이다. 이 기사에서는 YQL의 JSONP 지원을 설명하는 중이기 때문에 YQL 서비스에서 JSONP 응답을 받기 위해 두 가지 선택적 매개변수가 요청에 항상 포함되어 있어야 한다. 따라서 요청의 형식은 다음과 같아야 한다.

http://query.yahooapis.com/v1/public?q=[command]&format=json&callback=?

여기서, format은 요청된 응답 형식을 정의하는 요청 매개변수이고 callback은 웹 애플리케이션에서 사용하는 콜백 함수의 이름이다(이 경우에는 jQuery에서 제공함). 이 코드에서는 jQuery에게 함수를 자동으로 생성하도록 지시하기 위해 실제 함수 이름 대신 ? 기호를 콜백 함수 이름으로 입력했다.

Listing 2의 코드에서는 jQuery에서 YQL 서비스를 호출하는 일반적인 방법을 보여 준다.


Listing 2. jQuery에서 일반적으로 YQL을 호출하는 구문

jQuery.getJSON(yqlUrl, function(data) {
// data is the JSON response
// process the response here
}); 





위로


매시업 빌드

지금까지 쿼리를 통해 YQL에서 JSONP 응답을 받는 방법을 살펴보았으므로 이제 매시업 웹 페이지를 빌드하는 작업을 시작할 수 있다. 지금부터는 서로 다른 웹 데이터 소스에서 컨텐츠를 가져오지만 YQL이라는 통합 서비스를 사용하는 세 가지 위젯으로 구성된 하나의 웹 페이지를 개발하는 방법에 대해 설명한다.

첫 번째 위젯은 IBM®, Yahoo!, Google 및 Microsoft®의 최신 주가 정보를 쿼리하여 검색하는 주가 정보 위젯이다. 이 쿼리에 대한 데이터 소스는 Yahoo! Finance CSV 파일이다. Listing 3에서는 첫 번째 위젯에 대한 YQL을 보여 준다.


Listing 3. 첫 번째 주가 정보 위젯의 YQL
 
select symbol, price from csv 
  where url='http://download.finance.yahoo.com/d/quotes.csv?
  s=IBM,YHOO,GOOG,MSFT&f=sl1d1t1c1ohgv&e=.csv' and 
  columns='symbol,price,date,time,change,col1,high,low,col2'


두 번째 위젯은 Listing 4의 YQL로 데이터를 가져와서 The New York Times RSS 피드의 헤드라인 뉴스를 보여 준다.


Listing 4. 두 번째 RSS 피드 위젯의 YQL 코드
 
select title, link from rss 
  where url="http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml"


마지막으로, Listing 5의 세 번째 위젯은 우편 번호 10504(뉴욕 아몽크)에 해당하는 지역의 일기 예보를 보여 주는 일기 예보 위젯이다.


Listing 5. 마지막 세 번째 일기 예보 위젯

select * from weather.forecast where location=10504 


웹 페이지의 각 위젯에는 Listing 6과 같은 스켈리털 코드가 있다.


Listing 6. 각 위젯의 스켈리털 코드
   
<div class="widget">
  <div class="widget-head">[WIDGET HEADER]</div>
  <div class="widget-content" id="[CONTENT ID]">[WIDGET CONTENT]</div>
</div>


각 위젯은 widget 클래스 유형의 div 요소이고 헤더(widget-head)와 컨텐츠 영역(widget-content)을 가지고 있다. 위젯의 컨텐츠 영역은 JSONP 데이터를 가져와서 위젯의 컨텐츠 섹션에 추가하는 JavaScript 코드로 채워진다.

이제 매시업 웹 페이지를 빌드하는 첫 번째 단계로 주가 정보, NYT 뉴스 및 일기 예보에 대한 세 가지 위젯 자리 표시자를 정의한다. Listing 7에서는 위젯 자리 표시자를 보여 준다.


Listing 7. 위젯 자리 표시자

<div class="widget">
  <div class="widget-head">Lastest stock quotes</div>
  <div class="widget-content" id="quotes"></div>
</div>   
<div class="widget">
  <div class="widget-head">NYT news headlines</div>
  <div class="widget-content" id="headlines"></div>
</div>   
<div class="widget">
  <div class="widget-head">Weather for Armonk NY</div>
  <div class="widget-content" id="weather"> </div>
</div>   


컨텐츠 영역은 JSONP를 사용하여 동적 데이터로 채울 예정이므로 여기에서는 빈 상태로 둔다. jQuery를 사용하면 HTML 코드를 매우 빠르고 쉽게 생성할 수 있음을 알게 될 것이다. 이들 각 영역은 Listing 8의 스켈리털 jQuery 코드를 통해 채워진다.


Listing 8. 스켈리털 jQuery 코드

$.getJSON(yqlUrl, function(data){
  // loop through the items
  $.each(data.query.results.[ITEM NAME], function(index, item){
    // process each item here
    // generate HTML to append to the widget's content area
  });
});


Listing 8의 코드에서는 yqlUrl(사용자가 제공해야 함)에 대해 GET 요청을 실행하고 JSONP 응답을 가져온다. JSON 응답(이 코드에서는 data로 표현됨)이 수신되면 결과 항목 전체를 하나씩 처리할 수 있다. [ITEM NAME]은 데이터 소스에 따라 각기 다른 이름을 가지고 있는 항목 배열에 대한 자리 표시자이다. 앞에서 언급한 YQL 콘솔을 사용하여 결과 응답을 살펴보고 정확한 응답 구조를 확인할 수 있다.

첫 번째 위젯

Listing 9에서는 주가 정보 위젯의 컨텐츠를 채우는 첫 번째 jQuery 코드를 보여 준다.


Listing 9. 첫 번째 위젯의 JavaScript 코드


var yqlUrl1= "http://query.yahooapis.com/v1/public/yql?q=
  select%20symbol%2C%20price%20from%20csv%20
  where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes.csv%3F
  s%3DIBM%2CYHOO%2CGOOG%2CMSFT%26f%3Dsl1d1t1c1ohgv%26e%3D.csv'%20and%20
  columns%3D'symbol%2Cprice%2Cdate%2Ctime%2Cchange%2Ccol1%2Chigh%2Clow%2Ccol2'
  &format=json&callback=?";
$.getJSON(yqlUrl1, function(data){
  $.each(data.query.results.row, function(index, item){
    $('#quotes')
    .append(
      $('<p/>')
        .append($('<span class="left"/>').text(item.symbol))
        .append($('<span class="right"/>').text('$'+item.price))
      );
    });
});


여기에서 첫 번째 위젯에 대해 올바르게 이스케이프된 URL을 어떻게 구했을까? YQL 콘솔을 보면 화면 오른쪽 상단 모서리에 "The Rest query" 섹션이 있다. YQL 명령문에 대한 테스트가 완료되면 이 섹션에서 쿼리 문자열을 복사해서 getJSON() 함수의 첫 번째 매개변수로 사용해야 한다.

주가 정보 위젯은 항목을 순환하면서 두 개의 span 요소가 포함된 p 요소를 #quotes ID로 식별된 div 요소에 추가한다. Listing 10에서는 이 컨텐츠 영역에 대한 결과 HTML 코드를 보여 준다.


Listing 10. 첫 번째 위젯의 HTML 코드


 <div id="quotes" class="widget-content">
  <p>
    <span class="left">"IBM"</span>
    <span class="right">$91.51</span>
  </p>
  <p>
    <span class="left">"YHOO"</span>
    <span class="right">$12.22</span>
  </p>
  <p>
    <span class="left">"GOOG"</span>
    <span class="right">$353.11</span>
  </p>
  <p>
    <span class="left">"MSFT"</span>
    <span class="right">$18.12</span>
  </p>
</div>


두 번째 위젯

첫 번째 위젯을 완료했으므로 이제 두 번째 위젯을 진행하자.


Listing 11. 두 번째 위젯의 JavaScript 코드


var yqlUrl2= "http://query.yahooapis.com/v1/public/yql?q=
  select%20title%2C%20link%20from%20rss%20
  where%20url%3D%22http%3A%2F%2Fwww.nytimes.com%2Fservices%2Fxml%2Frss%2Fnyt%2F
  HomePage.xml%22&format=json&callback=?";
$.getJSON(yqlUrl2, function(data){
  $.each(data.query.results.item, function(index, item){
    $("<a href='" + item.link + "' target="_blank\"/>")
    .html(item.title)
    .appendTo($('#headlines'))
    .wrap('<p/>');
  });
});

			

Listing 11의 코드는 먼저 NYT RSS 피드의 titlelink 요소를 가져온다. 그런 다음 메인 기사에 대한 링크가 포함된 p 요소를 위젯의 컨텐츠 영역에 추가한다. Listing 12에서는 이 컨텐츠 영역에 대한 결과 HTML 코드를 보여 준다.


Listing 12. 두 번째 위젯의 HTML 코드


<div id="headlines" class="widget-content">
  <p>
    <a target="_blank" href="http://www.nytimes.com/2009/02/19/business/19housing.html
    ?partner=rss&emc=rss">Obama Unveils $75 Billion Plan to Fight Home Foreclosures</a>
  </p>
  <p>
    <a target="_blank" href="http://www.nytimes.com/2009/02/19/business/economy/19fed.html
    ?partner=rss&emc=rss">Fed Offers Bleak Economic Outlook</a>
  </p>
  ...
</div>

				

세 번째 위젯

세 번째 위젯은 앞의 두 위젯과 매우 비슷하게 작동한다. 하지만 이번에는 HTML 형식의 데이터가 이미 들어 있기 때문에 item.description을 컨텐츠 영역에 직접 추가한다.


Listing 13. 세 번째 위젯의 JavaScript 코드


var yqlUrl3= "http://query.yahooapis.com/v1/public/yql?q=
  select%20*%20from%20weather.forecast%20where%20location%3D10504&
  format=json&callback=?";
$.getJSON(yqlUrl3, function(data){
  $.each(data.query.results.channel, function(index, item){
    $('#weather')
    .append($('<p/>').html(item.description));
  });	
});

            

완성된 모습을 보여 주기 위해 Listing 14에서는 모든 코드를 모아서 보여 준다(위젯의 스타일을 지정하는 데 사용한 CSS 제외).


Listing 14. 샘플 매시업 페이지의 HTML 코드


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <script type="text/javascript" src="jquery-1.3.1.min.js"/>
    <style type="text/css">
    ...
    </style>
    <title>JSONP Mashup</title>
  </head>
  <body>
    <div class="widget">
      <div class="widget-head">Latest stock quotes</div>
      <div class="widget-content" id="quotes"/>
    </div>
    <div class="widget">
      <div class="widget-head">NYT news headlines</div>
      <div class="widget-content" id="headlines"/>
    </div>
    <div class="widget">
      <div class="widget-head">Weather for Armonk, NY</div>
      <div class="widget-content" id="weather"> </div>
    </div>
    <script type="text/javascript">
      var yqlUrl1="http://query.yahooapis.com/v1/public/yql?q=
        select%20symbol%2C%20price%20from%20csv%20
        where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes.csv%3F
        s%3DIBM%2CYHOO%2CGOOG%2CMSFT%26f%3Dsl1d1t1c1ohgv%26e%3D.csv'%20and%20
        columns%3D'symbol%2Cprice%2Cdate%2Ctime%2Cchange%2Ccol1%2Chigh%2Clow%2Ccol2'
        &format=json&callback=?";
      $.getJSON(yqlUrl1, function(data){
        $.each(data.query.results.row, function(index, item){
          $('#quotes')
          .append(
            $('<p/>')
            .append($('<span class="left"/>').text(item.symbol))
            .append($('<span class="right"/>').text('$'+item.price))
          );
        });
      });

      var yqlUrl2="http://query.yahooapis.com/v1/public/yql?q=
        select%20title%2C%20link%20from%20rss%20
        where%20url%3D%22http%3A%2F%2Fwww.nytimes.com%2Fservices%2Fxml%2Frss%2Fnyt%2F
        HomePage.xml%22&format=json&callback=?";
      $.getJSON(yqlUrl2, function(data){
        $.each(data.query.results.item, function(index, item){
          $("<a href='" + item.link + "' target="_blank\"/>")
          .html(item.title)
          .appendTo($('#headlines'))
          .wrap('<p/>');
        });
      });

      var yqlUrl3= "http://query.yahooapis.com/v1/public/yql?q=
        select%20*%20from%20weather.forecast%20where%20location%3D10504&
        format=json&callback=?";
      $.getJSON(yqlUrl3, function(data){
        $.each(data.query.results.channel, function(index, item){
          $('#weather')
          .append($('<p/>').html(item.description));
        });	
      });
    </script>
  </body>
</html>

            

그림 3은 이 기사가 작성된 당시의 결과 웹 페이지를 보여 주는 스크린샷이다.


그림 3. 샘플 매시업 페이지
주가 정보, New York Times 헤드라인 및 뉴욕 아몽크의 날씨를 보여 주는 결과 웹 페이지 화면



위로


결론

YQL은 서버 측 프록시를 사용하지 않고도 클라이언트 측 매시업을 사용할 수 있도록 지원하는 강력한 서비스이다. YQL의 JSONP 지원과 jQuery를 함께 사용하여 단일 통합 인터페이스를 통해 구조화된 웹 데이터에 액세스할 수 있다. 이 기사에서는 jQuery와 YQL을 사용하여 짧은 코드로 구성된 매시업 웹 페이지를 빌드하는 방법을 살펴보았다. 지금까지 살펴본 내용을 바탕으로 코드를 개선하여 뛰어난 매시업 웹 페이지를 빌드할 수 있다. 다음은 몇 가지 팁이다.

  • 클릭했을 때 컨텐츠 영역을 새로 고치는 이미지 링크를 위젯 헤더에 배치한다.
  • 종목 기호를 입력할 수 있는 입력 필드를 제공하고 입력된 기호에 대한 주가 정보만을 가져온다.
  • RSS 항목의 제목 및 링크뿐만 아니라 해당 설명도 함께 표시한다.


참고자료



필자소개

Photo of Seda Ozses

Seda Özses는 ibm.com 기업 웹 마스터 팀의 구성원이다. ibm.com 기업 웹 포털을 담당하고 있으며, XSL 작업과 팀의 요구사항을 관리하는 업무를 맡고 있다.


Photo of Salih Ergul

Salih Ergül은 통신 및 은행 산업의 대규모 업무 중심의 엔터프라이즈 애플리케이션 통합 프로젝트에 특화된 자영업자로서 활동 중인 IT 아키텍트이다. Java 프로그래밍에 관한 여러 편의 기사를 작성하기도 했으며, 현재 은행 산업과 관련된 프로젝트에 참여하고 있다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



 


 


 


이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us





위로


Microsoft, Windows, Windows NT 및 Windows 로고는 미국 또는 기타 국가에서 사용되는 Microsoft Corporation의 상표이다. 기타 회사, 제품 및 서비스 이름은 해당 회사의 상표 또는 서비스표이다. 기타 회사, 제품, 및 서비스명은 다른 상표나 서비스 마크일 수 있습니다.

developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의