2008년 10월
소개
잠재고객
이 도움말에서는 Blogger 가젯을 만드는 방법을 안내합니다. Google Data API 및 JavaScript 클라이언트 라이브러리에 대해 잘 알고 있다고 가정합니다. 또한 JavaScript에 능숙하고 gadgets.* API.
이 예에서는 가젯에서 외부 라이브러리를 성공적으로 사용하는 방법도 보여줍니다. jQuery (주로 UI 효과용)와 훌륭한 WYSIWYG 서식 있는 텍스트 편집기 플러그인인 TinyMCE를 사용했습니다.
동기
Google 데이터 API 중 하나와 함께 JSON을 사용하는 가젯을 만드는 데는 JavaScript가 거의 필요하지 않습니다. 이러한 가젯의 가장 큰 문제점은 데이터가 공개되어 읽기 전용이라는 것입니다. 더 흥미로운 가젯을 빌드하려면 사용자의 비공개 데이터 (인증이 필요한 항목)에 액세스해야 합니다. 지금까지 Google 계정 API를 활용할 수 있는 좋은 방법이 없었습니다. AuthSub에는 브라우저 리디렉션이 필요하고 ClientLogin은 클라이언트 측에서 사용자의 인증 정보를 노출합니다. type="url"
가젯을 해킹하는 것도 불편했습니다.
OAuth 프록시를 입력합니다.
OAuth 프록시
OAuth는 사용자가 다른 웹사이트나 가젯과 비공개 데이터를 공유할 수 있도록 지원하는 인증 표준입니다. OAuth 사양에 따라 모든 데이터 요청은 디지털 서명되어야 합니다. 이는 보안에 유용하지만 JavaScript 가젯의 경우 비공개 키를 관리하고 디지털 서명을 만드는 것은 안전하지 않습니다. 교차 도메인 문제라는 복잡한 요소도 추가됩니다.
다행히도 이러한 문제는 OAuth 프록시라는 가젯 플랫폼의 기능을 활용하여 해결할 수 있습니다. OAuth 프록시는 가젯 개발자가 더 쉽게 작업할 수 있도록 설계되었습니다. OAuth의 인증 세부정보를 대부분 숨기고 사용자를 대신하여 많은 작업을 처리합니다. 프록시는 가젯을 대신하여 데이터 요청에 서명하므로 비공개 키를 관리하거나 요청 서명에 대해 걱정할 필요가 없습니다. 잘 작동합니다.
OAuth 프록시는 가젯 사양의 구현인 Shindig라는 오픈소스 프로젝트를 기반으로 합니다.
참고: OAuth 프록시는 gadgets.*
API를 사용하고 OpenSocial 컨테이너에서 실행되는 가젯에만 지원됩니다.
레거시 가젯 API에서는 지원되지 않습니다.
시작하기
이 튜토리얼의 나머지 부분에서는 사용자의 Blogger 데이터에 액세스하는 가젯을 만드는 데 중점을 둡니다. 인증 (OAuth 프록시 사용), JavaScript 클라이언트 라이브러리 사용, 마지막으로 Blogger에 항목 게시를 살펴봅니다.
인증
먼저, 가젯이 OAuth를 사용하도록 알려야 합니다. 이렇게 하려면 가젯의 <ModulePrefs>
섹션에 <OAuth>
요소를 추가합니다.
<ModulePrefs> ... <OAuth> <Service name="google"> <Access url="https://www.google.com/accounts/OAuthGetAccessToken" method="GET" /> <Request url="https://www.google.com/accounts/OAuthGetRequestToken?scope=http://www.blogger.com/feeds/" method="GET" /> <Authorization url="https://www.google.com/accounts/OAuthAuthorizeToken? oauth_callback=http://oauth.gmodules.com/gadgets/oauthcallback" /> </Service> </OAuth> ... </ModulePrefs>
<Service>
요소의 세 가지 URL 엔드포인트는 Google의 OAuth 토큰 엔드포인트에 해당합니다. 다음은 쿼리 매개변수에 대한 설명입니다.
scope
이 매개변수는 요청 URL에 필요합니다. 가젯은 이 매개변수에 사용된
scope
의 데이터에만 액세스할 수 있습니다. 이 예에서 가젯은 Blogger에 액세스합니다. 가젯에서 두 개 이상의 Google Data API에 액세스하려면 추가scope
를%20
와 연결하세요. 예를 들어 캘린더와 블로거에 모두 액세스하려면 범위를http://www.blogger.com/feeds/%20http://www.google.com/calendar/feeds/
로 설정합니다.oauth_callback
이 매개변수는 승인 URL에서 선택사항입니다. 사용자가 데이터 액세스를 승인하면 OAuth 승인 페이지가 이 URL로 리디렉션됩니다. 이 매개변수를 생략하거나, 자체 '승인된 페이지'로 설정하거나,
http://oauth.gmodules.com/gadgets/oauthcallback
를 사용하는 것이 좋습니다. 후자는 사용자가 가젯을 처음 설치할 때 최상의 사용자 환경을 제공합니다. 이 페이지에서는 팝업 창을 자동으로 닫는 JavaScript 스니펫을 제공합니다.
이제 OAuth를 사용하는 가젯이 있으므로 사용자가 데이터에 대한 액세스를 승인해야 합니다. 인증 흐름은 다음과 같습니다.
- 가젯이 처음 로드되고 사용자의 블로거 데이터에 액세스하려고 시도합니다.
- 사용자가 가젯에 대한 액세스 권한을 부여하지 않아 요청이 실패합니다. 다행히도 응답에서 반환된 객체에는 사용자를 로그인으로 안내할 URL (
response.oauthApprovalUrl
)이 포함되어 있습니다. 가젯은 'Blogger에 로그인'을 표시하고 href를oauthApprovalUrl
값으로 설정합니다. - 그런 다음 사용자가 'Blogger에 로그인'을 클릭하면 OAuth 승인 페이지가 별도의 창에서 열립니다. 가젯은 사용자가 '액세스 승인 완료' 링크를 클릭하여 승인 프로세스를 완료할 때까지 기다립니다.
- 팝업에서 사용자는 가젯에 대한 액세스 권한을 부여하거나 거부합니다. '액세스 권한 부여'를 클릭하면
http://oauth.gmodules.com/gadgets/oauthcallback
로 이동하고 창이 닫힙니다. - 가젯은 창이 닫힌 것을 인식하고 사용자의 데이터를 다시 요청하여 Blogger에 두 번째로 액세스하려고 시도합니다. 창이 닫히는 것을 감지하기 위해 팝업 핸들러를 사용했습니다. 이 코드를 사용하지 않으면 사용자가 '액세스 권한을 승인했습니다'를 수동으로 클릭할 수 있습니다.
- 이제 가젯에 일반 UI가 표시됩니다. 이 뷰는 인증 토큰이 IssuedAuthSubTokens에서 취소되지 않는 한 유지됩니다.
위 단계에서 가젯에는 다음과 같은 세 가지 상태가 있습니다.
- 인증되지 않음 사용자가 승인 절차를 시작해야 합니다.
- 사용자가 데이터 액세스를 승인할 때까지 기다리는 중입니다.
- 인증됨 가젯이 정상적인 기능 상태를 표시합니다.
가젯에서 <div>
컨테이너를 사용하여 각 단계를 구분했습니다.
<Content type="html"> <![CDATA[ <!-- Normal state of the gadget. The user is authenticated --> <div id="main" style="display:none"> <form id="postForm" name="postForm" onsubmit="savePost(this); return false;"> <div id="messages" style="display: none"></div> <div class="selectFeed">Publish to: <select id="postFeedUri" name="postFeedUri" disabled="disabled"><option>loading blog list...</option></select> </div> <h4 style="clear:both">Title</h4> <input type="text" id="title" name="title"/> <h4>Content</h4> <textarea id="content" name="content" style="width:100%;height:200px;"></textarea> <h4 style="float:left;">Labels (comma separated)</h4><img src="blogger.png" style="float:right"/> <input type="text" id="categories" name="categories"/> <p><input type="submit" id="submitButton" value="Save"/> <input type="checkbox" id="draft" name="draft" checked="checked"/> <label for="draft">Draft?</label></p> </form> </div> <div id="approval" style="display: none"> <a href="#" id="personalize">Sign in to Blogger</a> </div> <div id="waiting" style="display: none"> <a href="#" id="approvalLink">I've approved access</a> </di <!-- An errors section is not necessary but great to have --> <div id="errors" style="display: none"></div> <!-- Also not necessary, but great for informing users --> <div id="loading"> <h3>Loading...</h3> <p><img src="ajax-loader.gif"></p> </div> ]]> </Content>
각 <div>
는 showOnly()
를 사용하여 단독으로 표시됩니다. 이 함수에 관한 자세한 내용은 전체 예시 가젯을 참고하세요.
JavaScript 클라이언트 라이브러리 사용
OpenSocial에서 원격 콘텐츠를 가져오려면 gadgets.*
API를 사용하여 gadgets.io.makeRequest
메서드를 호출합니다.
하지만 Google 데이터 가젯을 빌드하므로 gadgets.io.*
API를 건드릴 필요는 없습니다. 대신 각 Google 데이터 서비스에 요청을 보내는 특수 메서드가 있는 JavaScript 클라이언트 라이브러리를 활용하세요.
참고: 이 도움말을 작성하는 시점에 JavaScript 라이브러리는 Blogger, Calendar, Contacts, Finance, Google Base만 지원합니다. 다른 API 중 하나를 사용하려면 라이브러리 없이 gadgets.io.makeRequest
를 사용하세요.
라이브러리 로드
JavaScript 라이브러리를 로드하려면 <Content>
섹션에 공통 로더를 포함하고 가젯이 초기화되면 라이브러리를 가져옵니다. gadgets.util.registerOnLoadHandler()
에 콜백을 제공하면 가젯이 준비되는 시점을 파악하는 데 도움이 됩니다.
<Content type="html"> <![CDATA[ ... <script src="https://www.google.com/jsapi"></script> <script type="text/javascript"> var blogger = null; // make our service object global for later // Load the JS library and try to fetch data once it's ready function initGadget() { google.load('gdata', '1.x', {packages: ['blogger']}); // Save overhead, only load the Blogger service google.setOnLoadCallback(function () { blogger = new google.gdata.blogger.BloggerService('google-BloggerGadget-v1.0'); blogger.useOAuth('google'); fetchData(); }); } gadgets.util.registerOnLoadHandler(initGadget); </script> ... ]]> </Content>
blogger.useOAuth('google')
호출은 라이브러리에 일반 인증 방법인 AuthSubJS 대신 OAuth 프록시를 사용하도록 지시합니다.
마지막으로 가젯은 fetchData()
를 호출하여 사용자의 블로거 데이터를 가져오려고 시도합니다. 이 메서드는 아래에 정의되어 있습니다.
데이터를 가져오는 중입니다.
이제 모든 것이 설정되었으므로 실제로 Blogger에 데이터를 GET
하거나 POST
하는 방법은 무엇일까요?
OpenSocial의 일반적인 패러다임은 가젯에서 fetchData()
라는 함수를 정의하는 것입니다. 이 메서드는 일반적으로 인증의 여러 단계를 처리하고 gadgets.io.makeRequest
를 사용하여 데이터를 가져옵니다. JavaScript 클라이언트 라이브러리를 사용하므로 gadgets.io.makeRequest
가 blogger.getBlogFeed()
호출로 대체됩니다.
function fetchData() { jQuery('#errors').hide(); var callback = function(response) { if (response.oauthApprovalUrl) { // You can set the sign in link directly: // jQuery('#personalize').get(0).href = response.oauthApprovalUrl // OR use the popup.js handler var popup = shindig.oauth.popup({ destination: response.oauthApprovalUrl, windowOptions: 'height=600,width=800', onOpen: function() { showOnly('waiting'); }, onClose: function() { showOnly('loading'); fetchData(); } }); jQuery('#personalize').get(0).onclick = popup.createOpenerOnClick(); jQuery('#approvalLink').get(0).onclick = popup.createApprovedOnClick(); showOnly('approval'); } else if (response.feed) { showResults(response); showOnly('main'); } else { jQuery('#errors').html('Something went wrong').fadeIn(); showOnly('errors'); } }; blogger.getBlogFeed('http://www.blogger.com/feeds/default/blogs', callback, callback); }
이 함수가 두 번째로 호출되면 response.feed
에 데이터가 포함됩니다.
참고: getBlogFeed()
는 콜백과 오류 핸들러에 동일한 함수를 사용합니다.
Blogger에 항목 게시
마지막 단계는 블로그에 새 항목을 게시하는 것입니다. 아래 코드는 사용자가 '저장' 버튼을 클릭할 때 발생하는 상황을 보여줍니다.
function savePost(form) { jQuery('#messages').fadeOut(); jQuery('#submitButton').val('Publishing...').attr('disabled', 'disabled'); // trim whitespace from the input tags var input = form.categories.value; var categories = jQuery.trim(input) != '' ? input.split(',') : []; jQuery.each(categories, function(i, value) { var label = jQuery.trim(value); categories[i] = { scheme: 'http://www.blogger.com/atom/ns#', term: label }; }); // construct the blog post entry var newEntry = new google.gdata.blogger.BlogPostEntry({ title: { type: 'text', text: form.title.value }, content: { type: 'text', text: form.content.value }, categories: categories }); // publish as draft? var isDraft = form.draft.checked; if (isDraft) { newEntry.setControl({draft: {value: google.gdata.Draft.VALUE_YES}}); } // callback for insertEntry() var handleInsert = function(entryRoot) { var entry = entryRoot.entry; var str = isDraft ? '(as draft)' : '<a href="' + entry.getHtmlLink().getHref() + '" target="_blankt">View it</a>'; jQuery('#messages').html('Post published! ' + str).fadeIn(); jQuery('#submitButton').val('Save').removeAttr('disabled'); }; // error handler for insertEntry() var handleError = function(e) { var msg = e.cause ? e.cause.statusText + ': ' : ''; msg += e.message; alert('Error: ' + msg); }; blogger.insertEntry(form.postFeedUri.value, newEntry, handleInsert, handleError); }
결론
이제 Google Data API를 기반으로 가젯을 코딩할 수 있는 구성요소가 있습니다.
이 도움말을 통해 OAuth 프록시가 가젯 인증을 얼마나 간단하게 만드는지 이해하셨기를 바랍니다. 이 강력한 도구를 Google 데이터 JavaScript 클라이언트 라이브러리와 결합하면 흥미롭고, 대화형이며, 정교한 가젯을 쉽게 빌드할 수 있습니다.
이 도움말에 관해 궁금한 점이나 의견이 있다면 Google 계정 API 토론 포럼을 방문하세요.
리소스
- OAuth 가젯 작성 (전체 가젯 문서)
- Google Data API와 함께 OAuth 사용하기 (Google Data API와 함께 OAuth 사용에 관한 도움말)
- 웹 애플리케이션용 OAuth 인증 (전체 OAuth 문서)
- JavaScript 클라이언트 라이브러리
- Google Accounts API 토론 포럼