출판 산업과 어떤 식으로든 연결되어 일하는 사람이라면 Google Books에 대해 들어봤을 것이며, 단지 독서광에 지나지 않는 사람이라도 한 번쯤은 들어봤을 것이다. 이는 수백만 권의 도서를 스캔하여 온라인으로 미리 보거나 구매할 수 있게 함으로써, 세계 최대의 검색 가능한 디지털 도서관을 만들려는 Google의 원대한 시도이다. 또한, 이는 2009년 11월에야 해결된 집단 소송의 쟁점이 된 Google 최대의 논쟁거리였던 프로젝트 중 하나이기도 하다.
흥미로운 비공식 대화를 하는 것 외에, Google Books는 고유의 Data API 때문에 개발자 관점에서도 흥미를 끈다. 개발자는 이 API를 통해 Google Books 데이터베이스를 읽고 검색하여 사용자가 지정한 기준에 맞는 도서를 찾고, 다른 웹 애플리케이션에서 이런 검색 결과를 사용할 수 있다. XML이 지원되는 어떤 개발 툴킷을 통해서든 REST 모델에 따르는 이 API에 액세스할 수 있다. 이 API에는 이미 PHP, Java™ 및 기타 공통 프로그래밍 언어를 위한 클라이언트 라이브러리가 있다.
본 기사에서는 사용자 정의 PHP 애플리케이션으로 도서 검색 결과를 통합 및 사용하는 방법을 보여주는 Google Book Search Data API를 소개한다. 본 기사에는 키워드, 언어 또는 저자를 기준으로 도서를 검색하고, (ISBN 번호와 축소판 그림 이미지를 포함한) 도서 데이터를 검색하고, 데이터베이스에 이미 있는 도서에 리뷰와 등급을 추가하는 예제가 포함되어 있다. 그러면 이제 시작하자.
PHP 코드를 시작하기 전에, Google Book Search Data API에 대해 알아두어야 할 몇 가지 단어를 정리해보자. 모든 REST 기반 서비스와 마찬가지로, 이 API는 XML로 인코딩된 하나 이상의 입력 인수를 포함한 HTTP 요청을 수락하고 XML을 인식하는 어떤 클라이언트에서든 구문 분석할 수 있는 XML로 인코딩된 응답을 리턴한다. Google Book Search Data API를 사용하는 경우, 응답은 항상 요청된 정보를 포함한 Atom 피드로 구성된다.
일반적인 Book Search 피드에는 유용하고 적절한 애플리케이션을 빌드하기에 충분한 것 이상으로 방대한 정보가 포함되어 있다. 이 정보를 직접 확인하려면
자주 사용하는 웹 브라우저에서 http://books.google.com/books/feeds/volumes?q=php라는 URL로 액세스하면 된다. 이 REST 메소드는 php라는
키워드와 일치하는 도서 목록을 리턴한다. (결과 페이지의 소스 코드에서 볼 수 있는) 이 메소드에 대한 원시 XML 응답에는 이들 도서에 대한 세부 정보가 포함되고
목록 1과 같은 형식으로 표시될 것이다.
목록 1: Google Book Search 피드의 예
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom'
xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'
xmlns:gbs='http://schemas.google.com/books/2008'
xmlns:dc='http://purl.org/dc/terms'
xmlns:gd='http://schemas.google.com/g/2005'>
<id>http://www.google.com/books/feeds/volumes</id>
<updated>2009-12-28T06:14:28.000Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/books/2008#volume'/>
<title type='text'>Search results for php</title>
<link rel='alternate' type='text/html' href='http://www.google.com'/>
<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'
href='http://www.google.com/books/feeds/volumes'/>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/books/feeds/volumes?q=php'/>
<link rel='next' type='application/atom+xml'
href='http://www.google.com/books/feeds/volumes?q=php
&start-index=11&max-results=10'/>
<author>
<name>Google Books Search</name>
<uri>http://www.google.com</uri>
</author>
<generator version='beta'>Google Book Search data API</generator>
<openSearch:totalResults>277</openSearch:totalResults>
<openSearch:startIndex>1</openSearch:startIndex>
<openSearch:itemsPerPage>10</openSearch:itemsPerPage>
<entry>
<id>http://www.google.com/books/feeds/volumes/tywvv3ULal0C</id>
<updated>2009-12-28T06:14:28.000Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/books/2008#volume'/>
<title type='text'>Programming PHP</title>
<link rel='http://schemas.google.com/books/2008/thumbnail'
type='image/x-unknown' href='http://bks8.books.google.com/books?
id=tywvv3ULal0C&printsec=frontcover&img=1&zoom=5
&edge=curl&sig=ACfU3U0WFIZOyvLPjIv7jqlX4XZ7GI4TAg
&source=gbs_gdata'/>
<link rel='http://schemas.google.com/books/2008/info' type='text/html'
href='http://books.google.com/books?id=tywvv3ULal0C&dq=php
&ie=ISO-8859-1&source=gbs_gdata'/>
<link rel='http://schemas.google.com/books/2008/preview' type='text/html'
href='http://books.google.com/books?id=tywvv3ULal0C
&printsec=frontcover&dq=php&ie=ISO-8859-1&cd=1
&source=gbs_gdata'/>
<link rel='http://schemas.google.com/books/2008/annotation'
type='application/atom+xml'
href='http://www.google.com/books/feeds/users/me/volumes'/>
<link rel='alternate' type='text/html'
href='http://books.google.com/books?
id=tywvv3ULal0C&dq=php&ie=ISO-8859-1'/>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/books/feeds/volumes/tywvv3ULal0C'/>
<gbs:embeddability value='http://schemas.google.com/books/2008#embeddable'/>
<gbs:openAccess value='http://schemas.google.com/books/2008#disabled'/>
<gbs:viewability value='http://schemas.google.com/books/2008#view_partial'/>
<dc:creator>Rasmus Lerdorf</dc:creator>
<dc:creator>Kevin Tatroe</dc:creator>
<dc:creator>Peter MacIntyre</dc:creator>
<dc:date>2006</dc:date>
<dc:description>With style tips and practical programming advice,
this book will help you become not just a PHP programmer,
but a "good" PHP programmer.</dc:description>
<dc:format>521 pages</dc:format>
<dc:format>book</dc:format>
<dc:identifier>tywvv3ULal0C</dc:identifier>
<dc:identifier>ISBN:0596006810</dc:identifier>
<dc:identifier>ISBN:9780596006815</dc:identifier>
<dc:publisher>O'Reilly Media, Inc.</dc:publisher>
<dc:subject>Computers</dc:subject>
<dc:title>Programming PHP</dc:title>
</entry>
<entry>
...
</entry>
</feed>
|
이 출력을 빠르게 훑어보면서 다음과 같은 기본 요소를 익히도록 하자.
- Google Book Search Data API는 요청된 데이터를 포함한 Atom 피드로 REST 요청에 응답한다. 대부분의 경우, 가장 바깥쪽의
<feed>요소에 결과 세트의 현재, 다음 및 이전 페이지를 포함한<link>요소와 검색에 대한 요약 통계를 포함한<openSearch:>요소가 있다. - 가장 바깥쪽의
<feed>요소는 하나 이상의<entry>요소를 둘러싸고 있으며 각 요소는 검색 쿼리와 일치하는 도서 또는 "권(volume)"을 나타낸다. 각<entry>에는 제목, 설명, 출판 날짜, 저자 및 출판사를 포함하여 entry가 나타내는 도서에 대한 추가 정보가 있다. 또한, 각<entry>에는 자세한 도서 정보, 축소판 그림 이미지, 미리보기(사용 가능한 경우) 및 리뷰와 등급과 같은 어노테이션을 가리키는 URL 링크를 제공하는<link>요소가 있다. - 각 항목 내의
<dc:>네임스페이스 지정 요소에는 특별한 언급이 있다. 이들 요소는 간단한 정보 마크업 및 액세스에 대한 재사용 가능한 표준 정의 세트를 제공하는 DCMI(Dublin Core Metadata Initiative)의 요소에 상응한다. 목록 1에 나타낸 바와 같이, 이들 요소는 각 도서에 대한 제목, 저자, 출판사, 포맷, 주제 및 ISBN ID 정보를 둘러싸고 있다.
이런 방법으로 모든 Google Book Search Data API 함수에 공개적으로 액세스할 수 있는 것은 아니다. 인증 없이 검색 함수에 액세스할 수 있지만, 자신이 유효한 Google 계정의 사용자 이름과 비밀번호를 입력할 수 있는 인증된 사용자인 경우 (리뷰 및 레이블을 추가하거나 사용자 라이브러리에 도서를 추가하기 위한 함수를 포함하여) 데이터를 수정하는 다른 함수에만 액세스한다. 본 기사에서 두 가지 유형의 함수에 대한 예제를 모두 볼 수 있다.
공용 REST API를 통해 Google Book Search 결과에 액세스하는 방법을 알게 되었으므로, PHP 애플리케이션 내에서 같은 작업을 수행하는 방법을 살펴보자. 물론, 한 가지 방법은 PHP의 내장 XML 처리 확장(SimpleXML, DOM 또는 XMLReader)을 사용하여 Google Book Search에서 리턴되는 XML 피드를 구문 분석하고 그 XML 피드에서 적절한 정보 단편을 추출하는 것이다. 하지만, 이것은 그다지 편리한 방법이 아니며, 특히 대규모 피드나 대량의 네임스페이스 지정 정보를 다룰 때 불편하다. 그래서 본 기사에서는 PHP 애플리케이션을 Google Data API와 통합하려는 개발자를 위해 특별히 디자인된 Zend Framework의 Zend_Gdata 클라이언트 라이브러리라는 다른 접근 방식을 이용하겠다.
Zend_Gdata 라이브러리는 Zend Framework의 일부 또는 독립형 패키지로 다운로드할 수 있다(링크는 참고자료 참조). 이 라이브러리에는 특히 Google Book Search Data API를 사용하는 데 필요한 모듈과 데이터 액세스 및 인증을 단순화할 수 있는 메소드와 사전 정의된 클래스가 포함되어 있다. 이 라이브러리는 커뮤니티에서 테스트된 완전한 코드베이스를 애플리케이션에 제공할 뿐만 아니라 이 라이브러리를 사용하면 XML 트리를 탐색하는 기능이나 사용자 정의 네임스페이스를 처리하는 핵심 기능에 집중하는 대신 애플리케이션의 핵심 기능에 집중할 수 있다.
목록 2에서 Zend_Gdata 클라이언트 라이브러리를 사용하여 Google Book Search Data API로 도서 검색 결과의 피드를 검색하고 구문 분석하는 방법을 보여준다.
목록 2: Zend_Gdata 라이브러리를 이용한 검색 결과 가져오기
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";
try {
// perform login
$client = Zend_Gdata_ClientLogin::getHttpClient(
$user, $pass, 'print');
$client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
$books = new Zend_Gdata_Books($client);
// prepare and execute search query
$query = new Zend_Gdata_Books_VolumeQuery;
$query->setQuery(urlencode('robert crais'));
$feed = $books->getVolumeFeed($query);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Searching for book titles</title>
</head>
<body>
<h2><?php echo $feed->title; ?></h2>
<div>
<?php echo $feed->totalResults; ?> result(s) found.
</div>
<div id="results")
<ol>
<?php foreach ($feed as $entry): ?>
<li>
<?php echo $entry->getTitle(); ?>
</li>
<?php endforeach; ?>
</ol>
</div>
</body>
</html>
|
목록 2에서는 우선 Zend 클래스 라이브러리를 로드한 다음, Zend_Http_Client 클래스의 인스턴스를 초기화한다. 이 클라이언트에는 Google Book Search 서비스에 대해 인증된 연결을 설정하는 데 필요한 사용자 신임 정보가 제공된다. 인증된 연결이 만들어지면 Zend_Gdata_Books 클래스의 새 인스턴스가 초기화된다. 이 클래스는 Google Book Search Data API와 이루어지는 이후의 모든 상호 작용을 위한 제어점 역할을 한다.
아마 가장 많이 사용할 것으로 보이는 Zend_Gdata_Books 메소드는 검색 쿼리와 일치하는 도서 제목의 피드를 리턴하는 getVolumeFeed()
메소드일 것이다. 이 메소드는 setQuery() 클래스 메소드를 통해 쿼리 문자열 세트로 구성된 Zend_Gdata_Books_VolumeQuery 클래스의
인스턴스로 전달된다. getVolumeFeed() 메소드에 대한 응답은 목록 1에 표시된 것과 유사한 Atom 피드이며, 이
피드는 자동으로 구문 분석되어 피드에서 각각 하나의 <entry>를 나타내는 Zend_Gdata_Books_VolumeEntry 오브젝트의 배열로
변환된다. 이제는 간단히 이 배열을 계속 반복하고, 오브젝트 특성을 사용하여 각 항목의 세부사항을 검색하고, HTML 페이지로 전환할 수 있다.
그림 1은 'robert crais'라는 키워드와 일치하는 모든 도서 목록을 보여주는 출력 결과를 나타낸 것이다.
그림 1. 기본 Google Books API 검색의 결과
이런 기본적인 이해를 바탕으로, 더욱 활발한 대화식 환경으로 만들기 위해 목록 2를 꽤 쉽게 수정할 수 있다. 목록 3은 사용자가 입력한 도서 검색 쿼리를 수행할 때 사용될 수 있는 검색 양식을 추가하는 방법을 나타낸 것이다.
목록 3: 사용자가 입력한 키워드와 일치하는 검색 결과 가져오기
<?php
if (isset($_POST['submit'])) {
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";
try {
// perform login
$client = Zend_Gdata_ClientLogin::getHttpClient(
$user, $pass, 'print');
$client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
$books = new Zend_Gdata_Books($client);
// prepare and execute search query
$query = new Zend_Gdata_Books_VolumeQuery;
$query->setQuery(urlencode($_POST['q']));
$feed = $books->getVolumeFeed($query);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
}
?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Searching for book titles</title>
</head>
<body>
<h2>Search</h2>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
Search for:
<input type="text" name="q" value="<?php echo isset($_POST['q']) ?
$_POST['q'] : ''; ?>" />
<input type="submit" name="submit" value="Go" />
</form>
<?php if (isset($feed)): ?>
<h2>Search results for '<?php echo $_POST['q']; ?>'</h2>
<div>
<?php echo $feed->totalResults; ?> result(s) found.
</div>
<div id="results")
<ol>
<?php foreach ($feed as $entry): ?>
<li>
<a href="<?php echo $entry->getInfoLink()->getHref(); ?>">
<?php echo $entry->getTitle(); ?></a>
</li>
<?php endforeach; ?>
</ol>
</div>
<?php endif; ?>
</body>
</html>
|
그림 2는 'indian cooking'을 검색하여 생성된 출력 예제를 나타낸 것이다.
그림 2. 기본 Google Books API 검색 결과
목록 3에 하나의 추가 항목이 있는 것을 볼 수 있다. 즉, Google Book Search 웹 사이트의 도서 정보 페이지로 연결되는 링크를 리턴하는
Zend_Gdata_Books_VolumeEntry::getInfoLink() 메소드를 사용했다. 이 링크를 클릭하면 다른 것들 중에서도 자세한 도서 설명과 사용자
리뷰를 포함한 페이지로 리디렉션된다. 그림 3은 그런 페이지가 어떤 모습인지 보여주는 예제이다.
그림 3. 도서 세부사항 페이지
Google Book Search Data API로 전달되는 쿼리 문자열은 URL로 인코딩된 문자열이어야 한다는 점도 주목할 만하다. PHP의 urlencode()
메소드를 사용해도 이전의 두 목록에서 모두 같은 작업이 완료된다는 점을 알 수 있을 것이다.
목록 1에서 설명한 바와 같이, Google Book Search Data API에 의해 리턴되는 볼륨 피드에는 도서 제목, 저자 및 출판사 이름, ISBN 번호, 페이지 수, 주제 등과는 별개로 상당한 양의 정보가 포함된다. Zend_Gdata_Books에서는 이 모든 정보가 오브젝트 세트로 표시되고, PHP 스크립트의 범위 내에서 이 오브젝트 세트에 액세스하고 조작하여 더 많은 정보를 알려주는 검색 결과 페이지를 작성할 수 있다.
이에 대한 설명은 목록 4를 살펴보자.
목록 4: 도서 세부사항 검색
<?php
if (isset($_POST['submit'])) {
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";
try {
// perform login
$client = Zend_Gdata_ClientLogin::getHttpClient(
$user, $pass, 'print');
$client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
$books = new Zend_Gdata_Books($client);
// prepare and execute search query
$query = new Zend_Gdata_Books_VolumeQuery;
$query->setQuery(urlencode($_POST['q']));
$feed = $books->getVolumeFeed($query);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
}
?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Searching for book titles</title>
<style>
.entry {
height: 120px;
border-bottom: dashed silver 2px;
padding-top: 10px;
}
.thumbnail {
float: left;
border: solid black 2px;
padding: 2px;
margin-right: 10px;
}
.desc {
font-style: italic;
}
.small {
font-size: smaller;
}
</style>
</head>
<body>
<h2>Search</h2>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
Search for:
<input type="text" name="q" value="<?php echo isset($_POST['q']) ?
$_POST['q'] : ''; ?>" />
<input type="submit" name="submit" value="Go" />
</form>
<?php if (isset($feed)): ?>
<h2>Search results for '<?php echo $_POST['q']; ?>'</h2>
<div>
<?php echo $feed->totalResults; ?> result(s) found.
</div>
<div id="results">
<?php $x = 1; ?>
<?php foreach ($feed as $entry): ?>
<?php
//print_r($entry);
$book = new stdClass;
// get title
if (is_array($entry->getTitles())) {
foreach ($entry->getTitles() as $title) {
$book->titles[] = $title->getText();
}
}
// get authors
if (is_array($entry->getCreators())) {
foreach ($entry->getCreators() as $creator) {
$book->authors[] = $creator->getText();
}
}
// get publishers
if (is_array($entry->getPublishers())) {
foreach ($entry->getPublishers() as $publisher) {
$book->publishers[] = $publisher->getText();
}
}
// get publication date
if (is_array($entry->getDates())) {
$arr = $entry->getDates();
$book->pubdate = (is_object($arr[0])) ?
$arr[0]->getText() : 'Unspecified';
}
// get ISBN numbers
if (is_array($entry->getIdentifiers())) {
foreach ($entry->getIdentifiers() as $id) {
if (preg_match('/ISBN/', $id->getText())) {
$book->isbn[] = $id->getText();
}
}
}
// get first subject
if (is_array($entry->getSubjects())) {
$arr = $entry->getSubjects();
$book->subject = is_object($arr[0]) ?
$arr[0]->getText() : 'Unspecified';
}
// get first description
if (is_array($entry->getDescriptions())) {
$arr = $entry->getDescriptions();
$book->desc = is_object($arr[0]) ?
$arr[0]->getText() : 'No description available';
}
?>
<div class="entry">
<div class="thumbnail">
<img src="<?php echo ($entry->getThumbnailLink()) ?
$entry->getThumbnailLink()->getHref() : ''; ?>" />
</div>
<div class="data">
<?php echo $x; ?>. <?php echo ucwords(@implode(': ',
$book->titles)); ?><br/>
<?php echo @implode(', ', $book->authors); ?> |
<?php echo @implode(', ', $book->publishers); ?> |
<?php echo $book->subject; ?> |
<?php echo date('d M Y', strtotime($book->pubdate)); ?> <br/>
<span class="desc"><?php echo $book->desc; ?></span> <br/>
<span class="small"><?php echo @implode(', ', $book->isbn); ?> |
<a href="<?php echo $entry->getInfoLink()->getHref(); ?>">
More information</a>
</span>
</div>
</div>
<?php $x++; ?>
<?php endforeach; ?>
<?php endif; ?>
</body>
</html>
|
목록 4에서는 Zend_Gdata_Books_VolumeEntry 클래스의 새 메소드를 많이 사용했다. 다음은 그 중에서도 중요한 메소드를 간략히 정리한 것이다.
getDates()메소드는 도서 출판 날짜를 리턴한다.getCreators()메소드는 저자 이름을 리턴한다.getPublishers()메소드는 출판사 이름을 리턴한다.getSubjects()및getDescriptions()메소드는 도서의 주제와 설명을 리턴한다.getTitles()메소드는 도서 제목과 부제(있는 경우)를 리턴한다.getIdentifiers()메소드는 Google Book Search 레코드 ID뿐 아니라 도서의 ISBN-10 및 ISBN-13 번호 배열도 리턴한다.getThumbnailLink()메소드는 도서 표지의 축소판 그림 이미지로 연결되는 URL을 리턴한다.getVolumeId()메소드는 Google Book Search 서비스 내에서 도서의 고유 볼륨 ID를 리턴한다.
이 모든 메소드는 다양한 Dublin Core 메타데이터 요소에 해당하는 오브젝트 배열을 리턴한다. 그런 다음, 각 배열의 요소에 액세스하고 그 안에 있는 정보를 사용하여 검색 결과를 다시 구성하는 것은 개발자의 몫이다. 그림 4는 결과 예제를 나타낸 것이다.
그림 4. 표지 이미지와 추가적인 도서 데이터를 포함하도록 보강된 검색 결과를 포함한 Google Books API 검색의 결과
앞서 소개한 모든 예제에서 <openSearch:> 요소가 실제로는 훨씬 더 많은 수의 일치 항목을 표시하지만 검색 결과 피드에는 10개의 항목만 있다는 점을 알아차렸을 것이다. 이는 Google Book Search 피드가 기본적으로 피드당 10개의 일치 항목으로 제한되기 때문이다. 이것을 변경할 수 없는 것은 결코 아니다. REST 쿼리에 다음과 같은 매개변수를 적절히 추가하면 API 출력을 손쉽게 사용자 정의할 수 있다.
start-index매개변수, 피드에 있는 엔트리의 시작 오프셋을 지정한다.max-results매개변수, 피드에 있는 엔트리의 번호를 지정한다.min-viewability매개변수, 피드 항목에 부분 또는 전체 미리보기가 있는 도서만 포함할지 여부를 지정한다.
이런 매개변수 외에, 검색 쿼리에 추가 필터를 더해 제목, 저자, 출판사, 언어, 주제, 설명 또는 ISBN 번호를 기준으로 도서를 검색할 수도 있다. 목록 5는 그 방법을 나타낸 것이다.
목록 5: 저자, 제목 및 가독성을 기준으로 한 검색 결과 필터링
<?php
if (isset($_POST['submit'])) {
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";
try {
// perform login
$client = Zend_Gdata_ClientLogin::getHttpClient(
$user, $pass, 'print');
$client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
$books = new Zend_Gdata_Books($client);
// prepare and execute search query
$query = new Zend_Gdata_Books_VolumeQuery;
$queryStr = '';
if (!empty($_POST['title'])) {
$queryStr .= '+intitle:'.urlencode($_POST['title']);
}
if (!empty($_POST['author'])) {
$queryStr .= '+inauthor:'.urlencode($_POST['author']);
}
$query->setQuery($queryStr);
$query->setMinViewability($_POST['v']);
$query->setMaxResults(20);
$feed = $books->getVolumeFeed($query);
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
}
?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Searching for book titles</title>
<style>
.entry {
height: 120px;
border-bottom: dashed silver 2px;
padding-top: 10px;
}
.thumbnail {
float: left;
border: solid black 2px;
padding: 2px;
margin-right: 10px;
}
.desc {
font-style: italic;
}
.small {
font-size: smaller;
}
</style>
</head>
<body>
<h2>Search</h2>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
Title:
<input type="text" name="title" value="<?php echo isset($_POST['title']) ?
$_POST['title'] : ''; ?>" />
Author:
<input type="text" name="author" value="<?php echo isset($_POST['author']) ?
$_POST['author'] : ''; ?>" />
Viewability:
<select name="v">
<option value="none">Any</option>
<option value="partial_view">Partial</option>
<option value="full_view">Full</option>
</select>
<input type="submit" name="submit" value="Go" />
</form>
<?php if (isset($feed)): ?>
<h2>Search results for '<?php echo $query->getQuery(); ?>'
</h2>
<div>
<?php echo $feed->totalResults; ?> result(s) found.
</div>
<div id="results">
<?php $x = 1; ?>
<?php foreach ($feed as $entry): ?>
<?php
//print_r($entry);
$book = new stdClass;
// get title
if (is_array($entry->getTitles())) {
foreach ($entry->getTitles() as $title) {
$book->titles[] = $title->getText();
}
}
// get authors
if (is_array($entry->getCreators())) {
foreach ($entry->getCreators() as $creator) {
$book->authors[] = $creator->getText();
}
}
// get publishers
if (is_array($entry->getPublishers())) {
foreach ($entry->getPublishers() as $publisher) {
$book->publishers[] = $publisher->getText();
}
}
// get publication date
if (is_array($entry->getDates())) {
$arr = $entry->getDates();
$book->pubdate = (is_object($arr[0])) ?
$arr[0]->getText() : 'Unspecified';
}
// get ISBN numbers
if (is_array($entry->getIdentifiers())) {
foreach ($entry->getIdentifiers() as $id) {
if (preg_match('/ISBN/', $id->getText())) {
$book->isbn[] = $id->getText();
}
}
}
// get first subject
if (is_array($entry->getSubjects())) {
$arr = $entry->getSubjects();
$book->subject = is_object($arr[0]) ?
$arr[0]->getText() : 'Unspecified';
}
// get first description
if (is_array($entry->getDescriptions())) {
$arr = $entry->getDescriptions();
$book->desc = is_object($arr[0]) ?
$arr[0]->getText() : 'No description available';
}
?>
<div class="entry">
<div class="thumbnail">
<img src="<?php echo ($entry->getThumbnailLink()) ?
$entry->getThumbnailLink()->getHref() : ''; ?>" />
</div>
<div class="data">
<?php echo $x; ?>. <?php echo ucwords(@implode(': ',
$book->titles)); ?><br/>
<?php echo @implode(', ', $book->authors); ?> |
<?php echo @implode(', ', $book->publishers); ?> |
<?php echo $book->subject; ?> |
<?php echo date('d M Y', strtotime($book->pubdate)); ?> <br/>
<span class="desc"><?php echo $book->desc; ?></span>
<br/>
<span class="small"><?php echo @implode(', ', $book->isbn); ?> |
<a href="<?php echo $entry->getInfoLink()->getHref(); ?>">
More information</a>
</span>
</div>
</div>
<?php $x++; ?>
<?php endforeach; ?>
<?php endif; ?>
</body>
</html>
|
목록 4를 수정한 이 코드를 사용하면 제목, 저자 및 표시 유형에 대한 별개의 검색 필드가 표시된다. 수신된 입력 정보에 따라, 검색 쿼리는
적절한 한정자로 생성되어 Google Book Search API로 전송된다. min-viewability 및 max-results 입력
매개변수에 대한 오브젝트 지향 인터페이스를 제공하는 setMinViewability() 및 setMaxResults() 메소드에
주목하자.
그림 5와 그림 6은 목록 5의 출력을 나타낸 것으로, 전자는 제목 검색 결과를 표시하고 후자는 저자/제목 결합 검색 결과를 표시한다.
그림 5. 제목을 기준으로 필터링된 Google Books 검색 결과
그림 6. 저자 및 제목을 기준으로 필터링된 Google Books API 검색 결과
공개 검색을 허용하는 것 외에, Google Book Search를 통해 인증된 사용자는 자신의 가상 도서 라이브러리를 작성할 수도 있다. 이 "My Library" 기능을 사용하면 도서를 리뷰 및 레이블 지정하고 도서 콜렉션을 작성하여 다른 사용자가 공유할 수 있다. Google Book Search의 다른 기능들과 마찬가지로, 이 기능은 Google Book Search Data API를 통해 사용할 수 있다.
"My Library" 기능의 작동 방식을 보려면 Google 계정을 이용해 Google Book Search에 로그인하고 검색어를 입력한 후, 각각의 검색 결과 옆에 나타나는 "Add to my library"를 사용하여 가상 라이브러리 작성을 시작한다. 각 페이지의 오른쪽 위 모서리에 나타나는 "My Library" 링크를 사용하면 언제든 이 라이브러리에 액세스할 수 있다. 그림 7은 사용자 라이브러리의 예를 나타낸 것이다.
그림 7. Google Books 웹 사이트의 사용자 라이브러리
인증된 사용자의 라이브러리에 포함된 내용은 PHP 애플리케이션에서 구문 분석하기에 적합한 Atom 피드로 구할 수도 있다. 목록 1에 설명된
볼륨 피드와 마찬가지로, 이 피드에는 각각 사용자 라이브러리의 도서를 나타내는 <entry> 요소 세트가 포함된다. Zend_Gdata_Books
오브젝트의 getUserLibraryFeed() 메소드를 통해 PHP 오브젝트 세트로 이 피드를 구문 분석한 다음, 이를 사용하여 라이브러리의 HTML
보기를 생성할 수 있다. 목록 6에서는 다음을 보여준다.
목록 6: 사용자 라이브러리 내용 검색
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";
try {
// perform login
$client = Zend_Gdata_ClientLogin::getHttpClient(
$user, $pass, 'print');
$client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
$books = new Zend_Gdata_Books($client);
// get authenticated user's library feed
$feed = $books->getUserLibraryFeed();
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Displaying a user's library</title>
<style>
.entry {
height: 120px;
border-bottom: dashed silver 2px;
padding-top: 10px;
}
.thumbnail {
float: left;
border: solid black 2px;
padding: 2px;
margin-right: 10px;
}
.desc {
font-style: italic;
}
.small {
font-size: smaller;
}
</style>
</head>
<body>
<?php if (isset($feed)): ?>
<h2>My Library</h2>
<div>
<?php echo $feed->totalResults; ?> result(s) found.
</div>
<div id="results">
<?php $x = 1; ?>
<?php foreach ($feed as $entry): ?>
<?php
$book = new stdClass;
// get title
if (is_array($entry->getTitles())) {
foreach ($entry->getTitles() as $title) {
$book->titles[] = $title->getText();
}
}
// get authors
if (is_array($entry->getCreators())) {
foreach ($entry->getCreators() as $creator) {
$book->authors[] = $creator->getText();
}
}
// get publishers
if (is_array($entry->getPublishers())) {
foreach ($entry->getPublishers() as $publisher) {
$book->publishers[] = $publisher->getText();
}
}
// get publication date
if (is_array($entry->getDates())) {
$arr = $entry->getDates();
$book->pubdate = (is_object($arr[0])) ?
$arr[0]->getText() : 'Unspecified';
}
// get ISBN numbers
if (is_array($entry->getIdentifiers())) {
foreach ($entry->getIdentifiers() as $id) {
if (preg_match('/ISBN/', $id->getText())) {
$book->isbn[] = $id->getText();
}
}
}
// get first subject
if (is_array($entry->getSubjects())) {
$arr = $entry->getSubjects();
$book->subject = is_object($arr[0]) ?
$arr[0]->getText() : 'Unspecified';
}
// get first description
if (is_array($entry->getDescriptions())) {
$arr = $entry->getDescriptions();
$book->desc = is_object($arr[0]) ?
$arr[0]->getText() : 'No description available';
}
?>
<div class="entry">
<div class="thumbnail">
<img src="<?php echo ($entry->getThumbnailLink()) ?
$entry->getThumbnailLink()->getHref() : ''; ?>" />
</div>
<div class="data">
<?php echo $x; ?>. <?php echo ucwords(@implode(': ',
$book->titles)); ?><br/>
<?php echo @implode(', ', $book->authors); ?> |
<?php echo @implode(', ', $book->publishers); ?> |
<?php echo $book->subject; ?> |
<?php echo date('d M Y', strtotime($book->pubdate)); ?> <br/>
<span class="desc"><?php echo $book->desc; ?></span>
<br/>
<span class="small"><?php echo @implode(', ', $book->isbn); ?> |
Added to library on: <?php echo ($entry->getPublished()) ?
date('d M Y', strtotime($entry->getPublished()->getText())) : '';
?> |
<a href="<?php echo $entry->getInfoLink()->getHref(); ?>"
>More information</a>
</span>
</div>
</div>
<?php $x++; ?>
<?php endforeach; ?>
<?php endif; ?>
</body>
</html>
|
이 스크립트의 대부분은 본 기사의 이전 섹션에서 본 것이므로 친숙할 것이다. 이 스크립트는 Google Book Search 서비스에 대해 인증된 연결을 열고,
Zend_Gdata_Books 오브젝트를 초기화하고, getUserLibraryFeed() 메소드를 사용하여 사용자 라이브러리의 도서 목록을 포함한 피드를
검색한다. 이 피드는 PHP 오브젝트의 배열로 표시되고, 이제는 간단히 이 배열을 계속 반복하고 각 항목을 처리하고 적절한 HTML 마크업으로 결과를 표시할 수
있다.
그림 8은 결과의 예를 나타낸 것이다.
그림 8. 사용자 라이브러리 피드에 대한 Google Books API 요청의 결과
위와 같은 방법으로 사용자 라이브러리의 내용을 검색할 수 있지만, 사용자 라이브러리에 새 제목을 추가하는 문제는 어떨까? Google Book Search Data API에서는 단순히 도서의 고유 볼륨 ID를 포함한 XML 인코딩 방식의 <entry>를 사용자 라이브러리 피드에 게시하면 된다. 목록 7에 그런 POST 요청이 어떻게 보이는지 예제를 통해 나타내었다.
목록 7: 사용자 라이브러리에 도서를 추가하기 위한 POST 요청 예제
POST /books/feeds/users/me/collections/library/volumes HTTP/1.1 Host: books.google.com Connection: close User-Agent: MyCompany-MyApp-1.0 Zend_Framework_Gdata/1.9.0 authorization: GoogleLogin Content-Type: application/atom+xml Accept-encoding: identity Content-Length: 97 <atom:entry xmlns:atom="http://www.w3.org/2005/Atom"> <atom:id>BOOK_VOLUME_ID_HERE</atom:id> </atom:entry> |
Zend_Gdata_Books로 동일한 태스크를 완수하려면 새 Zend_Gdata_Books_VolumeEntry 오브젝트를 초기화하고 이를 볼륨 ID로 지정하여 insertVolume()
메소드로 사용자 라이브러리 피드에 연결한다. 목록 8은 그 코드를 나타낸 것이다.
목록 8: 사용자 라이브러리에 도서 추가
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";
try {
// perform login
$client = Zend_Gdata_ClientLogin::getHttpClient(
$user, $pass, 'print');
$books = new Zend_Gdata_Books($client);
// add book to user's library using volume ID
$id = 'BOOK_VOLUME_ID_HERE';
$entry = new Zend_Gdata_Books_VolumeEntry();
$entry->setId(new Zend_Gdata_App_Extension_Id($id));
$books->insertVolume(
$entry,
Zend_Gdata_Books::MY_LIBRARY_FEED_URI
);
// display success message
echo "Volume added successfully with ID: $id";
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
사용자가 라이브러리에 도서를 추가하도록 허용하는 것 외에, Google Book Search API에서는 도서에 리뷰와 레이블도 추가할 수 있게 허용한다. 리뷰와 레이블은
Google에서 "어노테이션"이라고 하는 것으로 저장되는데, 목록 1을 다시 보면 각각의 항목에 모두 어노테이션 URL이 포함된 것을 알 수
있다. 따라서 도서에 리뷰나 레이블을 추가하려면 해당 도서에 대한 XML 인코딩 방식의 <entry>를 작성하고,
리뷰 및/또는 레이블을 이 항목에 연결하고, 그 전체를 도서의 어노테이션 URL에 POST하기만 하면 된다.
목록 9는 그런 POST 요청이 어떤 모습으로 보일지 나타낸 예제이다.
목록 9: 도서 리뷰 추가를 위한 POST 요청 예제
POST /books/feeds/users/me/volumes HTTP/1.1 Host: www.google.com Connection: close User-Agent: MyCompany-MyApp-1.0 Zend_Framework_Gdata/1.9.0 authorization: GoogleLogin Accept-encoding: identity Content-Type: application/atom+xml Content-Length: 3291 <atom:entry xmlns:atom="http://www.w3.org/2005/Atom"> <openAccess xmlns="http://schemas.google.com/books/2008" value="http://schemas.google.com/books/2008#disabled"/> <atom:category term="http://schemas.google.com/books/2008#volume" scheme="http://schemas.google.com/g/2005#kind"/> <atom:id>http://www.google.com/books/feeds/volumes/BOOK_VOLUME_ID_HERE </atom:id> <atom:link href="http://bks7.books.google.com/books?id=BOOK_VOLUME_ID_HERE &printsec=frontcover&img=1&zoom=5&sig=ACfU3U0ayCK47roiq 7r_hf_Iy-tQ&source=gbs_gdata" rel="http://schemas.google.com/books/2008/thumbnail" type="image/x-unknown"/> <atom:link href="http://books.google.com/books?id=BOOK_VOLUME_ID_HERE &ie=ISO-8859-1&source=gbs_gdata" rel="http://schemas.google.com/books/2008/info" type="text/html"/> <atom:link href="http://www.google.com/books/feeds/users/me/volumes" rel="http://schemas.google.com/books/2008/annotation" type="application/atom+xml"/> <atom:link href="http://books.google.com/books?id=BOOK_VOLUME_ID_HERE &ie=ISO-8859-1" rel="alternate" type="text/html"/> <atom:link href="http://www.google.com/books/feeds/volumes/BOOK_VOLUME_ID_HERE" rel="self" type="application/atom+xml"/> <atom:title type="text">The Two Minute Rule</atom:title> <atom:updated>2009-12-28T10:15:44.000Z</atom:updated> <dc:creator xmlns:dc="http://purl.org/dc/terms">Robert Crais</dc:creator> <dc:date xmlns:dc="http://purl.org/dc/terms">2006-01-01</dc:date> <dc:format xmlns:dc="http://purl.org/dc/terms">Dimensions 10.8x17.2x3.0 cm </dc:format> <dc:format xmlns:dc="http://purl.org/dc/terms">465 pages</dc:format> <dc:format xmlns:dc="http://purl.org/dc/terms">book</dc:format> <dc:identifier xmlns:dc="http://purl.org/dc/terms">BOOK_VOLUME_ID_HERE </dc:identifier> <dc:identifier xmlns:dc="http://purl.org/dc/terms">ISBN:1111111111 </dc:identifier> <dc:identifier xmlns:dc="http://purl.org/dc/terms">ISBN:1111111111111 </dc:identifier> <dc:language xmlns:dc="http://purl.org/dc/terms">en</dc:language> <dc:publisher xmlns:dc="http://purl.org/dc/terms">Pocket Books </dc:publisher> <dc:subject xmlns:dc="http://purl.org/dc/terms">Fiction / Action & Adventure </dc:subject> <dc:subject xmlns:dc="http://purl.org/dc/terms">Fiction / Suspense </dc:subject> <dc:subject xmlns:dc="http://purl.org/dc/terms">Fiction / Action & Adventure </dc:subject> <dc:title xmlns:dc="http://purl.org/dc/terms">The Two Minute Rule </dc:title> <gbs:embeddability xmlns:gbs="http://schemas.google.com/books/2008" value="http://schemas.google.com/books/2008#not_embeddable"/> <gd:rating xmlns:gd="http://schemas.google.com/g/2005" min="1" max="5" average="4.20"/> <gbs:review xmlns:gbs="http://schemas.google.com/books/2008"> This book is amazing - v!</gbs:review> <gbs:viewability xmlns:gbs="http://schemas.google.com/books/2008" value="http://schemas.google.com/books/2008#view_no_pages"/> </atom:entry> |
목록 10은 대상 도서와 Zend_Gdata 라이브러리의 볼륨 ID를 사용하여 리뷰를 게시하는 예제이다.
목록 10: 도서 리뷰 추가
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";
try {
// perform login
$client = Zend_Gdata_ClientLogin::getHttpClient(
$user, $pass, 'print');
$books = new Zend_Gdata_Books($client);
// add review to book
$id = 'BOOK_VOLUME_ID_HERE';
$entry = $books->getVolumeEntry($id);
$review = new Zend_Gdata_Books_Extension_Review();
$review->setText("This book is amazing - v!");
$entry->setReview($review);
$books->insertVolume(
$entry,
$entry->getAnnotationLink()->getHref()
);
// display success message
echo "Review successfully added with ID: $id";
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
목록 10에서는 볼륨 ID를 사용하여 도서에 대한 현재 항목을 검색하는 데 getVolumeEntry() 메소드가 사용되고,
리뷰 텍스트가 포함된 Zend_Gdata_Books_Extension_Review 오브젝트가 setReview() 메소드를 통해 해당 항목에 연결된다. 그런 다음,
insertVolume() 메소드가 Google 서버에서 POST 요청 작성과 항목 업데이트를 처리한다.
비슷한 맥락에서, 사용자는 Google Book Search를 통해 설명 키워드로 각 도서에 태그 또는 "레이블"을 지정할 수 있다. 이것은 더 효율적이고 관련도가 높은 검색 결과를 낼 수 있는 유용한 커뮤니티 기능이다. 목록 11은 이들 레이블을 도서 항목에 프로그램을 통해 연결하는 방법을 보여주는 예제이다.
목록 11: 도서 레이블 추가
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";
try {
// perform login
$client = Zend_Gdata_ClientLogin::getHttpClient(
$user, $pass, 'print');
$books = new Zend_Gdata_Books($client);
// add labels to book
$id = 'BOOK_VOLUME_ID_HERE';
$entry = $books->getVolumeEntry($id);
$entry->setCategory(array(
new Zend_Gdata_App_Extension_Category('crime',
'http://schemas.google.com/books/2008/labels'),
new Zend_Gdata_App_Extension_Category('suspense',
'http://schemas.google.com/books/2008/labels'),
new Zend_Gdata_App_Extension_Category('elvis cole',
'http://schemas.google.com/books/2008/labels')
));
$books->insertVolume(
$entry,
$entry->getAnnotationLink()->getHref()
);
// display success message
echo "Labels successfully added for ID: $id";
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
|
목록 11에서는 각 레이블이 Zend_Gdata_App_Extension_Category 인스턴스로 표시되고, 이런 인스턴스는 setCategory()
메소드로 도서 항목에 연결된다. 그러면 insertVolume() 메소드가 호출되어 Google Book Search 데이터베이스의 도서 항목에 레이블을
추가한다.
Google Book Search에 추가되는 리뷰와 레이블은 비공개가 아니며, Google Books 웹 사이트나 공용 피드 URL을 통해 모든 인터넷 사용자가 볼 수 있다. 자세히 설명하자면, http://books.google.com/books/feeds/users/USER_ID/volumes라는 URL에서 사용자의 어노테이션 피드에 액세스하기만 하면 특정 사용자가 작성한 리뷰와 레이블을 전부 볼 수 있다. 이 URL의 USER_ID는 Google Book Search에서 사용자의 고유 ID 번호여야 하며, 그 사용자의 Google 계정 사용자 이름으로 하면 안 된다. 해당 사용자의 "My Library" URL 링크에서 그 사람의 Google Book Search ID 번호를 찾을 수 있다.
계속 발전되고 있는 중이지만, Google Book Search Data API는 개발자가 도서 검색 결과를 웹 애플리케이션에 통합할 수 있게 한다는 점에서 어마어마한 잠재력을 지니고 있다. 본 기사의 예제에서는 Google Book Search 볼륨 피드를 소개하고, 키워드, 저자 및 제목을 기준으로 비디오를 검색하는 방법을 보여주고, 검색 결과 피드에서 출판사 및 저자 정보, 축소판 그림 이미지 및 ISBN 번호를 포함한 도서 메타데이터를 추출하는 방법을 설명했다. 또한, Google Book Search의 커뮤니티 기능에 대한 특강도 제공하면서 프로그램으로 도서 항목에 리뷰와 레이블을 추가하는 방법도 설명했다.
이런 예제에서 입증되듯이, Google Book Search REST API는 새 웹 애플리케이션을 작성하는 문제에 관한 한 개발자에게 엄청난 유연성과 자유를 준다. 이 API는 도서 검색 데이터를 다른 웹 서비스의 데이터와 통합하려고 하거나 단순히 저자, 출판사 또는 소비자에 대한 사용자 정의 검색 인터페이스를 빌드하려는 경우에 매우 유용하다. 때때로 이 API로 여러 가지 시도를 해보면서 생각하는 바를 직접 실현해보는 것도 멋진 일일 것이다.
교육
- Developer's Guide 및
Reference Guide: Google Book Search API에 대해 자세히 알아보자.
- The Google Book Search blog: Google Books API에 대한 뉴스를 접할 수 있다.
- Google Account: 자신의 계정을 등록하여 시작할 수 있다.
- Google Book Search forum: Google Book
Search API 개발에 대한 토론 내용을 읽어보고 직접 참여도 해보자.
- Zend_Gdata_Books library: Zend Framework에
대한 자세한 정보와 Google Book Search Data API에서 Zend Framework를 사용하는 방법을 확인할 수 있다.
- Dublin Core Metadata Initiative: 다양한 목적과 비즈니스 모델을 뒷받침하는
상호 운용 가능한 메타데이터 표준에 대해 알아보자.
- 이 저자의 더 많은 기사(Vikram
Vaswani, developerWorks, 2007년 8월 현재): XML, 추가적인 Google API 및 기타 기술에 대한 기사를 읽을 수 있다.
- developerWorks의 XML 영역: XML 영역에서 기술 향상에 도움이 되는 참고자료를 얻을 수 있다.
- IBM XML 인증: XML 및 관련 기술에 대한 IBM 인증 개발자가 되는 방법을 찾아볼 수 있다.
- XML 기술 자료: developerWorks XML 영역에서 다양한 기술 관련 기사와 팁, 튜토리얼, 표준 및 IBM Redbook을 볼 수 있다.
- developerWorks 기술 행사 및 웹 캐스트: 이들 세션에 참가하여 최신 기술에 대한 정보를 얻을 수 있다.
- developerWorks
팟캐스트: 소프트웨어 개발자의 흥미로운 인터뷰와 토론을 확인할 수 있다.
제품 및 기술 얻기
- The Zend Gdata Client Library: PHP 5
애플리케이션에서 Google의 Data API에 액세스하기 위해 필요한 모든 것을 다운로드하고 얻을 수 있다.
- IBM 제품 평가
버전: 이 버전을 다운로드하거나 IBM SOA Sandbox에서
온라인 평가판을 탐색하여 DB2®, Lotus®, Rational®, Tivoli® 및 WebSphere®의 애플리케이션 개발 도구와 미들웨어 제품에서
실습을 해보자.
토론
- XML 영역 토론 포럼: 여러 XML 관련 토론에 참여해 볼 수 있다.
- developerWorks
포럼 & 블로그: 이러한 블로그를 읽어보고 참여할 수 있다.