2009년 2월
소개
"Ruby는 클라이언트 라이브러리 목록에서 어디에 있나요?"
동료 개발자인 제이피 피셔는 루비 온 레일(RoR)의 지속적인 인기에 힘입어 열정적인 깊이의 Ruby 유틸리티 라이브러리를 구축했습니다. 전체 클라이언트 라이브러리는 아니지만 인증 및 기본 XML 조작과 같은 기본 사항을 처리합니다. 또한 REXML 모듈 및 XPath를 사용하여 Atom 피드로 직접 작업해야 합니다.
대상
이 도움말은 Ruby를 사용해 Google Data API에 액세스하는 데 관심이 있는 개발자를 대상으로 합니다. 독자가 Ruby 프로그래밍 언어와 Rust 웹 개발 프레임워크를 잘 알고 있다고 가정합니다. 대부분의 샘플에서 Documents List API에 중점을 두지만 모든 Data API에 동일한 개념을 적용할 수 있습니다.
시작하기
요구사항
Google 데이터 Ruby 유틸리티 라이브러리 설치
라이브러리를 얻으려면 프로젝트 호스팅에서 직접 라이브러리 소스를 다운로드하거나 gem을 설치하면 됩니다.
sudo gem install gdata
도움말: gem list --local
을 실행하여 보석이 제대로 설치되었는지 확인하세요.
인증
ClientLogin
ClientLogin을 사용하면 애플리케이션이 사용자의 Google 또는 G Suite 계정에 프로그래매틱 방식으로 로그인할 수 있습니다. 사용자의 인증 정보가 확인되면 Google에서 인증 토큰을 발급하여 후속 API 요청에서 참조합니다. 토큰은 설정된 Google 서비스 기간으로 정의된 기간 동안 유효합니다. 보안상의 이유로 그리고 최상의 사용자 환경을 제공하려면 설치된 데스크톱 애플리케이션을 개발할 때만 ClientLogin을 사용해야 합니다. 웹 애플리케이션의 경우 AuthSub 또는 OAuth를 사용하는 것이 좋습니다.
Ruby 라이브러리에는 각 API의 클라이언트 클래스가 있습니다. 예를 들어 다음 코드 스니펫을 사용하여 user@gmail.com
를 Documents List Data API에 로그인합니다.
client = GData::Client::DocList.new client.clientlogin('user@gmail.com', 'pa$$word')
The YouTube Data API would be:
client = GData::Client::YouTube.new client.clientlogin('user@gmail.com', 'pa$$word')
구현된 서비스 클래스의 전체 목록을 참고하세요.
서비스에 클라이언트 클래스가 없으면 GData::Client::Base
클래스를 사용합니다.
예를 들어 다음 코드는 사용자가 G Suite 계정으로 로그인하도록 강제합니다.
client_login_handler = GData::Auth::ClientLogin
.new('writely', :account_type => 'HOSTED')
token = client_login_handler.get_token('user@example.com', 'pa$$word', 'google-RailsArticleSample-v1')
client = GData::Client::Base.new(:auth_handler => client_login_handler)
참고: 기본적으로 라이브러리는 accountType
에 HOSTED_OR_GOOGLE
를 사용합니다. 가능한 값은 HOSTED_OR_GOOGLE
, HOSTED
, GOOGLE
입니다.
ClientLogin 사용의 단점 중 하나는 로그인 시도에 실패할 경우 애플리케이션에 보안문자를 전송할 수 있다는 것입니다. 이 경우 추가 매개변수를 사용하여 clientlogin()
메서드를 호출하여 오류를 처리할 수 있습니다. client.clientlogin(username, password, captcha_token, captcha_answer)
보안문자 처리에 관한 자세한 내용은 설치된 애플리케이션 인증 문서를 참고하세요.
AuthSub
AuthSubRequest URL 생성
scope = 'http://www.google.com/calendar/feeds/' next_url = 'http://example.com/change/to/your/app' secure = false # set secure = true for signed AuthSub requests sess = true authsub_link = GData::Auth::AuthSub.get_url(next_url, scope, secure, sess)
이전 코드 블록은 authsub_link
에 다음 URL을 만듭니다.
https://www.google.com/accounts/AuthSubRequest?next=http%3A%2F%2Fexample.com%2Fchange%2Fto%2Fyour%2Fapp&scope=http%3A%2F%2Fwww.google.com%2Fcalendar%2Ffeeds%2F&session=1&secure=0
클라이언트 객체의 authsub_url
메서드를 사용할 수도 있습니다. 각 서비스 클래스에서 기본 authsub_scope
속성을 설정했으므로 직접 지정할 필요가 없습니다.
client = GData::Client::DocList.new next_url = 'http://example.com/change/to/your/app' secure = false # set secure = true for signed AuthSub requests sess = true domain = 'example.com' # force users to login to a G Suite hosted domain authsub_link = client.authsub_url(next_url, secure, sess, domain)
이전 코드 블록은 다음 URL을 만듭니다.
https://www.google.com/accounts/AuthSubRequest?next=http%3A%2F%2Fexample.com%2Fchange%2Fto%2Fyour%2Fapp&scope=http%3A%2F%2Fdocs.google.com%2Ffeeds%2F&session=1&secure=0&hd=example.com
일회용 토큰을 세션 토큰으로 업그레이드
사용자가 데이터에 대한 액세스 권한을 부여하면 AuthSub에서 사용자를 http://example.com/change/to/your/app?token=SINGLE_USE_TOKEN
으로 다시 리디렉션합니다. URL은 일회용 토큰이 쿼리 매개변수로 추가된 next_url
일 뿐입니다.
그런 다음 일회용 토큰을 장기 세션 토큰으로 교환합니다.
client.authsub_token = params[:token] # extract the single-use token from the URL query params session[:token] = client.auth_handler.upgrade() client.authsub_token = session[:token] if session[:token]
보안 AuthSub는 매우 유사합니다. 유일하게 추가되는 방법은 토큰을 업그레이드하기 전에 비공개 키를 설정하는 것입니다.
PRIVATE_KEY = '/path/to/private_key.pem' client.authsub_token = params[:token] client.authsub_private_key = PRIVATE_KEY session[:token] = client.auth_handler.upgrade() client.authsub_token = session[:token] if session[:token]
참고: 보안 토큰을 사용하려면 일회용 토큰을 요청할 때 secure=true
를 설정해야 합니다. 위의 AuthSubRequest URL 생성을 참조하세요.
토큰 관리
AuthSub는 토큰 관리를 위한 두 가지 추가 핸들러, AuthSubTokenInfo 및 AuthSubDismissToken을 제공합니다. AuthSubTokenInfo
는 토큰의 유효성을 확인하는 데 유용합니다. AuthSubRevokeToken
를 사용하면 사용자가 데이터 액세스를 중단할 수 있습니다. 앱에서는 권장사항으로 AuthSubRevokeToken
를 사용해야 합니다. 두 가지 방법 모두 Ruby 라이브러리에서 지원됩니다.
토큰의 메타데이터를 쿼리하려면 다음 안내를 따르세요.
client.auth_handler.info
세션 토큰을 취소하려면 다음 안내를 따르세요.
client.auth_handler.revoke
AuthSub에 대한 자세한 내용은 웹 애플리케이션용 AuthSub 인증 문서를 참조하세요.
OAuth
이 도움말을 작성하는 시점에서는 OAuth가 GData::Auth
모듈에 추가되지 않았습니다.
유틸리티 라이브러리에서 OAuth를 사용하는 것은 과제 OAuth-plugin 또는 Ruby OAuth gem을 사용할 때 비교적 간단합니다. 두 경우 모두 GData::HTTP::Request
객체를 만들고 각 라이브러리에서 생성된 Authorization
헤더를 전달하는 것이 좋습니다.
피드 액세스
GET (데이터 가져오기)
클라이언트 객체를 설정했으면 get()
메서드를 사용하여 Google 데이터 피드를 쿼리합니다. XPath는 특정 Atom 요소를 검색하는 데 사용할 수 있습니다. 다음은 사용자의 Google 문서를 가져오는 예입니다.
feed = client.get('http://docs.google.com/feeds/documents/private/full').to_xml feed.elements.each('entry') do |entry| puts 'title: ' + entry.elements['title'].text puts 'type: ' + entry.elements['category'].attribute('label').value puts 'updated: ' + entry.elements['updated'].text puts 'id: ' + entry.elements['id'].text # Extract the href value from each <atom:link> links = {} entry.elements.each('link') do |link| links[link.attribute('rel').value] = link.attribute('href').value end puts links.to_s end
POST (새 데이터 만들기)
클라이언트의 post()
메서드를 사용하여 서버에 새 데이터를 만듭니다. 다음 예에서는 new_writer@example.com
를 ID가 doc_id
인 문서에 공동작업자로 추가합니다.
# Return documents the authenticated user owns feed = client.get('http://docs.google.com/feeds/documents/private/full/-/mine').to_xml entry = feed.elements['entry'] # first <atom:entry> acl_entry = <<-EOF <entry xmlns="http://www.w3.org/2005/Atom" xmlns:gAcl='http://schemas.google.com/acl/2007'> <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule'/> <gAcl:role value='writer'/> <gAcl:scope type='user' value='new_writer@example.com'/> </entry> EOF # Regex the document id out from the full <atom:id>. # http://docs.google.com/feeds/documents/private/full/document%3Adfrk14g25fdsdwf -> document%3Adfrk14g25fdsdwf doc_id = entry.elements['id'].text[/full\/(.*%3[aA].*)$/, 1] response = client.post("http://docs.google.com/feeds/acl/private/full/#{doc_id}", acl_entry)
PUT (데이터 업데이트)
서버의 데이터를 업데이트하려면 클라이언트의 put()
메서드를 사용합니다. 다음 예시는 문서 제목을 업데이트합니다.
여기서는 이전 쿼리의 피드가 있다고 가정합니다.
entry = feed.elements['entry'] # first <atom:entry> # Update the document's title entry.elements['title'].text = 'Updated title' entry.add_namespace('http://www.w3.org/2005/Atom') entry.add_namespace('gd','http://schemas.google.com/g/2005') edit_uri = entry.elements["link[@rel='edit']"].attributes['href'] response = client.put(edit_uri, entry.to_s)
삭제
<atom:entry> 또는 기타 데이터를 서버에서 삭제하려면 delete()
메서드를 사용합니다.
다음 예시에서는 문서를 삭제합니다. 이 코드에는 이전 쿼리의 문서 항목이 있다고 가정합니다.
entry = feed.elements['entry'] # first <atom:entry> edit_uri = entry.elements["link[@rel='edit']"].attributes['href'] client.headers['If-Match'] = entry.attribute('etag').value # make sure we don't nuke another client's updates client.delete(edit_uri)
새 레일 애플리케이션 만들기
일반적으로 새 레일 앱을 만드는 첫 번째 연습에서는 Scaffold 생성기를 실행하여 MVC 파일을 만듭니다.
그런 다음 rake db:migrate
를 실행하여 데이터베이스 테이블을 설정합니다. 하지만 애플리케이션에서 Google Documents List API를 쿼리하기 때문에 일반 스캐폴딩 또는 데이터베이스가 거의 필요하지 않습니다. 대신 새 애플리케이션과 간단한 컨트롤러를 만듭니다.
rails doclist cd doclist ruby script/generate controller doclist
config/environment.rb
를 다음과 같이 변경합니다.
config.frameworks -= [ :active_record, :active_resource, :action_mailer ] config.gem 'gdata', :lib => 'gdata'
첫 번째 줄은 애플리케이션에서 ActiveRecord
를 연결 해제합니다.
두 번째 줄은 시작 시 gdata
gem을 로드합니다.
마지막으로 기본 경로('/
')를 DoclistController
의 documents
작업에 연결하기로 했습니다.
config/routes.rb
에 다음 줄을 추가합니다.
map.root :controller => 'doclist', :action => 'all'
컨트롤러 시작
스캐폴딩을 생성하지 않았으므로 app/controllers/doclist_controller.rb
의 DoclistController
에 'all
'라는 작업을 수동으로 추가합니다.
class DoclistController < ApplicationController def all @foo = 'I pity the foo!' end end
그런 다음 app/views/doclist/
아래에 all.html.erb
를 만듭니다.
<%= @foo %>
웹 서버 실행 및 개발 시작
이제 ruby script/server
를 호출하여 기본 웹 서버를 시작할 수 있습니다.
문제가 없으면 브라우저에서 http://localhost:3000/
을 가리키면 'I pity the foo!
'이(가) 표시됩니다.
도움말: public/index.html
을 삭제하거나 이름을 바꿔야 합니다.
작업이 완료되면 DocList Manager 프로젝트의 핵심인 DoclistController
과 ApplicationController
를 확인해 보세요. 또한 Google 주소록 API 호출을 처리하는 ContactsController
도 살펴볼 수 있습니다.
마무리
Google 데이터 레일 앱을 만드는 데 가장 어려운 부분은 레일 구성입니다. 하지만 1초는 애플리케이션을 배포하는 것입니다. 이를 위해 Apache용 mod_rails를 사용하는 것이 좋습니다. 설정, 설치, 실행도 매우 쉽습니다. 이제 바로 사용할 수 있습니다.
자료
- Google Data API 목록
- Google 데이터 Ruby 유틸리티 라이브러리 프로젝트 페이지
- 문서: Google Data API와 함께 Ruby 사용
- Ruby 다운로드
- RubyGems 및 레일 다운로드
부록
예
DocList Manager는 이 문서에서 다루는 주제를 보여주는 전체 Ruby on 레일 샘플입니다. 전체 소스 코드는 프로젝트 호스팅에서 제공됩니다.