<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="http://rss.egloos.com/style/blog.xsl" type="text/xsl" media="screen"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
	<title>넷콩님의 이글루</title>
	<link>http://netkong.egloos.com</link>
	<description></description>
	<language>ko</language>
	<pubDate>Thu, 05 Jul 2007 09:11:50 GMT</pubDate>
	<generator>Egloos</generator>
	<image>
		<title>넷콩님의 이글루</title>
		<url>http://md.egloos.com/img/samplelogo2.gif</url>
		<link>http://netkong.egloos.com</link>
		<width>80</width>
		<height>80</height>
		<description></description>
	</image>
  	<item>
		<title><![CDATA[ Sun의 OpenID 서버 구조 ]]> </title>
		<link>http://netkong.egloos.com/376587</link>
		<guid>http://netkong.egloos.com/376587</guid>
		<description>
			<![CDATA[ 
  title; OpenID @ Work - Architecture<br />
link; <a href="http://blogs.sun.com/hubertsblog/entry/openid_sun_architecture">http://blogs.sun.com/hubertsblog/entry/openid_sun_architecture</a><br />
<br />
Sun이 자사의 직원에게 OpenID를 제공한다고 발표한지 한달정도 지난 것 같군요. 실제로 구축된 서비스에 대하여 Sun의 관계자가 포스팅하였습니다.<br />
<img src="http://blog.sun.com/hubertsblog/resource/12_Juin_2007_Architecture.jpg" align="bottom" border="0" hspace="0"><br />
1.Sun OpenID를 얻기 위해 등록 절차를 거칩니다. 이 단계에서 Sun의 직원이 맞는지를 OpenSSO를 통해 확인하게됩니다. 기존의 OpenID 제공자는 이런 절차를 요구하지&nbsp;않고, 아무에게나 ID를 발급하는 Open 정책을 사용합니다. 가장큰 차이점이죠.<br />
2. 사용자는 RP를 방문하고, 1단계에서 발급받는 자신의 OpenID URL를 제시합니다.<br />
3. RP는 해당 OpenID URL에 접근하여, 사용자의 OpenID&nbsp;서버 정보를 알아냅니다.<br />
4-5. RP는 OpenID 서버와 신뢰 관계를 형성하고, association key를 생성합니다.<br />
6. RP는 사용자를 OpenID 서버로 리다이렉트시켜, 사용자가 로그인 정보를 가져오도록 합니다. 이 단계에서 OpenSSO가 사용됩니다.<br />
<br />
사용자가 로그인 정보를 가져오면, RP는 이 정보를 검증하고 사용자를 로그인시켜 줍니다.<br />
<br />
굳이 의미를 두자면, 1단계 등록 과정을 거치는 것이 가장 큰 차이점이죠. Daum이나 AOL이나 기존에 사용자의 ID를 보유하고있는 OpenID 서버라면 이 절차를 사용하면 됩니다. 기존의 OpenID 구축 절차와 별다른 차이가 없죠.<br />
<br />
기본 절차는 OpenID 스펙과 동일합니다.			 ]]> 
		</description>
		<category>OpenID</category>

		<comments>http://netkong.egloos.com/376587#comments</comments>
		<pubDate>Thu, 05 Jul 2007 09:11:50 GMT</pubDate>
		<dc:creator>넷콩</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 다음, 오픈아이디 제공 계획 발표 ]]> </title>
		<link>http://netkong.egloos.com/376575</link>
		<guid>http://netkong.egloos.com/376575</guid>
		<description>
			<![CDATA[ 
  title; 다음, 오픈아이디 전격 지원<br />
link; <a href="http://openid.or.kr/44">http://openid.or.kr/44</a><br />
summary;Daum Corp, one of the major portal site in Korea, announced the plan toa OpenID provider in last week.&nbsp;For the&nbsp;37 million users, Daum willprovide very trustful authentication service as a major portal.Actually there are three OpenID providers in Korea, MyID, IDtail, andidpia. Unless they appeals their invaluable utilities to the users,Daum will dominate OpenID field in Korea.<br />
<br />
다음(Daum)이 OpenID Provider가 되겠다는 계획을 발표하였습니다. 이번 달 내에 작업을 완료할 예정이라고 하네요.<br />
<br />
지난달까지 전세계의 OpenID는 약 9천만 개였습니다. 이제 1억3천개에 육박하겠군요.<br />
<br />
<blockquote>업계 관계자는 “다음의 한메일 가입자만 해도 3700만명 이상”이라며 “대형 포털인만큼 인증서비스의 신뢰성이 매우 높을 것”이라고 말했다. <br />
<br />
다음 인증서비스를 계기로 오픈ID 지원 사이트도 늘어날 전망이다. 태터툴즈·오픈마루·스프링노트·더블트랙 미투데이·라이프팟·아이두·펌핏 등 10여곳의 블로그, 미니블로그 및 위키사이트 등이 오픈ID를 사용한 로그인을 지원한다.<br />
</blockquote><br />
지금까지는 MyID, IDtail, idpia라는 조그만(?) 업체들이 OpenID 시장을 키우고 있었는데, 이제 이 업체들은 Daum이라는 거대 포털과 경쟁해야 하는 입장이 되었군요.<br />
<br />
<blockquote>권오성 오픈마루 과장은 “오픈ID 사용자가 많지 않은 상태에서 다음이 이를 대부분 흡수할 가능성이 있지만 오픈ID 지원 웹사이트 증가의 계기가 될 것”이라고 말했다.</blockquote><br />
물론 OpenID라는 파이를 크게 만들었다는 점은 이들 업체들이 반길만한 내용이지만, 사용자에게 정말 유용할만한 기능을 제공해줄수 없다면 모두 Daum으로 이동할 것입니다. 신뢰성, 안정성, 편의성 등등... 현재는 Daum이 가지고 있는 크레딧이 너무나크네요.<br />
       <!--       <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"		    xmlns:dc="http://purl.org/dc/elements/1.1/"		    xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">       <rdf:Description	        rdf:about="http://ayo79.egloos.com/3227538"	        dc:identifier="http://ayo79.egloos.com/3227538"	        dc:title="다음, 오픈아이디 제공 계획 발표"	        trackback:ping="http://ayo79.egloos.com/tb/3227538"/>       </rdf:RDF>       --><div id="e4c_list" style="border: 1px dashed rgb(221, 221, 221); margin: 20px 0pt 5px; padding: 5px 15px; clear: both; text-align: left;"><p class="rtitle">이 글과 관련있는 글을 자동검색한 결과입니다 <strong><a href="http://ayo79.egloos.com/3227538#" onclick="open_e4c_help(event);return false;" id="e4c_qmark" style="position: relative;">[?]</a></strong></p><img src="http://app.egloos.com/stat/st_e.php?e=3&amp;b=ayo79&amp;s=3227538" border="0" height="1" width="1"><ul><li><a href="http://ayo79.egloos.com/3160236" onclick="e4c_count('http://ayo79.egloos.com/3160236');">OpenID 유감에 대하여..</a> by S_H_Kim</li><li><a href="http://ayo79.egloos.com/3211646" onclick="e4c_count('http://ayo79.egloos.com/3211646');">OpenID 1.1 스펙 한글판</a> by S_H_Kim</li><li><a href="http://ayo79.egloos.com/3161169" onclick="e4c_count('http://ayo79.egloos.com/3161169');">Half-OpenID; 신뢰를 고려한 OpenID</a> by S_H_Kim</li></ul><br />
각 업체별 입장을 순전히 제 개인적 추측(?) 으로 정리해 보면요...<br />
myID.net (MyID 아닙니다 ^^) 의경우에는 오픈마루의 주력 서비스는 아니구요, 오히려 오픈마루의 다른 서비스들이 오픈아이디 기반으로 갈 것 이때문에, 대중성있는사용자 기반을 끌어내는데 꽤 큰 공을 한 것이구요. idpia 의 경우 전형적인 보안솔루션 업체이므로, 오픈아이디 대중화를통해서 기업시장에서의 오픈아이디가 힘을 받으면, 기업전용 오픈아이디 솔루션쪽을 보실 것 같구요.<br />
 idtail 은 재미있게도, 신규 웹2.0 서비스을 하시려고 하면서도, 안철수 연구소 소속이라 양다리도 가능하실 듯. 암튼, 모두에게 득이 더 클 것으로 생각됩니당.<br />
<br />
/Kay님, 정리하자면 1차적인 목표는 내부의 수요를 충족시키기 위함이로군요. 엔터프라이즈용 OpenID 솔루션에 대한 수요는 저 또한 동감하는 바입니다. myID.net 측에도 관련 문의를 많이 받고 계시죠? ㅎㅎ<br />
</div>			 ]]> 
		</description>
		<category>OpenID</category>

		<comments>http://netkong.egloos.com/376575#comments</comments>
		<pubDate>Thu, 05 Jul 2007 09:08:12 GMT</pubDate>
		<dc:creator>넷콩</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 당신의 비밀번호 안녕하신가요? ]]> </title>
		<link>http://netkong.egloos.com/373193</link>
		<guid>http://netkong.egloos.com/373193</guid>
		<description>
			<![CDATA[ 
  <font class="b-title7">■ 인터넷 비밀번호 관리요령                                                     <br />
</font> <font class="b-title7">문자·숫자·특수문자 섞어 8자 이상 돼야                                         <br />
</font> <font class="b-title7">자동로그인·오픈ID 인증서비스 등 편리                                           <br />
</font> <br />
  <img src="http://www.busanilbo.com/img/sub/s2000_line42.gif" usemap="#FPMap0" border="0" width="530"> <map name="FPMap0"><area href="javascript:fontPlus();" shape="rect" coords="394, 7, 432, 28"><area href="javascript:fontMinus();" shape="rect" coords="433, 5, 479, 28"><area href="javascript:print_popup('http://news.busanilbo.com/cgi-bin/NEWS2000/print_elec?date=20070620&time=1021092839&sort=B')" shape="rect" coords="478, 7, 528, 27">    </map> <font class="s-pretxt1">최근 비밀번호가 노출돼 사생활 침해 등의 피해사례가 잇따르고 있다. 비밀번호를 노출할 경우 사생활침해는 물론 금전적인 손실까지 볼 수 있어 세심한 주의가 요망된다. 비밀번호 관리요령 등에 대해 알아본다.</font><p> <table style="border: 1px solid rgb(153, 153, 153);" align="right" border="0" cellpadding="10" cellspacing="0" width="100"> <tbody><tr><td><table border="0"> <tbody><tr><td> <img src="http://www.busanilbo.com/news2000/photo/2007/0620/10212001i1.jpg" border="0"> </td></tr>  <tr><td>  <br />
</td></tr> </tbody></table>     </td></tr></tbody></table>  <font class="b-txt2" id="articleBody">사례1:톱스타 보아의 미니홈피 정보를 빼낸 범인은 메일을 통해 보아에게 사생활 정보를 유포하겠다며 금품을 요구하다 폭력행위 및처벌에 관한 법률 위반 등의 혐의로 구속됐다. 싸이월드 측은 "경찰에 따르면 가수 보아의 미니홈피는 해킹이 아니라 비밀번호유추에 의한 범죄"라고 밝혔다. 싸이월드는 또 "타인이 생각해 낼 수 있는 쉬운 조합의 비밀번호는 유실될 가능성이 있다"고지적했다. <br />
<br />
이처럼 비밀번호가 노출돼 사생활 침해가 잇따르고 있다. 특히 이달초 금융감독원 분쟁조정위원회는 카드 절도범이 비밀번호를유추해 불법적으로 부정현금인출 때 '은행에 과실이 없다'는 결정을 내리기도해 비밀번호 관리의 중요성을 더했다. 비밀번호를 잘못관리하면 자칫 금전적인 피해도 입을 수 있고 어디 하소연할 곳도 없다. 이번 기회에 자신의 비밀번호를 점검해보자. <br />
<br />
보안전문가들은 해킹에 강한 비밀번호는 최소 8자리 이상, 15자리 이상이면 이상적이라고 입을 모은다. 또 문자와 숫자, 특수문자 등을 섞어 만들면 더욱 안전하다는 것.<br />
<br />
＃기억하기 좋고 해킹에 강해야<br />
<br />
사례2: A씨는 예전에 자주 방문하던 한 인터넷 사이트를 들어갈 일이 생겼다. 그런데 아이디와 비밀번호가 생각나지않는다. 자주 사용하는 아이디와 비밀번호들을 아무리 입력해 봐도 잘못된 비밀번호라는 메시지만 나온다. 어쩔 수 없이 비밀번호찾기 등을 누른다. <br />
<br />
누구나 흔히 겪을 수 있는 일이다. 부경대 김창수(전자컴퓨터정보통신공학부) 교수는 "비밀번호 만드는 공식 여러 개를조합해 사용하면 해킹이나 유추를 차단하고 기억하기도 좋다"고 설명한다. 김 교수의 노하우를 살짝 공개하면 △영어이름 △음력생년월일 △연구실 번호 △팝송가사 등을 섞어 비밀번호를 만들어 사용하고 분기별로 조합방법을 다르게 한다는 것. 또 수첩 등에'생일+연구실' 등으로 조합방식만 메모해 놓으면 나중에 기억하기도 좋고 유출될 위험도 적다는 설명이다. <br />
<br />
＃자동로그인 프로그램도 편리<br />
<br />
비밀번호를 잘 잊어버리거나 수많은 비밀번호를 관리해야 사람은 자동로그인 프로그램을 이용하면 편리하다.'알패스(altools.co.kr)'나 '이지패스(easypass.secutronix.com)' 같은 무료 소프트웨어도 나와있다. 알패스는 사용자가 미리 입력한 웹사이트의 로그인 정보를 저장하였다가 해당 웹사이트가 열리면 자동으로 주소를 감지하여아이디와 비밀번호를 입력해준다. 이 프로그램만 설치되어 있으면 회사나 집 등 장소에 상관없이 이용할 수 있다.<br />
<br />
또 한 곳에 자신의 대표 아이디와 비밀번호, 그리고 이메일 주소를 등록해 놓고, 이 대표아이디로 어디서든 로그인할 수있는 '오픈아이디' 인증서비스 도입도 늘고 있는 추세다. 현재 '마이아이디넷(myid.net)'과 안철수연구소의'아이디테일(idtail.com)', 이니텍의 '아이디피아(idpia.com)' 등이 서비스를 시작했다.<br />
<br />
 임원철기자  <a href="mailto:wclim@busanilbo.com">wclim@busanilbo.com</a> </font> </p>   <font color="#333333" size="2">  <img src="http://www.busanilbo.com/img/sub/p_logo.gif" border="0"> / 입력시간: 2007. 06.20. 09:28</font>			 ]]> 
		</description>
		<category>OpenID</category>

		<comments>http://netkong.egloos.com/373193#comments</comments>
		<pubDate>Wed, 04 Jul 2007 13:12:20 GMT</pubDate>
		<dc:creator>넷콩</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 우리나라 오픈ID 생태계 둘러보기 ]]> </title>
		<link>http://netkong.egloos.com/373177</link>
		<guid>http://netkong.egloos.com/373177</guid>
		<description>
			<![CDATA[ 
  <p align="justify"><font face="Arial" size="2">지난 1월 </font><font face="Arial" size="2"><a class="con_link" href="http://blog.openmaru.com/" target="_blank">엔씨소프트 오픈마루 스튜디오</a>에서 오픈ID&nbsp;인증 서비스&nbsp;<a class="con_link" href="http://blog.myid.net/2" target="_blank">마이ID넷</a>을 서비스를 선보이면서 주목을 받았던 <a class="con_link" href="http://openid.co.kr/" target="_blank">오픈ID</a>의 성장 속도가 매우 빠른 것 같다. </font><font face="Arial" size="2">오픈ID를 지원하는 인터넷 서비스들이 속속 나오고 있고&nbsp;오픈ID 인증&nbsp;사업에 출사표를 던진 곳도 벌써 3개에 이른다.<br />
<br />
쓸 수 있는 사이트가 늘다보니 그 효과도 점점 커지는 모양새다. 써본 사람 입장에서 말하자면 회원 가입 안해도 되니 이 얼마나 좋은가~ 하나의 ID만 있으면 여러 서비스에 로그인할 수 있는 상황이 현실화되가는 모습에&nbsp;그저 놀랄 따름이다.<br />
<font face="Arial" size="2"><br />
<a class="con_link" href="http://www.bloter.net/_news/8df42826b87d16f1" target="_blank"><font color="#0000ff">"오픈ID, 사용자 중심의 인터넷 기반 될 것"</font></a></font><br />
<br />
</font><font face="Arial" size="2">개인 블로그를 제외하면 오픈ID로 로그인할 수 있는 우리나라 인터넷 서비스는 오픈마루 <a class="con_link" href="http://www.springnote.com/ko/" target="_blank">스프링노트,</a> 더블트랙 <a class="con_link" href="http://me2day.net/" target="_blank">미투데이</a>, <a class="con_link" href="http://www.lifepod.co.kr/chapter1/" target="_blank">라이프팟</a>, <a class="con_link" href="http://www.idoo.net/?menu=" target="_blank">아이두</a>가 대표적이다.&nbsp;국내 오픈ID 적용 사이트 목록은 <a class="con_link" href="http://forum.openid.or.kr/?q=aggregator/sources/1" target="_blank">오픈ID커뮤니티</a>를 참고하면 된다.<br />
<br />
<img style="margin: 10px;" alt="" src="http://www.bloter.net/photo/2007/04/8df06aff450b42d2_l.jpg" align="bottom" border="0"><br />
<br />
스프링노트 화면이다. <font face="Arial" size="2">스프링노트는 온라인상에 내 정보를 기록하고 관리할 수 있는&nbsp; '인터넷 상의 내 노트'를 표방하고 있는데, 벌써 가입자수가 1만명을 넘었다고 한다.<br />
<br />
<img style="margin: 10px;" alt="" src="http://www.bloter.net/photo/2007/04/8df42df8cdd0195a_l.jpg" align="bottom" border="0"><br />
<br />
<br />
지난 3월 블로고스피어를 뜨겁게 달군 미투데이 역시 오픈ID를 이용할 수 있는 곳이다. 오픈ID와 자신의 비밀번호만 치면 바로 로그인이 가능하다. 라이프팟 등도 비슷한 과정을 거쳐 로그인할 수 있다.<br />
<br />
오픈ID를 적극 포용한 서비스들은 대부분 새롭게 등장한&nbsp;뉴페이스다.&nbsp;이를 감안하면 오픈ID는 앞으로도&nbsp;네이버, 다음, 싸이월드 등 기존 인터넷 서비스들보다는 신생 사이트들을 강하게 파고들지 않을까 싶다.&nbsp;안철수판 딕닷컴 <a class="con_link" href="http://www.pumfit.com/" target="_blank">펌핏</a>에도 곧&nbsp;오픈ID가 적용될 예정이다.&nbsp;<br />
<br />
앞으로&nbsp;블로고스피어에서 관심을 끄는 2~3개의 인터넷 서비스가 오픈ID를 추가로 지원할 경우 우리나라 오픈ID&nbsp;생태계는 성장에 한층&nbsp;탄력을 받을 것 같다. 조심스럽지만&nbsp;"기존 인터넷 업체들도 오픈ID를 지원해야 한다"는 여론이 확산될 것이란 예상까지 해보게 된다.<br />
<br />
</font>오픈ID 인증 서비스 사업에 뛰어드는 업체들도 늘고 있다. 오픈마루에 이어 안철수연구소, 이니텍 등 보안 업체들이 공식적으로 출사표를&nbsp;던졌다. 안연구소와 이니텍은 비슷한 시점에 각각 <a class="con_link" href="http://www.idtail.com/" target="_blank">ID테일</a>과 <a class="con_link" href="http://www.idpia.com/" target="_blank">아이디피아</a>란 오픈ID 인증 서비스를 내놓은 상황이다.<br />
<br />
<font face="Arial" size="2"><a class="con_link" href="http://www.bloter.net/_news/8df42d870479969e" target="_blank">안랩,'안철수판' 딕닷컴을 띄운 이유는?</a></font><br />
<br />
개인적으로 이들 업체들이 오픈ID 서비스로 어떤 비즈니스 모델을 만들어낼지 매우 궁금하다. 초기 시장인 만큼, 당분은 파이를 키우는 마음으로 선의의 경쟁을 펼치겠지만 저변이 확대되면 웃는자와 우는자는&nbsp;나눠질 수 밖에 없다. 판세가 정해지는데 있어 서비스 업체가 갖고 있는 신뢰는 최대 변수가 될 가능성이 높다. 요즘들어 부쩍 '신뢰'라는 말을 강조하는 안연구소의 행보가 예사롭지 않은 것도 바로 이 때문일까~<br />
<br />
<font face="Arial" size="2"><a class="con_link" href="http://delight.bloter.net/_news/8df42b8c50a54bff" target="_blank">안철수 전 사장이 하고싶은 일...</a></font></font></p>			 ]]> 
		</description>
		<category>OpenID</category>

		<comments>http://netkong.egloos.com/373177#comments</comments>
		<pubDate>Wed, 04 Jul 2007 13:05:44 GMT</pubDate>
		<dc:creator>넷콩</dc:creator>
	</item>
	<item>
		<title><![CDATA[ OPEN ID ]]> </title>
		<link>http://netkong.egloos.com/373174</link>
		<guid>http://netkong.egloos.com/373174</guid>
		<description>
			<![CDATA[ 
  <div class="xhtmlEditorBody"><p>&nbsp;1.오픈아이디는 어떻게 움직이나<br />
&nbsp; -http://enthusiasm.cozy.org/archives/2005/05/openid/<br />
&nbsp; -http://enthusiasm.cozy.org/archives/2005/05/openid-part-ii/<br />
&nbsp; -http://enthusiasm.cozy.org/archives/2005/05/openid-part-iii-pingpong/<br />
&nbsp; <a class="external" title="-http://enthusiasm.cozy.org/archives/2005/05/openid-part-iv-url-as-global-identifier/" href="-http://enthusiasm.cozy.org/archives/2005/05/openid-part-iv-url-as-global-identifier/">-http://enthusiasm.cozy.org/archives/2005/05/openid-part-iv-url-as-global-identifier/</a></p><p>&nbsp;</p><p><img alt="" src="http://enthusiasm.cozy.org/images/OpenIDPingPong.png"></p><p>&nbsp;</p><p>Here is the scenario in words.</p><pre>1. Alice visits Steve.<br />
2. Steve prompts Alice for her OpenID URL.<br />
3. Alice reveals here OpenID URL to Steve.<br />
4. Steve cleans up the OpenID URL Alice Revealed.<br />
5. Steve Fetchs the OpenID page Alice revealed from Bob.<br />
6. Bob normalizes the OpenID URL and redirects Steve.<br />
7. Steve fetchs the actual OpenID from Bob based on Alice<br />
   and Bob's input.<br />
8. Bob returns Alice's OpenID page.<br />
9. Steve extracts the OpenID service end point from that page.<br />
10. Steve requests an assertion from Victor, via Alice, to prove<br />
    that Alice controls the OpenID page she claims.<br />
11. Alice asks Victor for the assertion Steve wants.<br />
12. Victor checks that it's Alice who's asking.<br />
13. Victor, now working for Alice, checks that Alice has authorized telling Steve anything about her.<br />
14. Victor creates the assertion Steve needs, checking of course that Alice controls this OpenID url.<br />
15. Victor signs the assertion.<br />
16. Victor sends that assertion back to Alice.<br />
17. Alice sends the assertion back to Steve.<br />
18. Steve verifies the Victor's signature.<br />
19. Steve studies the assertion and acts approprately.<br />
</pre><p>&nbsp;</p><p>-기술지원:http://forum.openid.or.kr/</p><p>-한글개요:http://www.openid.or.kr/category/%EA%B3%B5%ED%86%B5%20%EB%8F%84%EC%9B%80%EB%A7%90 </p><p><br />
2.오픈아이디 적용 과정 &amp; 사례</p><p>-마이 아이디넷 <a class="external" title="블로그:http://blog.myid.net/" href="http://pepx.springnote.com/pages/%EB%B8%94%EB%A1%9C%EA%B7%B8:http://blog.myid.net/">블로그:http://blog.myid.net/</a></p><p>-유저가 내 블로그로 URL myid 사용하기 예-http://blog.myid.net/14</p><p>-개발자가 쓴 Best Practice - <a href="http://coolengineer.com/407">http://coolengineer.com/407</a> , <a href="http://forum.openid.or.kr/?q=node/13">http://forum.openid.or.kr/?q=node/13</a></p><p>3.오픈 아이디 쓸려면 절차</p><p>-Joint Singning <a class="external" title="Up:http://blog.myid.net/32" href="up:http://blog.myid.net/32">Up:http://blog.myid.net/32</a></p><p>-인증화면 권장 폼:http://www.openidenabled.com/openid/openid-login-box-css-class/</p></div>			 ]]> 
		</description>
		<category>OpenID</category>

		<comments>http://netkong.egloos.com/373174#comments</comments>
		<pubDate>Wed, 04 Jul 2007 13:04:59 GMT</pubDate>
		<dc:creator>넷콩</dc:creator>
	</item>
	<item>
		<title><![CDATA[ OpenID, 너무 좋아서 힘든 서비스 ]]> </title>
		<link>http://netkong.egloos.com/373164</link>
		<guid>http://netkong.egloos.com/373164</guid>
		<description>
			<![CDATA[ 
  비단 제레미 리프킨의 <a href="http://book.naver.com/bookdb/book_detail.php?bid=5002" target="_blank">'소유의 종말'</a>을 인용하지 않더라도 이미 우리가 살고 있는 세상이 '소유'의 시대를 넘어서 '접속'의 시대로 접어들고 있다는 것은 부정할 수 없는 사실입니다. 어쩌면 이미 접어들었다고 표현하는 것이 맞을지도 모르죠. 이러한 시대상 속에서 일상적으로 벌어지는 '접속'이라는 행위의 흐름을 한곳으로 모을 수 있다면 그 영향력이 얼마나 엄청날까요? 그런 철학을 가지고 있는 분야가 제가 생각하는 <a href="http://en.wikipedia.org/wiki/Identity_management" target="_blank">Identity Management</a> 분야입니다.<br />
<br />
Idenetity Management를 가능하게 하는 여러 기술중 가장 주목하고 싶은것은 <a href="http://openid.co.kr/" target="_blank">OpenID</a>입니다. 비록 타 기술에 비해 완성도나 난이도가 떨어지고 보안성이 취약하다고 하더라도 '열린 표준'이라는 컨셉을 생각할 때 범용화 될 수 있는 개연성이 가장 클 것 같습니다. '열린 표준'이 가지는 힘의 우위는 세상을 바꿔놓은 HTTP의 경우를 예로 드는 것으로 대신하겠습니다.<br />
<br />
국내에서도 최근 OpenID를 서비스하는 Provider들이 세 군데나 등장했습니다. NC 소프트의 지원을 받는 오픈마루에서 서비스하는 <a href="www.myid.net" target="_blank">MyID</a>, 안철수 연구소의 후원을 받는 고슴도치플러스에서 서비스하는 <a href="http://www.idtail.com/" target="_blank">IDTail</a>과 전통적으로 보안분야에서 비즈니스를 영위하고 있는 이니텍에서 서비스하는 <a href="http://www.idpia.com/" target="_blank">IDpia</a>가 그것입니다. 이와 같은 IDP(ID Provider)들의 등장은 시장이 존재한다는 의미로 받아들일 수 있으며 MS나 Sun과 같은 Global Company의 움직임을 보고 있노라면 이 시장이 매우 커질 가능성이 큰 것이 아닌가...라고 추측할 수 있습니다.<br />
<br />
서비스 측면에서 생각한다면 OpenID와 같은 서비스의 미래는 매우 밝아 보입니다. 만일 OpenID가 범용화 된다면 사용자는 신뢰할 수 있는 IDP가 제공하는 주소형식으로된 하나의 ID/Password만을 관리하면 되고 SP(Service Provider)들은 위험하고 귀챦은 가입자 정보의 소유와 확인 작업을 IDP에 위임할 수 있습니다. 신규 SP들은 더 이상 사용자들에게 가입 행위를 강요하지 않아도 되고 정부는 보다 손쉽게 인터넷에서 활동하는 악플러들을 잡아낼 수도 있을지도 모릅니다. 네이버나 다음과 같은 메이져 SP들은 자신들이 가지고 있는 브랜드 파워를 극대화 하여 보다 강력한 Log-In 기반 서비스를 제공할 수도 있습니다. 특히나 사용자들은 하루에도 셀수 없이 등장하는 웹 서비스를 이용하기 위해 일일이 가입하는 수고를 할 필요가 없어지겠죠. 보다 안정성이 강화되고 보안성이 추가된다면 공인인증서를 대신하여 온라인 경제활동의 기반 역할을 할지도 모를 노릇입니다.<br />
<br />
구구절절이 예를 들지 않더라도 너무 훌륭한 서비스입니다.<br />
그래서 범용화 되지 못할 것 같습니다. 적어도 범용화 되기가 죽을 만큼 힘들 것 같습니다.<br />
<br />
이와 같은 서비스가 범용화 된다면 아마도 2~3개의 대형 IDP만이 시장을 지배할 것으로 생각됩니다. 보안성과 안전성을 확보하려면 여간 비용이 드는게 아닐테니까요. 또 사용자 역시 눈에 보이지 않고 어려운 기술용어를 신뢰하기 보다는 단순하게 IDP의 브랜드나 규모에 신뢰를 보일 것입니다. '열린 표준'의 효과로 다양한 IDP들이 등장하더라도 그리고 Consumer에 속한 서비스들이 등장하는 모든 IDP를 필터링 없이 지원한다고 하더라도 비즈니스의 특성을 고려할 때 이런 편중 현상은 막기 힘들 것 같군요.<br />
<br />
물론 몇몇 대형 IDP들이 시장을 지배한다고 해도 직접적으로 사용자 입장에서 나빠질 것은 없을겁니다. 이미 '웹서비스=Free'라는 공식이 진리가 되어버린 환경에서 성공한 IDP들이 독과점을 무기로 사용자에게 과금을 하는 어리석은 짓은 할리가 없으니까요. 힘들어지는 것은 새로이 등장할 중소 SP들일 것이고 싸우는 것은 IDP와 메이져 SP들이 아닐까 싶습니다. 다만 그로 인해 사용자들은 간접적으로 피해를 입게 되겠죠.<br />
<br />
몇년전 벌어졌던 BC카드와 이마트의 힘겨루기를 기억하실 겁니다.<br />
<br />
<div class="imageblock center" style="clear: both; text-align: center;"><a href="http://cfs3.tistory.com/upload_control/download.blog?fhandle=YmxvZzM1ODg5QGZzMy50aXN0b3J5LmNvbTovYXR0YWNoLzAvOS5qcGc=" target="_blank" rel="lightbox"><img alt="" src="http://cfs3.tistory.com/upload_control/download.blog?fhandle=YmxvZzM1ODg5QGZzMy50aXN0b3J5LmNvbTovYXR0YWNoLzAvOS5qcGc=" height="238" width="390"></a><p class="cap1">&lt;수수료를 놓고 벌어진 이마트와 BC카드의 힘겨루기&gt;</p></div><br />
신용카드 시스템은 두가지 비즈니스 영역을 가지고 있습니다. 하나는 사용자를 확인하는 '인증'의 영역이고 하나는 대금을 지불을 유애하는 '신용'의 기능입니다.&nbsp; 비록 두가지로 나눠져 있지만 마켓에서 카드사의 힘은 그 카드를 사용하는 사용자 '인증'에서 나옵니다. 즉, 사용자 수가 많은 카드사가 마켓에서 더 힘쎄다는 거죠. 그 힘을 무기로 카드사는 가맹점에게 수수료를 받습니다. <br />
<blockquote>내가 제공하는 신용카드를 통해 너에게 '접속'하는 고객이 있다면 나에게 수수료를 내야한다.</blockquote><br />
는게 카드사의 이야기입니다. 물런 사용자에게 서비스를 제공하는 이마트는 다르게 이야기합니다. <br />
<blockquote>고객이 내 서비스에 무슨 카드로 접속할 수 있는지는 내가 결정한다.<br />
고객은 너희 신용카드 아니라도 다른 신용카드로 접속할 수 있다.<br />
</blockquote>결국 이 싸움은 적절한 절충점을 찾은 것으로 보이지만 이마트의 승리로 끝났습니다. 결과를 놓고 보면 사용자 입장에선 매우 얄미운 싸움이었습니다. 이미 절충점을 찾아놓고도 힘겨루기를 했으니까요. BC카드와 이마트에게는 수수료 몇% 보다 더 중요한 것은 마켓의 힘이 누구에게 있냐는 것이었습니다. 그 만큼 비즈니스 사슬에서 우위를 점한다는 것은 기업에게 중요하죠.<br />
<br />
OpenID가 범용화 된다면 위와 같은 이슈가 분명히 생길것 같습니다. 사용자를 쥐고 있는 IDP와 메이져 SP간에 힘싸움이 벌어지겠죠. 걱정되는건 그 틈바구니에서 간접적으로 피해를 입을 사용자와 대형 IDP에 대항할 힘이 없는 중, 소 SP들입니다.<br />
<br />
<div class="imageblock center" style="clear: both; text-align: center;"><a href="http://cfs3.tistory.com/upload_control/download.blog?fhandle=YmxvZzM1ODg5QGZzMy50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTAuanBn" target="_blank" rel="lightbox"><img alt="사용자 삽입 이미지" src="http://cfs3.tistory.com/upload_control/download.blog?fhandle=YmxvZzM1ODg5QGZzMy50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTAuanBn" height="387" width="580"></a><p class="cap1">&lt;중, 소 카드 가맹점들의 집회&gt;</p></div><br />
<br />
아직 범용화 되지도 못한 서비스를 가지고 이런 걱정을 하는 것은 기우에 불과합니다. 하지만 이런 시각은 비즈니스를 하는 사람들이라면 누구나 예측가능한 것이고 그 예측을 기반으로 시장형성 초기에 내가 좀더 기득권을 가지려는 것은 기업의 당연한 본능입니다. 기술적 이슈나 서비스 본질을 두고 벌어지는 치열한 싸움은 시장 형성과 비즈니스 자체에 이로운 영향을 미칠겁니다. 하지만 아직 만들어지지도 않은 시장에서&nbsp; 미리 우위를 점하기 위해 벌어질 지리한 힘겨루기는 OpenID라는 좋은 서비스가, 아니 Identity Management라는 좋은 분야가 상업적으로 성공해서 범용화 되는데 큰 걸림돌로 작용할 것 같습니다.<br />
<br />
어쩌면 이런 류의 서비스는 너무 좋고 꼭 필요하며 마켓에서 가지는 힘이 너무 크므로<br />
이익을 추구하는 기업에서 제공하기 보다는 정부나 사단법인과 같은 곳에서 제공하는 것이 적절하지 않을까...라는 생각도 듭니다.<br />
<br />
만일 기업에서 서비스를 제공하게 된다면 <br />
위에 언급한 세 IDP를 포함하여 앞으로 등장할 우리나라 IDP가 힘의 중심에 설 수 있었으면 좋겠습니다. :)<br />
			 ]]> 
		</description>
		<category>OpenID</category>

		<comments>http://netkong.egloos.com/373164#comments</comments>
		<pubDate>Wed, 04 Jul 2007 13:02:25 GMT</pubDate>
		<dc:creator>넷콩</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 웹 2.0 기술의 주역 OpenAPI의 무한한 가능성  ]]> </title>
		<link>http://netkong.egloos.com/373156</link>
		<guid>http://netkong.egloos.com/373156</guid>
		<description>
			<![CDATA[ 
  <p class="title1"><b style="color: rgb(51, 51, 51);">웹2.0 시대의 견인차 Open API </b></p><p>&nbsp;</p><p>&nbsp;</p><p class="contentsbox">OpenAPI에 개발자들의 아이디어가 더해지면서 다양한 매쉬업 서비스들이 세상에 등장하고 있다. 이 서비스들은 기존에 생각지 못했던 일들을 가능하게 하거나, 다른 서비스 사업자의 서비스들을 활용하고 거기에 독창성을 더하여 큰 수익을 내고 있기도 하다. 구글과 몇몇 유명 해외 포털들이 API를 오픈하고 이로 인한 성과들이 나자, 국내의 포털과 사이트들도 자신들의 서비스를 개방하는데 앞장서고 있다. 구글 맵이나 다른 해외 API의 한글화 문제 탓에 활용을 꺼렸던 개발자들에게 국내 포털들의 API 오픈은 단비 같은 존재. 이번 특집에서는 구글과 네이버, 다음의 OpenAPI 활용법에 대해 알아보고 개발자들이 이 API들을 어떻게 활용해야 개발자의 역량을 키우고 수익도 올릴 수 있을지에 대해 알아본다.</p><p>&nbsp;</p><p class="author">기획·정리 <br />
| 정희용 기자 flytgr@imaso.co.kr</p><p>&nbsp;</p><p class="title1">웹 2.0 기술의 주역 OpenAPI의 무한한 가능성</p><p>&nbsp;</p><p class="contentsbox">OpenAPI는 ‘플랫폼으로서의 웹’이라는 특징을 기술적으로 구현시켜주는 대표적인 웹 2.0 기술이다. 이미 해외에서는 OpenAPI를 이용하여 만든 매쉬업을 통해 다양한 비즈니스 모델을 창출되고 있으며 차세대 웹의 핵심 기술로 평가하며 투자를 아끼지 않고 있다. 국내에서도 오랫동안 OpenAPI에 대한 관심과 투자가 지지부진 했으나, 최근 들어 OpenAPI에 대한 열기가 고조되고 있다. 이번 1부에서는 OpenAPI를 활용한 구체적인 사례와 비즈니스 모델을 통해 웹 2.0 기술의 미래를 조명한다.<br />
</p><br />
<p class="author">박지강 jkwave@gmail.com</p><p>&nbsp;</p><p>&nbsp;</p><p>우리는 빠르게 다가오는 새로운 시대에 유연하게 대처하기 위해 좀 더 표준을 지켜야한다. 또, 좀 더 가벼워져야 하고, 쉽게 다른 서비스와 통합 가능해져야 한다. 필자는 웹 2.0의 화두는 점점 무거워지는 기술 속에서 생산성을 확보하기 위한 치열한 싸움이라고 생각한다. 웹 2.0의 핵심이 데이터이기 때문에 새로운 콘텐츠를 누가 먼저 사용자에게 소개하느냐가 웹 개발 환경 업그레이드의 화두가 될 것이다.</p><p>&nbsp;</p><p>그럼 웹 2.0의 대표라고 할 수 있는 OpenAPI가 가지는 의미는 무엇일까? 흔히 이 OpenAPI를 공짜 서비스나 개발자용 장난감 퍼즐 정도로 치부하기도 하지만, OpenAPI는 그것을 사용하는 개발자의 역량에 따라 무한한 가능성을 발휘하는 신무기다. OpenAPI를 사용하면 지도 위에 부동산 정보를 표시할 수 있고, 쇼핑몰에 채팅을 결합할 수 있으며, 멀티미디어 포털도 만들 수 있다. 우리는 신속하게 변하는 차세대 서비스를 위해 웹 콘텐츠 조합이나 타 시스템과의 연동 시에 발생하는 웹 개발환경의 비용을 줄여주고, 큰 수익으로 연결되기도 한다. 이제부터 기존의 사례들을 통해 개발자가 OpenAPI를 어떻게 활용하고, 자신의 역량과 가치를 높이는 수단으로 쓸 수 있을 지에 대해 알아보자. </p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">OpenAPI의 성장과 수익모델</p><p>&nbsp;</p><p>&nbsp;</p><p>웹 2.0이 이전의 웹과 명확히 구분되는 중요한 기술적 특징은 바로 OpenAPI의 등장으로 인한 “플랫폼으로서의 웹”이다. </p><p>&nbsp;</p><p>OpenAPI는 기업 중심의 SOA(Service-Oriented Architectu re)가 웹에 반영된 결과물로써 웹 사이트가 자신의 기능을 이용할 수 있도록 공개한 프로그래밍 인터페이스를 말한다. 사용자는 웹 사이트의 내부를 모르더라도 공개된 API를 이용해 해당 사이트의 기능을 쉽게 사용할 수 있다. 이는 서비스 중심의 개발 방법으로 SOA의 기술적인 유전자를 웹에 이식한 것이다.</p><p>&nbsp;</p><p>하지만 이처럼 무척 가까워 보이는 SOA와 OpenAPI는 자세히 알고 보면 그리 친한 사이는 아닌 듯하다. SOA가 기술적으로 더욱 복잡하고 서비스의 캡슐화를 통해 기업의 프로세스를 조율하는 등 좀 더 고차원적인 개념이라면, OpenAPI는 데이터를 제어할 수 있는 간단하고 직관적인 인터페이스의 제공을 통해 사용자의 참여를 유도하는 사용자 중심의 비즈니스 모델이라고 할 수 있다. SOA라는 아키텍처가 참여를 중시하는 웹 2.0의 정신과 맞물려 OpenAPI을 탄생시킨 것이다.</p><p>&nbsp;</p><p>SOA를 도입해 얻을 수 있는 효과는 시장에 대한 빠른 적응력과 기업 내부의 생산성 제고 등 여러 가지 결과로 실현될 수 있어 그 실효성에 대해 다양한 논쟁을 일으키지만 OpenAPI는 명확해서 좋다. OpenAPI로 매쉬업이라는 명확한 결과물을 얻을 수 있기 때문이다. OpenAPI를 제공하는 서비스는 많지만 그 중에서도 제일 많이 사용되고 알려진 것은 아마도 구글 맵 OpenAPI일 것이다.</p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-01.jpg"></p><p class="style44" align="center">[그림1] 매쉬업에 사용된 OpenAPI점유율(출처 : ProgrammableWeb.com) </p><p class="style44" align="center">&nbsp;</p><p>구글 맵은 자바스크립트만을 이용하여 웹에 지도 정보를 표시하는 혁신적인 서비스다. 이 서비스는 AJAX란 용어가 구글 맵에서 영감을 받아 탄생했을 정도로 대중에게 많은 주목을 받았다. 구글 맵은 웹에 지도를 표시하고 위치 정보를 제어할 수 있는 기능을 OpenAPI로 제공한다. 위치 정보란 실생활에 밀접하게 사용되는 인프라 데이터이기 때문에 지도를 이용한 매쉬업은 가장 활발하게 생산되고 있다. 예를 들어 부동산 정보를 지도에 표시하는 매쉬업이나 소비자와 제일 가까운 자동차 판매처를 찾아내는 매쉬업 등 그 응용 영역은 무궁무진하다. </p><p>&nbsp;</p><p>이렇게 구글 맵의 강력한 기능을 쉽게 가져와 사용할 수 있다는 것은 개발자의 입장에서 보면 분명 열광할 만한 일이다. 하지만 구글은 어떤 이익을 기대하고 이런 API를 제공하는 것일까? 구글은 구글 맵을 이용할 수 있는 인터페이스를 공개하여 이미 많은 광고 효과를 얻었다. 구글에 대한 인식은 높아지고 방문자 수도 증가했을 것이다. 하지만 더욱 중요한 것은 그들이 추후에 지도 위에 광고를 표시할 수 있는 권리를 서비스 약관에 명시하고 있다는 점이다. 이처럼 생산자와 소비자 모두 참여를 통해 이익을 얻을 수 있는 플랫폼은 웹 2.0의 흐름과 정확히 일치한다고 볼 수 있다.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">개발자는 매쉬업을 통해 무엇을 얻을 수 있을까?</p><p>&nbsp;</p><p>&nbsp;</p><p>많은 사람들이 기발한 매쉬업에 열광하고 있지만 냉철한 시각으로 매쉬업을 비판하는 사람들도 있다. 그들은 매쉬업이 API 제공 서버에 의존적이기 때문에 서비스의 안정성을 보장하지 않고, API 사용 횟수나 데이터 전송량에 제한이 있다고 불평한다. 또한 상업적 용도에 제한을 가하는 경우도 있고, 누구나 비슷한 서비스를 만들 수 있다는 점을 지적한다. 그래서 비즈니스 모델로서 매쉬업은 큰 가치가 없다는 결론을 내리고 있다. 하지만 실제로 매쉬업이 여러 가지 방법으로 수익을 거둘 수 있다는 명백한 증거는 주위에서 쉽게 확인할 수 있다. 현재 알려진 가장 확실한 수익 모델은 광고와 제휴 프로그램이다.</p><p>&nbsp;</p><p>● 광고 <br />
광고는 사이트의 가장 보편적인 수익 모델이며 이는 매쉬업에서도 마찬가지다. 단순히 OpenAPI의 조합만으로 만들어진 매쉬업은 다양한 수익 모델을 만들어내기가 어렵다. 그러므로 기발하고 다양하지만 데이터에 대한 소유권을 가지고 있지 않은 매쉬업은 광고가 가장 유력한 수익모델일 수밖에 없다.</p><p>&nbsp;</p><p>현재 지속적으로 생산되고 있는 매쉬업의 대부분은 구글 애드센스(Google AdSense)와 같은 키워드 광고 프로그램을 도입하고 있다. 구글 애드센스는 문맥 검색을 통해 웹 페이지에 알맞은 광고를 제공하는 맞춤형 광고 프로그램이다. 애드센스를 이용하면 간단한 HTML 코드를 사이트에 붙이기만 하면 추가적인 노력 없이 자동으로 광고가 개제되고 그로 인한 수익을 받게 된다. 물론 큰 수익은 아니지만 충분한 헌신 없이 매쉬업 개발자가 취할 수 있는 최선의 수익모델이라 할 수 있다.</p><p>&nbsp;</p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-02.jpg"></p><p class="style44" align="center">[화면1] 하단의 회색 박스에 구글 애드센스를 설치한 그림 단어 생성 매쉬업 </p><p>&nbsp;</p><p>하지만 좀 더 많은 관리와 추가적인 노력으로 사용자의 방문수가 점점 올라간다면 직접 광고주를 모집하거나 더 나은 조건의 광고를 유치하느라 동분서주할 수도 있을 것이다. 아직까지는 매쉬업을 비즈니스를 추진하는 수단으로 사용하기보다는 호기심을 충족시키거나 기발한 아이디어를 현실화하기 위해 만드는 경우가 대다수이다. 매쉬업을 만든 후 시장을 관망하며 사용자의 평가만 기다리는 안일한 개발자는 단지 구글 애드센스로 사이트 호스팅 비용만 버는 괴짜로 남을 것이며, 매쉬업을 비즈니스를 도구로 적극적으로 활용한다면 광고주의 환영을 받는 혁신가로 남을 것이다.</p><p>&nbsp;</p><p>● 제휴 프로그램</p><p>&nbsp;</p><p>매쉬업의 또 다른 비즈니스 모델은 제휴 프로그램이다. 아담 트래첸버그는 Dude, Where’s My Used Car?(https://www. dudewheresmyusedcar.com)라는 다소 긴 제목의 매쉬업을 만들었다. 이 매쉬업은 구글 맵과 이베이의 자동차 카테고리 상품을 조합한 사이트이다. 이 사이트는 사용자의 위치에 가장 근접한 중고차 판매자를 찾아내는 일을 수행하며, 그가 개발한 서버에는 OpenAPI를 다루는 페이지 외에 아무런 데이터도 가지고 있지 않았다. 아담은 2005년에 열린 웹 2.0 컨퍼런스에서 자신이 만든 매쉬업은 사용자에게 이베이에서 제공하지 않는 지도 정보를 제공하는 동시에 이베이에서 할 수 있는 많은 기능들도 추가적으로 제공하였기 때문에 방문자에게 색다른 만족을 줄 수 있다고 말했다. </p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-03.jpg"></p><p class="style44" align="center">[화면2] 구글 맵과 이베이를 조합한 Dude, Where's My Used Car? </p><p>&nbsp;</p><p>이베이의 API를 이용한 매쉬업에 지속적인 방문자를 확보할 수 있다면 이베이의 제휴프로그램으로 수익을 거둘 수 있다. 제휴 프로그램은 어떤 일을 할까? 아담이 만든 매쉬업은 이베이의 잠재고객을 창출하는데 크게 기여한다. 사이트의 검색 결과가 이베이의 자동차 카테고리의 자동차 구매 페이지와 연결 되어있기 때문이다. 실제로 이베이는 자사의 상품에 구매를 유발하는 제휴사에게 금액으로 보상하는 제휴 프로그램을 마련하고 있다. 사용자는 매쉬업을 통해 위치 검색 결과로 이베이의 자동차 구매 페이지를 접속할 수 있고, 사용자가 자동차를 구매하면 이베이가 그 수익의 일부를 매쉬업에 제공함으로써 아담이 돈을 벌 수 있는 것이다.</p><p>&nbsp;</p><p>앞서 열거한 두 가지 외에도 충분히 다른 비즈니스 모델들도 있을 수 있다. 매쉬업은 계속 진화하고 있으며, 그 가능성을 예측하는 것은 불가능하기 때문이다. 이 가능성을 비즈니스 모델로 바꾸는 주체는 OpenAPI를 제공하는 선도 기업과 매쉬업을 창출해내는 혁신가들이다.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">거액의 투자를 받은 매쉬업</p><p>&nbsp;</p><p>&nbsp;</p><p>지금까지는 매쉬업을 통해 구현할 수 있는 일반적인 수익 모델을 정리해보았다. 하지만 빈손이 아니라 경쟁력 있는 데이터와 OpenAPI를 결합시키면 백만장자가 될 기회를 좀 더 빨리 얻게 될지도 모른다. 다음은 투자를 받은 매쉬업의 사례들이다.</p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-04.jpg"></p><p class="style44" align="center">[화면3] 구글 맵 Open API를 이용한 부동산 정보 사이트 Trulia </p><p>&nbsp;</p><p>Trulia.com은 구글 맵 OpenAPI를 이용한 부동산 정보 매쉬업을 만들어 Accel Partner란 벤처 캐피탈에게 약 800만 달러에 달하는 투자를 받았다. 이 사이트는 구글 맵 위에 부동산 정보를 뿌려 사용자가 지도를 이용해 편리하게 부동산 정보를 검색할 수 있는 사용자 인터페이스를 구현하여 많은 호응을 얻었다.</p><p>&nbsp;</p><p>부동산 정보 사이트인 Zillow는 마이크로소프트의 버추얼 어스(Virtual Earth) OpenAPI를 사용하여 매물로 나온 부동산의 실제 사진을 원하는 방향에서 상세히 볼 수 있다. 이 기능은 Zillow에서 “Bird’s Eye View”로 불리는데 새의 눈으로 본 시점이라는 뜻이다. Zillow는 Benchmark Capital로부터 약 5,700만 달러의 투자를 받았다. 물론 이 사이트는 단순히 지도를 이용한 부동산 정보 사이트로 이런 어마어마한 투자를 받은 것은 아니다. Zillow는 해당 가격대의 낮은 범죄율을 가진 지역 내 집이나 높은 등급의 초등학교 위치에 있는 30분 거리에 있는 집을 검색할 수 있는 데이터를 갖추었고, 자신의 소유의 집에 대한 가격을 주변 환경 요인에 입각하여 평가를 해주는 기능도 가지고 있다. 하지만 Virtual Earth의 API를 사용해 집을 육안으로 확인할 수 있는 기능을 보탬으로써 사용자에게 더 많은 만족을 주었고 이는 더 많은 투자를 받을 수 있는 계기가 되었을 것이다.</p><p>&nbsp;</p><p>이 사례들은 매쉬업을 통해 누군가의 투자를 받으려면 비즈니스를 수행할 수 있는 기본적인 기반을 갖추고 있어야 함을 보여준다.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">매쉬업 비즈니스의 눈부신 미래</p><p>&nbsp;</p><p>&nbsp;</p><p>OpenAPI와 매쉬업은 단지 괴짜들이 가지고 놀 수 있는 개발자용 장난감처럼 보일 수도 있지만 기본적으로 OpenAPI는 사이트 개발의 생산성을 높여주는 전략적 제휴의 훌륭한 도구이다. 다른 곳의 가치 있는 자원을 마음만 먹으면 사용할 수 있다는 것은 그 활용의 범위도 무궁무진하다는 증거이다. 단지 장난감처럼 레고 블록을 쌓듯이 가지고 놀며 지나치기엔 너무나 유용한 기회이다. 단지 미래의 활용 가능성은 차치하더라도 우리가 흔히 겪는 비즈니스 사례에 OpenAPI를 대입하더라도 충분히 그 가치를 깨달을 수 있다. OpenAPI와 매쉬업을 활용한 비즈니스 사례들을 살펴보자.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">OpenAPI를 이용해 킬러 사이트 만들기</p><p>&nbsp;</p><p>&nbsp;</p><p>기존의 사이트가 가지지 못한 창의적이고 독창적인 사이트를 기획하여 개발하는 것은 비즈니스를 수익으로 변화시키기 위해 가장 우선시 되어야 할 것이다. 하지만 새로운 사이트를 직접 만드는 작업은 그리 쉬운 일이 아니다. 웹 페이지는 둘째치더라도 데이터베이스와 웹 서버 설정까지 신경을 써야 할 것들은 한두 가지가 아니다. 이처럼 경쟁력 있는 사이트를 만들기 위해서는 적지 않은 개발 리소스가 투입되고, 투자비용을 회수하기 위해 모험적인 시도를 하기 보다는 좀 더 안정적이고 보수적인 시각으로 사이트를 구축하게 된다. OpenAPI는 새로운 사이트를 구축할 때 좀 더 낮은 비용으로 빨리 새로운 사이트를 구축할 수 있도록 도와준다. </p><p>&nbsp;</p><p>아무런 컨텐츠도 가지고 있지 않고 맘대로 움직일 수 있는 신체와 아이디어밖에 없는 빈털터리라면 여러 가지 OpenAPI를 조합하여 새로운 서비스를 만들어 보자. 매쉬업 캠프의 두 번째 모임에서 최고의 매쉬업으로 꼽힌 Weatherbonk(http://www. weatherbank.com)는 무려 열 개의 OpenAPI를 조합하여 지도 위에 기상 정보와 해당 지역의 실시간 날씨 사진, 교통 상황 정보 등 수많은 정보를 지도 위에 표시하는 매쉬업이다.</p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-05.jpg"></p><p class="style44" align="center">[화면4] 해당 지역의 실시간 날씨 사진을 보여주는 Weahterbonk </p><p>&nbsp;</p><p>이 새로운 스타일의 기상 정보 사이트는 많은 블로거들과 언론에게 호평을 받고 있으며 구글의 키워드 광고 API인 애드센스(AdSense)로 수익을 얻고 있다. 물론 이처럼 열 개 정도의 많은 API를 조합해야지 훌륭한 사이트가 만들어지는 것은 아니다. 한두 개 정도의 API만으로도 독창적인 사이트를 만들 수 있다. </p><p>&nbsp;</p><p>하지만 이처럼 매력적인 매쉬업들이 많음에도 불구하고 다양한 수익 모델을 찾기는 쉽지가 않다. OpenAPI로 고객에게 서비스하는 데이터들은 모두 매쉬업 개발자 소유가 아니다. API 제공 기업의 소유이기 때문이다. 그러므로 OpenAPI만으로 만든 매쉬업은 광고나 제휴 프로그램같이 제한된 수익 모델을 가질 수밖에 없다. Weatherbonk의 개발자인 데이비드 쇼어(David Schorr)는 광고 이외에도 호텔이나 항공사의 예약 프로그램과 제휴하여 수익을 얻을 가능성이 있지만 제휴를 맺기가 아직까지 쉽지가 않다고 한다. 물론 인터넷에서 광고나 제휴 프로그램은 수익을 낼 수 있는 전통적인 비즈니스 모델이다. 하지만 현재는 구글의 광고 중계 API인 애드워즈를 사용하거나 아마존이나 이베이 등 몇 개의 기업만이 제휴 프로그램을 진행하고 있기 때문에 선택의 폭과 수익의 질은 떨어질 수밖에 없다. 그렇다고 좌절할 필요는 없다. OpenAPI와 매쉬업 시장은 이제 성숙기에 접어들었고 앞으로 보다 많은 기업들이 제휴 프로그램과 광고 모델을 제시할 것이다. 대표적으로 지도 OpenAPI 제공 업체들은 지도 위에 광고를 표시할 움직임을 보이고 있으며 이 광고 수익을 매쉬업과 공유할 계획도 세우고 있다. 이제 다시 장밋빛 미래가 아닌 냉정한 현실로 돌아오자. 지금 당장 OpenAPI로 좀 더 경쟁력 있는 사이트를 만들 수는 없을까?</p><p>&nbsp;</p><p>이미 가지고 있는 컨텐츠가 있다면 OpenAPI를 추가하여 더욱 경쟁력 있는 새로운 사이트를 만들 수 있다. 예를 들어 부동산 정보나 여행 정보, 맛집 정보와 같은 위치 기반 데이터를 가지고 있다면 지도를 제공하는 네이버 지도, 구글 맵, 야후 맵 등을 이용해 새로운 사이트를 만들 수 있다. 물론 네이버 지도를 제외한 구글 맵이나 야후 맵은 해외에서는 유명한 지도 API이지만 국내에서 대체 무슨 용도로 사용할 수 있냐고 반문할 수도 있다. 하지만 만약 해외여행에 관한 서비스를 기획하고 있다면 어떨까? 어학연수를 위한 수많은 교육 기관을 소개하는 것은 어떨까? 이처럼 발상의 전환은 OpenAPI를 활용하는데 큰 원동력이 될 것이다. 미국에서 열린 매쉬업 정보 공유 모임인 매쉬업 캠프(http:// www.mashupcamp.com)에서 최고의 매쉬업으로 선정되었던 Podbop(http://www.podbop.org)를 살펴보자. </p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-06.jpg"></p><p class="style44" align="center">[화면5] 매쉬업 캠프에서 최고의 매쉬업으로 선정된 Podbop </p><p>&nbsp;</p><p>Podbop은 이벤트 정보를 서비스하고 있는 Eventful(http:// www.eventful.com)의 OpenAPI와 음악을 하는 아티스트의 데이터를 연결하여 전 세계의 콘서트 정보를 확인할 수 있는 사이트이다. 물론 Eventful에는 콘서트 정보와 같은 음악 이벤트만 서비스하는 것이 아니다. 하지만 OpenAPI의 기능을 이용하여 “music”이라는 태그가 붙어 있는 이벤트만 가져올 수 있기 때문에 이런 콘서트 검색 사이트가 가능한 것이다. 이것이 전부가 아니다. 콘서트를 열 예정인 아티스트의 무료 mp3를 함께 제공해서 음악을 미리 듣고 콘서트 참여 여부를 결정할 수 있도록 만들어서 사용자의 궁금증을 해소시키고 있다. 이 독창적인 사이트는 Eventful의 방대한 이벤트 데이터베이스를 이용하지 않았다면 높은 구축비용 때문에 시도도 해보지 못하고 아이디어로만 남았을 것이다. 이 사이트의 성공 비결은 자신이 소유하고 있는 컨텐츠로 인해 비즈니스 경쟁력을 자체적으로 확보할 수 있었고 OpenAPI를 사용해 컨텐츠를 더욱 빛나게 만들었기 때문이다. 이는 단지 OpenAPI만을 조합한 매쉬업의 현실적인 한계를 극복한 훌륭한 매쉬업 사례라 할 수 있다.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">OpenAPI로 기존 사이트를 업그레이드하자</p><p>&nbsp;</p><p>&nbsp;</p><p>기존의 서비스에 OpenAPI를 추가하여 쉽고 빠르게 좀 더 나은 서비스를 만들 수 있다. Simplyhired.com은 새로운 개념의 구인 전문 검색 사이트이다. 이 사이트는 채용 전문 사이트의 정보와 회사 홈페이지의 구인 정보 등 여러 가지 구인 정보 페이지에서 데이터를 수집하는 전문 검색 엔진(Vertical Search Engine)을 활용한 사이트이다. 하지만 이게 전부가 아니다. 구글 맵의 OpenAPI와 LinkedIn(http://www.linkedln.com), Pay Scale (http://www.payscale.com), ZoomInfo(http://www. zoominfo.com)의 기능을 제휴를 통해 통합하여 만든 사이트이기도 한다. 검색 엔진을 통해 수집한 채용 정보를 바탕으로 구글 맵은 회사의 위치를 알려 주고, LinkedIn은 인맥 정보를 알려준다. 그리고 PayScale은 해당 직업의 연봉 정보를 알려주며, ZoomInfo는 회사 정보를 알려준다. </p><p>&nbsp;</p><p>결국 이 사이트는 OpenAPI를 이용해 다른 경쟁 사이트와 차별화된 사이트를 구성하여 사용자를 끌어들였고, 투자자들의 도움을 받아 사용자들의 트래픽으로 광고비를 벌어들이고 있다.</p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-07.jpg"></p><p class="style44" align="center">[화면6] 구인 회사의 위치를 구글 맵으로 보여주는 Simplyhired.com </p><p>&nbsp;</p><p>Simplyhired는 처음부터 여러 기업들과 전략적 제휴를 맺었던 것은 아니다. 채용 정보 전문 검색 엔진이란 핵심 기술을 이용하여 사이트를 오픈한 후 구글 맵의 OpenAPI를 사용하였고 Linkedln, PayScale, ZoomInfo와 같은 채용 관련 정보를 가진 기업과 전략적 제휴를 맺으며 정보의 질을 점점 높였다. 이처럼 한 사이트에서 채용에 대한 모든 정보를 볼 수 있도록 다른 기업과의 제휴를 통해 개선에 개선을 거듭한 결과 Simplyhired는 최고의 직업 검색 사이트로 성장하게 되었다.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">기업 간의 매혹적인 제휴, 엔터프라이즈 매쉬업</p><p>&nbsp;</p><p>&nbsp;</p><p>우리는 매쉬업이 SOA의 소비자 버전이라는 사실을 기억해야 한다. SOA라는 기업용 서비스 지향 아키텍처가 웹의 사용자 레벨로 보급된 산물이 바로 개발자들이 만들어 내는 기발한 매쉬업이다. 하지만 여러 가지 데이터의 손쉬운 조합이라는 어디서나 통용될 수 있는 비즈니스 기회를 굳이 웹에서 사용자에게만 제한시킬 필요는 없다. 기업 간의 전략적 제휴에도 충분히 매쉬업이 사용될 수 있다. 이름하여 엔터프라이즈 매쉬업(Enterprise Mashup)이다.</p><p>&nbsp;</p><p>물론 기업 간의 전략적 제휴는 지금까지 항상 있어왔다. 하지만 서로 다른 시스템과 컨텐츠로 인해 인터페이스를 맞추어 데이터를 통합하기란 쉬운 일이 아니다. 하지만 XML 포맷이 범용화 되고 RSS와 OpenAPI와 같은 열린 데이터 채널이 웹 2.0 기술로 주목을 받으면서 데이터를 주고받는 방식이 점점 표준화되고 있기 때문에 기업 간의 제휴에 매쉬업을 사용하면 좀 더 적은 비용으로 좀 더 빨리 새로운 비즈니스를 펼칠 수 있다. 이런 특징은 사용자를 중심으로 빠르게 변화하는 인터넷 비즈니스에 신속하게 적응하기 위해 반드시 필요한 기업의 조건으로 정확히 SOA의 최종 목표이기도 하다.</p><p>&nbsp;</p><p>예를 들어 택배 회사의 콜 센터와 네이버 지도의 OpenAPI가 제휴를 맺으면 고객의 데이터를 지도 위에 시각적으로 확인할 수 있는 훌륭한 엔터프라이즈 매쉬업이 탄생할 것이다. 일본의 자동차 회사인 혼다(Honda)는 구글 어스(Google Earth)를 통해 도로의 교통량 확인 텔레매틱스(Telematics) 서비스를 고객에게 제공하고 있다.</p><p>&nbsp;</p><p>이처럼 서로의 이익을 위해 기업이 가지고 있는 핵심 역량을 공개하고 공유하는 일은 무한 경쟁 시대에서 살아남기 위해 피할 수 없는 선택이며 엔터프라이즈 매쉬업은 그에 대한 이상적인 선택이 될 수 있다. 물론 가볍고 빠른 개발 속도를 가진 매쉬업은 기업 간의 치명적인 비즈니스 데이터를 거래하기엔 여러 가지 명백한 보안적인 문제를 가지고 있다. 하지만 치명적이지 않은 분야의 프로세스와 로직에는 매쉬업이 충분히 그 강력한 효과를 발휘할 수 있다. 이처럼 매쉬업은 기업이 SOA를 채택해야 하는 이유를 서서히 입증하고 있으며, 엔터프라이즈 매쉬업으로 인해 소비자 중심의 매쉬업과 기업 중심의 SOA의 경계는 점점 모호해 지고 있다. </p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">기회란 아무 때나 오지 않는다</p><p>&nbsp;</p><p>&nbsp;</p><p>지금 이 시간에도 OpenAPI를 제공하는 사이트는 끊임없이 늘어나며, 그에 발맞추어 매쉬업의 숫자도 증가하고 있다. OpenAPI와 매쉬업에 대한 대표적인 정보 사이트인 프로그래머블웹(http://www.programmableweb.com)에 의하면 2007년 3월 기준, 전 세계적으로 398개의 API와 1,683개의 매쉬업이 존재하며 하루에 약 3.08개의 매쉬업이 생성된다고 한다. 구글 맵은 수백 개의 매쉬업을 가지고 있고 아마존은 API에 과금을 하여 큰 성공을 거두고 있다. 또, 가트너 그룹은 Ajax와 매쉬업이 향후 10년간 기업에 큰 영향을 줄 것이라고 전망하고 있다. 국내에서는 오로지 네이버와 다음만이 OpenAPI를 제공하고 있는 상황이다.</p><p>&nbsp;</p><p>하지만 국내에 매쉬업이 많지 않다고 하여 그리 비관할 만한 상황은 아니다. 다수의 조합으로 이루어지는 매쉬업의 특성상 OpenAPI의 수만큼 매쉬업은 비례하여 증가하기 때문이다. 다행히도 국내의 힘 있는 포탈들이 OpenAPI의 제공을 계획하여 진행하고 있다고 한다. OpenAPI의 종류가 더 많아진다면 국내의 매쉬업 시장도 더욱 성장하게 될 것이다. 네이버와 다음이 공동으로 개최한 매쉬업 캠프도 OpenAPI에 대한 구체적인 기업의 지원이 시작된 첫 사례이기에 많은 희망을 갖게 한다. 하지만 국내 OpenAPI의 수가 많아질 때까지 무작정 기다리는 일은 수없이 지나가는 기회를 놓치는 것과 같다. 이미 해외에 사용할 수 있는 수많은 OpenAPI들이 당신을 기다리고 있으며 나름대로의 수익구조를 갖추고 있는 훌륭한 매쉬업 레퍼런스들도 널려있다. 웹에서만큼은 국내와 해외의 구분이 큰 의미를 가지지 못한다. 구글 맵과 같은 경우 국내의 해외여행 정보 사이트나 이민, 유학정보 사이트에 충분히 활용될 수 있다. 그 밖에 해외 API를 활용할 수 있는 좀 더 구체적인 사례를 들어보자. 위즈위드(http:// www.wizwid.com)로 대변되는 해외 구매 대행 사이트들은 해외쇼핑몰들의 상품정보를 수동으로 입력하거나 별도의 웹스크래핑 툴로 긁어와 국내의 사용자들에게 전시한다. 그리고 국내 사용자들이 결제한 상품을 해당 해외쇼핑몰에 대신 결제해주고 배송해주는 역할을 한다. 이 사이트들에게 해외쇼핑몰들의 상품정보를 빠르고 신속하게 가져오는 기능은 무엇보다 중요한데 해외의 쇼핑 API를 이용하면 이런 기능을 쉽게 구현할 수 있다. 이베이나 아마존 등과 같은 쇼핑사이트들이 이미 상품정보를 API로 제공하고 있게 때문이다. </p><p>&nbsp;</p><p>인터넷 주소에 국가 명이나 도시 명을 적는 곳은 없다. 웹은 사회적으로는 누구에게나 열린 공간이며 비즈니스 적으로는 세계를 대상으로 한 무한 경쟁의 시장이다. 네이버, 다음, 구글이나 야후와 같은 세계적인 공룡 IT 기업과 전략적 제휴를 맺고 싶은가? 그럼 그들과 함께 매쉬업을 만들어라. <br />
</p><p>&nbsp;</p><p class="sourcebox"><strong>돈 버는 매쉬업의 특징</strong><br />
<br />
누군가의 지갑에서 큰돈을 꺼내려면 사용자의 요구를 충족시켜 비즈니스를 할 수 있는 경쟁력 있는 서비스가 바탕이 되어야 한다. 특히 투자를 받은 부동산 매쉬업의 특징은 다음의 두 가지로 요약된다. 이것은 비단 지도 관련 매쉬업에만 해당되는 법칙은 아니다. 기발한 아이디어와 비즈니스를 할 수 있는 추진력이 있다면 데이터와 OpenAPI를 사용하여 킬러 사이트를 만들어 육백만 달러의 사나이가 될 수 있는 기회는 항상 열려있다.<br />
<br />
● OpenAPI외에도 경쟁력 있는 데이터를 확보하고 있다.<br />
● 소비자가 돈을 지출해야 하는 행위와 관련이 있다.</p><br />
<p><br />
<br />
<a href="http://www.dbguide.net/" target="_blank"><b><font color="midnightblue">제공 : DB포탈사이트 DBguide.net </font></b></a></p><br />
<div align="right">출처 : Micro Software [2007년 4월호] </div>			 ]]> 
		</description>
		<category>OpenID</category>

		<comments>http://netkong.egloos.com/373156#comments</comments>
		<pubDate>Wed, 04 Jul 2007 12:59:45 GMT</pubDate>
		<dc:creator>넷콩</dc:creator>
	</item>
	<item>
		<title><![CDATA[ OpenAPI 왕국 구글의 캘린더 API 활용하기 ]]> </title>
		<link>http://netkong.egloos.com/373153</link>
		<guid>http://netkong.egloos.com/373153</guid>
		<description>
			<![CDATA[ 
  <p class="title1"><b style="color: rgb(51, 51, 51);">웹2.0 시대의 견인차 Open API </b></p><p>&nbsp;</p><p>&nbsp;</p><p class="contentsbox">OpenAPI에 개발자들의 아이디어가 더해지면서 다양한 매쉬업 서비스들이 세상에 등장하고 있다. 이 서비스들은 기존에 생각지 못했던 일들을 가능하게 하거나, 다른 서비스 사업자의 서비스들을 활용하고 거기에 독창성을 더하여 큰 수익을 내고 있기도 하다. 구글과 몇몇 유명 해외 포털들이 API를 오픈하고 이로 인한 성과들이 나자, 국내의 포털과 사이트들도 자신들의 서비스를 개방하는데 앞장서고 있다. 구글 맵이나 다른 해외 API의 한글화 문제 탓에 활용을 꺼렸던 개발자들에게 국내 포털들의 API 오픈은 단비 같은 존재. 이번 특집에서는 구글과 네이버, 다음의 OpenAPI 활용법에 대해 알아보고 개발자들이 이 API들을 어떻게 활용해야 개발자의 역량을 키우고 수익도 올릴 수 있을지에 대해 알아본다.</p><p>&nbsp;</p><p class="author">기획·정리 <br />
| 정희용 기자 flytgr@imaso.co.kr</p><p>&nbsp;</p><p class="title1">OpenAPI 왕국 구글의 캘린더 API 활용하기</p><p>&nbsp;</p><p class="contentsbox">OpenAPI 하면 가장 먼저 떠오르는 기업은 역시 구글이다. 웹 2.0을 이야기하면서 가장 많이 소개되는 API는 단연 구글맵이다. 이미 작년과 재작년 여러 매체와 블로그, 사이트들을 통해 구글맵을 이용한 활용법이나 매쉬업 사례들을 많이 접해보았을 것이기에 여기에서는 구글의 캘린더 API를 사용하는 몇 가지 예제들에 대해 알아본다. 다들 알고 있듯이 OpenAPI란 사용법이 그리 복잡하지 않기에 사용법 보다는 그것을 얼마나 풍부한 상상력으로 활용하느냐에 따라 그 가치가 달라진다고 할 수 있다. 여기에서 소개되는 간단한 예제들에 독자 여러분의 창의력을 더해보자. </p><p class="author">&nbsp;</p><p class="author">김민수 mskim@transware.co.jp</p><p>&nbsp;</p><p>&nbsp;</p><p>구글이 API를 처음 오픈했을 당시만 하더라도 자신들의 콘텐츠 서비스를 다른 사람들이 마음대로 쓰도록 오픈한다는 자체를 이해하기 힘들었다. 하지만 얼마 지나지 않아 사용자가 늘고 광고수익으로까지 이어지면서 API의 오픈이 비즈니스적으로 의미가 있음을 세상이 인식하기 시작했다. 이 때문에 서비스를 오픈하는 포털들이 점점 늘어나고 있다.</p><p>&nbsp;</p><p>구글의 서비스 중 가장 잘 알려진 것은 다들 잘 알고 있는 구글 맵이다. 여러 매체에서 구글 맵을 얼마나 소개했는지 일반인들 중에는 구글이 지도 서비스를 하는 회사라고 생각하는 사람들도 있을 정도이다. 필자가 처음 구글 맵을 접하고 자바 애플릿이 아니면서도 웹에서 너무나 부드럽게 이미지 로딩과 스크롤이 된다는 데 충격을 받은 기억이 난다. 웹을 느리고 버벅거리게 만들며 문법도 답답한 탓에 거의 무시하던 자바스크립트가 발달한 하드웨어에 XML과 RPC가 비동기로 이어지면서 불가능 하다고 여기던 일을 현실로 바꿔놓은 것이다. 지도는 여러 분야에 활용할 수 있지만, 구글 맵의 활용 방법들에 대해서는 여러 차례 원고로 다뤄졌기 때문에 여기에서는 구글 캘린더의 사용법에 대해 알아본다.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">구글의 캘린더 서비스</p><p>&nbsp;</p><p>&nbsp;</p><p>구글의 캘린더 서비스는 가장 오래된 서비스 중 하나다. 아웃룩의 스케줄 관리처럼 다양한 스케줄 관리를 웹상에서 할 수 있는 서비스이다. </p><p>&nbsp;</p><p>국내의 웹 개발 언어는 주로 PHP와 자바로 양분된다. 이중 PHP는 중소 웹호스팅 업체 중심으로 활용되고 있고, 자바는 좀 더 규모가 큰 대기업이나 관공서, 금융권의 SI 프로젝트에 쓰이고 있다. 2부는 API의 사용법을 이해하는 것을 목적으로 하기 때문에 여기에서는 두 언어를 통해 서비스를 구현하는 방법을 비교하며 설명할 것이다.</p><p>&nbsp;</p><p>PHP의 구글 캘린더(Google Calendar) API를 이용하는 방법은 여러 가지가 있다. 커뮤니티 차원에서 만든 클래스인 일종의 레퍼(Wrapper) 역할을 하는 오픈 소스 라이브러리와 젠드(Zend) 사의 프레임워크에서 제공하는 GData 클래스 패키지 라이브러리가 있다. 여기서는 이미 잘 알려져 있는 Zend 사의 프레임워크 대신 PEAR 기반의 라이브러리를 이용해 본다.</p><p>&nbsp;</p><p>자바는 두 말할 필요 없이 구글에서 공식적으로 자바 클라이언트 라이브러리가 있으므로 고민할 필요가 없다. 사실 구글은 이미 자세한 튜터리얼과 사용 예까지 제공하고 있기 때문에, 2부에서 다뤄지는 내용을 이미 잘 알고 있는 독자들도 있을 것이다. 이 글은 구글의 영문 매뉴얼만으로는 이해가 잘 안 되는 독자들에게 가이드를 주기 위해 만들어 졌으니 참고하길 바란다. 아직 API의 활용이 서툰 독자라면 2부의 내용을 다른 API의 사용법을 익히는 발판으로 삼을 수 있을 것이다.</p><p>&nbsp;</p><p>&nbsp;</p><table bgcolor="#ffcccc" bordercolor="#000000" cellpadding="1" width="550"><tbody><tr><td><p class="style44" align="center">&nbsp;</p><p class="style44" align="center">구글 API의 동작 방식</p><p align="center">&nbsp;</p><p align="left">[그림1]은 구글 서버와 연결하여 데이터를 가져오고, 사용자 측 웹 브라우저에서 비동기적인 데이터 처리를 HTML에서 구현하는 구조를 간단히 그린 것이다.</p><p align="left">[그림1]을 살펴보면 구글의 모든 API는 대부분 이와 같은 방식으로 동작하며 개발 언어와 API이름 정도만 바뀐다고 보아도 틀리지 않다. </p><p align="left">&nbsp;</p><p align="center"><img src="http://www.dbguide.net/images/know/tech/070605-08.jpg"></p><p>&nbsp;</p><p align="left">[그림1] Google Web Toolkit</p><p align="left">(출처 : http://hinchcliffe.org/img/googlegwt.jpg) </p></td></tr></tbody></table><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">구글 캘린더 API의 구조</p><p>&nbsp;</p><p>&nbsp;</p><p>구글 캘린더 API를 사용하려면 먼저 몇 가지 준비를 해 두어야한다. 당연한 얘기지만 우선 구글 계정을 취득해야 한다. 그런 뒤에 구글에 로그인한 뒤에 화면 좌측에 있는 [Calenders]목록에서 [Calender setting]을 선택한다. </p><p>&nbsp;</p><p>마지막으로 Calendar Address나 Private Address의 [HTM L] 아이콘의 링크 URL을 카피하는데, 이 URL은 &lt;iframe&gt; 태그를 사용하고 Calendar를 포함하여 표시하는 URL로 사용된다. 다음은 이렇게 취득한 URL을 iframe에 적용한 기본사용법이다. </p><p>&nbsp;</p><p>&lt; iframe <br />
src=http://www.google.com/calendar/embed?src=myaccount%40gmail.com&amp;pvttk=xxxxxxxxxxxxxxxx name=”Calendar” width=”300” height=”672”&gt;</p><p>&nbsp;</p><p>&lt;표1&gt;에서 보듯 사용목적에 따라 링크를 구분한다.</p><p>&nbsp;</p><table bgcolor="#ffffff" border="1" bordercolor="#ffffff" cellpadding="1" cellspacing="0" width="550"><tbody><tr><td bordercolor="#000000" bgcolor="#999999"><div class="logout2" align="center"><strong>주소</strong></div></td><td bordercolor="#000000" bgcolor="#999999"><p class="logout2" align="center"><strong>설 명</strong></p></td></tr><tr><td bordercolor="#000000" bgcolor="#ffffff"><div align="center">Calendar</div></td><td bordercolor="#000000" bgcolor="#ffffff"><p>Address public으로 공개할 때 접근하는 주소 </p></td></tr><tr><td bordercolor="#000000" bgcolor="#ffffff"><div align="center">Private</div></td><td bordercolor="#000000" bgcolor="#ffffff"><p>Address 자기만의 키값으로 접근하는 주소 </p></td></tr></tbody></table><p>[표1] 링크 구분 </p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">자바를 이용한 캘린더 API 활용</p><p>&nbsp;</p><p>&nbsp;</p><p>웹 개발 언어의 대명사처럼 쓰이고 있는 자바의 경우 구글에서 라이브러리를 직접 만들어 제공하고 있어 사용이 편리하다. 구글의 캘린더 API를 사용하려면 http://code.google.com/apis /gdata/client-java.html에서 필요한 클래스 라이브러리를 다운로드 받으면 된다. 링크 화면에 있는［Download the Java client library.]를 클릭하면 다운로드할 수 있다.</p><p>&nbsp;</p><p>다운로드한 파일의 압축을 해제한 후에 gdata\java\lib의 안에 있는 gdata-client-1.0.jar와　gdata-calendar-1.0.jar 파일에 대해서 CLASSPATH을 추가한다. 이 두 개의 JAR 파일은 요즘 대세인 이클립스나 넷빈즈 등의 통합 개발 환경(IDE)에서 이용하는 라이브러리니 꼭 추가해 두기를 바란다.</p><p>&nbsp;</p><p>여기까지 했다면 이제 코드를 작성할 분비는 모두 끝난 것이다. 필자는 JDK 1.5.0 update 11를 이용해서 테스트했지만 1.6.x 버전에서도 똑같이 동작할 것이다. 여기서는 GUI를 배제한 구글 캘린더 API만을 테스트하기 위한 프로그램이므로 main 메쏘드만 정의해본다.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">구글 GData 클래스 라이브러리를 사용한 예제</p><p>&nbsp;</p><p>&nbsp;</p><p>자 그럼 이제 실제 자바 코드를 순서대로 만들어보자. 가장 먼저 해야 할 것은 클래스 선언부인 import이다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 1&gt; 클래스 선언부</strong></span></td></tr><tr><td><p align="left">import java.net.URL;<br />
import java.util.Calendar;<br />
import java.util.Date;<br />
import com.google.gdata.data.*;<br />
import com.google.gdata.data.extensions.*;<br />
import com.google.gdata.client.*;<br />
import com.google.gdata.client.calendar.*;</p><p align="left">public class GCal<br />
{<br />
public static void main(String[] args)</p></td></tr></tbody></table><p>&nbsp;</p><p>그 다음으로 해야할 일은 &lt;리스트 2&gt;와 같이 구글 캘린더에서 사용할 구글 어카운드 메일 주소와 패스워드 등의 정보를 변수에 지정하는 것이다. 간단한 구문들이기 때문에 주석을 참고하면 별도의 설명이 없더라도 쉽게 이해할 수 있을 것이다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bordercolor="#000000" bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 2&gt; 변수 정의</strong></span></td></tr><tr><td bordercolor="#000000"><p>// 구글 캘린더에서 사용할 Google Account Email 주소</p><p>String gLoginAddr = "myaccount@gmail.com";　<br />
// Google Calendar 패스워드인 Google Account 패스워드<br />
String gLoginPass = "mypassword";<br />
// Calendar 등록용：스케줄의 제목 (한글 사용가능)<br />
String title = "고객 미팅";<br />
// Calendar 등록용：장소 (한글 사용가능)<br />
String place = "삼성동 코엑스";<br />
// Calendar 등록용：내용 ( 한글 사용가능 )<br />
String memo = "제품계약";</p></td></tr></tbody></table><p>&nbsp;</p><p>구글의 캘린더 API를 실제로 조작하는 부분은 이제부터 시작이다. 먼저 할 일은 구글 캘린더 API용 서비스 URL과 URL 클래스를 새로 생성하는 것이다. 여기에 추가로 try 문의 괄호 안은 예외를 catch한다(&lt;리스트 2&gt; 참조).</p><p>&nbsp;</p><p>&nbsp;</p><p>구글 API의 동작 방식<br />
&lt;그림 1&gt;은 구글 서버와 연결하여 데이터를 가져오고, 사용자 측 웹 브라우저에서 비동기적인 데이터 처리를 HTML에서 구현하는 구조를 간단히 그린 것이다. &lt;그림 1&gt;을 살펴보면 구글의 모든 API는 대부분 이와 같은 방식으로 동작하며 개발 언어와 API 이름 정도만 바뀐다고 보아도 틀리지 않다.</p><p><br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 3&gt; URL 설정</strong></span></td></tr><tr><td>try<br />
{<br />
// Google Calendar용 서비스 URL 설정<br />
URL postUrl = new URL("http://www.google.com/calendar/feeds/default/private/full");</td></tr></tbody></table><p>&nbsp;</p><p>클래스를 생성하고 난 뒤에 할 일은 이벤트 등록용 클래스를 정의하고, 스케줄의 타이틀, 내용을 적는 것이다. 스케줄의 타이틀에는 setTitle 메소드, 스케줄의 상세 정보에는 setContent 메소드로 등록할 수 있다. 작성 애플리케이션명의 이름도 정할 수 있으니 적어둔다.</p><p><br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 4&gt; 내용 등록 </strong></span></td></tr><tr><td>// 이벤트 등록용 클래스 정의<br />
EventEntry myEntry = new EventEntry();<br />
// 스케줄의 타이틀 (title 은 앞에서 정의한 것입니다.)<br />
myEntry.setTitle(new PlainTextConstruct(title)); <br />
// 스케줄 상세 정보 (memo 는 앞에서 정의한 것입니다.)<br />
myEntry.setContent(new PlainTextConstruct(memo)); <br />
// 작성 애플리케이션명<br />
Person author = new Person("Google Calendar Application", null, gLoginAddr);<br />
myEntry.getAuthors().add(author);</td></tr></tbody></table><p><br />
이번에는 이벤트 등록용 클래스에 스케줄링 하는 시간대를 등록할 차례다. 표준 시간대 GMT+9에 해당하는 우리나라의 경우 다음과 같은 순서로 등록하면 된다.</p><p>&nbsp;</p><p>① DateTime형 오브젝트를 이벤트 개시일 인자(argument)로 넣어 생성한 뒤에 새 객체를 만든다.</p><p>&nbsp;</p><p>② 생성한 오브젝트의 타임 존은 +0900이므로 ‘9’로 설정한다.</p><p>&nbsp;</p><p>③ DateTime형 오브젝트를 이벤트 종료 일시 인자로 넣어 생성한 뒤에 새 객체를 만든다.</p><p>&nbsp;</p><p>④ 생성한 오브젝트의 타임 존은 +0900이므로 ‘9’로 설정한다.</p><p>&nbsp;</p><p>⑤ When 형태 오브젝트는 인자가 없으니 새 객체를 만든다.</p><p>&nbsp;</p><p>⑥ When 형태 오브젝트에 ①과 생성한 오브젝트를 인자에 setStartTime 메소드를 호출한다.</p><p>&nbsp;</p><p>⑦ When 형태 오브젝트에 ③과 생성한 오브젝트를 인자에 setEndTime 메소드를 호출한다.</p><p>&nbsp;</p><p>⑧ ①에서 생성한 Where 형태 오브젝트의 인자에 addTime 메소드를 호출해 등록한다.</p><p>&lt;리스트 5&gt;는 이 순서에 의해 만들어진 코드다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 5&gt; 일시 시간 등록</strong></span></td></tr><tr><td>// 개시 일시를 DateTime 형태 오브젝트로 설정<br />
DateTime startTime = new DateTime(new Date(2007-1900,2-1,5,12,0));<br />
startTime.setTzShift(9); <br />
// 종료 일시를 DateTime형태 오브젝트로 설정<br />
DateTime endTime = new DateTime(new Date(2007-1900,2-1,5,13,0));<br />
endTime.setTzShift(9); <br />
// 개시 종료 일시를 When형태 오브젝트에 대입해 이벤트 클래스에 추가<br />
When eventTimes = new When();<br />
eventTimes.setStartTime(startTime);<br />
eventTimes.setEndTime(endTime);<br />
myEntry.addTime(eventTimes);</td></tr></tbody></table><p><br />
이제 이벤트 등록용 클래스에 스케줄 하는 시간대를 등록해야 하는데, 먼저 Where 형태 오브젝트는 인자가 없으므로 new 하여 새로운 객체를 생성한다. 장소 정보를 대입한 String 형태의 오브젝트를 인자에 setValueString 메소드를 호출한다. 마지막으로 앞서 만든 Where 형태 오브젝트를 인자에 addLocation 메소드를 호출해 등록한다(&lt;리스트 6&gt; 참조).</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 6&gt; 이벤트에 시간 추가</strong></span></td></tr><tr><td>// 장소를 Where형태 오브젝트에 대입해 이벤트 클래스에 추가<br />
Where evLocation = new Where();<br />
// place 는 앞에서 정의한 것이다.<br />
evLocation.setValueString(place);　<br />
myEntry.addLocation(evLocation);</td></tr></tbody></table><p><br />
&lt;리스트 7&gt;은 구글 캘린더 API 서비스에 접속하기 위해 사용하는 코드인데, new 할 때의 인자는 임의의 애플리케이션 이름을 의미한다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><p class="logout2"><strong>&lt;리스트 7&gt; 서비스 접속</strong></p></td></tr><tr><td>// Google Calendar서비스에 접속<br />
CalendarService myService = new CalendarService("Google Calendar Application");</td></tr></tbody></table><p><br />
&lt;리스트 8&gt;은 구글 캘린더 API의 서비스를 인증하는 코드이다. 이때, 구글 캘린더 로그인으로 사용한다. 리스트에서처럼 gmail 주소와 패스워드를 사용하여 CalendarService 오브젝트의 setUserCredentials 메소드를 호출한다.<br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 8&gt; 서비스 인증</strong></span></td></tr><tr><td>// Google Calendar 서비스 인증<br />
myService.setUserCredentials(gLoginAddr, gLoginPass);</td></tr></tbody></table><p>&nbsp;</p><p>이제 스케줄만 추가하면 된다. &lt;리스트 9&gt;에서처럼 앞서 정의한 구글 캘린더 API 서비스 URL 오브젝트와 이벤트 등록용 클래스 오브젝트를 인자에 넣고 CalendarService 오브젝트의 insert 메소드를 호출한다. 반환 값의 EventEntry 형의 오브젝트는 나중에 사용하므로 반드시 보존해 두어야한다. </p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 9&gt; 스케쥴 추가</strong></span></td></tr><tr><td>// 스케줄을 추가한다<br />
EventEntry insertedEntry = myService.insert(postUrl, myEntry);</td></tr></tbody></table><p><br />
입력된 스케줄의 내용을 수정하거나 내용이 추가될 수도 있으므로 이번에는 특정 스케줄을 조작하는 방법에 대해 알아본다. 스케줄을 조작하려면 우선 특정 스케줄을 수정하는 데 필요한 리퀘스트를 취득해야한다. &lt;리스트 10&gt;은 새로 등록된 스케줄의 반환 값을 사용해서 리퀘스트를 취득하는 코드이다. 이것은 정해진 순서이므로 이대로 이용하면 좋을 것이다.</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 10&gt; 리퀘스트 취득</strong></span></td></tr><tr><td>// 특정 스케줄을 조작하는 리퀘스트를 취득<br />
URL entryUrl = new URL(insertedEntry.getSelfLink() .getHref());<br />
EventEntry retrievedEntry = myService.getEntry(entryUrl, EventEntry.class);</td></tr></tbody></table><p><br />
스케줄을 수정할때 꼭 마지막으로 추가한 것만 수정하란 법은 없다. 이번에는 키워드를 이용하여 특정 스케줄을 찾는 방법에 대해 알아보자. 가장 먼저 해야 할 일은 구글 캘린더 API 서비스용 URL형 오브젝트를 인자에 Query형 오브젝트를 새로 만드는 것이다. 그러고 나서 검색하고 싶은 스케줄의 키워드를 setFullTextQuery 메소드로 설정한다. 이때, 검색하는 대상은 스케줄의 타이틀이 된다. 앞서 만든 Query형 오브젝트를 인자에 CalendarService 오브젝트의 Query 메소드를 호출한다. 반환 값은 Feed형의 오브젝트가 된다. 이 Feed형 오브젝트의 getEntries 메소드를 호출하여 검색한 결과의 유무를 확인하고 임의의 처리를 실행한다. &lt;리스트 11&gt;은 이 순서에 의해 스케줄을 찾아서 검색된 스케줄의 타이틀을 콘솔에 출력하는 코드다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2 logout2"><strong>&lt;리스트 11&gt; 스케줄 찾기</strong></span></td></tr><tr><td>// 특정의 스케줄을 찾는다<br />
Query myQuery = new Query(postUrl);<br />
myQuery.setFullTextQuery("Meeting");<br />
Feed myResultsFeed = myService.query(myQuery, Feed.class);<br />
if (myResultsFeed.getEntries().size() &gt; 0)<br />
{<br />
Entry firstMatchEntry = myResultsFeed.getEntries().get(0); <br />
System.out.println("Titie: " + firstMatchEntry.getTitle().getPlainText());<br />
}</td></tr></tbody></table><p>&nbsp;</p><p>이벤트 정보를 갱신하려면 먼저 EventEntry형 오브젝트에 갱신하고 싶은 정보를 추가한 후에 앞서 설면한 방법으로 리퀘스트를 취득해야 한다. 그 뒤에 캘린더 서비스 오브젝트의 업데이트를 호출하면 된다. 이때, 반환 값의 EventEntry형 오브젝트는 반드시 보존해 둬야한다(&lt;리스트 12&gt; 참조).</p><p>&nbsp;</p><p>이벤트를 추가했으면 삭제하는 기능도 필요하다. 이번에는 이벤트를 삭제하는 방법에 대해 알아보자. 이벤트 정보를 삭제하려면 먼저 앞서 설명한 방법으로 리퀘스트를 취득한 뒤에, 캘린더 서비스 오브젝트의 delete 메소드를　호출하면 된다. 이때, 반환 값의 EventEntry형 오브젝트는 반드시 보존해 둬야한다(&lt;리스트 13&gt; 참조).</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 12&gt; 이벤트 갱신</strong></span></td></tr><tr><td>// 특정의 이벤트의 정보를 갱신<br />
myEntry.setTitle(new PlainTextConstruct("긴급 회의"));<br />
URL editUrl = new URL(retrievedEntry.getEditLink(). getHref());<br />
EventEntry updatedEntry = myService.update(editUrl, myEntry);</td></tr></tbody></table><p><br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2">&lt;리스트 13&gt; 이벤트 삭제</span></td></tr><tr><td>// 특정의 이벤트의 정보를 삭제<br />
URL deleteURL = new URL(updatedEntry.getEditLink(). getHref());<br />
myService.delete(deleteURL);</td></tr></tbody></table><p><br />
지금까지 자바에서 구글 캘린더 API를 사용하는 기본적인 방법에 대해 알아봤다. 다음은 PHP에서 사용하는 방법에 대해 알아볼 차례다. 두 언어의 API 호출 순서와 사용법은 많이 다르지만, 내부적으로 데이터를 처리하는 방법은 같으므로 중복되는 내용은 제외하고 차이점에 대해 보다 자세히 알아볼 것이다.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">PHP를 이용한 캘린더 API 활용</p><p>&nbsp;</p><p>&nbsp;</p><p>PHP는 자바와 달리 구글에서 직접 제공해 주는 라이브러리가 없다. 구글에 링크된 PHP 레퍼런스 사이트는 Zend 사에서 만든 라이브러리 프레임워크다. 어느 곳에서 제공하는가는 큰 문제가 되지는 않지만, API의 스타일이 구글의 스타일과 많이 다르다는 점에는 주목해 볼만하다. 구글에서 직접 제공한 자바 클래스는 자바가 기본적으로 OOP를 지원하는 언어이므로 오브젝트 중심으로 만들어졌다는 느낌이 강하다. 반면에 Zend 사의 프레임워크는 PHP의 다른 프레임워크와 데이터가 중심이 되어 만들어진 클래스 API다. 문제는 이 프레임워크가 PHP 5 전용이라 아직까지 많이 사용되는 PHP 4를 지원하지 않기 때문에 여기서는 Google_GData class를 기준으로 알아본다.</p><p>&nbsp;</p><p>&nbsp;</p><p><strong>PHP 4/5 class library for Google Data APIs</strong></p><p>&nbsp;</p><p>&nbsp;</p><p>이 라이브러리는 GData API와의 통신을 처리하는 PHP 4/5 버전을 지원하는 심플한 클래스 라이브러리다(피드의 해석이나 작성을 실시하는 기능은 제공되지 않는다).</p><p>&nbsp;</p><p>공식 홈페이지: http://www.rcdtokyo.com/etc/gdataapis/</p><p>&nbsp;</p><table border="1" bordercolor="#000000" cellpadding="1" width="550"><tbody><tr><td bgcolor="#ffcccc"><div align="center"><span class="style44">클래스 구성 내용</span></div></td></tr><tr><td bgcolor="#ffcccc"><br />
● Google<br />
- Account.php - 어카운트 인증 API용 클래스<br />
- GData.php - GData API의 공통 클래스<br />
- Calendar.php - Calendar 데이터 API용 클래스<br />
- Blogger.php - Blogger 데이터 API용 클래스<br />
● test.php - 테스트 애플리케이션1<br />
● gbase_demo_alt.php - 테스트 애플리케이션2<br />
● XMLParseIntoStruct.php - XML을 배열을 처리하는 범용의 SAX파서<br />
● README</td></tr></tbody></table><p>&nbsp;</p><p>&nbsp;</p><p>이 클래스의 구성 내용 중 테스트 애플리케이션1(test.php)은 다음에서 설명하는 두 어카운트 인증 API(ClientLogin와Auth Sub)를 각각 사용하여 캘린더의 피드를 취득하는 간단한 기능을 담당한다. 테스트 애플리케이션2(gbase_demo_alt.php)는 Goo gle Base 투고와 편집을 실시하는 것이다. 이는 Google에서 제공하는 Google Base 데이터 API의 PHP 데모를 이 클래스 라이브러리를 사용하여 고쳐 쓴 것이다. 테스트 애플리케이션2를 실행시키기 전에 API 키를 취득하고, 이 스크립트 안에 표기되어 있는 모든 ‘GOOGLE_BASE_DEVELOPER_KEY’의 값을 설정해 주면 된다.</p><p>&nbsp;</p><p>구글 캘린더 데이터 API를 액세스 할 때에는 ‘magicCookie’라고 부르는 URL을 이용하여 비공개 인증을 하지 않지만 스케줄의 추가와 변경, 삭제 시에는 인증을 해야 한다.</p><p>&nbsp;</p><p>&nbsp;</p><p><strong>어카운트 인증의 개요</strong></p><p>&nbsp;</p><p>&nbsp;</p><p>여기에서는 캘린더 데이터 API에서 최초로 어카운트를 인증하는 방법에 대해 알아본다. 구글의 각 서비스 API는 애플리케이션이 리퀘스트를 실시할 때 인증하도록 하고 있다. 이때, 인증은 유저 ID와 패스워드를 이용하는 것이 아니라, 어카운트 인증 API에 의해서 발행되는 대체 데이터를 이용하는데, 이 대체 데이터를 토큰(token)이라고 부른다. 토큰은 그 유효범위 내에서 반복하여 사용할 수 있기 때문에, 애플리케이션을 액세스할 때마다 토큰을 취득할 필요는 없다.</p><p>&nbsp;</p><p>어카운트 인증 API는 ClientLogin와 AuthSub 방식으로 사용할 수 있다. ClientLogin는 데스크톱 애플리케이션에서 사용한다. 유저 ID와 패스워드는 애플리케이션이 직접 취급한니다. 토큰은 애플리케이션이 유저 ID와 패스워드를 송신하여 발행된다. </p><p>&nbsp;</p><p>AuthSub는 웹 애플리케이션용이다. 애플리케이션은 유저 ID와 패스워드는 취급하지 않는다. 토큰은 유저가 Google 어카운트의 웹 사이트에서 그 애플리케이션에 대해서 액세스를 허가하는 조작을하여 발행된다. </p><p>&nbsp;</p><p>AuthSub는 웹 애플리케이션에서 유저를 구글 어카운트의 웹 사이트에 유도하고 애플리케이션에 대한 액세스의 허가를 의뢰한다. 이때 URL은 ‘next’ 파라미터에서 AuthSub의 응답을 처리하여 지정한다.</p><p>&nbsp;</p><p>&nbsp;</p><p><strong>ClientLogin</strong></p><p>&nbsp;</p><p>&nbsp;</p><p>ClientLogin의 예를 보자. https://www.google.com/acc ounts/ClientLogin에 다음과 같은 리퀘스트를 보낸 뒤에 같은 응답이 나오는지 확인해보자.</p><p>&nbsp;</p><p>POST /accounts/ClientLogin HTTP/1.1</p><p>Content-Type: application/x-www-form-urlencoded</p><p>&nbsp;</p><p>Email=Email&amp;Passwd=Passwd&amp;service=service&amp;source=source</p><p>&nbsp;</p><p>이때, 사용되는 POST 데이터의 내용은 &lt;표 2&gt;와 같다.<br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>Key</strong></span></td><td bgcolor="#999999"><span class="logout2"><strong>value</strong></span></td></tr><tr><td>Email</td><td>유저ID(도메인명을 포함한 메일 주소) </td></tr><tr><td>Passwd</td><td>패스워드</td></tr><tr><td>service</td><td>대상 서비스의 ID(GoogleCalendar의 경우는 /cl) </td></tr><tr><td>source</td><td>어플리케이션의 ID{임의의 문자열로 (기업명-어플리케이션명-버전)형식이 추천되고 있습니다 } </td></tr><tr><td>logintoken</td><td>CAPTCHA챌린지의 토큰(CAPTCHA챌린지 이외에서는 생략) </td></tr><tr><td>logincaptcha</td><td>CAPTCHA챌린지의 응답(CAPTCHA챌린지 이외에서는 생략) </td></tr></tbody></table><p>[표2] POST 데이터 테이블 </p><p>&nbsp;</p><p>리퀘스트가 성공할 경우의 응답은 HTTP 200 OK가 된다. 그리고 그 BODY는 아래와 같은 ‘키=값’ 형식의 텍스트가 표시된다. 이 중에서 ‘Auth’ 키의 값이 토큰이지만 다른 값은 현시점에서는 사용되고 있지 않는다.</p><p>&nbsp;</p><p>SID=DQAAAGgA...7Zg8CTN<br />
LSID=DQAAAGsA...lk8BBbG<br />
Auth=DQAAAGgA...dk3fA5N</p><p>&nbsp;</p><p>만약 리퀘스트가 실패하면 그 BODY가 다음과 같은 ‘키=값’ 형식의 텍스트로 표시된다. ‘Error’ 키의 값이 ‘CaptchaRe quired’인 경우가 있는데, 이것은 ClientLogin이지만 로봇 등에 의한 부정 침입의 가능성을 의심하여 CAPTCHA 챌린지(일종의 화상 인증)를 요구하고 있는 것이다.</p><p>&nbsp;</p><p>Error=CaptchaRequired<br />
CaptchaToken=DQAAAGgA...dkI1LK9<br />
CaptchaUrl=Captcha?ctoken=DQAAAGgA...dkI1LK9</p><p>&nbsp;</p><p>이런 경우 애플리케이션은 ‘CaptchaToken’ 키에 나타난 값과 ‘CaptchaUrl’ 키에 나타난 URL, 그리고 표시된 CAPTCHA 챌린지 화상의 응답을 각각 ‘logintoken’과 ‘logincaptcha’의 값을 포스트 데이터에 추가한다. 이렇게하여 ClientLogin의 리퀘스를 다시 실시하는 것이다.</p><p>&nbsp;</p><p>&lt;리스트 14&gt;는 라이브러리를 이용하여 ClientLogin과 토큰을 취득하여 표시해 주는 코드이다. 여기에서 취득한 토큰은 일단 PHP의 세션 데이터에 보관된다. 토큰은 반복해서 사용할 수 있기 때문에 애플리케이션이 서비스 API에 여러 차례의 리퀘스트를 실시할 스케줄이라면 토큰을 PHP의 세션 데이터에 보관하면, 리퀘스트할 때마다 토큰을 취득하지 않고 보존되어 있는 것을 사용할 수 있다.</p><p>&nbsp;</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 14&gt; ClientLogin 토큰 취득</strong></span></td></tr><tr><td><p><br />
&lt;?php<br />
$email = 'myaccount@gmail.com';<br />
$password = 'password';</p><p>require_once 'Google/Calendar.php';<br />
$service = new Google_Calendar;</p><p>session_start();<br />
if (!isset($_SESSION['tokens'])) {<br />
$_SESSION['tokens'] = array();<br />
}<br />
if (!isset($_SESSION['tokens']['calendar'])) {<br />
if (!$service-&gt;requestClientLogin($email, $password)) {<br />
exit("ClientLogin has failed.n".$service-&gt;getResponseBody());<br />
}<br />
$_SESSION['tokens']['calendar'] = array(<br />
$service-&gt;token,<br />
$service-&gt;authType<br />
);<br />
}<br />
var_dump($_SESSION['tokens']);<br />
?&gt;</p></td></tr></tbody></table><p>&nbsp;</p><p>이 경우 실제로 API에 리퀘스트를 실시할 때 토큰을 취득한 어카운트 인증 API는 ClientLogin나 AuthSub에 의해서 송신된 어카운트의 내용이 다르다. 때문에, 토큰에는 그것을 취득한 어카운트 인증 API의 종류(이 클래스에서는 authType 프로퍼티)도 함께 붙여두어야 한다.</p><p>&nbsp;</p><p>또, 토큰은 각 서비스 API마다 다르므로 애플리케이션이 다수의 서비스를 이용하는 경우에는 앞서 해시의 키를 서비스 이름으로 사용한 것처럼, 그것이 어느 서비스를 위한 것인지 식별할 수 있도록 해 두는 것이 좋다</p><p>AuthSub, AuthSubTokenInfo에 의해서 토큰의 대상 서비스를 확인할 수 있다).</p><p>&nbsp;</p><p><strong>AuthSub</strong></p><p>&nbsp;</p><p>AuthSub 토큰은 구글 어카운트의 웹 사이트에서 표시되는 액세스 요구의 확인 폼이다. 이 토큰은 사용자가 ‘액세스를 허가’를 클릭할 때 발생된다. 사용자는 우선 https://www.google. com/accounts/AuthSubRequest에 다음의 파라미터를 쿼리-문자열로 지정한 URL에 액세스한다(웹 애플리케이션은 유저에게 이 URL을 표시하고 액세스의 허가를 의뢰한다).</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>Key</strong></span></td><td bgcolor="#999999"><span class="logout2"><strong>Value</strong></span></td></tr><tr><td>next</td><td>액세스가 허가되었을 경우에 행해지는 리디렉트처의 URL </td></tr><tr><td>&nbsp;</td><td>(AuthSub의 응답을 처리하는 웹 어플리케이션의 URL </td></tr><tr><td>scope</td><td>대상서비스의 URL (GooleCalendar의 경우는 {http://www.google.com/calendar/feeds/)} </td></tr><tr><td>session</td><td>일회용 토큰을 세션 토큰과 교환하는지 아닌지 </td></tr></tbody></table><p>[표3] 쿼리 문자열 값 </p><p>&nbsp;</p><p>사용자가 ‘액세스를 허가’를 클릭하면 AuthSub는 ‘next’ 파라미터로 지정되었다가 URL에 ‘token’ 파라미터를 부가해 리디렉트한다.<br />
이 ‘token’ 파라미터의 값은 일회용 토큰(one-time|single use token)이다. 일회용 토큰이라고는 하지만 쿼리에 있는 「sess ion」 파라미터 값이 「1」인 경우, 반복 이용할 수 있는 세션 토큰(multi-use session token)과 교환할 수 있다. 일회용 토큰을 세션 토큰과 교환하려면 https://www.google.com/accounts/ AuthSubSessionToken에 대해서 다음과 같이 리퀘스트를 송신한다. Authorization 헤더로 지정한 token은 일회용 토큰의 값이다.</p><p>&nbsp;</p><p>GET /accounts/AuthSubSessionToken HTTP/1.1<br />
Authorization: AuthSub token=”token”</p><p>&nbsp;</p><p>리퀘스트가 성공하면 HTTP 200 OK가 표시되고 BODY는 ‘키=값’ 형식의 텍스트가 된다. 이 중에서 ‘Token’ 키의 값은 세션 토큰이다. 다른 값에 대해서는 현시점에서는 사용되고 있지 않다.</p><p>&nbsp;</p><p>Token=DQAA...7DCTN<br />
Expiration=20061004T123456Z</p><p>&nbsp;</p><p>사용자가 다음의 링크를 클릭하면 표시되는 액세스 확인 폼에서 ‘액세스의 허가’를 클릭하면 http://www.abcd.com/gcal/ auth.php?token=token URL에 리디렉트 된다. 이 URL의 ‘token’ 파라미터 값은 캘린더 데이터 API를 대상으로 한 세션 토큰과 교환 할 수 있는 일회용 토큰이다.</p><p>&nbsp;</p><p>&lt;a href=”&lt;?php<br />
require_once ‘Google/Calendar.php’;<br />
echo Google_Calendar::getAuthSubRequestUrl(‘http://www. abcd.com/gcal/auth.php’)<br />
?&gt;”&gt;</p><p>&nbsp;</p><p>&lt;리스트 15&gt;은 토큰을 취득한 뒤에 보존하는 코드다. 여기에서는 일회용 토큰(‘token’ 파라미터의 값)을 세션 토큰과 교환하고 있다. 취득한 토큰은 ClientLogin의 예와 같이 PHP의 세션 데이터에 보존된다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 15&gt; AuthSub 토큰 취득 후 보존</strong></span></td></tr><tr><td><p>&lt;?php<br />
require_once 'Google/Calendar.php';<br />
$service = new Google_Calendar;</p><p>session_start();<br />
if (isset($_GET['token']) and strlen($_GET['token']) &gt; 0) {<br />
if (!$service-&gt;requestAuthSubSessionToken($_GET['token'])) {<br />
exit("AuthSubSessionToken has failed.n".$service-&gt;getResponseBody());<br />
}<br />
if (!isset($_SESSION['tokens'])) {<br />
$_SESSION['tokens'] = array();<br />
}<br />
$_SESSION['tokens']['calendar'] = array(<br />
$service-&gt;token,<br />
$service-&gt;authType<br />
);<br />
var_dump($_SESSION['tokens']);<br />
}<br />
?&gt;</p></td></tr></tbody></table><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">토큰의 확인과 폐기</p><p>&nbsp;</p><p>&nbsp;</p><p>AuthSub의 유효한 토큰의 발행 수는 1 유저, 1 애플리케이션으로 제한된다. 그 때문 취득한 토큰을 폐기(revoke)해야 하는 경우도 생긴다. 토큰이 유효한지 확인하려면 https://www.google. com/accounts/AuthSubTokenInfo에 대해서 다음과 같이 리퀘스트를 송신한다.</p><p>&nbsp;</p><p>GET /accounts/AuthSubTokenInfo HTTP/1.1<br />
Authorization: AuthSub token=”token”</p><p>&nbsp;</p><p>지정한 토큰이 유효하다면 HTTP 200 OK가 표시되고 BODY는 다음과 같이 ‘키=값’ 형식의 텍스트가 된다.</p><p>&nbsp;</p><p>Target=www.abcd.com<br />
Scope=http://www.google.com/calendar/feeds/<br />
Secure=false</p><p>&nbsp;</p><p>유효한 토큰을 폐기하려면 https://www.google.com/ accounts/AuthSubRevokeToken에 대해서 다음과 같이 리퀘스트를 송신한다.</p><p>&nbsp;</p><p>GET /accounts/AuthSubRevokeToken HTTP/1.1<br />
Authorization: AuthSub token=”token”</p><p>&nbsp;</p><p>이때, 리퀘스트가 성공하면 HTTP 200 OK가 표시된다. 덧붙여 사용자는 구글 어카운트 웹 사이트의 ‘어카운트 정보’ 페이지를 이용해서 현재 유효한 AuthSub 토큰의 확인과 폐기를 할 수 있다. 또 ,AuthSub의 액세스 요구 시에 이미 제한된 수를 초과하여 발행되고 있다면 그와 관련된 메시지도 표시된다.<br />
&lt;리스트 16&gt;은 토큰의 유효성을 확인한 뒤에 제한 개수를 초과하는 유효한 토큰을 폐기하는 코드이다. </p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 16&gt; 취득한 토큰 폐기</strong></span></td></tr><tr><td><p>&lt;?php<br />
$token = 'GD32CMCL25aZ-v____8B';</p><p>require_once 'Google/Calendar.php';<br />
$service = new Google_Account;</p><p>if (!$service-&gt;requestAuthSubTokenInfo($token)) {<br />
echo("Token $token is not valid.");<br />
} else {<br />
if (!$service-&gt;requestAuthSubRevokeToken($token)) {<br />
exit("AuthSubRevokeToken has failed.n".$service-&gt;getResponseBody());<br />
}<br />
echo("Token $token has been revoked and is no longer valid.");<br />
}<br />
?&gt;</p></td></tr></tbody></table><p>&nbsp;</p><p><strong>Calendar 데이터의 취득</strong></p><p>&nbsp;</p><p>구글 캘린더 데이터 API와 애플리케이션은 Atom 1.0(또는 RSS 2.0)에 준한 GData로 불리는 피드(Feed) 데이터를 HTTP통신으로 교환한다. 구글 캘린더의 피드는 http://www.google. com/calendar/feeds/User_ID/Visibility/Projection[/Entry_ID|?Query_String] 형식의 URL에 액세스 하여 취득한다. 하지만 이벤트의 추가나 변경, 삭제를 실시하는 애플리케이션에서는 일반적으로 http://www.google.com/calendar/feeds/default/ private/full에 대해서 다음과 같은 리퀘스트를 송신하고 읽고 쓰기의 어느 것에도 이용할 수 있는 비공개 스케줄을 포함한 피드를 취득한다.</p><p>&nbsp;</p><p>GET /calendar/feeds/default/private/full[/Entry_ID|?Query_String] HTTP/1.1<br />
Authorization: [GoogleLogin auth=ClientLogin_token|AuthSub token=”AuthSub_token”]</p><p>&nbsp;</p><p>URL에 &lt;표4&gt;와 같은 검색 파라미터를 쿼리-문자열로 지정하면 조건에 맞는 피드를 취득할 수 있다. 더불어 날짜는 RFC3339 형식으로 지정한다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>Key</strong></span></td><td bgcolor="#999999"><span class="logout2"><strong>Value</strong></span></td></tr><tr><td>q</td><td>문자열의 검색식(구글의 웹 검색에서처럼 「"」,「ㅣ」,「ㅡ」등의 오퍼레이터를 사용할 수 있다) </td></tr><tr><td>max-results</td><td>최대 취득 건수(생략 시 :25건) </td></tr><tr><td>start-index</td><td>취득 개시 엔트리의 색인 번호(생략 시 :1) </td></tr><tr><td>orderby</td><td>엔트리의 줄 순서 (생략 시 :갱신 일시 순서 starttime : 개시 일시 순서) </td></tr><tr><td>start-min</td><td>가장 낡은 이벤트의 개시 일시(생략 시 : 1970-01-01) </td></tr><tr><td>start-max</td><td>가장 새로운 이벤트의 종료 일시(생략 시 : 2031-01-01) </td></tr><tr><td>updated-min</td><td>가장 낡은 엔트리의 갱신 일시 </td></tr><tr><td>updated-max</td><td>엔트리의 author, name 요소 또는 author,emai 요소(완전 일치) </td></tr><tr><td>author</td><td>피드 종류별(생략 시 : Atom 1.0lrss : RSS 2.0) </td></tr><tr><td>alt</td><td>&nbsp;</td></tr></tbody></table><p>[표4] Calendar 검색 형식 </p><p>&nbsp;</p><p>검색 파라미터 중에 start-min과 start-max, orderby는 캘린더 데이터 API에만 있는 것이고 그 이외는 GData에도 있는 공통 파라미터이다. 덧붙여 캐린더 데이터 API는 GData 공통의 검색 파라미터 중에서 category는 지원하지 않는다.<br />
&lt;리스트 17&gt; 캘린더의 데이터 피드를 취득하는 코드다. 여기에서는 ClientLogin와 토큰을 취득한 뒤에 개시된 스케줄 중에서 ‘약속’이나 ‘회의’라는 문자열을 포함하는 이벤트를 검색한다. 그리고 지정한 문자열을 포함하는 이벤트 중 가장 최근의 10건에 해당하는 피드를 취득한다.</p><p><br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 17&gt; Calendar 데이터 피드 취득</strong></span></td></tr><tr><td><p>&lt;?php<br />
$email = 'example@gmail.com';<br />
$password = 'password';</p><p>require_once 'Google/Calendar.php';<br />
$service = new Google_Calendar;</p><p>if (!$service-&gt;requestClientLogin($email, $password)) {<br />
exit("ClientLogin has failed.n".$service-&gt;getResponseBody());<br />
}<br />
$queries = array(<br />
'q' =&gt; '약속|회의,<br />
'max-results' =&gt; 10,<br />
'orderby' =&gt; 'starttime',<br />
'start-min' =&gt; date('Y-m-dTH:i:s+09:00', time())<br />
);<br />
if (!$service-&gt;requestFeed($queries)) {<br />
exit("Requesting a feed has failed.n".$service-&gt;getResponseBody());<br />
}<br />
header('Content-Type:application/xml;charset=UTF-8');<br />
echo $service-&gt;getResponseBody();<br />
?&gt;</p></td></tr></tbody></table><p>&nbsp;</p><p><strong>이벤트의 추가</strong></p><p>&nbsp;</p><p>이벤트를 추가하려면 http://www.google.com/calendar/ feeds/default/private/full에 대해서 다음과 같이 리퀘스트를 송신한다.</p><p>&nbsp;</p><p>POST /calendar/feeds/default/private/full HTTP/1.1<br />
Authorization: [GoogleLogin auth=”ClientLogin_token”|AuthSub token=”AuthSub_token”]<br />
Content-Type: application/atom+xml</p><p>&nbsp;</p><p>&lt;리스트 18&gt;는 Atom 1.0의 스펙에 맞춘 GData 의 활용 예이다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 18&gt; GData 피드 데이터</strong></span></td></tr><tr><td><p>&lt;entry<br />
xmlns="http://www.w3.org/2005/Atom"<br />
xmlns:gd="http://schemas.google.com/g/2005"&gt;<br />
&lt;category<br />
scheme="http://schemas.google.com/g/2005#kind"<br />
term="http://schemas.google.com/g/2005#event"&gt;<br />
&lt;/category&gt;<br />
&lt;title type="text"&gt;고객 접대&lt;/title&gt;<br />
&lt;content type="text"&gt;코엑스에서 계약관계로 만남&lt;/content&gt;<br />
&lt;gd:where valueString=”미팅”&gt;<br />
&lt;/gd:where&gt;<br />
&lt;gd:when<br />
startTime="2006-10-07T15:00:00+09:00"<br />
endTime="2006-10-07T17:00:00+09:00"&gt;<br />
&lt;/gd:when&gt;<br />
&lt;/entry&gt;</p><p>&lt;content type="text"&gt;코엑스에서 계약관계로 만남&lt;/content&gt;<br />
&lt;gd:where valueString=”미팅”&gt;<br />
&lt;/gd:where&gt;<br />
&lt;gd:when<br />
startTime="2006-10-07T15:00:00+09:00"<br />
endTime="2006-10-07T17:00:00+09:00"&gt;<br />
&lt;/gd:when&gt;<br />
&lt;/entry&gt;</p></td></tr></tbody></table><p>&nbsp;</p><p>이벤트가 ‘종일’인 경우에는 gd:when 요소의 startTime/ endTime 속성 치에 날짜만 지정하면 된다. ‘반복’ 이벤트인 경우에는 gd:recurrence 요소를 지정한다.<br />
GData의 문자 인코딩은 UTF-8이다. 일시는 Atom 1.0 RFC 3339 형식에서 지정한다. 이때, 리퀘스트가 성공하면 HTTP 201 Created가 표시되고 BODY는 송신한 GData에 id 요소나 updated 요소 등이 추가된 피드 데이터가 된다.<br />
&lt;리스트 19&gt;은 ClientLogin 그리고 토큰을 취득한 후에 이벤트를 추가하는 예제이다.<br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 19&gt; 캘린더 이벤트 추가</strong></span></td></tr><tr><td><p>&lt;?php<br />
$email = 'example@gmail.com';<br />
$password = 'password';</p><p>$entry = &lt;&lt;&lt;GDATA<br />
&lt;entry<br />
xmlns="http://www.w3.org/2005/Atom"<br />
xmlns:gd="http://schemas.google.com/g/2005"&gt;<br />
&lt;category<br />
scheme="http://schemas.google.com/g/2005#kind"<br />
term="http://schemas.google.com/g/2005#event"&gt;<br />
&lt;/category&gt;<br />
&lt;title type="text"&gt;고객 접대&lt;/title&gt;<br />
&lt;content type="text"&gt;코엑스에서 계약관계로 만남&lt;/content&gt;<br />
&lt;gd:where valueString="미팅"&gt;<br />
&lt;/gd:where&gt;<br />
&lt;gd:when<br />
startTime="2006-10-07T15:00:00+09:00"<br />
endTime="2006-10-07T17:00:00+09:00"&gt;<br />
&lt;/gd:when&gt;<br />
&lt;/entry&gt;<br />
GDATA;</p><p>require_once 'Google/Calendar.php';<br />
$service = new Google_Calendar;</p><p>if (!$service-&gt;requestClientLogin($email, $password)) {<br />
exit("ClientLogin has failed.n".$service-&gt;getResponseBody());<br />
}<br />
if (!$service-&gt;insert($entry)) {<br />
exit("Inserting an entry has failed.n".$service-&gt;getResponseBody());<br />
}<br />
header('Content-Type:application/xml;charset=UTF-8');<br />
echo $service-&gt;getResponseBody();<br />
?&gt;</p><p>}<br />
header('Content-Type:application/xml;charset=UTF-8');<br />
echo $service-&gt;getResponseBody();<br />
?&gt;</p></td></tr></tbody></table><p>&nbsp;</p><p>&nbsp;</p><p><strong>이벤트의 변경과 삭제</strong></p><p>&nbsp;</p><p>이벤트의 변경 및 삭제는 그 이벤트 엔트리의 link 요소 중에서 rel 속성이 ‘edit’의 href 속성에 나타나고 있는 URL에 대해서 리퀘스트를 송신한다.<br />
이벤트를 변경할 때에는 다음과 같이 PUT 메소드(또는 X-Http-Method-Override헤더에 「PUT」을 지정한 POST메소드)를 이용하고 변경한 GData를 송신하면 된다.</p><p>&nbsp;</p><p>PUT Edit_URL HTTP/1.1<br />
Authorization: [GoogleLogin auth=”ClientLogin_token”|AuthSub token=”AuthSub_token”]<br />
Content-Type: application/atom+xml</p><p>&nbsp;</p><p>이벤트를 삭제하려면 다음과 같이 DELETE 메소드(또는 X-Http-Method-Override헤더에 「DELETE」를 지정한 POST메소드)를 이용한다.</p><p>&nbsp;</p><p>DELETE Edit_URL HTTP/1.1<br />
Authorization: [GoogleLogin auth=”ClientLogin_token”|AuthSub token=”AuthSub_token”]</p><p>&nbsp;</p><p>리퀘스트가 모두 성공하면 HTTP 200 OK가 표시된다. &lt;리스트 20&gt;은 ClientLogin과 토큰을 취득한 후에 이벤트의 개시와 종료 일시를 변경하는 코드이다.</p><p><br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 20&gt; 캘린더 이벤트 변경</strong></span></td></tr><tr><td><p>&lt;?php<br />
$email = 'example@gmail.com';<br />
$password = 'password';</p><p>$edit_url = 'http://www.google.com/calendar/feeds/default/private/full/abcd/1234';<br />
$entry = &lt;&lt;&lt;GDATA<br />
&lt;entry<br />
xmlns="http://www.w3.org/2005/Atom"<br />
xmlns:gd="http://schemas.google.com/g/2005"&gt;<br />
&lt;category<br />
scheme="http://schemas.google.com/g/2005#kind"<br />
term="http://schemas.google.com/g/2005#event"&gt;<br />
&lt;/category&gt;<br />
&lt;gd:when<br />
startTime="2006-10-07T14:00:00+09:00"<br />
endTime="2006-10-07T18:00:00+09:00"&gt;<br />
&lt;/gd:when&gt;<br />
&lt;/entry&gt;<br />
GDATA;</p><p>require_once 'Google/Calendar.php';<br />
$service = new Google_Calendar;</p><p>if (!$service-&gt;requestClientLogin($email, $password)) {<br />
exit("ClientLogin has failed.n".$service-&gt;getResponseBody());<br />
}<br />
if (!$service-&gt;update($entry, $edit_url)) {<br />
exit("Updating an entry has failed.n".$service-&gt;getResponseBody());<br />
}<br />
header('Content-Type:application/xml;charset=UTF-8');<br />
echo $service-&gt;getResponseBody();<br />
?&gt;</p></td></tr></tbody></table><p>&nbsp;</p><p><br />
지금까지 구글의 캘린더 API를 사용하는 방법에 대해 간단히 알아보았다. 일단 캘린더 API의 사용법을 잘 익혀둔다면 구글에서 제공하는 레퍼런스를 참고하여 다른 서비스 API도 쉽게 사용할 수 있을 것이다. 어차피 복잡한 통신 프로토콜의 처리 등은 API가 알아서 처리해 주니 우리는 데이터 처리만 신경 쓰면 되는 것이다. <br />
</p><p>&nbsp;</p><table border="0" width="550"><tbody><tr><td bordercolor="#ffffff" bgcolor="#cccccc"><p>참고 자료<br />
1) Google Data APIs JAVA Developer’s Guide : http://code.google.com/apis/gdata/client-java.html<br />
2) PHP 4/5 class library for Google Data APIs Download Link : http://www.rcdtokyo.com/etc/gdataapis/gdataapis.zip</p></td></tr></tbody></table><p>&nbsp;</p><p><br />
</p><p><br />
<br />
<a href="http://www.dbguide.net/" target="_blank"><b><font color="midnightblue">제공 : DB포탈사이트 DBguide.net </font></b></a></p><br />
<div align="right">출처 : Micro Software [2007년 4월호]</div>			 ]]> 
		</description>
		<category>OpenID</category>

		<comments>http://netkong.egloos.com/373153#comments</comments>
		<pubDate>Wed, 04 Jul 2007 12:59:00 GMT</pubDate>
		<dc:creator>넷콩</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 네이버 검색 기술을 이용한 지역검색 서비스 만들기  ]]> </title>
		<link>http://netkong.egloos.com/373151</link>
		<guid>http://netkong.egloos.com/373151</guid>
		<description>
			<![CDATA[ 
  <p class="title1"><b style="color: rgb(51, 51, 51);">웹2.0 시대의 견인차 Open API </b></p><p>&nbsp;</p><p>&nbsp;</p><p class="contentsbox">OpenAPI에 개발자들의 아이디어가 더해지면서 다양한 매쉬업 서비스들이 세상에 등장하고 있다. 이 서비스들은 기존에 생각지 못했던 일들을 가능하게 하거나, 다른 서비스 사업자의 서비스들을 활용하고 거기에 독창성을 더하여 큰 수익을 내고 있기도 하다. 구글과 몇몇 유명 해외 포털들이 API를 오픈하고 이로 인한 성과들이 나자, 국내의 포털과 사이트들도 자신들의 서비스를 개방하는데 앞장서고 있다. 구글 맵이나 다른 해외 API의 한글화 문제 탓에 활용을 꺼렸던 개발자들에게 국내 포털들의 API 오픈은 단비 같은 존재. 이번 특집에서는 구글과 네이버, 다음의 OpenAPI 활용법에 대해 알아보고 개발자들이 이 API들을 어떻게 활용해야 개발자의 역량을 키우고 수익도 올릴 수 있을지에 대해 알아본다.</p><p>&nbsp;</p><p class="author">기획·정리 <br />
| 정희용 기자 flytgr@imaso.co.kr</p><p>&nbsp;</p><p class="title1">네이버 검색 기술을 이용한 지역검색 서비스 만들기</p><p>&nbsp;</p><p class="contentsbox">OpenAPI의 효용은 검색 엔진 제작이나 검색 DB 구축, 지역 DB 구축 등 웬만한 시간과 노력으로는 쉽게 만들어질 수 없는 기술과 콘텐츠들을, 얼마든지 쉽게 가져다 응용할 수 있다는 데에 있다. 시간과 돈이 많이 드는 기반 기술들이 OpenAPI로 제공되고, 개발자는 거기에 자신의 아이디어를 입혀 상상했던 프로그램을 좀 더 쉽게 만들어 낼 수 있도록 하는 것, 그것이 바로 OpenAPI의 매력이 아닐까? 3부에서는 국내 포털 중 가장 먼저 OpenAPI를 제공하기 시작한 네이버의 API를 이용한 예제를 따라 해 보면서, OpenAPI를 활용한 응용서비스 개발의 기초를 다져보자. </p><p class="author">&nbsp;</p><p class="author">장정환 inome@nhncorp.com</p><p>&nbsp;</p><p>&nbsp;</p><p>지금부터 우리는 지도를 이용하여 다음과 같은 기능을 가진 간단한 응용프로그램을 만들어 볼 것이다. </p><p>&nbsp;</p><p>여러 가지 검색 API중 지역 검색 API(http://openapi.naver. com/page.nhn? PageId=22)를 이용하여 업체의 정보를 얻고, 이 정보를 바탕으로 지도상에 업체의 위치를 표시한다. 지도에 표시된 업체를 선택하면, 업체에 대한 내용을 블로그 검색 API(http://openapi. naver.com/page.nhn?PageId=02)를 사용하여 동적으로 링크를 표시하는 프로그램이다. 완성된 프로그램이라기보다는 지도 API와 검색 API의 활용법을 보여주는 프로그램이므로 이 점을 주의해서 살펴보자. </p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">API 키 발급받기</p><p>&nbsp;</p><p>&nbsp;</p><p>네이버에서 제공하는 OpenAPI를 이용하려면, 우선 네이버 API 이용 등록을 통해 API 키를 발급받아야 한다. 키에는 검색을 위한 키와 지도 사용을 위한 키가 있다. 이번 프로그램에서는 지도 API와 검색 API를 동시에 사용하므로 두 가지 키를 모두 발급받아야 프로그램을 만들 수 있다.</p><p>&nbsp;</p><p>&nbsp;</p><p><strong>검색 API 키 발급 받기</strong></p><p>&nbsp;</p><p>&nbsp;</p><p>검색 API 키는 API 이용등록 페이지(http://openapi.naver. com/register.nhn)에서 발급 받을 수 있다. Email과 연락처, 사용 예상 API와 사용용도 등을 기입하고 이용약관에 동의하면 바로 검색 API 키를 발급 받을 수 있다. 검색 API 키는 네이버 ID 하나 당 한 개씩 발급되며 하루 5천 개의 질의를 할 수 있다.</p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-09.jpg"></p><p>[화면1] API 이용등록 페이지 </p><p>&nbsp;</p><p><strong>지도 API 키 발급 받기</strong><br />
지도 API 키도 검색 API 키와 마찬가지로 API 이용등록 페이지(http://openapi.naver.com/register.nhn)에서 발급 받을 수 있다. 지도 API 키의 발급은 검색 API 키를 발급 받는 것과는 조금 차이가 있다. 키를 발급 받을 때, 지도 API 키를 이용하려는 도메인과 디렉토리 정보를 넣어야 키를 발급 받을 수 있다는 점이다.<br />
도메인과 디렉토리 정보를 입력하여 지도 API 키를 발급 받으면, 해당 키는 등록한 URL 하에서만 사용할 수 있다. 따라서 정상적으로 키를 발급 받고도 URL이 맞지 않으면 지도가 출력되지 않으므로, 지도가 정상적으로 보이지 않는 경우 지도 API 키를 발급 받을 때 입력한 URL과 현재 개발 중인 페이지가 일치하는 지 확인해봐야 한다. 만약 여러 도메인에서 지도 API를 사용하려면, 추가 지도 API 키를 발급 받아 사용하면 된다.<br />
기본 포트(80)가 아닌 다른 포트를 사용할 경우, 키를 발급 받을 때 포트 정보를 입력하여 지도 API 키를 발급받아야 한다. 지도 API 키는 하루에 5만 번의 요청을 할 수 있다. 이는 하나의 사용자 ID당 제한 횟수로써 만약 지도 API 키를 다섯 개 발급 받았다면 다섯 개 키를 모두 합해 5만 번의 요청을 할 수 있다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>기준 이상의 질의를 사용하려면 </strong></span></td></tr><tr><td><p align="left">네이버의 OpenAPI는 네이버에서 요청하는 몇 가지 기준만 맞춘다면 상업적인 용도로도 사용할 수 있다. 위에 언급된 것처럼 하루 5천 질의 (검색 API의 경우)나 하루 5만 요청(지도 API의 경우)이 사용하기에 충분하지 않다면, OpenAPI 제휴 페이지(http://openapi.naver.com/cooperation.html)를 통해 제휴 신청을 하면 제한 없이 OpenAPI를 사 용할 수 있다.</p></td></tr></tbody></table><p>&nbsp;</p><p class="sub1">개발 환경의 구성</p><p>&nbsp;</p><p>&nbsp;</p><p>이 프로그램은 PHP와 자바스크립트로 이루어져 있다. PHP는 버전 5이상이어야 하며, 자바스크립트를 실행시키기 위해서 파이어폭스 1.5 이상이나 인터넷 익스플로러 6 이상을 사용해야 한다. 지도 API를 사용하기 위해서는 도메인 주소나 IP가 있어야 하므로 서버가 필요하다.</p><p>&nbsp;</p><p><strong>프로그램의 구조</strong></p><p>&nbsp;</p><p>지금부터 만들어 볼 프로그램은 크게 두 개의 파일로 이루어진다. 프로그램의 메인이 되는 mapsearch.php와 블로그의 검색 결과를 전달해 줄 blogsearch.php이다. mapsearch.php에서는 지역 검색 API를 이용하여 지역 정보를 얻어오고, 이 정보를 지도에 표시하는 기능을 한다. blogsearch.php에서는 검색 결과 타이틀을 질의어로 삼아 블로그 검색 API를 이용하여 해당 업체/기관에 대한 블로그 검색 결과를 보여준다. <br />
</p><table border="1" bordercolor="#000000" width="600"><tbody><tr><td colspan="2" bgcolor="#cccccc"><p>지도API 살펴보기 </p><p>&nbsp;</p></td></tr><tr><td colspan="2" bgcolor="#cccccc"><p>프로그램을 만드는 동안 사용되는 주요 클래스는 다음 표와 같다. 그 밖의 추가적인 정보를 위해서는 지도 API 클래스 참조 페이지(http://openapi.naver.com/page.nhn?Pageld=19_3)를 참고하길 바란다. </p><p>&nbsp;</p></td></tr><tr><td bgcolor="#999999"><span class="logout2"><strong>클래스명</strong></span></td><td bgcolor="#999999"><span class="logout2"><strong>역할</strong></span></td></tr><tr><td>NMap</td><td>지도 객체를 위한 클래스, 지도 API에서 가장 중요한 클래스다. </td></tr><tr><td>NSize</td><td>사이즈를 표현하기 위한 클래스 </td></tr><tr><td>NPoint</td><td>특정한 점을 표현하기 위한 클래스 </td></tr><tr><td><p>NEvent</p></td><td>NMap, MNark, NlnfoWindow 객체에 이벤트를 등록하기 위한 클래스 </td></tr><tr><td>NMark</td><td>마커를 표현하기 위한 클래스, 아이콘 객체에 등록된 이미지를 NMap 객체에 추가하는 역할을 한다. </td></tr><tr><td>NIcon</td><td>아이콘을 위한 클래스. 이 객체를 직접 NMap 객체에 추가할 수는 없으므로 NMark 클래스를 사용해야 한다. </td></tr><tr><td>NInfoWindow</td><td>정보 창을 위한 클래스 </td></tr><tr><td>Nxmlhttp</td><td>간단하게 Ajax를 사용할 수 있도록 해주는 클래스 </td></tr><tr><td>NZoomControl</td><td>지도를 확대, 축소할 수 있는 컨트롤을 제공하는 클래스 </td></tr></tbody></table><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">지도 띄워보기</p><p>&nbsp;</p><p>지도 API 키를 발급받았다면 아주 간단한 코드로 지도를 띄울 수 있다. &lt;리스트 1&gt;은 화면상에 지도를 표시하고 검색을 위한 검색창을 화면에 출력하기 위한 코드이다. </p><p>&nbsp;</p><p>지도를 띄우기 위해 가장 먼저 할 일은 지도 API를 사용하기 위해 네이버에서 제공하는 스크립트를 include 하는 것이다. 이때 key의 인자로 미리 발급받은 지도 API 키를 입력해야 한다. 그 다음, 지도를 출력할 컨테이너를 설정한다. 여기서는 div 요소를 사용하였다. 다음으로 NMap 객체를 생성한다. NMap 객체를 생성할 때는 지도를 출력할 컨테이너에 대한 참조를 인자로 전달해야 한다. 컨테이너에 표시할 지도의 영역은 setBound() 메소드를 사용하여 설정한다. </p><p>&nbsp;</p><p>여기까지 마치면 기본적인 지도가 출력되는 것을 확인할 수 있다. </p><p>&nbsp;</p><p>여기에 손쉽게 지도를 확대, 축소하기 위한 줌 컨트롤 객체를 추가한다. setAlign(), setValign() 메소드를 사용하여 줌 컨트롤 객체가 지도 영역 상에 표시되는 위치를 지정한다.</p><p>&nbsp;</p><p>지도가 출력되는 영역의 사이즈를 변경하려면 div 요소의 사이즈를 변경하고, NMap객체를 생성할 때 인자로 넘겨주는 너비와 높이의 값을 변경시켜주면 된다. NMap 객체를 생성할 때 너비와 높이는 인자로 넘겨주지 않아도 되는데, 이 경우 컨테이너의 너비와 높이 값을 사용하게 된다.<br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 1&gt; 지도 띄우기</strong></span></td></tr><tr><td><p>&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;meta http-equiv=Content-Type content="text/html; charset=utf-8"&gt;<br />
&lt;meta http-equiv=Cache-Control content=No-Cache&gt;<br />
&lt;meta http-equiv=Pragma content=No-Cache&gt;<br />
&lt;title&gt;Map Search&lt;/title&gt;<br />
&lt;/head&gt;<br />
&lt;body style="margin:0px 0px 0px 0px"&gt;<br />
&lt;script type="text/JavaScript" src="http://maps.naver.com/ js/naverMap.naver?key=지도API 키"&gt;&lt;/script&gt;<br />
&lt;div id='mapContainer' style='width:960px;height:550px'&gt; &lt;/div&gt; <br />
&lt;script type="text/javascript"&gt;<br />
// 기본 지도 생성<br />
var mapObj = new NMap(document.getElementById('mapContainer'),960,550);<br />
mapObj.setBound(319198, 527730, 323198, 531730); <br />
mapObj.zoomOut();</p><p>// 확대, 축소를 위한 컨트롤을 생성한다.<br />
var zoom = new NZoomControl();<br />
zoom.setAlign("right");<br />
zoom.setValign("bottom");<br />
mapObj.addControl(zoom);<br />
&lt;/script&gt;</p><p>&lt;div id="searchform"&gt;<br />
&lt;form name="mapsearch" method="get" action="mapsearch1.php"&gt;<br />
&lt;input type="text" name="query"&gt;<br />
&lt;input type="submit" value="Map Search"&gt;<br />
&lt;/form&gt;<br />
&lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p></td></tr></tbody></table><p>&nbsp;</p><p>&lt;리스트 1&gt;에서는 특정한 영역을 기준으로 지도를 표시하기 위해 setBound() 메소드를 사용했다. 특정한 점을 중심으로 지도를 표시해야 할 때는 setCenter()나 setCenterAndZoom() 메소드를 사용하면 편리하다. 이 소스는 다음과 같이 사용할 수 있다.</p><p>&nbsp;</p><p>mapObj.setCenter(new NPoint(321198, 529730));<br />
mapObj.setCenterAndZoom(new NPoint(321198, 529730), 3);<br />
</p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-10.jpg"></p><p>[화면2] (리스트1) 을 실행시킨 화면</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">지역 정보를 검색하여 지도에 표시하기</p><p>&nbsp;</p><p><br />
이번에는 검색창에 질의어를 입력하면 지역 검색 API를 호출하여 얻은 결과 값이 지도에 표시되는 기능에 대해 알아보자. 이때, 추천 수를 기준으로 정렬하도록 옵션을 설정하였다(sort= vote). 여기서는 utf-8 캐릭터 셋을 사용하도록 되어 있기 때문에 질의문에 대해서 별다른 처리를 하지 않았으나 utf-8이 아닌 캐릭터 셋을 사용하는 경우에는 iconv() 함수를 사용하여 질의를 utf-8로 변환하여 서버에 요청해야 한다. XML을 파싱하기 위해서는 PHP5 이상에서 제공하는 simplexml_load_file() 함수를 사용하였다. simpelxml_load_file() 함수는 파싱하려는 XML 문서의 위치를 지정하면 XML 문서를 파싱하여 SimleXMLElement 오브젝트 형태로 반환해준다. SimpleXMLElement 오브젝트를 사용하면 손쉽게 XML 문서에 접근할 수 있다. &lt;리스트 2-1&gt;은 이렇게 만들어진 코드다. <br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 2-1&gt; XML 파싱하기</strong></span></td></tr><tr><td><p>&lt;?<br />
Header("Content-Type: text/html; charset=UTF-8");<br />
define('MAPKEY', '지도 API 키');<br />
define('NAVERKEY', '검색 API 키');</p><p>$minx = 999999;<br />
$maxx = 0;<br />
$miny = 999999;<br />
$maxy = 0;<br />
$query = trim($_GET["query"]);</p><p>if(strlen($query) &gt; 0){<br />
$encodedquery = urlencode($query);<br />
$url = "http://openapi.naver.com/search?query=$encodedquery&amp;target=local&amp;sort=vote&amp;key=".NAVERKEY;<br />
$result = simplexml_load_file($url);<br />
$list = array();<br />
$result = $result-&gt;channel;<br />
foreach($result-&gt;item as $item){<br />
$title = $item-&gt;title<br />
$link = $item-&gt;link<br />
$desc = $item-&gt;description<br />
$tel = $item-&gt;telephone;<br />
$addr = $item-&gt;address<br />
$mapx = $item-&gt;mapx;<br />
$mapy = $item-&gt;mapy</p><p>// 지도가 표시될 영역을 결정<br />
$minx = min($minx, $mapx);<br />
$maxx = max($maxx, $mapx);<br />
$miny = min($miny, $mapy);<br />
$maxy = max($maxy, $mapy);</p><p>$tmparr = array($title, $link, $desc, $tel, $addr, $mapx, $mapy);<br />
array_push($list, $tmparr);<br />
}<br />
$intVal = 30;<br />
$minx -= $intVal;<br />
$maxx += $intVal;<br />
$miny -= $intVal;<br />
$maxy += $intVal;<br />
}</p><p>?&gt;<br />
</p></td></tr></tbody></table><p>&nbsp;</p><p>서버에서 반환해 준 XML 문서를 파싱한 이후에는 각각의 item 요소를 확인하여 검색 결과를 배열에 저장한다. 지도에서 표시할 영역이 어느 정도가 될지 결정해야 한다. 그리고 이렇게 결정된 값은 NMap.setBound() 메소드를 사용하여 지도에 반영하게 된다.<br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 2-2&gt; 기본 지도와 확대, 축소 컨트롤 생성</strong></span></td></tr><tr><td><p>&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;meta http-equiv=Content-Type content="text/html; charset=utf-8"&gt;<br />
&lt;meta http-equiv=Cache-Control content=No-Cache&gt;<br />
&lt;meta http-equiv=Pragma content=No-Cache&gt;<br />
&lt;title&gt;Map Search&lt;/title&gt;<br />
&lt;/head&gt;<br />
&lt;body style="margin:0px 0px 0px 0px"&gt;<br />
&lt;script type="text/JavaScript" src="http:<br />
//maps.naver.com/js/naverMap.naver?key=&lt;?=MAPKEY?&gt;"&gt;&lt;/script&gt;<br />
&lt;div id='mapContainer' style='width:960px;height:550px'&gt; &lt;/div&gt;<br />
&lt;script type="text/javascript"&gt;<br />
// 기본 지도 생성<br />
var mapObj = new NMap(document.getElementById('mapContainer'),960,550);<br />
mapObj.setBound(&lt;?=$minx?&gt;, &lt;?=$miny?&gt;, &lt;?=$maxx?&gt;, &lt;?=$maxy?&gt;);<br />
mapObj.zoomOut();</p><p>// 확대, 축소를 위한 컨트롤을 생성한다.<br />
var zoom = new NZoomControl(); <br />
zoom.setAlign("right"); <br />
zoom.setValign("bottom"); <br />
mapObj.addControl(zoom);</p></td></tr></tbody></table><p>&nbsp;</p><p>데이터를 배열에 저장한 후에는 이를 지도에 추가시켜 주어야 한다. 이를 위해서 setInfo() 함수를 생성하였다. setInfo() 함수의 내용은 검색 결과에 따라 PHP에서 동적으로 생성하는 코드로 initMarker() 함수를 반복적으로 호출하는 역할을 한다.</p><p>&nbsp;</p><p>initMarker() 함수는 NIcon 객체를 생성하고 이를 NMark 객체를 이용하여 지도에 추가하여 지도상에 이미지가 출력될 수 있도록 한다. 생성된 NMark 객체에는 NEvent.addListener() 함수를 사용하여 mouseover 이벤트와 이벤트가 발생할 때 실행할 코드를 등록한다. mouseover 이벤트가 발생하면 NInfoWindow 객체가 출력하는 내용을 갱신하고 위치를 변경하게 된다. 그리고 다시 NInfoWindow 객체가 화면에 표시될 수 있도록 설정을 변경한다. NInfoWindow 객체가 출력하는 내용은 HTML 코드로 되어 있으며, 그 내용은 getContent에서 생성하여 반환한다.<br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 2-3&gt; 데이터 배열을 지도에 추가하기</strong></span></td></tr><tr><td><p><br />
function setInfo(){<br />
&lt;?<br />
for($i = 0; $i &lt; count($list); $i++){<br />
$cnt = $i + 1;<br />
$title = $list[$i][0];<br />
$tel = $list[$i][3];<br />
$mapx = $list[$i][5];<br />
$mapy = $list[$i][6];<br />
echo "initMarker(new NPoint($mapx, $mapy), $cnt, new Array('$title', '$tel') );\n";<br />
}<br />
?&gt;</p><p>}</p><p>function getContent(content){<br />
var title = content[0];<br />
var tel = content[1];</p><p>var body = ' \<br />
&lt;div style="width:220px;border:dotted 1px #000000; background:#ffffff;padding:5px 5px 5px 5px;"&gt; \<br />
&lt;div style="font-size:10pt;font-family:굴림, tahoma;font-weight:bold;float:left;"&gt;'+title+'&lt;/div&gt; \<br />
&lt;div style="font-size:8pt;font-family:굴림, tahoma;"&gt;'+tel+'&lt;/div&gt; \<br />
&lt;div style="margin:10px 3px 3px 80px;"&gt;&lt;a href="javascript:infowin.hideWindow()"&gt;&lt;img src=http://static.naver.com/n/cmn/btn_close.gif border=0 width=48 height=17&gt;&lt;/a&gt;&lt;/div&gt; \<br />
';<br />
return body;<br />
}</p></td></tr></tbody></table><p>이렇게 생성된 마커를 addOverlay() 메소드를 사용하여 이미 생성된 mapObj 객체에 추가하면 지도에 출력된다. &lt;리스트 2-1&gt;에서 &lt;리스트 2-4&gt;의 코드를 연결하면 지역정보를 검색하여 지도에 표시하는 코드가 된다. 완성된 전체 코드는 이 달의 디스켓에 포함되어 있으니 참고하길 바란다.<br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 2-4&gt; 검색 결과 표시</strong></span></td></tr><tr><td><p>// 정보 출력을 위한 NInfoWindow 객체를 생성하여 등록한다.<br />
var infowin = new NInfoWindow();<br />
mapObj.addOverlay(infowin);</p><p>// 검색 결과를 마커를 사용하여 지도에 표시한다.<br />
function initMarker(pos, count, content){<br />
var iconUrl = 'http://sstatic.naver.com/search/local/icon3/icos_L'+String.fromCharCode(64+count)+'.gif';<br />
// 마커 생성<br />
var marker = new NMark(pos, new NIcon(iconUrl, new NSize(16, 15)));<br />
// marker 객체에 마우스가 오버했을 때, 실행할 함수를 등록한다.<br />
NEvent.addListener(marker, "mouseover",<br />
function(pos){<br />
infowin.set(pos, getContent(content));<br />
infowin.showWindow();<br />
}<br />
);<br />
// 지도에 마커를 등록한다.<br />
mapObj.addOverlay(marker);<br />
}</p><p>// 검색된 결과를 지도에 표시한다.<br />
setInfo();<br />
&lt;/script&gt;<br />
&lt;div id="searchform"&gt;<br />
&lt;form name="mapsearch" method="get" action="mapsearch2.php"&gt;<br />
&lt;input type="text" name="query"&gt;<br />
&lt;input type="submit" value="Map Search"&gt;<br />
&lt;/form&gt;<br />
&lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p></td></tr></tbody></table><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-11.jpg"></p><p>[화면3] (리스트2) 을 실행시킨 화면 </p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">블로그 검색하기</p><p>&nbsp;</p><p>&nbsp;</p><p>블로그를 검색하는 blogsearch.php 파일은 질의어를 받아 서버에 요청하고 서버에서 반환되는 XML 결과를 가공하지 않고 반환한다.<br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 3&gt; 블로그 검색 코드</strong></span></td></tr><tr><td><p>&lt;?<br />
Header("Content-Type: text/html; charset=UTF-8");<br />
header("Cache-Control: no-store, no-cache, must-revalidate");<br />
header("Cache-Control: post-check=0, pre-check=0", false);<br />
header("Pragma: no-cache");<br />
define('NAVERKEY', ' 검색 API 키');</p><p>if(strlen($query) &gt; 0){<br />
$encodedquery = urlencode($query);<br />
$url = "http://openapi.naver.com/search?query=$encodedquery&amp;target=blog&amp;key=".NAVERKEY;<br />
$data = file_get_contents($url);<br />
echo $data;<br />
}<br />
?&gt; </p></td></tr></tbody></table><p>&nbsp;</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="600"><tbody><tr><td bgcolor="#cccccc"><strong>xml2obj.js</strong></td></tr><tr><td bgcolor="#cccccc"><p>네이버에서 제공하는 OpenAPI는 반환 값이 대부분 XML 형태의 문서이므로 이 문서를 PHP나 자바스크립트에서 활용하려면 XML 문서를 파싱해야한다. PHP에서는 PHP가 제공하는 simple xml 관련 함수를 사용하였다. 자바스크립트에는 XML을 파싱하는 여러 가지 라이브러리가 있으나 XML DOM을 사용하여 파싱하는 경우 파싱 속도가 느린 문제가 있다. 이 문제를 해결하기 위해 XML 문서를 정규표현식을 이용하여 object로 변환하도록 하였다.</p></td></tr><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 1&gt; Ajax 기능 스키마</strong></span></td></tr><tr><td><p>/**<br />
* @projectDescription Jindo Json Extend<br />
* @copyright NHN corp. &lt;http://www.nhncorp.com&gt;<br />
* @author AjaxUI Team (gony)<br />
* @version 0.1<br />
* @since 0.2.9 &lt;jindo.do.js&gt;<br />
*/</p><p>var JINDO = new Object();<br />
JINDO.xml2obj = function(xml) {<br />
var obj = {}, que = [], depth = 0;</p><p>// attribute를 해석하기 위한 함수 <br />
var parse_attr = function(oobj, str) {<br />
str.replace(/([^=\s]+)\s*=\s*”([^”]*)”/g, function(a0,a1,a2) {<br />
oobj[a1] = a2;<br />
});<br />
}<br />
<br />
// 주석, XML선언, 태그 사이 공백 등의 의미없는 코드를 삭제<br />
xml = xml.replace(/&lt;(\?|\!-)[^&gt;]*&gt;/g,’’).replace(/&gt;\s+&lt;/g, ‘&gt;&lt;’);<br />
<br />
// 하위 노드가 없는 태그는 하나의 닫힌 태그로 수정<br />
xml = xml.replace(/&lt;([^!][^ &gt;]+)(\s[^&gt;]*)?&gt;&lt;\/\1&gt;/g, ‘&lt;$1$2 /&gt;’).replace(/^\s+|\s+$/g, ‘’);</p><p>// 함수 객체를 정규표현식 처리의 인자로 줘서 iterator로 사용한다.<br />
xml = xml.replace(/&lt;\/?([^\!][^ &gt;]+)(\s[^&gt;]*)?&gt;(&lt;\/\$1&gt;|&lt;\!\[CDATA\[(?:(.|\s)*?)\]\]&gt;|[^&lt;&gt;]*)/g, function(a0,a1,a2,a3) {<br />
// IE에서 일치하는 내용이 없으면 undefined로 전달된다.<br />
// 따라서 빈 문자열로 변경해 다른 브라우저와의 호환성을 맞춘다<br />
if (typeof a1 == ‘undefined’) a1 = ‘’;<br />
if (typeof a2 == ‘undefined’) a2 = ‘’;<br />
if (typeof a3 == ‘undefined’) a3 = ‘’;<br />
<br />
if (a0.substr(1,1) == ‘/’) { // 현재 태그가 닫는 태그라면,<br />
// 깊이를 1만큼 감소 한다<br />
depth--;<br />
} else if (que.length == 0) { // 객체 큐에 객체가 없다면,<br />
que[depth] = obj; // 초기의 객체를 큐에 넣고<br />
parse_attr(obj, a2); // attribute를 해석한다<br />
} else {<br />
var k = a1, o = {}, is_closed = false;<br />
<br />
is_closed = (a2.substr(-1,1) == ‘/’);<br />
if (a3.length &gt; 0 || is_closed) { // 텍스트 노드가 있다면<br />
o = a3; // 추가할 객체는 문자열 객체<br />
<br />
// CDATA라면 전달받은 그대로 리턴하고<br />
// 그렇지 않다면 decode 해서 리턴한다.<br />
if (o.substr(0,9) == ‘&lt;![CDATA[‘ &amp;&amp; o.substr(-3,3) == ‘]]&gt;’) o = o.substring(9, o.length-3);<br />
else o = o.replace(/&amp;lt;/g, ‘&lt;’).replace(/&amp;gt;/g, ‘&gt;’).replace(/&amp;amp;/g, ‘&amp;’);<br />
}<br />
<br />
// 객체를 할당하기 전에 태그 이름이 이미 존재하는지 살펴본다.<br />
// 이전에 존재하는 태그라면, 배열로 만든다. 이미 배열이라면 현재의 객체를 배열에 추가한다.<br />
if (typeof que[depth][k] == ‘undefined’) {<br />
que[depth][k] = o;<br />
} else { <br />
var v = que[depth][k];<br />
if (que[depth][k].constructor != Array) que[depth][k] = [v];<br />
que[depth][k].push(o);<br />
}</p><p>// attribute를 해석한다<br />
parse_attr(o, a2);<br />
<br />
if (!is_closed) que[++depth] = o; <br />
}<br />
<br />
return ‘’;<br />
});<br />
<br />
return obj;<br />
}<br />
</p></td></tr></tbody></table><p>&nbsp;</p><p>&nbsp;</p><p>블로그 검색 결과 보여주기</p><p>&nbsp;</p><p>블로그 검색 결과는 NInfoWindow의 객체에서 보여줄 것이므로 NInfoWindow 객체의 내용을 채워주는 getContent() 함수를 수정해야 한다. </p><p>&nbsp;</p><p>getContent() 함수 내에 블로그 검색 결과를 보여줄 div 요소를 두 개 추가하고, 안쪽에 추가된 div 요소의 경우 id를 tmpl로 지정하여 쉽게 참조할 수 있도록 한다. 그리고 마커에 mouseo ver 이벤트가 발생하였을 때, 블로그를 검색하여 데이터를 가져올 수 있도록 마커의 이벤트를 처리하는 익명 함수 내에 getIn fo() 함수를 호출하는 코드를 추가한다. </p><p>&nbsp;</p><p>getInfo() 함수는 NXmlhttp 클래스를 이용한다. NXmlhttp 클래스는 Ajax를 간단하게 사용할 수 있도록 지도 API에서 기본적으로 제공해주는 클래스이다. NXmlhttp 객체를 생성하여 반환 받을 문서의 유형을 설정하고, 데이터를 요청할 url과 콜백 함수를 지정하여 loadhttp() 메소드를 호출하면 NXmlhttp 객체에서는 해당 url에 요청을 보내고 결과를 받아 콜백 함수를 호출하게 된다. </p><p>&nbsp;</p><p>콜백 함수로 선언된 processInfo() 함수에서는 blog search. php에서 반환된 XML을 JSON 형태로, JSON 형태를 객체로 변환한다. 그리고 객체에서 각 검색 결과 아이템의 title과 link를 추출하여 검색 결과를 구성한다.</p><p>&nbsp;</p><p>&lt;리스트 4&gt;는 &lt;리스트 2&gt;에서 수정, 추가된 부분만을 표시한 것이다.</p><p>&nbsp;</p><p>지금까지 네이버 지도 API와 블로그 검색 API를 이용하여 간단한 프로그램을 만들어 보았다. 이 프로그램은 완성도가 높은 프로그램은 아니다. </p><p>&nbsp;</p><p>다만, 네이버의 OpenAPI를 어떻게 사용하는지에 대한 간단한 가이드 정도로 생각하면 좋을 것이다. OpenAPI를 활용하는 프로그램에서 중요한 것은 ‘어떻게 프로그램을 만드느냐’가 아니라 ‘어떤 프로그램을 만드느냐’라고 생각한다. 네이버에서는 여러분들이 손쉽게 OpenAPI를 활용하여 프로그램을 만들 수 있도록 계속해서 준비 중에 있다. 더 많은 개발자들의 다양한 아이디어로 OpenAPI를 활용한 여러 가지 프로그램이 만들어지길 바란다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 4&gt; 블로그 검색 결과 표시를 위해 &lt;리스트 2&gt;에서 수정된 부분</strong></span></td></tr><tr><td><p>- 생략 -</p><p>function processInfo(res){<br />
var target = document.getElementById("tmpl");<br />
var obj = JINDO.xml2obj(res);</p><p>var items = obj.channel.item || [];<br />
for(var i = 0; i &lt; items.length; i++){<br />
var title = items[i].title;<br />
var link = items[i].link;<br />
if(title.length &gt; 15){<br />
title = title.substring(0, 15) + “...”;<br />
}<br />
var con = "&lt;li&gt;&lt;a href=\"" + link + "\" target=_blank&gt;"+title+"&lt;/a&gt;&lt;br&gt;";<br />
target.innerHTML += con;<br />
}<br />
}}</p><p>function setInfo(){<br />
&lt;?<br />
for($i = 0; $i &lt; count($list); $i++){<br />
$cnt = $i + 1;<br />
$title = $list[$i][0];<br />
$tel = $list[$i][3];<br />
$mapx = $list[$i][5];<br />
$mapy = $list[$i][6];<br />
echo "initMarker(new NPoint($mapx, $mapy), $cnt, new Array('$title', '$tel') );\n";<br />
}<br />
?&gt;</p><p>}</p><p>function getContent(content){<br />
var title = content[0];<br />
var tel = content[1];</p><p>var body = ' \<br />
&lt;div style="width:220px;border:dotted 1px #000000; background:#ffffff;padding:5px 5px 5px 5px;"&gt; \<br />
&lt;div style="font-size:10pt;font-family:굴림, tahoma;font-weight:bold;float:left;"&gt;'+title+'&lt;/div&gt; \<br />
&lt;div style="font-size:8pt;font-family:굴림, tahoma;"&gt;'+tel+'&lt;/div&gt; \<br />
&lt;div class="bar" style="width: 200px;overflow:auto;"&gt;&lt;div style="padding:0px;font-family:굴림,tahoma;font-size:8pt;" id="tmpl"&gt;\<br />
&lt;/div&gt;&lt;/div&gt; \<br />
&lt;div style="margin:10px 3px 3px 80px;"&gt;&lt;a href="javascript:infowin.hideWindow()"&gt;&lt;img src=http://static.naver.com/n/cmn/btn_close.gif border=0 width=48 height=17&gt;&lt;/a&gt;&lt;/div&gt; \<br />
';<br />
return body;<br />
}</p><p>- 생략 -<br />
</p></td></tr></tbody></table><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-12.jpg"></p><p>[화면4] (리스트4)를 실행시킨 화면 </p><p>&nbsp;</p><p>다른 네이버 OpenAPI에 대한 자세한 내용은 네이버 Open A PI 공식페이지(http://openapi.naver.com)를 참조하면 된다. 만약 다른 사람들이 네이버 OpenAPI를 이용해 만든 다양한 매쉬업들을 보고 싶거나, 내가 만든 매쉬업 프로그램을 자랑하고 싶다면 공식 카페(http://cafe.naver.com/openapi.cafe)를 이용하면 된다. </p><p>&nbsp;</p><p>&nbsp;</p><table bgcolor="#ffffcc" border="0" width="600"><tbody><tr><td><p>cover story plus</p><p>주변에서 접할 수 있는 스크립트의 예</p><p>다음과 NHN이 함께하는 ‘2007 매쉬업 경진대회’</p><p>&nbsp;</p><p><br />
웹 2.0의 화두 매쉬업. 문제는 IT 강국이라 목소리를 높이는 우리나라에는 매쉬업 사이트나 서비스가 별로 없다는 점이다. 이런 아쉬움을 달래기 위해 대한민국 OpenAPI를 선도하는 다음과 네이버가 발 벗고 나섰다. 웹 2.0 문화를 선도하는 오픈API를 통해 보다 창의적이고 풍요로운 인터넷 세상을 만들기 위한 매쉬업 경진대회를 개최한 것이다. </p><p>&nbsp;</p><p>참가신청은 3월 말일로 끝나니 책을 받아보자마자 매쉬업 경진대회 홈페이지로 달려가든지 다음을 기약해 봐야겠다. 예선 심사를 거친 뒤에 결선은 4월 5일에 치러지는데, 본선 입상자들에게는 상금과 함께 특별한 선물도 주어진다. 바로 ‘다음과 NHN에 입사 시 1차 서류 전형 면제’가 그것이다.</p><p>&nbsp;</p><p>경력이 없거나 학력에 관계없이 국내 최대 포털 업체에 입사할 수 있는 기회가 열린다니 그 기회를 놓칠 리 없다. 기자가 네이버에서 매쉬업 경진대회를 담당하고 있는 신수완 과장을 만난 3월 15일에 이미 참가 신청자가 300팀이 넘었다니, 행운의 열쇠를 잡기 위한 각축전이 만만치 않을 듯하다. </p><p>&nbsp;</p><p>그럼 이 경진대회의 심사 기준은 뭘까? 창의성, 유용성, 완성도, 기술성, 편의성과 디자인으로 구분된 심사 기준 중 가장 큰 비중을 차지하는 것은 역시 창의성이다. 그 뒤를 잇는 것이 유용성과 완성도다. 한국 개발자들의 독창적인 매쉬업들이 많이 나오길 바란다.</p><p>&nbsp;</p><p>NHN 신수완 과장은 “매쉬업 경진대회는 매년 정기적으로 진행할 계획”이라며 “아직은 OpenAPI를 공개하고 있는 사이트가 많지 않아 다음과 네이버가 주도하지만, 해를 거듭할 수록 더욱 많은 업체들이 함께 참여할 수 있길 바란다”고 말했다. NHN은 매쉬업 경진대회 이외에도 개발자와 학생들을 대상으로 하는 개발자 컨퍼런스와 세미나 등 다양한 정책적 지원도 점차 늘려갈 방침이다.</p><p>&nbsp;</p><p>아무쪼록 두 포털의 이번 시도를 밑거름으로 한국의 OpenAPI와 매쉬업 그 밖의 다양한 웹 2.0 기술들이 무럭무럭 성장하길 기대해본다.</p><p><br />
글 | 정희용 기자(flytgr@imaso.co.kr)</p></td></tr></tbody></table><p><br />
</p><p>이달의 디스켓 : Naver_API.zip<br />
참고 자료<br />
1) 네이버 OpenAPI, http://openapi.naver.com/<br />
2) Cascading Style Sheet, http://www.w3.org/Style/CSS/<br />
3) HTML, http://www.w3.org/html/<br />
4) PHP, http://www.php.net/<br />
5) JSON, http://www.json.org/</p><p>&nbsp;</p><p>&nbsp;</p><p><a href="http://www.dbguide.net/" target="_blank"><b><font color="midnightblue">제공 : DB포탈사이트 DBguide.net </font></b></a></p><br />
<div align="right">출처 : Micro Software [2007년 4월호]</div>			 ]]> 
		</description>
		<category>OpenID</category>

		<comments>http://netkong.egloos.com/373151#comments</comments>
		<pubDate>Wed, 04 Jul 2007 12:58:25 GMT</pubDate>
		<dc:creator>넷콩</dc:creator>
	</item>
	<item>
		<title><![CDATA[ Daum API를 활용한 PostVideo 만들기  ]]> </title>
		<link>http://netkong.egloos.com/373149</link>
		<guid>http://netkong.egloos.com/373149</guid>
		<description>
			<![CDATA[ 
  <p class="title1"><b style="color: rgb(51, 51, 51);">웹2.0 시대의 견인차 Open API </b></p><p>&nbsp;</p><p>&nbsp;</p><p class="contentsbox">OpenAPI에 개발자들의 아이디어가 더해지면서 다양한 매쉬업 서비스들이 세상에 등장하고 있다. 이 서비스들은 기존에 생각지 못했던 일들을 가능하게 하거나, 다른 서비스 사업자의 서비스들을 활용하고 거기에 독창성을 더하여 큰 수익을 내고 있기도 하다. 구글과 몇몇 유명 해외 포털들이 API를 오픈하고 이로 인한 성과들이 나자, 국내의 포털과 사이트들도 자신들의 서비스를 개방하는데 앞장서고 있다. 구글 맵이나 다른 해외 API의 한글화 문제 탓에 활용을 꺼렸던 개발자들에게 국내 포털들의 API 오픈은 단비 같은 존재. 이번 특집에서는 구글과 네이버, 다음의 OpenAPI 활용법에 대해 알아보고 개발자들이 이 API들을 어떻게 활용해야 개발자의 역량을 키우고 수익도 올릴 수 있을지에 대해 알아본다.</p><p>&nbsp;</p><p class="author">기획·정리 <br />
| 정희용 기자 flytgr@imaso.co.kr</p><p>&nbsp;</p><p class="title1">Daum API를 활용한 PostVideo 만들기</p><p>&nbsp;</p><p class="contentsbox">지난 달 다음커뮤니케이션(이하 다음)과 네이버가 함께 ‘2007 대한민국 매쉬업 경진대회’를 개최하고, 서울과 대전에서 오프라인 부속 행사로 매쉬업 캠프를 진행했다. 휴일임에도 불구하고 자리를 가득 메운 참가자들과 학생, 개발자, 기획자 등 인원구성도 다양했다. 매쉬업 캠프에 참가하고 있으려니 늦게나마 국내에서도 OpenAPI와 매쉬업에 대한 관심이 높아지고 있음을 실감할 수 있었다.</p><p>&nbsp;</p><p>&nbsp;</p><p>400 개에 달하는 OpenAPI가 공개되어 있고, 프로그래머블웹(www.ProgrammableWeb.com)에 등록된 매쉬업의 수만 1,700 개에 육박하는 상황에서도 매일 3개 이상의 매쉬업이 꾸준히 만들어지고 있다. 기술적 흥미의 수준을 넘어서 어떻게 새로운 비즈니스 가치를 창출하고 인터넷 생태계를 형성해 나갈 것것인지 고민해온 사람들이 이미 실질적인 결과물을 만들어내기 시작했다. 하지만 국내에서는 공개되는 OpenAPI의 수가 늘어나고 있음에도 불구하고 업체의 지원이나 사용자의 참여 모두 다소 정체된 모습을 보여 왔다. 꽤 오랜 시간 동안 2%(혹은 그 이상) 부족한 갈증이 지속되어 오다가 최근에서야 변화의 조짐을 보이기 시작했다. 국내 블로그 검색 사이트(www.blogreader.co.kr)에서 ‘open api’를 입력하면 검색되는 140여 포스팅 중에서 절반에 가까운 60여 건이 최근 1개월 이내에 집중되어 있다. 절대적인 수치보다는 사용자들의 관심이 급격하게 고조되고 있다는 사실이 고무적이다. 이번 특집 기사가 이처럼 고조된 관심이 가시적인 성과로 드러나는 계기가 되었으면 한다.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">다음의 OpenAPI 소개</p><p>&nbsp;</p><p>&nbsp;</p><p>다음은 네이버에 이어 작년부터 OpenAPI를 공개하고 있다. RSS 피드로 제공하는 콘텐츠 서비스(다음 첫 화면, 영화, 뉴스 등)가 있고, 검색 API는 일본어 사전, 교보문고 DB와 연동되는 도서 정보를 포함하여 각 서비스의 콘텐츠를 검색해 준다. 검색 API도 결과를 RSS 형태로 돌려주어 콘텐츠 서비스와 동일하게 RSS 리더에 등록하거나 RSS 파싱 도구를 사용해서 손쉽게 필요한 정보를 뽑아낼 수 있다. 또한 출력 형태를 지정하면 JSON (JavaScript Object Notation)이나 XML 포맷으로도 받아낼 수 있으니 취향이나 주어진 개발 환경에 맞게 선택하면 되겠다. 여행 API를 이용하면 항공권, 여행 상품권 및 여행 후기 등을 검색할 수 있으며 출력 포맷은 검색 API와 동일하게 RSS(기본 값)와 JSON, XML 중에서 선택할 수 있다. 디앤샵 API는 디앤샵과 온켓에서 상품을 검색하거나, 특정 상품의 정보를 조회할 수 있는 기능을 제공하는데, 출력 포맷은 XML 형태만 지원하고 있다.</p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-13.jpg"></p><p>[화면1]Daum 첫 화면의 뉴스 RSS피드와 RSS, JSON, XML포맷으로 본 뉴스 검색 API호출 결과 </p><p>&nbsp;</p><p>다음 OpenAPI를 사용하려면 다음 DNA 개발자 네트워크에서 ‘오픈 API 일반 사용자 등록’을 통해서 사용자 인증키를 발급 받아야 한다. 인증키는 서비스 종류에 따라 검색과 블로그, 쇼핑, 여행 API 호출용으로 구별하여 발급하는데, 이는 인증키 별로 하루에 사용할 수 있는 API 호출 건수가 제한되어 있기 때문이다. 서비스 이용 방법(http://dna.daum.net/apis/GettingSt arted) 페이지에 인증키 발급 및 기본적인 테스트 방법이 화면 이미지와 함께 단계별로 설명되어 있으니 아직 인증키를 발급 받지 않은 독자들도 어려움 없이 OpenAPI 개발을 시작할 수 있을 것이다. 각 API에 대한 문서는 읽기 전용 위키 형태로 제공되고 있다.</p><p>&nbsp;</p><p>API 문서는 블로그 API와 인증 API를 제외하면 모두 같은 포맷을 따르고 있으며 샘플 URL이 제공되어 여기서 apikey 값만 발급 받은 해당 서비스의 사용자 인증키로 바꾸면 웹 브라우저 주소창에 넣어서 곧바로 결과를 확인해 볼 수 있다. 또한 문서에 명시되어 있는 요청 변수들을 추가하거나 값을 조정하면서 결과에 어떻게 반영되는지 볼 수 있기 때문에 문서 내용을 파악하는데 어려움이 없을 것이다.</p><p>&nbsp;</p><p>여기까지 설명하면서 블로그 API와 인증 API는 전혀 언급하지 않는 것을 궁금하게 여기는 독자가 있을 것 같다. 블로그 API는 다양한 기능을 제공하며 각 기능에 따라 인증 API를 통해서 보다 복잡한 인증 절차를 거쳐야 하는 경우도 있고, 일부 요청은 XML-RPC 방식으로 호출해야 하는 등 예외적인 면이 있다. 이들 두 API는 일반적인 설명이 끝난 뒤에 따로 다루기로 한다.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1">인증키와 서명키</p><p>&nbsp;</p><p>&nbsp;</p><p>API 문서의 인증 파라미터 부분은 약간의 설명이 필요할 것 같다. 인증 파라미터는 OpenAPI 요청을 처리하는 서버에서 호출자를 식별하는 키로 사용된다. 파라미터 apikey가 이에 해당하며 반드시 지정해야 한다. 인증키 별로 하루에 5,000 회까지 호출할 수 있다. 개발한 애플리케이션을 배포하게 되면 모든 사용자의 요청이 개발자의 인증키를 사용하게 되므로 제한 횟수를 초과하는 경우가 발생할 수 있다. 이런 경우 애플리케이션 인증키를 지정하면 해당 애플리케이션 인증키에 대해서 별도의 트래픽 제한 조정을 요청할 수 있다. ‘오픈 API 개발자 등록’ 링크를 클릭해서 발급 받을 수 있지만 아직 애플리케이션 인증키에 대한 트래픽 정책이 공지되지 않은 상태이고 apid 인자를 요구하는 API는 뒤에서 설명할 인증 API 뿐이므로 일단은 apikey만 사용한다고 생각하는 쪽이 편할 것이다.</p><p>&nbsp;</p><p>‘apikey=&lt;사용자 인증키&gt;’만 넘길 경우 트래픽 제한 이외에도 보안 이슈가 발생할 수 있다. 인증 파라미터가 HTTP 프로토콜을 통해서 평문으로 전송되므로 외부에 노출되어 도용당할 우려가 있다. 이를 막기 위해서 요청 URL을 서명해서 변조나 재사용이 불가능하게 만드는 방법을 제공한다. 다음 OpenAPI 서명 방법(http://dna.daum.net/apis/HowToSign) 페이지에서 서명 절차에 대한 설명과 자바, 자바스크립트, PHP 예제 코드가 제공된다. nonce를 생성하는 방법이 어렵지 않고, 서명 알고리즘은 RFC 2104에 정의된 HMACSHA1을 따르므로 제공된 예제 코드를 참조하면 다른 언어를 사용하더라도 서명하는 함수를 작성할 수 있을 것이다. 실제로 파이썬으로 구현한 예(kwryu78님)가 DNA 포럼의 인증 API 게시판에 질문 내용과 함께 올라와 있기도 하다.</p><p>&nbsp;</p><p>서명 인증 방식은 서명키를 인증 서버와 사용자가 공유한 상태에서 전송하려는 데이터로부터 공유된 키를 사용한 해시(서명 값)를 만들어내는 것이다. 사용자는 데이터와 서명 값을 함께 전송하고, 인증 서버는 앞서 공유했던 키를 이용해서 전달받은 데이터의 해시를 만들어서 사용자가 보낸 서명 값과 일치하는지 확인한다. 다운로드 받은 파일에 문제가 없는지 확인하기 위해 많이 사용되고 있는 MD5 체크섬을 생각하면 된다. ts와 nonce는 불규칙하게 유일한 값을 만들어낼 목적으로 사용된다. 동일한 ts, nonce 값은 한 번 밖에 사용하지 못하고 요청 주소에서 ts, nonce를 변경하면 sig 값이 달라져야 한다. 따라서 서명 인증 파라미터가 포함된 요청은 중간에서 가로채더라도 서명키가 없으면 다시 사용하거나 내용을 변조해서 사용할 수 없다.</p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-14.jpg"></p><p>[그림1] 서명 인증 파라미터 작동 원리</p><p>&nbsp;</p><p class="sub1">블로그 API와 인증 API</p><p>&nbsp;</p><p>&nbsp;</p><p>다음의 블로그 API는 지난 2005년 비공식적으로 개발자들에게 공개되어 테스트 된 적이 있다. 당시에 이를 이용한 원격 글쓰기, 블로그 이전 도구 등의 프로그램이 개발되기도 했다. XML-RPC 메시지 안에 아이디와 패스워드를 담아서 보내는 인증 방식을 개선하기 위해 한동안 서비스가 중단되었다가 인증 API 기반으로 동작하는 현재의 모습으로 다시 공개된 것이다. </p><p>&nbsp;</p><p>인증 방식이 완전히 달라지고 API가 제공하는 기능이 많이 변했기 때문에 기존의 프로그램은 사용이 어려운 상태다. 하루가 다르게 변화하는 세상에서 2년이나 지나간 이야기를 들추어내는 것은 비공식 공개 당시에 자료들이 블로그 게시물 형태로 남아 있어서 시간이 지난 후에도 그 자료들을 바탕으로 API 사용을 시도하는 경우를 목격했기 때문이다. 이제 새로운 블로그 API의 모습을 살펴보자. 현재 블로그 API가 제공하는 기능은 다음과 같다.</p><p>&nbsp;</p><p>● 블로그 관리 </p><p>&nbsp;</p><p>·블로그 개설 여부 확인<br />
·블로그 이름 중복 확인<br />
·블로그 개설</p><p>&nbsp;</p><p>● 블로그 게시물 읽고 쓰기<br />
·게시물 목록 가져오기<br />
·게시물 본문 가져오기<br />
·댓글 목록 가져오기<br />
·게시물 쓰기(제목, 본문, Tag 지정)</p><p>&nbsp;</p><p>● 블로거 기자단(UserToken 제공자가 블로거 기자단 가입했을 경우)<br />
·블로거 기자단 카테고리 목록<br />
·블로거 기자단 자격으로 게시물 쓰기</p><p>&nbsp;</p><p>● 미니 알리미<br />
·알리미 구독 리스트<br />
·미니 알리미 내 글에 대한 반응(내 글에 달린 댓글 목록)</p><p>&nbsp;</p><p>● 블로그 TOP 화면의 섹션 게시물 목록<br />
·테마 블로그<br />
·추천 동영상<br />
·블로거 기자단<br />
·베스트 블로거<br />
·추천 커뮤니티</p><p>&nbsp;</p><p>목록에서 확인할 수 있는 것처럼 블로그 API는 상당히 다양한 기능을 제공하고 있다. 일부 기능은 XML-RPC 방식으로 호출해야 하는 등 앞서 살펴본 API들과는 상이한 점들이 있다. 이러한 차이점 때문에 API 문서도 다른 API의 일관된 포맷에서 다소 벗어나 있고, 변경된 사항에 대한 업데이트가 늦어진 탓인지 설명이 부족하다고 느껴지는 부분이 발견되기도 한다. 호출 및 인증 유형에 따라 블로그 API를 살펴보면서 보충이 필요한 설명을 덧붙이도록 하겠다.</p><p>&nbsp;</p><p>&nbsp;</p><p><strong>인증 API</strong></p><p>&nbsp;</p><p>&nbsp;</p><p>블로그 API를 둘러보기 전에 뒤로 미뤄 왔던 인증 API에 대해서 알아보자. 인증 API는 일차적으로 아이디와 패스워드를 노출시키지 않고 글을 쓰려는 사용자의 신원을 확인하는 기능을 한다. 그렇다면 사용자 인증키와 서명키의 역할도 이와 같지 않았던가? 그렇다면 인증 API는 무엇을 위해 존재하는가?</p><p>&nbsp;</p><p>질문은 잠시 뒤로 미뤄두고 게시물을 올리는 블로그 API를 사용하면 어떤 것을 만들어낼 수 있을지 생각해보자. 대표적인 동영상 공유 사이트 유튜브(YouTube)에서 힌트를 얻을 수 있다.</p><p>&nbsp;</p><p>유튜브에서 마음에 드는 동영상을 발견하면 사이트에 즐겨찾기로 등록하거나, 이메일에 동영상 링크를 담아서 보내거나, 사이트 내부에서 운영되는 그룹에 담을 수 있을 뿐만 아니라 Blo gger, WordPress 등의 블로그 사이트에 게시물로 포스팅 하는 기능을 제공할 수 있다. 블로그 API에 글쓰기 기능이 있으니 유사한 기능을 만드는 것도 어렵지 않을 것이다. 이 정도에서 답을 찾아낸 독자도 있으리라 생각한다. 미디어 콘텐츠를 제공하는 사이트를 운영하면서 좋은 콘텐츠를 블로그로 퍼갈 수 있는 기능을 개발하는데, 사용자 인증키를 이용해서 API를 사용해도 아무 문제가 없을까? 해당 기능을 이용하고자 하는 모든 사용자들이 오픈 API 사용자로 등록해야 할 뿐만 아니라 사용자가 비밀스럽게 보관해야 할 서명키까지 사이트에 제공해야 한다는 문제가 생긴다. 인증 API는 바로 이 문제를 해결해준다.</p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-15.jpg"></p><p>[화면2] 유투브의 PostVideo </p><p>&nbsp;</p><p>&nbsp;</p><p>예로 든 것처럼 인증 API는 개발자 개인이 블로그 API를 사용하는 것이 아니라 자체 회원을 가지는 서비스 제공 사이트에서 블로그 API를 이용해서 편의를 제공하는 상황을 염두에 두고 만들어졌다. 인증 API가 사용되는 상황에는 개발자와 인증 API 서버뿐만 아니라 개발자가 개발한 서비스, 그리고 그 서비스를 사용하는 일반 사용자가 모두 관여하기 때문에 그림이 좀 복잡해진다. 유튜브에 다음 블로그 포스팅 기능을 추가하는 상황을 가정해보자. 엘리스라는 사용자가 유튜브에서 동영상을 감상하다가 뮤직 비디오 한 편을 다음 블로그에 포스팅 하려고 한다. 인증 API 서버는 앨리스가 다음 계정을 가지고 있는 정상적인 사용자라는 사실을 확인하고, 앨리스가 동영상을 블로그에 올리기 위해 유튜브 서비스가 호출하는 블로그 API 요청이 앨리스 자신의 권한을 가지고 실행되도록 권한을 부여하는 것에 대한 동의를 얻어야 한다. 이 절차를 마치면 유튜브 서비스에 앨리스의 권한을 확인할 수 있는 사용자 인증 토큰을 발급한다. 유튜브 서비스는 발급받은 토큰을 DB에 저장하여 앨리스가 블로그 포스팅을 요구할 때마다 이 인증 토큰을 블로그 API와 함께 사용하여 다음 블로그 서비스에 글을 올린다. 이 때 인증 API 서버는 ‘유튜브 서비스에게’ 앨리스의 권한을 부여한 것이기 때문에 블로그 API를 사용할 때 요청하는 주체가 유튜브 서비스라는 사실도 확인시켜 주어야 한다. 바로 이것이 인증키 별 트래픽 제한을 설명할 때 언급했던 애플리케이션 인증키다.</p><p>&nbsp;</p><p>인증 API를 통한 토큰 발급 과정과 여기에 참여하는 각 주체 사이의 상호작용은 Daum 인증 API 페이지(http://dna.daum. net/apis/account)에 잘 설명되어 있으니 앞서 가정한 상황과 비교하며 되짚어보면 명확하게 정리할 수 있을 것이다. 문서에서 ‘외부 웹 사이트’로 지칭하는 주체가 가상의 ‘유튜브 서비스’에 해당한다.</p><p>&nbsp;</p><p>이제 인증 API와 블로그 API를 함께 사용하여 서비스를 구축하는 관점에서 정리해보자.</p><p>&nbsp;</p><p>· 애플리케이션 인증키를 받은 서비스는 사용자의 동의를 얻어 사용자 인증 토큰을 발급받는다.<br />
· 사용자 인증 토큰과 함께 사용하면 블로그 API는 토큰 발급 시 인증을 거친 사용자의 권한으로 작동한다.<br />
· 인증 토큰을 사용할 때는 토큰을 발급 받을 때 사용한 애플리케이션 인증키(apid)도 함께 지정해야 한다.</p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1"><strong>블로그 API, 호출 및 인증 유형</strong></p><p>&nbsp;</p><p>&nbsp;</p><p>인증 API를 소개하기 전에 2% 부족함을 보여주는 블로그 API 매뉴얼 문서(http://dna.daum.net/apis/blog)를 이야기했다. 지금부터 이어지는 설명은 그런 부분들을 보완하는 보충 자료의 성격을 갖는다. 기사를 읽으면서 매뉴얼을 참고해서 이해를 깊게 해도 좋고, 일단 스치듯 읽어두고 나중에 실제 개발을 위해서 매뉴얼을 읽을 때 부족한 부분을 보완하는 용도로 활용해도 좋겠다. 호출 및 인증 유형을 기준으로 API를 분류하여 설명하기 때문에 API를 나열하는 순서가 매뉴얼과 같지 않다.</p><p>&nbsp;</p><p>● XML 문서 형태로 제공되는 기능들</p><p>자체 정의한 XML 포맷을 따른다는 점을 제외하면 RSS 피드 방식과 같다. HTTP 프로토콜로 문서를 읽어오기만 하면 되며 URL에 사용자 인증키를 추가하지 않아도 된다. </p><p>&nbsp;</p><p>● REST 호출, 사용자 인증키만 요구하는 기능 들<br />
이 유형에 속하는 API는 블로그 이름을 지정해서 글 목록을 가져오는 ArticleList.do뿐이다. 블로그를 지정하는 blogname은 필수 항목이고 가져올 목록 범위를 지정하는 listScale(기본 값 20), curPage, minno, maxno 등을 지정하지 않으면 최근 게시물 목록을 20개까지 가져온다.</p><p>&nbsp;</p><p>● REST 호출, 사용자 인증 토큰을 지정해야 하는 기능<br />
블로거 기자단에 가입하면 블로그에 글을 올릴 때 블로거 기자단 섹션에 게시되도록 할 수 있다. 이 때 어느 카테고리에 글이 등록될지 지정해야 한다. 이 때 사용하는 뉴스 카테고리 리스트를 받아오는 명령이 http://apis.daum.net/blog/NewsCateg ory.do이다. 이 분류는 기자단에 등록된 사용자만 조회할 수 있다. 때문에 사용자 인증 토큰을 지정하지 않거나 기자단에 등록하지 않은 사용자의 인증 토큰을 지정하면 빈 카테고리가 반환된다. </p><p>&nbsp;</p><p>● XML-RPC 호출, 사용자 인증키만 요구하는 기능<br />
XML-RPC 메소드 daum.blog.openapi.checkBlogName. execute는 문자열 파라미터 blogName과 같은 이름의 블로그가 이미 존재하는지 여부를 확인한다. 이런 확인은 웹 브라우저 주소 창에 http://blog.daum.net/&lt;블로그 이름&gt;과 같이 입력하면 누구나 확인할 수 있기 때문에 사용자 인증이 의미가 없다. 따라서 사용자 인증키만 확인하고 결과를 제공한다.</p><p>&nbsp;</p><p>● XML-RPC 호출, 사용자 인증 토큰을 생략할 수 있는 경우<br />
XML-RPC 메소드 daum.blog.openapi.checkBlog.execute는 사용자의 블로그 개설 여부를 확인한 뒤에, 개설하였으면 블로그 주소를, 개설하지 않았으면 빈 문자열을 반환한다. 특정 사용자의 블로그 개설 여부는 본인 아이디로 로그인하기 전에는 확인할 수 없으므로 사용자 인증이 필요하다. 사용자 인증 토큰을 지정하면 해당 사용자의 계정으로 확인해 주고, 이를 생략하면 API 사용자 인증키를 소유한 계정으로 확인한다.<br />
daum.blog.openapi.newPost.execute는 제목과 본문, Tag를 지정해서 사용자의 블로그에 새 글을 등록해준다. 다음 블로그 게시물은 다음과 같이 주소가 구성되어 있다. 글 등록이 성공하면 API가 이 주소에서 &lt;ArticleNumber&gt;에 해당하는 게시물 번호를 반환한다.</p><p>http://blog.daum.net/&lt;BlogName&gt;/&lt;ArticleNumber&gt;</p><p>여기서 &lt;BlogName&gt;은 앞서 살펴본 daum.blog.openapi. checkBlog.execute를 같은 인증 설정으로 호출해서 얻을 수 있다. 이 정보들을 조합하여 글 올리기가 성공했을 때 새로 등록된 글로 바로 가는 링크를 제공할 수 있다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>REST와 XML-RPC</strong></span></td></tr><tr><td><p>오픈 API 호출 방식을 지칭할 때 사용하는 REST는 HTTP 프로토콜을 통해서 특정 도메인의 정보를 전송하는 간단한(SOAP처럼 추가적인 메시징 레이어를 더하거나 HTTP 쿠키를 사용해서 세션 트래킹을 사용하지 않는) 인터페이스를 말한다. 오픈 API를 사용하는 개발자의 입장에서 보면 요청 URL만 만들어내면 HTTP 클라이언트 라이브러리를 통해서 정적인 웹 페이지를 읽어 들이는 것과 동일한 방법으로 결과를 읽어 들이는 방식이라고 말할 수 있겠다. 파이썬이나 PHP의 경우 다음과 같이 단 한 줄의 코드로 호출이 이루어진다.</p><p>&nbsp;</p><p>result = urllib.urlopen(url).read() # python<br />
result = file_get_contents(url); # PHP</p><p>&nbsp;</p><p>인증 파라미터는 다른 모든 파라미터와 마찬가지로 url 안에 GET 파라미터 형태로 집어넣는다.<br />
XML-RPC는 XML 포맷으로 호출 내용을 인코딩하고 HTTP로 원격 컴퓨터에 전달하는 원격 프로시저 호출 프로토콜이다. XML-RPC 스펙이 정의하는 XML 포맷에 맞추어 메소드 이름과 파라미터 리스트를 인코딩하여 서버에 보내고, 역시 XML 포맷으로 호출 결과를 받아보는 방식이다. 내부적으로는 ‘XML 메시지 생성 → 메시지 전송 → 응답 XML 수신 → 응답 XML 해석’의 과정을 동일하게 거치겠지만 개발자가 접하게 되는 인터페이스는 어떤 XML-RPC 라이브러리를 선택하느냐에 따라 상당히 달라질 수 있다. 이 경우에도 접속 대상인 서버를 URL 형태로 지정한다는 점에서는 차이가 없는데, 인증 파라미터는 바로 이 URL에 REST 방식과 동일한 방법으로 추가해주면 된다. 대표적인 XML-RPC 호출 코드를 보고 어느 부분에 인증 파라미터가 추가되는 것인지 확인해보자.</p><p>&nbsp;</p><p>### python, using xmlrpclib<br />
url = ‘http://apis.daum.net/blog/XMLRPC.do’<br />
signed_url = url_hmac(url, auth_params) # Sign the URL!<br />
server = xmlrpclib.Server(signed_url)<br />
result = server.daum.blog.openapi.checkBlogName.execute(blogname)</p><p>&nbsp;</p><p>파이썬에서는 URL이 가리키는 대상을 서버 객체로 추상화 해준다. 서버 객체를 생성할 때 지정하는 URL에 인증 파라미터와 사용자 인증 토큰(필요 시)을 추가하고 서명하면 된다.</p><p>&nbsp;</p><p>### PHP, using XML-RPC for PHP<br />
$methodName = ‘method_name’;<br />
$params = array(new xmlrpcval($param, “string”));<br />
$req_msg = new xmlrpcmsg($methodName, $params);<br />
$url = sign($url, $auth_params); # Sign the URL!<br />
$client = new xmlrpc_client($url); <br />
$resp = $client-&gt;send($req_msg);</p><p>&nbsp;</p><p>PHP는 XML 메시지를 명시적으로 구성해 놓고 클라이언트 객체에 접속해야 할 주소로 URL을 지정하는 스타일을 보여준다. 여기서도 XML-RPC 클라이언트 객체를 생성할 때 넘기는 URL에 적당한 인증 파라미터를 지정한다.<br />
</p></td></tr></tbody></table><p>&nbsp;</p><p>● XML-RPC 호출, 사용자 인증 토큰을 지정해야 하는 경우<br />
XML-RPC 메소드 daum.blog.openapi.newPost.execute NewsReporter는 newsCateId라는 파라미터가 하나 추가된 것을 제외하면 daum.blog.openapi.newPost.execute와 동일하다. http://apis.daum.net/blog/NewsCategory.do를 호출해서 얻은 값에서 게시물을 포함시킬 카테고리를 선택해서 해당 엘리먼트(newCate)의 id 속성 값을 지정하는 것이다. </p><p>&lt;표 1&gt;은 지금까지 살펴본 내용을 표로 정리한 것이다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="600"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>메소드 이름 / REST 주소 </strong></span></td><td bgcolor="#999999"><span class="logout2 style45"><strong>호출방식 </strong></span></td><td bgcolor="#999999"><span class="logout2 style45"><strong>인증토큰</strong></span></td><td bgcolor="#999999"><span class="logout2"><strong>비고</strong></span></td></tr><tr><td>http://blog.daum.net/_top/_themeblog.xml </td><td>REST</td><td>NO</td><td>&nbsp;</td></tr><tr><td>http://blog.daum.net/_top/_recoMovie.xml</td><td>REST</td><td>NO</td><td>&nbsp;</td></tr><tr><td>http://blog.daum.net/_top/_blogernews.xml</td><td>REST</td><td>NO</td><td>&nbsp;</td></tr><tr><td>http://blog.daum.net/_top/_todaynew.xml</td><td>REST</td><td>NO</td><td>&nbsp;</td></tr><tr><td>http://blog.daum.net/_top/RecomCommunity.xml</td><td>REST</td><td>NO</td><td>&nbsp;</td></tr><tr><td>http://apis.daum.net/blog/ArticleList.do</td><td>REST</td><td>NO</td><td>&nbsp;</td></tr><tr><td>http://apis.daum.net/blog/ArticleComment.do </td><td>REST</td><td>Optional</td><td>&nbsp;</td></tr><tr><td>http://apis.daum.net/blog/ArticleView.do</td><td>REST</td><td>Optional</td><td>&nbsp;</td></tr><tr><td>http://apis.daum.net/blog/NewsCategory.do</td><td>REST</td><td>YES</td><td>인증 토큰 소유자가 뉴스 기자단 이어야한다</td></tr><tr><td>http://apis.daum.net/blog/MyAlarmyArticle.do </td><td>REST</td><td>YES</td><td>&nbsp;</td></tr><tr><td>http://apis.daum.net/blog/MyAlarmyArticleCmt.do</td><td>REST</td><td>YES</td><td>&nbsp;</td></tr><tr><td>daum.blog.openapi.checkBlogName.execute</td><td>XML-RPC </td><td>NO</td><td>&nbsp;</td></tr><tr><td>daum.blog.openapi.newPost.execute </td><td>XML-RPC </td><td>Optional</td><td>인증 토큰을 지정하지 않으면 인증키 소유자</td></tr><tr><td>daum.blog.openapi.checkBlog.execute</td><td>XML-RPC </td><td>Optional</td><td>인증 토큰을 지정하지 않으면 인증키 소유자</td></tr><tr><td>daum.blog.openapi.makeBlog.execute</td><td>XML-RPC </td><td>Optional</td><td>인증 토큰을 지정하지 않으면 인증키 소유자</td></tr><tr><td>daum.blog.openapi.newPost.executeNewsReporter</td><td>XML-RPC </td><td>YES</td><td>인증 토큰 소유자가 뉴스 기자단 이어야한다</td></tr></tbody></table><p>[표1] 블로그 호출 및 인증 방식 </p><p>&nbsp;</p><p>&nbsp;</p><p class="sub1"><strong>Post Video 구현하기</strong></p><p>&nbsp;</p><p>&nbsp;</p><p>어떤 언어를 선택해도 적용될 수 있는 기본적인 개념들을 설명하려다 보니 제대로 된 예제 하나 없이 말을 너무 많이 늘어놓은 듯하다. 이제 머리에 새로 집어넣은 지식들을 실천을 통해 검증해 볼 때가 됐다. 인증 API를 설명할 때 언급했던 유튜브 동영상 포스팅 가상 시나리오가 예제로 적당할 것 같다. 각 주체의 행위를 중심으로 동영상이 포스팅 되기까지의 과정을 잘라보면 어떤 API를 이용해서 어떤 작업을 해야 할지 확인할 수 있다. 단계별로 짚어 가면서 구현 해보자. 예제 코드는 PHP로 작성했는데, 작업 내용을 이해하면 어떤 언어로든 어렵지 않게 옮길 수 있을 것이다.</p><p>&nbsp;</p><p><img src="http://www.dbguide.net/images/know/tech/070605-16.jpg"></p><p>[그림2] 사용자, 서버 사이의 요청과 응답 </p><p>&nbsp;</p><p>1. 사용자의 Posting 요청<br />
&lt;그림 2&gt;는 앞서 보았던 &lt;화면 2&gt;의 상황이다. 입력 폼으로부터 사용자 입력 데이터를 전달하는데, 본문 내용의 특정 부분에 대상이 되는 동영상 링크나 임베딩 시키는 코드를 추가하는 등의 처리가 필요할 것이다. 아직 API 호출은 전혀 필요치 않다.</p><p>&nbsp;</p><p>2. 사용자 인증 토큰 확인 <br />
사용자 인증 토큰이 일단 발급되고 나면 서비스 쪽에서 이를 관리하며 토큰이 만료되기 전까지는 추가적인 인증 없이 사용할 수 있다. 이 단계에서는 글쓰기를 요청한 사용자의 계정(유튜브 서비스 계정)이 만료되지 않은 토큰을 가지고 있는지 확인해야 한다. 간단한 DB 질의 정도의 작업이니 따로 코드를 제공하지 않고 넘어가도록 하겠다.</p><p>&nbsp;</p><p>3~6. 사용자 인증 토큰 발급 과정<br />
유효한 토큰이 없는 상황이라면 인증 API를 통해서 앨리스의 인증토큰을 발급 받아야 한다. 3번 단계에서 서비스는 사용자를 인증 API 서버가 제공하는 페이지로 리다이렉트 시키면서 토큰이 발급되고 나면 사용자 웹 브라우저가 돌아가야 할, 다음 처리를 위한 페이지 주소를 서버에 넘겨준다.<br />
</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스크 1&gt;post_movie.php 토큰이 없을 때 실행되는 부분</strong></span></td></tr><tr><td><p>$return_url = ‘http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/store_token.php';<br />
$auth_api_url = 'https://apis.daum.net/account/login.daum';<br />
##### 토큰이 발급된 후 사용자가 이동해야 할 페이지 주소를 GET 파라미터로 넘긴다<br />
$api_param = 'returl='.$return_url;<br />
$auth_url = DaumOpenAPI_Sign($auth_api_url, $api_param);<br />
##### HTTP header를 이용해서 리다이렉트 시킨다<br />
header('Location: '.$auth_url);</p></td></tr></tbody></table><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 2&gt; daum_openapi.php URL을 sign하는 함수 부분</strong></span></td></tr><tr><td><p>function DaumOpenAPI_Sign($plain_url, $api_param) {<br />
global $apid;<br />
global $apikey;<br />
global $sig_key;<br />
$plain_url .= '?apikey='.$apikey.'&amp;'.$api_param ;<br />
if ($apid != '') {<br />
$plain_url .= '&amp;apid='.$apid;<br />
}</p><p>$bin_sig_key = pack ( "H*" , $sig_key );<br />
$timestamp = gmdate( 'YmdHis' );<br />
$nonce = "";<br />
for ( $i=0; $i&lt; 8 ; $i++) {<br />
$hex_byte = sprintf("%02s", dechex( mt_rand(0,255)));<br />
$nonce = $nonce . $hex_byte;<br />
}</p><p>$plain_url .= '&amp;ts='.$timestamp.'&amp;nonce='.$nonce ;<br />
$signature = hash_hmac('sha1', $plain_url, $bin_sig_key);<br />
$signed_url = $plain_url.'&amp;sigalg=hmacsha1&amp;sig='.$signature;<br />
return $signed_url;<br />
}</p></td></tr></tbody></table><p>&nbsp;</p><p>사용자가 리다이렉트 된 페이지의 내용을 확인하고 인증 토큰 전달에 동의한 뒤 ID, 패스워드를 제대로 입력하면 서버는 returl로 받았던 페이지를 보여준다. 이 때 앞서 서비스가 사용자를 서버로 리다이렉트 시킬 때와 마찬가지로 utref라는 값을 GET 파라미터로 서비스에 전달한다. 이제 6번 작업, 토큰을 받아오는 페이지가 실행된다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 3&gt; store_token.php</strong></span></td></tr><tr><td><p>$utref = $_GET['utref']; ## 서버에서 사용자를 리다이렉트 할 때 지정해준 파라미터 <br />
$duip = $_SERVER['REMOTE_ADDR']; ## 사용자 PC의 IP 주소<br />
## 토큰을 잘 저장하고 나면 블로그 글쓰기 작업을 진행하도록 다음 페이지 주소 지정<br />
$next_url = 'http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/post_movie.php';</p><p>$base_url = 'https://apis.daum.net/account/token.daum';<br />
$api_param = 'utref='.$utref.'&amp;duip='.$duip;<br />
$token_url = DaumOpenAPI_Sign($base_url, $api_param);<br />
## 발급된 토큰을 읽어온다<br />
$content = file_get_contents($token_url, FALSE, NULL);<br />
if (strncasecmp($content, '&lt;?xml', 5) == 0) { ## Error! <br />
header("Content-Type: text/xml");<br />
echo $content;<br />
} else {<br />
sscanf($content, "token=%s\texpire=%s", $usertoken, $expiredate);<br />
session_start();<br />
## 사용자의 토큰을 유튜브 사용자 계정과 연계해서 DB에 저장한다고 가정한 코드<br />
$userid = $_SESSION['user_id'];<br />
init_db();<br />
put_a_token($userid, $usertoken, $expiredate);<br />
close_db();<br />
## redirect!<br />
echo '&lt;meta http-equiv="refresh" content="0;url='.$return_url.'"&gt;';<br />
}<br />
</p></td></tr></tbody></table><p>&nbsp;</p><p>&nbsp;</p><p>7. 블로그 API를 통한 게시물 등록<br />
앨리스의 토큰을 얻었으므로 해당 토큰이 만료되기 전까지 자유롭게 앨리스의 권한으로 블로그 API를 실행할 수 있다. HTML 폼에서 데이터를 가져오는 부분은 생략하고 블로그 API를 호출하는 부분만 살펴보자.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 4&gt; post_movie.php 토큰이 없을 때 실행되는 부분</strong></span></td></tr><tr><td><p>$subj = $_POST['subj'];<br />
$body = $_POST['body']; ## 사용자가 직접 작성한 내용에 동영상 링크가 추가된 상태라고 가정<br />
$tag = $_POST['tag'];<br />
$result = DaumOpenAPI_Post($subj, $body, $tag);<br />
if (!$result) {<br />
## Error 발생. 적절한 방법으로 사용자에게 등록 실패를 알린다<br />
} else {<br />
## 성공, $result에는 등록된 글 번호가 저장되어 있다<br />
} <br />
</p></td></tr></tbody></table><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 5&gt; daum_openapi.php </strong></span></td></tr><tr><td><p>$xmlrpc_url = "http://apis.daum.net/blog/XMLRPC.do";<br />
function _token_param($token) {<br />
$param = '';<br />
if ($token) {<br />
$duip = $_SERVER['REMOTE_ADDR'];<br />
$param = 'dutoken='.$token.'&amp;duip='.$duip;<br />
}<br />
return $param;<br />
}<br />
function DaumOpenAPI_Post($subj, $body, $tag, $token=NULL) {<br />
global $xmlrpc_url;<br />
$param = _token_param($token);<br />
$signed_url = DaumOpenAPI_Sign($xmlrpc_url, $param);<br />
$method_name = 'daum.blog.openapi.newPost.execute';<br />
$params = array(<br />
new xmlrpcval($subj, "string"),<br />
new xmlrpcval($body, "string"),<br />
new xmlrpcval($tag, "string")<br />
);<br />
$xml_msg = new xmlrpcmsg($method_name, $params);<br />
$client = new xmlrpc_client($signed_url);<br />
$resp = $client-&gt;send($xml_msg);<br />
if ($resp-&gt;faultCode()) {<br />
echo "error: ".$resp-&gt;faultString();<br />
return FALSE;<br />
} else {<br />
$kind = $resp-&gt;value()-&gt;kindof();<br />
if ($kind == 'scalar') {<br />
return $resp-&gt;value()-&gt;scalarval(); // article no<br />
} else {<br />
return FALSE;<br />
}<br />
}<br />
}</p></td></tr></tbody></table><p>&nbsp;</p><p>&nbsp;</p><p><strong>앨리스가 아직 블로그를 개설하지 않았을 경우의 처리</strong></p><p>&nbsp;</p><p>예외적인 경우를 모두 포함하면 그림이 너무 복잡해지므로 ‘앨리스가 다음 계정을 가지고 있지만 블로그는 아직 만들지 않은 경우’의 처리는 누락되어 있다. 토큰을 발급받아 읽어온 뒤에 API를 호출하여 블로그 개설 여부를 확인할 수 있다.</p><p>&nbsp;</p><table border="1" bordercolor="#000000" width="550"><tbody><tr><td bgcolor="#999999"><span class="logout2"><strong>&lt;리스트 6&gt; daum_openapi.php </strong></span></td></tr><tr><td><p>function DaumOpenAPI_CheckBlog($token=NULL) {<br />
global $xmlrpc_url;<br />
$param = _token_param($token);<br />
$signed_url = DaumOpenAPI_Sign($xmlrpc_url, $param);<br />
$method_name = 'daum.blog.openapi.checkBlog.execute';<br />
$params = array();<br />
$xml_msg = new xmlrpcmsg($method_name, $params);<br />
$client = new xmlrpc_client($signed_url);<br />
$resp = $client-&gt;send($xml_msg);<br />
if ($resp-&gt;faultCode()) {<br />
echo "error: ".$resp-&gt;faultString();<br />
return FALSE;<br />
} else {<br />
$kind = $resp-&gt;value()-&gt;kindof();<br />
if ($kind == 'scalar') {<br />
return $resp-&gt;value()-&gt;scalarval(); // blog address or ''<br />
} else {<br />
return FALSE;<br />
}<br />
}<br />
}</p></td></tr></tbody></table><p>&nbsp;</p><p>&nbsp;</p><p>블로그가 개설되지 않은 상황에서는 여러 가지 처리를 할 수 있다. 사용자에게 블로그를 개설한 뒤에 시도해 달라고 안내하는 게으른 처리가 가능한가 하면, 사용자로부터 희망하는 블로그 이름을 입력받은 다음 중복 여부를 확인하면서 중복될 경우에는 중복되지 않는 이름을 생성해서 추천하는 복잡한 기능을 제공할 수도 있다. 또는 블로그 이름은 언제든 변경할 수 있다는 점에 착안해서 무작위 문자열로 개설하고 포스팅을 마친 다음 원하는 이름으로 변경하라고 안내하는 방법도 생각해 볼 수 있겠다. </p><table border="0" bordercolor="#000000" cellpadding="1" width="600"><tbody><tr><td bordercolor="#000000"><p class="style45">참고 자료</p><p class="style45"><br />
1) Daum DNA 개발자네트워크 홈페이지, http://dna.daum.net<br />
2) DNA 포럼, http://dna.daum.net/forum<br />
3) 2007 대한민국 매쉬업 경진대회 홈페이지, http://mashupkorea.org <br />
4) 위키백과/HMAC, http://en.wikipedia.org/wiki/HMAC <br />
5) 이글루스 블로그 이전 프로그램, Blogyltransferase, http://openlook.org/blog/1055l <br />
6) DAUM BLOG API(비공식 공개 버전), http://blog.naver.com/nhsbs/120012199638<br />
7) 위키백과/REST, http://en.wikipedia.org/wiki/Representational_State_Transfer<br />
8) XML-RPC HOWTO, http://www.faqs.org/docs/Linux-HOWTO/XML-RPC-HOWTO.html<br />
9) ProgrammableWeb, http://www.programmableweb.com</p></td></tr></tbody></table><p>&nbsp;</p><p><a href="http://www.dbguide.net/" target="_blank"><b><font color="midnightblue">제공 : DB포탈사이트 DBguide.net </font></b></a></p><br />
<div align="right">출처 : Micro Software [2007년 4월호]</div>			 ]]> 
		</description>
		<category>OpenID</category>

		<comments>http://netkong.egloos.com/373149#comments</comments>
		<pubDate>Wed, 04 Jul 2007 12:57:50 GMT</pubDate>
		<dc:creator>넷콩</dc:creator>
	</item>
</channel>
</rss>
