<?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>Hans Life Story~</title>
	<link>http://topic.egloos.com</link>
	<description>Hans life story~</description>
	<language>ko</language>
	<pubDate>Sat, 05 Apr 2008 18:49:47 GMT</pubDate>
	<generator>Egloos</generator>
	<image>
		<title>Hans Life Story~</title>
		<url>http://pds3.egloos.com/logo/200707/04/32/e0044232.png</url>
		<link>http://topic.egloos.com</link>
		<width>80</width>
		<height>122</height>
		<description>Hans life story~</description>
	</image>
  	<item>
		<title><![CDATA[ Radeon HD 4000 series specifications surfaces ]]> </title>
		<link>http://topic.egloos.com/1586010</link>
		<guid>http://topic.egloos.com/1586010</guid>
		<description>
			<![CDATA[ 
  <span style="font-style: italic;">article: </span><a style="font-style: italic;" href="http://www.nordichardware.com/news,7356.html">http://www.nordichardware.com/news,7356.html</a><br />
<span class="textstandard"><span class="textstandard"><span class="textstandard"><img src="http://www.nordichardware.com/image3.php?id=33&amp;" style="border: 1px solid black;" align="right" hspace="10" vspace="10"></span></span></span><br />
<span class="textstandard"><p>The ATI Radeon HD 4000 series is slatedfor late Q2. Information about the high-end RV770 has been leaking ontothe web,<span class="textstandard"><span class="textstandard"></span></span><span class="textstandard"></span> from here and there, but the exact specifications has remainedin the shadows. German hardware site Hartware.net has gotten theirhands on what seems to be pretty authentic information. As far as wecan tell, it looks believable and matches the rumors going around.We're still far away from the launch and the figures are subject tochange. We also have some information on our own to share with you.</p><p><br />
</p><p>Ifyou're into extreme single-core GPUs you may want to stop reading now.ATI's future is value-oriented and if you're longing for that 1 billiontransistor megachip, you can stop doing it right now. ATI isn't intothat. We should have told you this sooner. ATI is focusing on bang forthe buck and if you want more performance you should get a second card,or get the card with two cores.</p><p><br />
 </p><p>Considering the flexibility and scaling that CrossFireX offers,we're not exactly saddened by AMD's decision to steer ATI towardfocusing more on the price/performance ratio than on raw performance.It is harder to write drivers for a multi-GPU, but when you make surethat you have a good foundation, such as CrossFireX, it might be worththe risk.</p><p><br />
</p><p>The <a set="yes" linkindex="31" href="http://www.hartware.de/news_44085.html" target="_blank"><u>information published elsewhere</u></a>suggests that ATI will use GDDR5 to a great extent, which surprise us alittle. On the other hand, ATI may know something about GDDR5 that wedon't (we would be surprised otherwise). RV770 has GDDR5 support, butwhether ATI will actually use it remains to be seen. GDDR4 with most ofthe high-end cards is a highly likely scenario. The frequenciessuggested here are actually lower than what good GDDR4 chips arecapable of.</p><p><br />
 </p><p><table style="width: 634px; height: 252px;" class="texttable" align="center" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td bgcolor="#bddae8">Radeon HD </td><td bgcolor="#bddae8"><div align="center">Shaders</div></td><td bgcolor="#bddae8"><div align="center">Core(s)</div></td><td bgcolor="#bddae8"><div align="center">VRAM</div></td><td bgcolor="#bddae8"><div align="center">GFLOPS</div></td><td bgcolor="#bddae8"><div align="center">Frequency (MHz) </div></td></tr><tr><td bgcolor="#f4f9fb">4870X2</td><td bgcolor="#f4f9fb"><div align="center">2x480</div></td><td bgcolor="#f4f9fb"><div align="center">2xRV770</div></td><td bgcolor="#f4f9fb"><div align="center">1GB GDDR5</div></td><td bgcolor="#f4f9fb"><div align="center">2016</div></td><td bgcolor="#f4f9fb"><div align="center">1050/1800</div></td></tr><tr><td bgcolor="#f4f9fb">4870</td><td bgcolor="#f4f9fb"><div align="center">480</div></td><td bgcolor="#f4f9fb"><div align="center">RV770</div></td><td bgcolor="#f4f9fb"><div align="center">1GB GDDR5</div></td><td bgcolor="#f4f9fb"><div align="center">1008</div></td><td bgcolor="#f4f9fb"><div align="center">1050/2200</div></td></tr><tr><td bgcolor="#f4f9fb">4850</td><td bgcolor="#f4f9fb"><div align="center">480</div></td><td bgcolor="#f4f9fb"><div align="center">RV770</div></td><td bgcolor="#f4f9fb"><div align="center">512MB GDDR5</div></td><td bgcolor="#f4f9fb"><div align="center">816</div></td><td bgcolor="#f4f9fb"><div align="center">850/1800</div></td></tr><tr><td bgcolor="#f4f9fb">4670</td><td bgcolor="#f4f9fb"><div align="center">240</div></td><td bgcolor="#f4f9fb"><div align="center">RV740</div></td><td bgcolor="#f4f9fb"><div align="center">512MB GDDR4</div></td><td bgcolor="#f4f9fb"><div align="center">480</div></td><td bgcolor="#f4f9fb"><div align="center">1000/1200</div></td></tr><tr><td bgcolor="#f4f9fb">4650</td><td bgcolor="#f4f9fb"><div align="center">240</div></td><td bgcolor="#f4f9fb"><div align="center">RV740</div></td><td bgcolor="#f4f9fb"><div align="center">256MB GDDR4</div></td><td bgcolor="#f4f9fb"><div align="center">384</div></td><td bgcolor="#f4f9fb"><div align="center">800/1000</div></td></tr><tr><td bgcolor="#f4f9fb">4470</td><td bgcolor="#f4f9fb"><div align="center">40</div></td><td bgcolor="#f4f9fb"><div align="center">RV710</div></td><td bgcolor="#f4f9fb"><div align="center">256MB GDDR3</div></td><td bgcolor="#f4f9fb"><div align="center">-</div></td><td bgcolor="#f4f9fb"><div align="center">900/800</div></td></tr><tr><td bgcolor="#f4f9fb">4450</td><td bgcolor="#f4f9fb"><div align="center">40</div></td><td bgcolor="#f4f9fb"><div align="center">RV710</div></td><td bgcolor="#f4f9fb"><div align="center">128MB GDDR2</div></td><td bgcolor="#f4f9fb"><div align="center">-</div></td><td bgcolor="#f4f9fb"><div align="center">700/500</div></td></tr></tbody></table></p><p><br />
</p><p>RV770 will break 1TFLOPS, while the R700, with two RV770, should becapable of twice that, more than 2TFLOPS. This is higher than what hehad expected, but then again the core frequencies are also higher thanexpected. All cores are made by TSMC and their 55nm process. We'restill trying to hunt down more reliable information on the design ofthe "core".</p><p><br />
 </p><p>On top of the information Hartware.net published we've completed thetables with some additional information, among others the target pricepoints. AMD/ATI's goal is to keep the prices at a point where they arefirst of all affordable, but also a thorn in the side of NVIDIA. Theprices in the table are the not the final MSRP, but the price ATI aimsto stick below. Meaning that the retail prices should end up lower thanwhat the tables shows.</p><p><br />
</p><p>When AMD/ATI, unveiled the Radeon HD 3000 series they had added anifty feature called PowerPlay. PowerPlay dynamically controls thepower consumption and will severely reduce the power consumption whenidle, but also reduce the peak consumption somewhat. When we look atthe figures they don't quite add up, but as stated above, these figuresare all most likely going to change before the launch. The idle powerconsumptions of all cards are extremely low and even the dual-coreRadeon HD 4870X2 will consume less than 25W when idle.</p><p><br />
 </p><p><table style="width: 616px; height: 144px;" class="texttable" align="center" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td bgcolor="#bddae8">Radeon HD </td><td bgcolor="#bddae8"><div align="center">Core(s)</div></td><td bgcolor="#bddae8"><div align="center">Idle</div></td><td bgcolor="#bddae8"><div align="center">Load</div></td><td bgcolor="#bddae8"><div align="center">Price</div></td></tr><tr><td bgcolor="#f4f9fb">4870X2</td><td bgcolor="#f4f9fb"><div align="center">2xRV770</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;25W</div></td><td bgcolor="#f4f9fb"><div align="center">250W</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;$499</div></td></tr><tr><td bgcolor="#f4f9fb">4870</td><td bgcolor="#f4f9fb"><div align="center">RV770</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;10W</div></td><td bgcolor="#f4f9fb"><div align="center">150W</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;$299</div></td></tr><tr><td bgcolor="#f4f9fb">4850</td><td bgcolor="#f4f9fb"><div align="center">RV770</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;10W</div></td><td bgcolor="#f4f9fb"><div align="center">120W</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;$249</div></td></tr><tr><td bgcolor="#f4f9fb">4670</td><td bgcolor="#f4f9fb"><div align="center">RV740</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;10W</div></td><td bgcolor="#f4f9fb"><div align="center">100W</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;$149</div></td></tr><tr><td bgcolor="#f4f9fb">4650</td><td bgcolor="#f4f9fb"><div align="center">RV740</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;10W</div></td><td bgcolor="#f4f9fb"><div align="center">80W</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;$129</div></td></tr><tr><td bgcolor="#f4f9fb">4470</td><td bgcolor="#f4f9fb"><div align="center">RV710</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;10W</div></td><td bgcolor="#f4f9fb"><div align="center">50W</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;$79</div></td></tr><tr><td bgcolor="#f4f9fb">4450</td><td bgcolor="#f4f9fb"><div align="center">RV710</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;10W</div></td><td bgcolor="#f4f9fb"><div align="center">30W</div></td><td bgcolor="#f4f9fb"><div align="center">&lt;$59</div></td></tr></tbody></table></p><p><br />
</p><p>The number of TMUs have finally been increased, actually doubled, to32 with RV770, while RV740 sports 24 TMUs, and the low-end RV710 has 8TMUs. Don't bother getting upset with the 256-bit memory bus because itwill not become any kind of bottleneck. The only time it might be evenclose to that is when you're pouring liquid nitrogen into the containerand have the GPU running at +50% of stock frequency, which will happenthough.</p><p><br />
</p><p><table style="width: 630px; height: 72px;" class="texttable" align="center" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td bgcolor="#bddae8">Core</td><td bgcolor="#bddae8"><div align="center">Shaders</div></td><td bgcolor="#bddae8"><div align="center">TMUs</div></td><td bgcolor="#bddae8"><div align="center">ROPs</div></td><td bgcolor="#bddae8"><div align="center">Bus</div></td></tr><tr><td bgcolor="#f4f9fb">RV770</td><td bgcolor="#f4f9fb"><div align="center">480</div></td><td bgcolor="#f4f9fb"><div align="center">32</div></td><td bgcolor="#f4f9fb"><div align="center">16</div></td><td bgcolor="#f4f9fb"><div align="center">256-bit</div></td></tr><tr><td bgcolor="#f4f9fb">RV740</td><td bgcolor="#f4f9fb"><div align="center">240</div></td><td bgcolor="#f4f9fb"><div align="center">24</div></td><td bgcolor="#f4f9fb"><div align="center">12</div></td><td bgcolor="#f4f9fb"><div align="center">256-bit</div></td></tr><tr><td bgcolor="#f4f9fb">RV710</td><td bgcolor="#f4f9fb"><div align="center">40</div></td><td bgcolor="#f4f9fb"><div align="center">8</div></td><td bgcolor="#f4f9fb"><div align="center">4</div></td><td bgcolor="#f4f9fb"><div align="center">128-bit</div></td></tr></tbody></table></p><p><br />
</p><p>To end this long and speculative post, we would like to say that ifnot all, most of the variables here are subject to change and should beconsidered with a "tiny" pinch of salt. We're still 4 month away fromthe launch.</p></span><br />
<br />
<br />
<br/><br/>tag : <a href="/tag/vga" rel="tag">vga</a>,&nbsp;<a href="/tag/radeon" rel="tag">radeon</a>,&nbsp;<a href="/tag/ati" rel="tag">ati</a>,&nbsp;<a href="/tag/hd3870x2" rel="tag">hd3870x2</a>,&nbsp;<a href="/tag/hd3870" rel="tag">hd3870</a>			 ]]> 
		</description>
		<category>Interest</category>
		<category>vga</category>
		<category>radeon</category>
		<category>ati</category>
		<category>hd3870x2</category>
		<category>hd3870</category>

		<comments>http://topic.egloos.com/1586010#comments</comments>
		<pubDate>Sat, 05 Apr 2008 18:49:47 GMT</pubDate>
		<dc:creator>Hans</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 정말 간만에 튕기는 Guitar Hero II ]]> </title>
		<link>http://topic.egloos.com/736630</link>
		<guid>http://topic.egloos.com/736630</guid>
		<description>
			<![CDATA[ 
  퇴근하고 집에 와서 간만에 Guitar Hero II CD를 넣고 튕겨봤다..<br />
역시나 오랜만에 해서 그런지 잘 안된다..<br />
그래도 명작답게 재미있네.... 빨리 Guitar Hero III 가 발매되어야 할텐데...<br />
<br />
<object height="350" width="425"><param name="movie" value="http://www.youtube.com/v/04TvbIBcczo"><embed src="http://www.youtube.com/v/04TvbIBcczo" type="application/x-shockwave-flash" wmode="transparent" height="350" width="425"></object><br />
<br/><br/>tag : <a href="/tag/guitarhero" rel="tag">guitarhero</a>,&nbsp;<a href="/tag/xbox" rel="tag">xbox</a>,&nbsp;<a href="/tag/Xbox360" rel="tag">Xbox360</a>,&nbsp;<a href="/tag/game" rel="tag">game</a>,&nbsp;<a href="/tag/엑스박스" rel="tag">엑스박스</a>,&nbsp;<a href="/tag/기타히어로" rel="tag">기타히어로</a>			 ]]> 
		</description>
		<category>Interest</category>
		<category>guitarhero</category>
		<category>xbox</category>
		<category>Xbox360</category>
		<category>game</category>
		<category>엑스박스</category>
		<category>기타히어로</category>

		<comments>http://topic.egloos.com/736630#comments</comments>
		<pubDate>Mon, 10 Sep 2007 18:42:41 GMT</pubDate>
		<dc:creator>Hans</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 구글 검색 엔진의 해부학 - The anatomy of large scale search engine ]]> </title>
		<link>http://topic.egloos.com/537703</link>
		<guid>http://topic.egloos.com/537703</guid>
		<description>
			<![CDATA[ 
  <div style="text-align: right;"><span style="color: rgb(204, 102, 0);">구글 개발자들이 쓴 'The anatomy of large scale search engine' 논문 번역</span><br />
</div><br />
<br />
<h3>Abstract</h3>      <p>이 논문을 통해 우리는 구글(Google)이라는, 하이퍼텍스트를 통해 나타나는 구조적 특징을 대폭 사용한 대형 검색 엔진의프로토타입을 제시하고자 한다. 구글은 웹을 능률적으로 긁어와서 인덱싱(색인화)한 다음 (crawling &amp;indexing) 기존의 시스템보다 훨씬 더 만족스런 검색 결과를 나타낼 수 있도록 디자인되었다. 최소 2천 4백만 페이지로이뤄진 하이퍼링크 데이타베이스와 풀 텍스트로 이뤄진 구글의 프로토 타입은 http://google.stanford.edu의주소로 이용해 볼 수 있다.</p>   <p><img src="http://www.emh.co.kr/images/google_logo.gif" alt="google search engin 구글" align="right" border="0" height="110" hspace="10" vspace="10" width="276">검색엔진을 제작한다는 것은 상당히 도전적인 과제다. 검색 엔진은 수억에서 수십억 개의 웹 페이지와 수억-수십억 개의 용어들을 함께인덱싱한다. 또한 검색엔진은 매일 수천 만 개의 질의어에 응답한다. 웹 기반의 대형 검색엔진의 중요성이 분명함에도 불구하고 이에대해 학문적으로 연구된 바는 거의 없다. 게다가 웹의 분화와 테크널러지의 발달이 매우 빠르기 때문에 오늘 웹 검색엔진을 만드는것은 3년 전에 만드는 것과 전혀 다르다. 이 논문에서 우리는 우리가 만든 대형 웹 검색엔진에 대해서 자세하게 묘사하고자한다.(현 시점까지 이렇게 자세한 내용이 공개된 것은 최초라 할 수 있다.)</p>      <p>전통적인 검색 기술을 거대한 크기의 데이타에 맞게 확장하는 것에서 초래되는 문제들은 별개로 하더라도, 보다 나은 검색결과를 나타낼 수 있도록 하이퍼텍스트에 나타나는 부가적인 정보를 이용하는 문제 같은 새로운 기술적 과제들이 있다. 이 논문에서는이와 같은 하이퍼텍스트에 존재하는 부가적인 정보를 실제 사용 가능한 대형 시스템을 구축하는 데 어떻게 활용할 수 있는가라는문제에 대한 해결책을 제시한다. 또한 우리는 웹처럼 아무나 원하는 것을 출판할 수 있는 조절되지 않는 하이퍼텍스트 문서컬렉션(uncontrolled hypertext collections)을 어떻게 효과적으로 다룰 수 있을지의 문제도 살펴본다.</p>      <h3>1. 개괄</h3>      <p>웹은 정보검색(IR; Information Retrieval)에 새로운 과제를 안겨줬다. 웹에 존재하는 정보들은 매우빠르게 늘어나고 있다. 그리고 웹에서 무엇인가를 찾는 것에 익숙하지 못한 새로운 사용자들의 숫자도 급속하게 늘어나고 있다.사용자들이 웹 써핑을 할 때 대개 링크 그래프(link graph)를 이용하는 경향이 크다. 사람이 직접 만든 목록 중 아주높은 품질의 목록(야후! 같은)에서 출발하거나 검색엔진을 이용한다. 사람이 직접 유지관리하는 목록은 보편적인 주제를 효과적으로커버할 수 있다는 장점이 있지만, 주관적이기 쉽고 구축/유지 비용이 매우 높고, 개선이 느리고 모든 특이한 주제를 커버할 수없다는 단점이 있다. 한편 키워드 매칭(keyword matching)을 기반으로 하는 자동화된 검색엔진(automatedsearch engine)은 대개 너무 많은 낮은 질의 맷치를 결과로 돌려주는 경우가 잦다. 게다가 어떤 광고인들은 자동화된검색엔진이 엉뚱한 결과를 나타낼 수 있는 방법을 사용해서 사람들의 주의를 끌어가려는 시도를 한다. 우리는 이와 같은 기존시스템의 여러가지 문제점들을 해결한 대형 검색엔진을 구축했다. 특히 우리 검색엔진은 훨씬 높은 수준의 검색 결과를 제공하기 위해하이퍼텍스트에 존재하는 부가적인 구조를 대폭 사용했다. 우리는 우리 시스템 이름을 '구글'(Google)로 택했는데, 이것은 10<sup>100</sup> 또는 'googol'을 뜻하는 일반적인 철자이기 때문이기도 하고 매우 큰 스케일의 검색엔진을 구축하겠다는 우리의 목표와 잘 부합되기 때문이기도 했다.</p>      <h4>1.1 웹 검색엔진의 확장: 1994 - 2000</h4>      <p>검색엔진 기술은 웹의 성장세에 맞춰 극적으로 확장되어 왔다. 1994 년 최초의 검색엔진 중 하나인 World WideWeb Worm(WWWW)은 110,000 페이지의 웹문서 및 웹을 통해 접근가능한 문서를 색인화(indexing;인덱싱)한다.1997년 현재, 최고 수준의 검색엔진들은 2백만 문서에서(WebCrawler) 1억 개의 문서까지 인덱싱했다고 주장하고 있다.2000년 말쯤이면, 약 10억 개 이상의 문서에 대한 포괄적인 인덱스(comprehensive index)가 만들어질 것으로예상되고 있다. 검색엔진이 다루는 질의어(queries)의 숫자 역시 믿기지 않을 정도로 성장해 왔다. 1994년 3,4월경,WWWW은 매일 평균 1500여 개의 질의어를 받았었다. 그런데 1997년 11월, 알타비스타(AltaVista)의 주장에따르면 매일 약 2천만 개의 질의어를 처리하고 있다 한다. 웹 사용자가 더욱 늘어나게 됨에따라, 2000년 말쯤에 이르면 탑검색엔진들은 매일 평균 약 수억 개의 질의어를 다루게 될 것이다. 우리 시스템은 검색엔진 기술을 위와 같은 놀라운 크기의 숫자를다룰 수 있게 확장하는 데 있어 발생하는 많은 문제점들을 그 질적인 측면에서나 확장성 면에서나 잘 해결해 보겠다는 목표를 갖고있다.</p>      <h4>1.2 구글(Google): 웹과 함께 확장한다</h4>      <p>오늘날의 웹 정도를 포괄하는 검색엔진을 만드는 일도 많은 도전적 과제를 해결해야 한다. 웹 문서들을 모으고 최신 상태로유지하기 위해서는 빠른 속도의 크롤링 기술(crawling technology)이 필요하다. 그리고 색인(index)을 저장하고때로는 문서 자체를 저장하기 위해 저장 공간은 반드시 효율적으로 사용되어야만 한다. 인덱싱 시스템은 수백 기가바이트의 데이타를효율적으로 처리할 수 있어야만 하고 질의어 역시 초당 수백, 수천 개 이상의 빠른 속도로 처리되어야 한다. </p>      <p>이런 과제들은 웹이 계속 성장해 감에 따라 갈수록 어려워지고 있다. 하드웨어 성능과 비용이 극적으로 좋아지고 있는 것은이런 문제점들을 어느 정도는 상쇄한다. 그러나 거기에도 주목할 만한 예외가 있다. 디스크 검색 속도(disk seektime)라든지 운영체계의 강력함(robustness)은 별로 개선되지 못하고 있다. 구글을 디자인함에 있어, 우리는 웹의 성장속도와 테크널러지의 변천 속도 모두를 고려해 왔다. 구글은 극단적으로 큰 데이타 셋(data sets)을 위해서도 충분히 확장될수 있도록 디자인되어 있다. 인덱스를 저장하기 위한 저장 공간을 효율적으로 사용할 뿐만 아니라 구글의 데이타구조는 빠른 억세스,효율적인 억세스에 적합하도록 최적화되어 있다. (4.2 섹션에서 자세히 다룬다) 그리고 HTML이나 텍스트를 저장하고 인덱싱하는비용은 그 양이 늘어남에 비해 상대적으로 감소할 것으로 예상된다. 이것은 구글과 같은 중앙집중식 시스템의 확장성에 좋은 영향을미치게 된다.</p><h4>1.3 디자인 목표</h4>      <h5>1.3.1 검색 품질의 개선</h5>      <p>우리의 주된 목표는 웹 검색 엔진의 질적인 면을 개선하는 것이었다. 1994년 당시만 해도 완전한 검색엔진 인덱스를갖춤으로써 무엇이든 쉽게 찾을 수 있을 것이라 믿는 사람들이 있었다. "Best of the Web 1994 --Navigators"에는, "최상의 네비게이션 서비스는 웹상의 거의 모든 것을 쉽게 찾을 수 있도록 해줘야 한다 (일단 모든데이타가 입력되고 나면)" 라고 실려있었던 것이다. 하지만 1997년의 웹은 그 전과 전혀 다른 양상이다. 최근 검색 엔진을사용해 본 사람이라면 누구나 인덱스 자체의 완전성이 검색 결과의 품질을 결정하는 유일한 요소가 아님을 얘기할 것이다. "쓰레기검색 결과"(Junk results)가 원하는 결과를 압도해버리는 것이 드물지 않다. 사실, 1997년 11월 현재, 검색창에검색엔진 자신의 이름을 입력했을 때 탑 10 결과 내에 자신의 이름이 들어있는 검색 엔진은 상위 4 개의 상업적 검색 엔진에불과하다.</p>       <p>이것의 주된 원인은, 문서의 수는 기하급수적으로 증가해온 반면 사용자가 문서를 찾는 능력은 그렇지 못했기 때문이다.사람들은 여전히 검색 결과 중 수십 개 정도만을 보려한다. 그러므로 문서 모음(이하 컬렉션, collection)의 크기가증가함에 따라 대단히 높은 프리시젼(precision)<span class="fnum">역자주</span>을 가진 툴이 필요해진다. (precision은 검색 결과 중 실제 검색어와 관계되는 결과의 비율)</p>      <p>사실 우리는, "관계되는"이라는 단어의 의미를 아주 높은 수준으로 규정하려 했는데 그 이유는 '약간' 관계되는 문서들만해도 수만 개 이상이기 때문이다. 극도로 높은 수준의 프리시젼은 심지어 리콜(recall)을 희생해서라도 달성해야 할 만큼중요하다. (recall은 관계되는 문서 중 얼마나 많은 것을 찾아낼 수 있느냐를 의미) </p>      <p>최근, 하이퍼텍스트적인 정보를 보다 더 많이 이용함으로써 검색이나 다른 부문의 기능을 개선할 수 있을 것이라는 낙관적인전망이 많이 나오고 있다. 특히 링크 구조와 링크 텍스트는 "관계성 판단"(relevance judgement)과 질적인필터링에 있어서 많은 정보를 제공할 수 있다. 구글은 그 링크 구조와 앵커 텍스트(anchor text)를 사용하고 있다.</p><div class="footnote"><span class="fnum">역자주 : </span> recall과precision은 정보검색(IR)에서 중요한 성능 측정 기준으로 사용하는 지표입니다. precision은 검색 결과 중에실제로 '관계되는' 문서가 몇 개인가를 의미합니다. 즉, 결과의 '정확도'입니다. recall은 검색어와 관계되는 문서 전체중에 몇 개를 찾아내느냐입니다. precision은 보통 상위 몇 위까지 중 관계되는 문서가 몇 개인가 형태로 평가합니다.<br />
<br />
예를 들어 어떤 컬렉션의 총 문서 갯수는 100 개이고 이 중에 '사과'와 관계되는 문서가 30 개 있다고합시다. 질의어 '사과'에 대해서 어떤 검색 시스템이 총 15 개의 결과를 되돌려 주었고 상위 10 위까지의 결과 중 실제로사과와 관계되는 문서가 8 개였다면 precision과 recall은 이렇게 계산합니다. <br />
<br />
상위 10 위에서의 precision = 8 / 10 = 0.8<br />
recall = 15/30 = 0.5<br />
<br />
논문은, 웹 검색의 경우 리콜이 극도로 높고 (대개 검색결과가 수만 페이지 이상이기 때문에) 사용자들은 상위 몇 개만을 보려하기때문에 프리시젼이 극도로 높아야만 한다는 것을 얘기하고 있습니다. 소규모 도서관 정보 검색 시스템이라면 얘기가 전혀 다릅니다.관계되는 모든 서적을 다 찾아내는 것이 더 중요할 수 있습니다. 그 때는 리콜이 더 중요합니다. 그렇다면 리콜과 프리시젼은 어떤관계일까요? 반비례일까요, 비례일까요? 아니면? </div>      <h5>1.3.2 검색 엔진에 관한 학술 연구</h5>      <p>웹은 자체 성장속도 뿐만 아니라 상업화의 속도도 엄청나게 빠르다. 1993 년에는 .com 도메인이 전체의 1.5%였다.그러던 것이 1997 년에는 전체의 60%를 차지하고 있다. 검색엔진 역시 학술적 영역에서 벗어나 상업화되어 왔다. 현재까지기업체에서 개발한 검색엔진의 대부분은 기술적인 디테일을 거의 발표하지 않고 있다. 검색 엔진 기술은 장막에 가려진 채 광고지향적인 것으로 남아있는 실정이다. 우리는 구글을 통해서 검색 엔진 개발과 이해를 보다 학술적인 영역으로 끌어와 보고자 했다.</p>      <p>또 하나 중요한 디자인 목표는 상당한 숫자의 사람들이 실제로 사용할 수 있는 시스템을 구축해 보자는 것이었다. 구축한시스템이 실제로 사용되어야 한다는 점이 중요한데 그 이유는, 오늘날의 웹 시스템에서 만들어질 수 있는 대용량의 유시지데이타(usage data)를 활용함으로써 아주 흥미로운 연구가 이뤄질 수 있다고 생각하기 때문이다. 예를 들면 매일매일이뤄지는 수억 건의 검색 행위와 관계되는 데이타가 그렇다. 하지만 이런 데이타는 확보하기가 매우 어렵다. 상업적 가치가 높다고여겨져서 공개되지 않기 때문이다.</p>      <p>마지막 디자인 목표는 대용량 웹 데이타상에서 많은 새로운 연구 활동이 이뤄질 수 있도록 그 기반을 구축해 보겠다는것이었다. 새로운 연구에 사용되게 만들기 위해 구글은 크롤링한 실제 문서 그 자체를 압축된 형태로 저장한다. 구글을 디자인함에있어 우리의 주된 목표 중 하나는 다른 연구자들이 웹의 상당한 부분을 처리해서 흥미로운 결과를 내놓은 것에 쉽게 참여할 수 있는길을 터주자는 것이었다. 구글 시스템을 가동한 지 얼마되지 않았음에도 구글에 의해 생성된 데이타베이스를 이용한 여러 편의 연구가이미 발표되었고 또한 많은 연구가 현재 진행중이다. 또 하나의 목표는 구글을 일종의 우주 실험실과 같은 환경으로 만들어서 다른연구자들이나 학생들이 대형 웹 데이타상에서 여러가지 흥미로운 실험을 제안하고 실행해 볼 수 있게 하겠다는 것이다.</p>      <p>구글 검색 엔진은 검색 결과가 높은 프리시젼을 갖도록 두 가지 중요한 특징을 부여했다. <br />
첫째, 구글은 개별 웹 페이지 품질을 순위 매기기 위해 웹의 링크 구조를 이용한다. 이 랭킹은 페이지랭크(PageRank)라 일컬어지며 <a linkindex="12" href="http://www.emh.co.kr/xhtml/google_pagerank_citation_ranking1.html">다른 논문에서</a> 자세히 설명했다. 둘째, 구글은 검색 결과를 개선하기 위해서 링크를 사용한다.</p>      <h4>2.1 페이지랭크(PageRank) : 웹에 순서를 매긴다</h4>      <p>웹의 인용(링크) 그래프는 기존의 웹 검색 엔진들이 거의 사용하지 않고 있는 중요한 자원 중 하나이다. 우리는 총5억1800만 개의 하이퍼링크를 담고 있는 링크 지도를 만들었는데 이것은 전체 웹의 상당 부분을 포괄하는 것이다. 이 지도를이용하면 어떤 웹 페이지의 "페이지랭크" 값을 빠르게 계산할 수 있다. 페이지랭크는 일반적인 사용자가 생각하는 특정 페이지의중요성과 잘 상응하는 인용 중요성의 객관적인 측정치다. 인간 판단과의 이런 연관성 때문에 페이지랭크는 웹 키워드 검색 결과를순위 매기는 데 있어 최상의 수단이 된다. 대부분의 일반적 검색어에 있어서, 문서 제목과 검색어가 일치하는지만을 평가하는 단순한텍스트 매칭 검색 엔진을 이용한 결과에서도, 그 결과를 페이지랭크로 순위를 매기는 경우 상당한 성능을 보여준다. 물론 구글시스템과 같이 완전한 텍스트 검색을 수행하는 시스템에서도 페이지랭크는 매우 큰 도움을 준다.</p>      <h5>2.1.1 페이지랭크 계산 방법</h5>      <p>학술 문헌 인용 방식을 웹에도 적용해보려는 시도가 있어 왔는데 대개 어떤 페이지의 인용 횟수(<a linkindex="13" href="http://www.emh.co.kr/xhtml/google_pagerank_citation_ranking1.html#back_link">백링크; back link</a>)를 세는 방식으로 이뤄진다. 어떤 페이지가 얼마나 많이 인용(참조)되고 있는가를 셈으로써 그 페이지의 중요성이나 품질을 추정해볼수 있는 것이다. 페이지랭크는 이 아이디어를 더욱 확장해서 단순히 모든 링크를 세는 것에서 한 발 더 나아가 그 링크가 어떤페이지로부터 왔는지를 차별화했고, 링크를 하고 있는 페이지로부터 외부로 나가는 총 링크 갯수로노멀라이징(normalizing)했다. 페이지랭크는 다음과 같이 정의된다:</p>      <p>페이지 A를 가리키는 다른 페이지들이 T1, T2, ... Tn 까지 있다고 하자. ( = T1,...Tn은 페이지 A를 인용) <br />
퍼래미터 d는 damping factor로 0에서 1 사이의 값을 갖는다. 우리는 보통 d = 0.85로 했다. d값에 관해서는 다음 섹션에서 다룬다.<br />
C(A)는 페이지 A에서 밖으로 나가는 링크의 갯수다. 이때 A 페이지의 페이지랭크 PR(A)는:<br />
<br />
</p><div class="imageCenter"><img src="http://www.emh.co.kr/images/pagerank.gif" alt="pagerank 페이지랭크" border="0" height="57" width="649"></div>      <p>페이지랭크 PR(A)는 단순한 반복 알고리듬(iterative algorithm)을 이용해서 계산할 수 있으며, 그 값은웹 링크를 노멀라이징해서 행렬로 바꾸었을 때 주고유벡터(principal eigenvector)에 해당한다. 또한 2천6백만페이지의 페이지랭크는 중간 크기의 웍스테이션에서도 몇 시간 정도면 계산할 수 있다. 이에 관해서는 이 페이퍼의 범위를 벗어나는많은 세부사항이 있다. </p>      <h5>2.1.2 직관적 정당화</h5>      <p>페이지랭크는 사용자 행동을 모델링한 것으로 생각해볼 수 있다.<br />
 "랜덤 써퍼"가 한 명 있다고 하자. 이 사람은무작위로 선택한 어떤 웹 페이지에서 출발해서 백버튼을 누르지 않고 계속 링크를 따라 클릭해 나간다. 그러다가 지루해지면 또 다른무작위로 선택된 페이지에서 써핑을 시작할 것이다. 랜덤 써퍼가 특정 페이지를 방문할 확률이 바로 그 페이지의 페이지랭크다.그리고 d damping factor는 랜덤 써퍼가 어떤 페이지를 읽다가 지루해져서 또 다른 랜덤 페이지를 찾게될 확률을뜻한다. 페이지랭크의 변형된 형태 중에서 중요한 것 중 하나가 댐핑 팩터(damping factor) d를 특정 페이지 하나또는 일군의 페이지에만 선택적으로 적용하는 것이다. 이렇게 함으로써 사용자화(personalization)가 가능하며 랭킹을올리기 위해 교묘하게 조작하는 것을 사실상 불가능하게 만들 수 있다. 그 외에도 많은 페이지랭크의 확장이 있다.</p>      <p>또 하나의 직관적인 정당화는, 페이지랭크가 올라가기 위해서는 많은 페이지가 어떤 한 페이지를 가리켜야 하거나 특정 페이지를가리키는 페이지 그 자체의 페이지랭크 값이 커야 한다는 점이다. 직관적으로도 웹상의 여러 곳에서 인용되고 있는 페이지는 살펴볼만한 가치가 있다는 의미이므로 쉽게 이해가 된다. 또한 Yahoo!와 같은 중요한 곳에서 인용이 되고 있다면 링크가 오직 한개뿐일지라도 그 페이지는 살펴볼 가치가 있을 것이다. 어떤 페이지가 품질이 낮거나 링크가 깨져있다면, Yahoo!같은 곳에서 그페이지로 링크를 걸어놓지 않을 것이기 때문이다. 페이지랭크는 이 두 가지 경우 모두를 잘 다루고 있으며 양자 사이의 모든 부분도웹의 링크 구조를 통해 가중치를 재귀적으로 전파시켜 나감으로써 잘 다루고 있다. </p>      <h4>2.2 앵커 텍스트(Anchor Text)</h4>      <p>우리 검색 엔진은 링크의 텍스트 그 자체를 특별하게 다룬다. 대부분의 검색 엔진들은 링크의 텍스트를 링크를 담고 있는 그페이지와만 연관시킨다. 우리는 더 나아가 링크가 가리키는 페이지까지 링크의 텍스트와 연관시킨다. 이것은 여러가지 장점이 있다.첫째, 앵커는 종종 그 링크가 담겨있는 페이지보다 그 링크가 가리키는 페이지에 대한 보다 정확한 설명을 담고 있는 경우가 많다.둘째, 일반적인 텍스트 검색 엔진이 인덱싱할 수 없는 이미지나 프로그램, 데이타베이스로의 앵커(링크)도 존재할 수 있다.그러므로 앵커를 활용하면 실제로 크롤링되지 않은 웹 페이지들까지 찾아낼 수 있다. 물론 크롤링되지 않은 페이지들이 문제를 일으킬수 있다는 점은 주의해야 한다. 이 페이지들은 사용자에게 결과로 뿌려주기 전에 유효성을 먼저 테스트 해야한다. 심지어 실제존재하지 않는 페이지인데도 가리키는 링크가 있기 때문에 반환될 수도 있다. 하지만 이런 검색 결과를 분류하는 것이 가능하므로특별한 문제를 일으키는 경우는 거의 없다. </p>      <p>앵커 텍스트를 그 앵커가 가리키는 페이지로 전파시켜 나간다는 아이디어는 World Wide Web Worm 검색 엔진에서구현되었었다. 앵커 텍스트가 텍스트가 아닌 정보를 검색하는데 도움이 되었고, 검색 엔진이 다운로드한 문서보다 훨씬 더 많은부분을 커버할 수 있게 확장해주기 때문이다. 앵커 텍스트를 효율적으로 사용하려면 대용량의 데이타를 처리해야만 하기 때문에기술적으로 까다롭다. 우리는 크롤링한 2400만 페이지에서 약 2억5900만 개 이상의 앵커를 인덱싱할 수 있었다.</p>      <h4>2.3 다른 특징들</h4>      <p>페이지랭크 기술과 앵커 텍스트를 사용한다는 점 외에 구글은 몇 가지 다른 특징을 가진다.<br />
첫째, 구글은 모든 힛(hit)에 관한 위치 정보를 저장하기 때문에 검색 時 근접도를 광범위하게 활용한다. 둘째, 구글은 어떤단어의 폰트 크기와 같은 시각적인 세부 요소를 추적한다. 폰트 싸이즈가 큰 단어나 볼드체로 된 단어는 그렇지 않은 단어에 비해더 높은 가중치가 부여된다. 셋째, 구글은 완전한 HTML도 저장하기 때문에 이를 이용할 수 있다.</p>      <h3>3. 관련 연구</h3>      <p>웹 상의 검색 연구는 역사가 얼마 되지 않는다. World Wide Web Worm (WWWW) 검색 엔진이 대표적인최초의 검색엔진이다. WWWW을 기점으로 그 뒤에 몇 개의 학술적 목적의 검색엔진이 나타났다. 웹의 성장세나 검색 엔진의중요성에 비해 현대적 웹 검색엔진에 관한 문서는 거의 없는 실정이다. Michael Mauldin(Lycos 의 ChiefScientist)씨는, "라이코스를 포함한 여러 서비스들은 자기 데이타베이스의 디테일들을 엄격하게 감추고 있다"고 밝혔다.하지만 검색엔진의 특정 기능에 관해서는 상당한 양의 연구가 진행되어 왔다. 특히 기존의 상업적 검색엔진을 이용한 결과물을후처리(post processing)한 것에 관한 부문이 두드러진다. 반면 정보검색(IR, InformationRetrieval)에 관해서는, 특히 잘 조절되고 있는 컬렉션을 대상으로한 것은, 이미 많은 연구가 나와있다. 다음 두섹션에서, 우리는 이들 연구를 웹에서 보다 더 잘 동작하도록 확장하는 방법을 살펴볼 것이다.</p>      <h4>3.1 정보 검색</h4>      <p>정보 검색 시스템에 관한 연구는 오래 전부터 있어 왔으며 잘 정리되어 있다. 하지만 대부분의 정보 검색 시스템에 관한연구는 소규모의 잘 통제되고 있는 동질적인 컬렉션(a small well controlled homogenouscollection)을 대상으로 하고 있다. 예를 들면 과학 논문이나 서로 연관되는 뉴스 기사들을 대상으로 하고 있다. 실제정보 검색의 가장 대표적인 벤치마크로 사용되는 TREC(Text Retrieval Conference)의 경우 아주 작은 크기의잘 통제되어 있는 컬렉션을 이용한다. "초대형" 벤치마크라고 해 봐야 겨우 20기가 바이트에 지나지 않는다. 반면 우리가모아놓은 2천400만 개의 웹 페이지는 147기가 바이트에 이른다. TREC에서는 좋은 결과를 보이더라도 웹에서는 좋은 결과를나타내지 못하는 경우가 많다. 예를 들어, 표준적인 벡터 공간 모형(Vector Space Model)은 질의어와 문서를 단어빈도에 의거한 벡터로 파악해서 질의어에 가장 근접한 문서를 되돌려주는 방식이다. 하지만 웹에서 벡터 공간 모형을 사용하면 질의어외에 몇 단어 없는 매우 짧은 문서가 반환되는 경우가 많다. 메이져 검색 엔진에 "Bill Clinton"이라는 질의어를 넣어보면 "Bill Clinton Sucks"라는 문장과 사진이 담겨 있는 페이지만 결과로 되돌려 준다. 어떤 사람은 질의어 외에부가적으로 단어를 추가해서 사용자가 찾는 단어를 더 정확하게 표현할 수 있는것 아니냐고 주장한다. 우리는 그런 주장에 전혀동의하지 않는다. 사용자가 "Bill Clinton"이라는 질의어를 입력했다면 당연히 합리적으로 받아들일 수 있는 결과를 얻어야한다. 웹에는 그 주제에 관한 엄청나게 많은 고품질의 페이지가 있기 때문이다. 이런 예들을 보면서 우리는 표준적인 정보 검색연구를 웹에 효과적으로 적용하기 위해서는 더욱 많은 확장이 필요하다고 생각하게 되었다.</p>      <h4>3.2 웹과 잘 통제되는 컬렉션 사이의 차이점들</h4>      <p>웹은 전혀 통제되지 않는 이질적인 문서들로 이뤄진 거대한 컬렉션이다. 웹상의 문서는 문서 내부적으로도 극단적으로 다양할뿐만 아니라 문서 외부적인 메타 정보 역시 매우 다양하다. 예를 들어, 여러 웹 문서들은 내부적으로 사용 언어 측면에서 다르고(인간의 언어 측면에서도 그렇고 컴퓨터 언어 측면에서도 그렇다), 어휘에 있어서도 다르고 (이메일 주소, 링크, 우편 번호,전화 번호, 제품 번호 등), 포맷이나 유형 면에서도 다르며 (텍스트, HTML, PDF, 이미지, 싸운드) 심지어 어떤문서들은 컴퓨터에 의해 생성되고 있는 것이다. (로그 파일, DB 로부터 출력된 내용)</p>      <p>메타 정보의 경우도 마찬가지다. <br />
우리는 외부 메타 정보를 어떤 문서 내부에는 담겨 있지 않은 정보로, 그 문서 자체에 관해 유추할 수 있는 정보로 정의한다.외부 메타 정보에는 그 페이지의 명성, 업데잇 빈도, 품질, 인기도 또는 유시지(usage), 그리고 인용 등이 있다. 외부메타 정보는 그 잠재적 소스가 다양할 뿐만 아니라, 측정값 역시 큰 차이가 난다. 야후! 홈페이지와 수십 년된 낡은 기사를비교해 보자. 야후!는 매일 수백만 페이지뷰 이상을 받지만, 후자의 경우는 십 년만에 한 번 찾아지거나 할 것이다. 이 경우사용도는 현격하게 차이가 난다. 그리고 검색 엔진은 이 둘을 전혀 다른 방식으로 다뤄야 한다는 것 역시 당연하다.</p>      <p>잘 통제되는 컬렉션과 웹이 크게 다른 또 다른 점은, 웹에서는 누가 무엇을 올려놓을지를 조절할 방법이 사실상 없다는점이다. 무엇이든 퍼블리슁할 수 있다는 웹의 유연성이 트래픽을 안내하는 검색 엔진의 엄청난 영향력과 맞물리면, 검색 엔진을교묘하게 조절해서 이득을 취해가려는 회사들이 심각한 문제가 된다. 이런 점들은 전통적인 폐쇄적 정보검색 시스템에서는 전혀 문제가되지 않았었다.</p>      <p>웹 검색 엔진의 경우 메타 데이타(<a linkindex="14" href="http://www.emh.co.kr/xhtml/metatag.html">메타 택 (Meta Tag)</a>)를 사용하려는 시도가 거의 실패로 돌아갔다는 점 또한 특기할 만하다. 실패한 이유는 검색 엔진을 악용하기 위해 메타 정보가남용되었기 때문이다. 심지어 메타 태그를 이용, 검색 엔진을 조작하는 쪽으로 특화한 회사들도 상당수 존재할 정도이다. </p><br />
<br />
<br />
<br />
<br />
문서출처: <a set="yes" linkindex="9" href="http://www.emh.co.kr/">이명헌 경영스쿨</a> <a set="yes" linkindex="10" href="http://www.emh.co.kr/xhtml/google_search_engine.html">http://www.emh.co.kr/xhtml/google_search_engine.html</a> <br />
 이 문서를 게시하거나 프린트하려면 위 문서출처를 반드시 포함해야 합니다.(참고: <a set="yes" linkindex="11" rel="license" href="http://creativecommons.org/licenses/by-nc-nd/2.0/kr/deed.kr">저작권정책</a>)<br />
<br/><br/>tag : <a href="/tag/검색엔진" rel="tag">검색엔진</a>,&nbsp;<a href="/tag/웹" rel="tag">웹</a>,&nbsp;<a href="/tag/구글" rel="tag">구글</a>,&nbsp;<a href="/tag/인덱싱" rel="tag">인덱싱</a>,&nbsp;<a href="/tag/엔진" rel="tag">엔진</a>,&nbsp;<a href="/tag/하이퍼텍스트" rel="tag">하이퍼텍스트</a>,&nbsp;<a href="/tag/인덱스" rel="tag">인덱스</a>,&nbsp;<a href="/tag/검색" rel="tag">검색</a>			 ]]> 
		</description>
		<category>Search Engine</category>
		<category>검색엔진</category>
		<category>웹</category>
		<category>구글</category>
		<category>인덱싱</category>
		<category>엔진</category>
		<category>하이퍼텍스트</category>
		<category>인덱스</category>
		<category>검색</category>

		<comments>http://topic.egloos.com/537703#comments</comments>
		<pubDate>Mon, 13 Aug 2007 11:44:03 GMT</pubDate>
		<dc:creator>Hans</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 링크 구조 기반 검색 앨거리듬, HITS ]]> </title>
		<link>http://topic.egloos.com/537684</link>
		<guid>http://topic.egloos.com/537684</guid>
		<description>
			<![CDATA[ 
  <div style="text-align: right;"><span style="font-family: '굴림','Gulim'; color: rgb(204, 102, 0);">클라인버그 교수의 "Authoritative sources in a hyperlinked environment" 논문 요약</span><br />
<span style="font-family: '굴림','Gulim'; color: rgb(204, 102, 0);"></span></div><span style="font-family: '굴림','Gulim'; color: rgb(204, 102, 0);"><br />
<span style="color: rgb(0, 0, 0);"></span><br />
</span><div class="contentProper"><h3>개괄</h3><p>논문의 도입부에서는 질의어와 'authoratative sources'의 관계, 그리고 링크 구조의 분석 방법등을다룹니다. 우선 "broad search topic"이란 문구가 나오는데요, 검색어는 주제의 범위가 넓은 것과 특화된 것이있습니다. 예를 들어 "학교"라는 검색어는 대단히 광범위한 검색어로 많은 결과가 리턴됩니다. 반면 "정보검색"이라는 질의어는매우 특별한 것으로 결과로 반환되는 것이 훨씬 적습니다. "Hubs and authorites"라는 링크 구조 모델을 다루는 본논문에서 소개하는 알고리듬은 전자와 같은 광범위한 검색 키워드에 대한 검색결과를 어떻게 링크 구조를 이용해서 정제할 수 있을까를모색해 본 것입니다. 범위가 넓은 주제에 대한 검색 결과중 어떤 것이 가장 '권위 있는' 페이지인지를 찾아내는 방법을 생각해보는 것입니다. </p><p>우리가 어떤 검색을 했을 때 결과로 반환되는 페이지가 '좋은 결과다'라고 판단하는 것은 주관적입니다. 검색 결과의 품질에대한 평가는 지극히 주관적이기 때문에 그 결과가 검색어와 관련 있다, 없다를 판단하는 데 있어서 인간의 판단이 배제된 어떤객관적인 기준, 나아가서 알고리듬으로 구현할 수 있을 만큼 공식화된 방법이 없을까를 찾아낼 필요가 있습니다. 이 부분을 무시한대부분의 검색 엔진 기술들은 검색 속도나 저장 효율 등에만 얽매이고 있는데 이것은 중요한 문제를 젖혀둔 채 부수적인 것에 매달린것일 수 있습니다. 무엇이 관련된 페이지이고, 그 관련된 페이지 중에 어떤 것이 '좋은' 페이지인가를 판단하는 객관적인 방법을찾는 것이 훨씬 중요합니다. 이 논문은 그 목적을 달성하기 위한 하나의 방법을 제공하고 있습니다.</p><h4>"authority"란 무엇인가?</h4><p>검색어는 특화된 것이 있고 광범위한 것이 있다고 했습니다. 예를 들어, "펄에서 url을 인코딩하는 데 사용되는 모듈은?"같은 질의어는 대단히 특화된 것입니다. 반면, "자바 프로그래밍 언어에 관한 정보"는 광범위합니다. 전자와 같은 질의어는 희소성문제가 생깁니다. 해당 정보를 담고 있는 페이지 수가 매우 적은 데서 비롯되는 문제입니다. 역으로 후자의 경우는 과다성 문제가생깁니다. 관련되는 페이지가 너무 많아서 문제가 됩니다. 과다성 문제가 생기는 경우 인간이 처리할 수 있는 수준을 넘어선 양의정보가 제공되기 때문에 그 결과들 중 어떤 것이 가장 '권위 있는', '확실한' 페이지들인지 찾아낼 방법이 있어야 합니다. </p><p>그렇다면 '권위 있다'는 것은 어떤 의미일까요? 예를 들어 이런 것입니다. 검색어로 "harvard"를 입력하면 수만,수십만 페이지가 결과로 뜰 것입니다. 그 중 가장 '권위 있는' 페이지는 당연히 www.harvard.edu입니다. 그런데 이런'권위 있는' 페이지를 찾아낼 문서 자체의 내부적 특성이 없습니다.</p><p>예컨데 단어 빈도수를 생각해 봅시다. www.harvard.edu는 "harvard"라는 단어가 가장 많이 등장하는페이지가 아닙니다. 단어 빈도수만을 기준으로 '권위'를 추정하는 경우 전혀 엉뚱한 페이지가 가장 관련성이 높은 페이지가 될 수있습니다. </p><p>그렇다면 url은 어떨까요? 위 경우는 ".edu"가 들어간 것 중 "harvard"가 들어간 페이지를 찾으면 해당은되겠습니다만 모든 검색어에 일반적으로 적용할 수 있는 방법은 아닙니다. url 자체가 '권위'를 판단하는데 어떤 힌트를 주기힘듭니다. 문서의 길이는 어떨까요? 그것도 별로 효과가 없습니다. 검색 결과 중 긴 페이지를 찾는다고 반드시 그 페이지가 권위가있느냐면 그렇지 않을 가능성이 훨씬 높습니다.</p><p>문서 내부적인 정보만으로는 어떤 페이지가 권위있는 곳이다 아니다를 판단하기가 대단히 곤란합니다. </p><p>하나 더 예를 들어 봅시다. "검색 엔진"이라는 질의어에 대한 결과 중 권위 있는 곳은 네이버라든지 구글이라든지, 엠파스,다음 등입니다. 그런데 이들 페이지가 질의어 "검색 엔진"과 어떤 관련성을 갖나요? "검색 엔진"이라는 단어가 가장 많이등장하는 것도 아니고 특별히 문서 자체에서 이들의 권위를 유추해 낼 방법이 없습니다. </p><p>그렇다면 검색창에 "검색 엔진"이라고 입력을 했을 때 어떻게 하면 위와 같은 '권위 있는' 곳을 찾아낼 수 있을까요?오쏘리티를 찾겠다는 것은 바로 이 문제를 해결할 방법을 찾는 것입니다. 검색어에 대한 검색 결과 중 어떤 것이 가장 '좋은'페이지인가를 판단해 보겠다는 것이고 그런 '좋은' 페이지들을 오쏘리티라 하는 것입니다.</p><h4>하이퍼링크가 해결책</h4><p>위 문제를 해결하는 중요한 수단이 하이퍼링크를 활용하는 것입니다.<br />
하이퍼링크는 사람의 판단이 포함되어 있기 때문입니다. 우리가 어떤 페이지를 링크하는 것은 대체로 그 페이지가 '좋은' 페이지이기때문입니다. 어떤 페이지를 링크할 것인가 말 것인가의 결정에는 인간 판단이 함께 인코딩되어 있습니다. 그러므로 링크를사용함으로써 위에서 말한 오쏘리티를 찾아낼 수 있는 것입니다.</p> <p>다른 곳에서 링크가 많이 되어 있는 페이지가 있다면 그 페이지는 살펴볼 가치가 있는 페이지일 가능성이 높습니다. 또 하나,링크를 활용할 때의 장점은 문서 자체 내에 그 문서의 우수성을 판단할 기준이 담겨있지 않다는 부분도 해결된다는 점입니다. 그문서가 길든 짧든, 질의어와 맷취가 많이 되든 적게 되든, 그 문서의 우수성을 판단해 볼 수 있습니다.</p><p>링크도 물론 문제는 있습니다. 예컨데 링크가 다른 목적으로 된 경우가 꽤 있습니다. 광고성 링크도 있을 수 있고, 내부 <a linkindex="12" href="http://www.emh.co.kr/xhtml/useful_navigation.html">네비게이션</a> 목적의 링크도 있습니다. 링크가 반드시 권위있는 곳이기 때문에 이뤄진 것이 아닐 수 있습니다.</p><h3>HITS 알고리듬</h3><p>HITS 알고리듬은 크게 2단계로 나뉩니다. 먼저 질의어와 관계있는 페이지들의 부분집합(서브 그래프(subgraph))을만드는 단계입니다. 그 다음엔, 만들어진 서브 그래프를 이용해서 헙과 오쏘리티(hubs &amp; authorities)를계산해내는 단계입니다.</p><h4>1. 서브그래프(subgraph) 만들기</h4><p>먼저, 하이퍼링크로 연결된 페이지들의 컬렉션 V를 G = (V,E)라는 directed graph로 표현합니다. 이때 각각의 노드는 각 페이지에 해당하고 (p,q) ∈ E는 p에서 q로의 링크가 있다는 것을 뜻합니다. 그리고,</p><ul><li>어떤 노드 p의 out-degree: 밖으로 나가는 링크의 갯수	</li><li>어떤 노드 p의 in-degree : 노드 p를 가리키는 링크의 갯수	</li><li>G[W] : V에 속하는 부분집합 W로부터 만든 그래프	</li><li>질의어 : σ라 합니다.</li></ul><p>이제 광범위 검색 주제어인 질의어 σ에 대한 오쏘리티를 링크 구조만을 이용해서 어떻게 찾을 수 있는지 생각해 봅시다.질의어 σ를 담고 있는 페이지 전체 집합을 Qσ라 합시다. 알고리듬은 이 Qσ를 대상으로 하면 안 됩니다. 그 이유는 첫째,질의어를 담고 있는 페이지는 아마도 수백만 페이지 이상일 것이기 때문에 'computationally expensive'합니다.둘째, 앞에서 살펴본대로 중요한 오쏘리티는 질의어 자체를 담고 있지 않은 경우도 매우 많습니다.</p><p>우리가 원하는 집합을 Sσ라 하면, Sσ는 이런 특성을 가지면 좋을 것입니다. </p><ol><li>상대적으로 작아야 한다.	</li><li>관계되는 페이지가 많아야 한다.	</li><li>대부분의 오쏘리티들을 담고 있으면 좋겠다.</li></ol><p>알고리듬의 첫 단계인 서브 그래프를 만드는 단계는 바로 이런 특징을 갖는 Sσ를 찾아내는 것입니다. 그러면 Sσ를 어떻게 찾아낼까요?</p><p>일반적인 텍스트 기반 검색엔진에 질의어를 넣었을 때의 결과 중 상위 t개의 페이지를 루트셋(root set) Rσ라합시다. 이 Rσ는 아마도 위의 조건 중 1,2번은 만족하지만 3번은 만족하지 않을 수 있습니다. 그러므로 Rσ를 이용해서 강한오쏘리티(strong authorities)를 찾아낼 수 있다면 우리가 원하는 Sσ에 가까운 서브 그래프를 만들어 낼 수 있을것입니다. </p><p>그런데 오쏘리티는 Rσ에 있는 페이지들이 가리키는 페이지들 중에 많이 존재할 가능성이 높습니다. 관계되는 페이지들이가리키고 있는 페이지는 '권위 있는' 페이지일 가능성이 크기 때문입니다. 따라서 Rσ를 링크를 이용해서 확장하면 우리가 원하는강력한 오쏘리티가 들어있으면서, 작고, 관계성 높은 서브 그래프를 만들어 낼 수 있을 것입니다. 이것을 알고리듬으로 표현하면이렇게 됩니다.</p><pre><code>Subgraph(σ, ε, t, d)<br />
 σ : a query string<br />
 ε : a text-based search engin<br />
 t,d : natural numbers<br />
 Let Rσ denote the top t results of ε and σ<br />
<br />
 Set Sσ := Rσ<br />
 For each page p ∈ Rσ<br />
  Let T+(p) denote the set of all pages p points to<br />
  Let T-(p) denote the set of all pages pointing to p<br />
  Add all pages T+(p) to Sσ<br />
  If |T-(p)| ≤ d then<br />
	Add all pages in T-(p) to Sσ<br />
  Else<br />
   Add an arbituray set of d pages from T-(p) to Sσ<br />
  End<br />
 Return Sσ</code></pre><p>다른 부분은 쉽게 이해가 될 것이고, T-(p)가 d보다 작거나 같을 때 이것을 Sσ에 포함시킨다는 부분이 약간 이상하게느껴질 겁니다. T-(p)중 몇 개만을 취한 까닭은 무엇일까요? 만약 Rσ에 야후!가 들어있다고 해 봅시다. 그러면 야후!를가리키는 페이지는 수백, 수천만 개 이상일 것이기 때문에 이들을 다 포함시키는 경우 Sσ가 턱없이 커집니다. 그러므로 일정한개수만 포함시키는 것입니다. </p><p>위와 같은 과정을 통해서 얻어낸 Sσ를 "σ의 base set"이라고 합시다. 이 베이쓰 셋을 구하기 위해 이 논문에서는검색 엔진으로는 알타비스타를 사용했고 t=200, d=50 으로 했다고 합니다. 이렇게 했을 때 대략 1000-5000개 정도의페이지를 담고 있는 Sσ가 만들어졌다고 합니다. </p><div class="imageCenter"><img src="http://www.emh.co.kr/images/expanding_root_set.gif" alt="root set" border="0" height="403" width="541"></div><p>이렇게 얻어진 서브그래프는 몇가지 휴리스틱스를 적용함으로써 조금 더 줄일 수가 있습니다. 예를 들어, 순수하게 네비게이션의용도로만 쓰이는 링크는 '권위'를 부여하는 기능이 없으므로 배제할 수 있습니다. 도메인 네임을 살펴 봐서 동일한 곳에서 동일한곳으로 연결되고 있는 링크는 네비게이션 목적일 가능성이 높으므로 제외합니다. 또는, 어떤 한 도메인 내의 많은 페이지가 외부의어떤 한 페이지로만 링크가 되고 있는 경우도 광고성 링크거나 특별히 트래픽을 몰아줄 계약을 체결했을 가능성이 높습니다. 이런것들을 제외하기 위해 단일 도메인에서 특정 페이지 p로의 링크가 있는 페이지의 갯수는 4개-8개로 제한합니다.</p><h4>2. 헙과 오쏘리티 계산</h4><p>앞 단계에서 만든 서브그래프를 이용, 이제 우리가 최종적으로 구하고자 하는 헙(hubs)과오쏘리티(authorities)를 찾아냅니다. 일단 Sσ를 그래프화 한것을 Gσ라 합시다. 이제 링크 구조를 이용해서 이Gσ속에 존재하는 헙과 오쏘리티를 찾아내는데, 제일 쉽게 생각해 볼 수 있는 것이 Gσ내의 페이지들을 in-degree 순으로순위를 매기는 것입니다. 이것은 직관적으로 좋은 방법일 것 같은 느낌이 듭니다. 일단 Gσ라는 특정 검색어와 관계성이 높은페이지들 집합 속에서 다른 페이지로부터의 링크가 많다는 것은 그 만큼 '좋은' 페이지일 가능성이 높아지기 때문입니다. 하지만실제로 그렇게 해보면 강력한 오쏘리티와 보편적으로 인기가 높은 페이지(universally popular pages) 사이의긴장이라는 문제가 생깁니다. 예를 들어 "java"라는 질의어의 경우 www.gamelan.com과 java.sun.com이라는결과와 함께 카리비안 휴양 관련 싸이트와 아마존 홈페이지가 함께 순위권에 듭니다. 이것은 특정 주제에 관한 오쏘리티와 함께'주제에 관계없이 링크가 많이 된'(universally popular) 것이 존재하기 때문입니다. 이 문제의 해결책은 페이지의텍스트 내용도 같이 감안해서 검색어와 매칭되는 단어가 등장하는 것을 골라낸다 정도가 될 것인데 이것도 실제로 해보면 별로 효과가없다고 합니다. </p><p>오히려 논문의 저자는 순수하게 링크 구조만을 활용해서 이 문제를 해결할 수가 있다고 하는데요. 그 출발점은 이렇습니다.</p><blockquote>"모든 오쏘리티들은 큰 in-degree를 갖는다는 점과 함께 그 오쏘리티들을 가르키고 있는 페이지들 역시 중복된다는 공통점을 갖는다"</blockquote><p>어떤 주제에 관한 오쏘리티들을 많이 링크하고 있는 페이지를 중심축 역할을 한다는 의미에서 헙이라고 명명합시다. 그러면 앞의기술은, "좋은 오쏘리티들은 in-degree가 높다는 점과 함께 많은 헙들로 부터 링크되어 있다는 공통점이 있다."는 얘기가됩니다. 여러 헙들로부터 링크되어 있을수록 좋은 오쏘리티가 되며, 여러 오쏘리티를 링크하고 있을수록 좋은 헙이 되는 것입니다.즉, 헙과 오쏘리티는 상호강화적인 관계(mutually reinforcing relationship)입니다.</p><p>그러므로 좋은 오쏘리티는 좋은 헙을 찾는 것을 통해서 찾아낼 수 있고, 좋은 헙은 좋은 오쏘리티를 통해서 찾아낼 수있습니다. 그리고 이들 헙과 오쏘리티는 광범위적 질의어의 검색 결과 중에서도 특별히 '좋은' 페이지로 생각해 볼 수 있는것입니다.</p><p></p><div class="imageCenter"><img src="http://www.emh.co.kr/images/hubs_authorities.gif" alt="hubs and authorities" border="0" height="277" width="597"><br />
반복 알고리듬(An Iteration Algorithm)</div><p>위에서 살펴본 내용을 이제 수학적으로 기술해 봅시다.<br />
"authority weight", 즉 오쏘리티 가중치를(높을수록 좋은 오쏘리티)  x(p)라 하고,"hub weight", 헙 가중치를(높을수록 좋은 헙) y(p)라 하면 다음과 같은 두 가지의 연산을 생각해 볼 수 있습니다.</p><div class="imageCenter"><table><tbody><tr><td>I Operation : </td><td><img src="http://www.emh.co.kr/images/i_operation.gif" alt="i operation" border="0" height="41" width="127"></td></tr><tr><td>O Operation : </td><td><img src="http://www.emh.co.kr/images/o_operation.gif" alt="o operation" border="0" height="45" width="127"></td></tr></tbody></table></div><p>q--&gt;p로의 링크가 있을 때 p 페이지의 오쏘리티 가중치는 q 페이지들의 헙 가중치 y(p)를 모두 합한 것입니다.<br />
p--&gt;q로의 링크가 있을 때 p 페이지의 헙 가중치는 q 페이지의 오쏘리티 가중치 x(q)를 모두 합한 것입니다.</p><p>그런데 이것은 반복적 알고리듬(iterative algorithm)이기 때문에 이터레이션을 시켜서 계산해야 합니다. 그렇게반복 연산을 했을 때 어떤 일정한 값으로 수렴하면서 평형을 이루는지 알아보는 것입니다. 그리고 수렴해서 일정한 값들을 갖는다면,우리는 각 페이지들의 최종 헙 가중치와 오쏘리티 가중치를 알게 될 것입니다. 어떤 페이지가 얼마나 좋은 헙인지, 얼마나 좋은오쏘리티인지를 알 수 있게 되는 것입니다.<br />
이것을 알고리듬 형태로 표시해 볼까요?<br />
</p><p>x(p)의 집합 {x(p)}를 벡터 x라 하고, y(p)의 집합 {y(p)}를 벡터 y라 하면, </p><pre><code>Iterate(G,k)<br />
 G : a collection of n linked pages<br />
 k : a natural number<br />
 Let z denote the vector (1,1,1,...,1) ∈ R<sup>n</sup>.<br />
 Set x0 := z.<br />
 Set y0 := z.<br />
 For i = 1,2,...,k<br />
  Apply I operation to (x<sub>i-1</sub>, y<sub>i-1</sub>), obtaining new x-weights x'<sub>i</sub>.<br />
  Apply O operation to (x'<sub>i</sub>, y<sub>i-1</sub>), obtaining new y-weights y'<sub>i</sub>.<br />
  Normalize x'<sub>i</sub>, obtaining x<sub>i</sub>.<br />
  Normalize y'<sub>i</sub>, obtaining y<sub>i</sub>.<br />
 End<br />
 Return (x<sub>k</sub>, y<sub>k</sub>).</code></pre><p>처음에는 모든 페이지에 대해서 헙 가중치, 오쏘리티 가중치를 1로 해서 I operation을 시행한 다음 얻은 새로운 x'를 이용, 이번에는 O operation (x만 x'<sub>i</sub> 이고 y 는 i-1 이라는 점에 주목하세요)을 시행해서 새로운 y'을 얻고, 이를 노멀라이징한 다음 다시 반복합니다. 언제까지? 우리가 정한 k번까지로 되어 있습니다. 알고리듬 자체는 아주 단순한 것입니다. </p><p>이때 노멀라이징하는 방법으로는 이 논문에서는, </p><pre><code>∑ x(p)<sup>2</sup> = 1<br />
∑y(p)<sup>2</sup> = 1</code></pre><p>을 사용했습니다. </p><p>위에서 최종적으로 얻은 벡터 x의 각 원소는 각 페이지의 오쏘리티 가중치입니다. 벡터 y의 각 원소는 각 페이지의 헙가중치를 가리킨다는 점을 다시 상기하세요. 그리고, k값을 '상당히' 크게 해서 이터레이션을 계속 시키면 x, y 모두 일정한값으로 수렴합니다. 일정한 값으로 안정이 되고 나서 얻은 x<sub>k</sub>, y<sub>k</sub> 중에서 각각 상위 c개씩을 뽑아 내면 이들이 바로 우리가 찾는 좋은 헙과 좋은 오쏘리티가 되는 것입니다. </p><p>이 알고리듬을 실제 구현해서 그 결과를 싣고 있는데 상당히 인상적입니다. 예를 들어, "Gates"라는 검색어에 대해서 상위 3개의 오쏘리티는,<br />
 http://www.roadahead.com/ , http://www.microsoft.com/, http://www.microsoft.com/corpinfo/bill-g.html<br />
로 나타났습니다. 순수하게 알타비스타에서 검색한 결과는 http://www.roadahead.com 페이지가 123번째 결과로 나왔다 합니다.</p> <p>"search engines"라는 검색어에 대해서도 상위 5위까지를 살펴보면, <br />
http://www.yahoo.com/, http://www.excite.com/ , http://www.mckinley.com/ (Magellan 검색엔진),http://www.lycos.com/, http://www.altavista.digital.com/ <br />
입니다. 우리가 찾는 오쏘리티를 잘 찾아낸다는 것을 알 수 있습니다.</p><p>정리해 봅시다. 이 논문을 통해 텍스트적인 정보를 전혀 감안하지 않은, 순수하게 링크 구조만을 사용해도 상당한 수준으로'좋은' 페이지를 판단해낼 수 있다는 사실을 알 수 있니다. 특히 페이지 내부적인 정보만으로는 그 페이지가 검색 결과 내에서얼마나 '좋은' 페이지인지를 판단하기가 힘든 데, 이 때 하이퍼링크를 이용함으로써 이 문제를 보다 객관적으로 해결할 수 있다는것을 알 수 있습니다.</p></div><br />
<br />
<br />
<br />
문서출처: <a set="yes" linkindex="9" href="http://www.emh.co.kr/">이명헌 경영스쿨</a> <a set="yes" linkindex="10" href="http://www.emh.co.kr/xhtml/hubs_and_authorities.html">http://www.emh.co.kr/xhtml/hubs_and_authorities.html</a> <br />
 이 문서를 게시하거나 프린트하려면 위 문서출처를 반드시 포함해야 합니다.(참고: <a set="yes" linkindex="11" rel="license" href="http://creativecommons.org/licenses/by-nc-nd/2.0/kr/deed.kr">저작권정책</a>)<br />
<br/><br/>tag : <a href="/tag/네비게이션" rel="tag">네비게이션</a>,&nbsp;<a href="/tag/검색엔진" rel="tag">검색엔진</a>,&nbsp;<a href="/tag/노드" rel="tag">노드</a>,&nbsp;<a href="/tag/하이퍼링크" rel="tag">하이퍼링크</a>,&nbsp;<a href="/tag/검색" rel="tag">검색</a>,&nbsp;<a href="/tag/엔진" rel="tag">엔진</a>,&nbsp;<a href="/tag/페이지" rel="tag">페이지</a>			 ]]> 
		</description>
		<category>Interest</category>
		<category>네비게이션</category>
		<category>검색엔진</category>
		<category>노드</category>
		<category>하이퍼링크</category>
		<category>검색</category>
		<category>엔진</category>
		<category>페이지</category>

		<comments>http://topic.egloos.com/537684#comments</comments>
		<pubDate>Mon, 13 Aug 2007 11:39:36 GMT</pubDate>
		<dc:creator>Hans</dc:creator>
	</item>
	<item>
		<title><![CDATA[ Google Search Engine 해부 - 구글 페이지랭크(PageRank) 알고리즘. ]]> </title>
		<link>http://topic.egloos.com/537660</link>
		<guid>http://topic.egloos.com/537660</guid>
		<description>
			<![CDATA[ 
  <div class="contentProper"><h3>Abstract</h3><p>웹 페이지의 '중요성'은 본질적으로 주관적인 문제여서 읽는 사람의 관심사나 지식 그리고 태도 등에 의존한다. 하지만 웹페이지의 상대적 중요성에 관해서는 객관적으로 얘기할 수 있는 부분이 많다. 이 논문은 객관적이고 기계적으로 웹 페이지를 랭킹해서읽는 사람의 관심이나 기울이는 주의를 효과적으로 측정할 수 있는 수단인 "PageRank"를 소개한다. 우리는페이지랭크(PageRank)를 이상적인 랜덤 웹 써퍼(random web surfer)에 비교해 볼 것이며, 어떻게 많은 웹페이지를 대상으로 PageRank를 능률적으로 계산할 수 있는지를 설명할 것이다. 그리고 어떤 방식으로 PageRank를검색이나 사용자 네비게이션에 응용할 수 있는지도 보여 주고자 한다.</p>        <h3>1. 도입과 동기(Introduction and Motivation)</h3><p>월드와이드웹(World Wide Web)은 정보검색(Information Retrieval)에 새로운 과제를 안겨 주었다.웹은 매우 거대하며 이질적(heterogenous)이다. 현재 추산으로도 약 1억5천만 페이지 이상이 웹에 존재하며, 이 숫자는매년 적어도 두 배씩 커지고 있다. 더욱 중요한 점은, 웹 페이지들이 극단적으로 다양하다는 것이다. 예를 들면 "Joe가 오늘점심 때 뭘 먹었지?"와 같은 질문이 있는가하면 정보검색에 관한 전문적 논문집이 있기도 하다. 이런 주된 도전 과제들 외에도웹에는 익숙하지 못한 초보 사용자들과 검색 엔진의 랭킹 기능(ranking function)을 교묘히 이용하려는 많은 웹페이지들로부터 비롯되는 문제점이 있다.</p>        <p>그러나 웹은 다른 "평면적"인 문서 컬렉션(flat document collections)과 달리 하이퍼텍스트가 있다.하이퍼텍스트(hypertext)는 웹 페이지 자체의 텍스트 외에 링크 구조(link structure)나 링크 텍스트(linktext)같은 상당한 수준의 부가적인 정보를 제공한다. </p>             <p>이 논문에서 우리는, 모든웹 페이지를 보편적 "중요도" 순으로 순위를 매기기 위해 웹의 링크 구조를 사용하였다. 이 랭킹은 페이지랭크(PageRank)라하며, 검색엔진 사용자나 웹 사용자가 거대한 이질적 세계인 월드와이드웹을 빠르게 이해할 수 있게 도와준다. </p>               <h4>1.1 웹 페이지의 다양성(Diversity of Web Pages)</h4>     <p>학술적 인용(academic citation)을 분석한 문헌은 이미 많이 존재하지만 웹 페이지와 학술 출판물 사이에는 많은 중요한차이가 있다. 학술 논문은 철두철미하게 리뷰되지만 웹 페이지는 '품질 관리'나 '출판 비용' 없이 늘어난다. 단순한 프로그램하나만으로도 아주 많은 페이지를 손쉽게 만들어 낼 수 있으며 인위적으로 인용 횟수를 쉽게 부풀릴 수 있다. 웹 환경 속에는 그안에서 이익을 찾는 많은 벤쳐들이 있기 때문에 이들이 사용자의 주의를 끌어오는 전략 역시 검색엔진 알고리듬의 발달에 맞춰서 함께진화되어 왔다. 이러한 이유로 복제가능한 특징을 세는 방식으로 웹 페이지를 평가하려는 전략은 손쉽게 악용될 수 있다. 게다가,학술 논문의 경우는 그 갯수를 정확히 셀 수 있을 뿐만 아니라 사실상 질적인 면 및 인용 횟수 등에서 유사하고 그 목적 역시비슷하다.(대개 '지식의 몸체'를 키우기 위한 목적으로 만들어진다.) 하지만 웹 페이지는 질적인 면에서나 사용적인 측면, 인용,길이 등에 있어서 학술 논문보다 훨씬 더 다양하다. IBM 컴퓨터에 관한 애매한 질문들을 모아놓은 것은 IBM 홈페이지와 매우다르다. 운전자에게 휴대폰이 미치는 영향에 관해서 연구한 논문은 특정 휴대폰 회사의 광고와 매우 다르다. 사용자가 읽은 웹페이지의 평균적인 질은 평균적인 웹 페이지의 질보다 높다. 그것은 웹 페이지를 만들고 퍼블리슁하는 것이 매우 쉽기 때문에 웹에는사용자들이 읽지 않으려 하는 많은 저품질의 웹 페이지가 있기 때문이다. </p>             <p>웹 페이지에는 여러 가지 분화될 수 있는 요소가 많이 있다. 이 논문에서 우리는 그 중의 하나 - 웹 페이지의 상대적 중요성을 어떻게 추산할 것인가 - 라는 문제를 주로 다룬다.</p>                <h4>1.2 페이지랭크(PageRank)</h4>     <p>웹페이지의 상대적 중요성을 측정하기 위해 우리는 웹 그래프를 기반으로 웹 페이지를 랭킹(ranking)하는 방식인 페이지랭크를제안한다. 페이지랭크는 검색이나 브라우징, 트래픽 추산에 적용될 수 있다. 섹션 2에서는 페이지랭크의 수학적 기술을 다룰 것이며직관적인 정당화(intuitive justification)를 얘기할 것이다. 섹션 3에서는 5억1800만 개에 이르는하이퍼링크에 대해 어떻게 효율적으로 페이지랭크를 계산할 수 있는지 보여주고자 한다. 페이지랭크의 유용성을 테스트하기 위해 우리는<a linkindex="12" href="http://www.emh.co.kr/xhtml/google_search_engine.html">구글(Google)</a>이라는 웹 검색 엔진을 구축했다. 이것은 섹션 5에서 다룬다. 섹션 7.3에서는 페이지랭크가 어떻게 브라우징을 도울 수 있는지 보여주고자 한다.</p>               <h3>2. 웹 상의 모든 페이지의 순위 매기기(A ranking for every page on the Web)</h3>                <h4>2.1 관련 자료</h4>     <p>학술 인용 분석에 관해서는 매우 많은 연구가 이미 존재한다. Goofman은 과학 커뮤니티에서 일종의 유행병처럼 정보 흐름이 퍼져 나간다는 것을 주장한 흥미로운 이론을 발표하기도 했다.</p>              <p>웹같은 대형 하이퍼텍스트 시스템에서 어떤 방식으로 링크 구조(link structure)를 이용할 수 있는지에 관해서도 최근들어상당한 연구가 이뤄지고 있다. Pitkow는 얼마 전에 다양한 방식의 링크 기반 분석을 설명한 "월드와이드웹 생태계의특징"이라는 제목의 박사 학위 논문을 완성했다. Weiss는 링크 구조를 감안한 클러스터링 방식에 대해서 논했다.Spertus는 여러 가지 적용사례에 있어서 링크 구조로 부터 얻어낼 수 있는 정보에 관해 발표했다. 좋은 시각화를 위해서는하이퍼텍스트에 부가적인 구조가 필요하다는 연구도 있었다. Kleinberg는 웹을 서로 인용하는 행렬로 보고 그고유벡터(eigenvector)를 계산하는 방식을 기반으로 "<a linkindex="13" href="http://www.emh.co.kr/xhtml/hubs_and_authorities.html">헙 &amp; 오쏘리티(Hubs and Authorities) 모델</a>"이라는 흥미로운 모델을 개발했다. 마지막으로, 도서관 커뮤니티 쪽에서는 웹의 "질"이라는 것에 대해 관심을 갖고 있기도 하다.</p>             <p>일반적인 인용 분석 테크닉을 웹의 하이퍼텍스트적 인용 구조에 적용하고자 시도하는 것은 너무도 자연스러운 것이다. 단순하게 웹페이지에 있는 각각의 링크를 학술적 인용처럼 생각해 볼 수 있는 것이다. 야후! 같은 메이져 페이지는 야후!를 가리키는 수 만,수십 만 개의 백 링크(backlinks) 또는 인용을 갖고 있는 것이다.</p>             <p>야후!홈페이지가 아주 많은 백 링크를 갖고 있다는 사실은 야후! 홈페이지가 매우 중요하다는 사실을 함축한다. 사실 많은 웹검색엔진들은 어떤 페이지가 얼마나 중요한가 내지는 높은 질을 갖고 있는가를 판단할 때 백 링크 숫자를 바탕으로 가중치를 주고있다. 하지만 단순히 백 링크의 갯수를 세는 것은 많은 문제점을 갖는다. 이 문제점들은 학술 인용 데이타베이스에는 존재하지 않는웹만의 특징과 관련이 있는 것들이다.</p>        <a name="back_link"></a>        <h4>2.2 웹의 링크 구조(Link Structure of the Web)</h4>     <p>약간의 편차는 있지만 현재 크롤링 가능한 웹 그래프는 약 1억5천만개의 노드(node;페이지)와 17억 개의엣지(edge;링크)가 있다고 알려져 있다. 각각의 웹 페이지는 그 페이지로부터 밖으로 나가는 포워드 링크(forwardlink; outedges)와 그 페이지를 가리키는 백 링크(backlink; inedges)를 갖는다. 어떤 페이지의 모든 백링크를 다 찾아낸다는 것은 불가능하지만 페이지를 다운로드하고 나면, 포워드 링크가 무엇인지는 알 수 있다.</p>        <div class="imageCenter"><img src="http://www.emh.co.kr/images/backlink.gif" alt="backlink 백 링크" border="0" height="265" width="262"></div>            <p>웹페이지가 백 링크를 몇 개나 갖느냐는 매우 다양하다. 우리가 갖고 있는 데이타베이스에 따르면 넷스케잎 홈페이지는 62804개의백 링크를 갖는데 반해 대개의 페이지들은 단지 몇 개의 백 링크만을 갖는다. 일반적으로 링크가 많이 된 페이지일수록 그렇지 못한페이지보다 더 "중요하다". 학술 인용에서도 인용의 횟수를 세는 단순한 방법이 미래의 노벨상 수상자를 예측하는 데 사용될 수있다. 페이지랭크는 인용 횟수를 세는 방식 이상의 훨씬 더 정교화된 방법을 제시한다.</p>             <p>페이지랭크가 흥미로운 이유는 인용 횟수가 일반적인 의미의 중요성과 일치하지 않는 경우가 매우 많기 때문이다. 어떤 웹 페이지가야후!에 링크가 되어 있다면 그 페이지는 오직 하나의 백 링크밖에 없지만 그 링크는 매우 중요한 링크다. 야후!에 링크된 그페이지는 다른 별 볼 일 없는 여러 곳에서 링크된 페이지보다 더 높은 순위를 가져야 한다. 페이지랭크는 링크 구조만을 사용해서어떻게 "중요성"을 정확히 추정해낼 수 있을까를 시도한 것이다.</p>                <h4>2.3 링크를 통한 랭킹의 전파(Propagation of Ranking through Links)</h4>     <p>위의 논의를 기초로, 우리는 페이지랭크에 대한 직관적 기술을 다음과 같이 할 수 있다: 어떤 페이지가 높은 랭크의 백 링크를 많이가질수록 그 페이지의 랭크도 올라간다. 이것은 어떤 페이지가 많은 백 링크를 갖는 경우와 몇 개의 높은 랭크값 백 링크를 갖는경우 모두를 포괄하는 것이다.</p><h4>2.4 페이지랭크(PageRank)의 정의</h4><p>어떤 웹 페이지를 u라고 하고 u 페이지가 가리키는 페이지들의 집합을 Fu, u 페이지를 가리키는 페이지의 집합을 Bu라하자. Nu = |Fu|라 하고, 이것은 u 페이지로부터 나가는 링크의 갯수, 즉 Fu의 갯수다. 그리고 노멀라이제이션에사용되는 팩터를 c라고 하자.(노멀라이제이션은 전체 웹 페이지의 랭크 총합을 일정하게 하기 위해서다.)</p><p>일단, 단순 랭킹 R을 정의하는 것에서 출발해 보자. 단순 랭킹 R은 페이지랭크(PageRank)를 약간 단순화시킨 버전이다.</p><div class="imageCenter"><img src="http://www.emh.co.kr/images/simple_pagerank_formula.gif" alt="Simple PageRank" height="90" width="237"></div><p>위 식은 전 섹션에서 얘기한 직관을 공식화한 것이다. 어떤 페이지가 가리키는 페이지들의 랭크에 균일하게 기여하기 위해,링크가 나가는 페이지의 랭크를 그 페이지의 포워드 링크 갯수로 나누고 있다는 점에 주의하자. 그리고 c는 1보다 작아야 하는데,c &lt; 1인 이유는 포워드 링크가 없는 페이지도 많이 있기 때문에 그런 페이지들의 가중치는 시스템 속에서 사라질 수 있기때문이다.(섹션 2.7을 참조하라.) 위 등식은 재귀적(recursive)인 식이지만 초기 랭크 집합을 주고 수렴할 때까지연산을 함으로써 계산할 수 있다. </p><div class="imageCenter"><img src="http://www.emh.co.kr/images/simple_pagerank.gif" alt="단순 버전 페이지랭크"><br />
<br />
그림 2 단순화된 페이지랭크의 계산<br />
<br />
<img src="http://www.emh.co.kr/images/simple_pagerank_calculation.gif" alt="단순 버전 페이지랭크의 계산" height="214" width="353"><br />
그림 3 정상상태를 이루고 있는 페이지들</div><p>그림 2는 한 쌍의 페이지로부터 다른 한 쌍의 페이지로 랭크가 전파되어 나가는 것을 보여주고 있다. 그림 3에서는 일군의 페이지들 사이에서 일정한 정상상태(steady state)의 솔루션을 이루고 있는 것을 볼 수 있다.</p><p>이것을 다른 방식으로 표현해 보자. 각 행과 열이 웹 페이지에 대응하는 정방행렬을 A라 하자. 그리고, 페이지 u에서 v로 가는 연결(edge)이 있다면 <code>A<sub>u,v</sub> = 1/N<sub>u</sub></code>이라 하고, 엣지가 없다면 <code>A<sub>u,v</sub></code>는 0이라 하자. R을 웹 페이지들의 벡터로 생각해 보면, <code>R = cAR이</code>된다. 그러므로 R은 A의 아이겐벡터(eigenvector; 고유벡터)가 되고 아이겐밸류는 c이다. 사실, 우리가 원하는 것은A의 지배적 고유벡터(dominant eigenvector)다. 이것은 A를 여러 비퇴화적 시작 벡터(nondegeneratestart vector)에 반복적으로 적용함으로써 계산될 수 있을 것이다.</p><div class="imageCenter"><img src="http://www.emh.co.kr/images/rank_sink.gif" alt="랭크 싱크" height="156" width="374"><br />
그림 4 랭크 싱크</div><p>위에서 살펴 본 단순화된 랭킹 함수는 약간의 문제가 있다. 두 페이지가 서로서로 가리키고 있으며 다른 페이지로는 연결되어있지 않은 경우를 생각해 보자. 다른 웹 페이지가 그 두 페이지 중 하나를 가리키고 있는 경우, 반복연산(iteration)이진행되면서 그 루프에서는 랭크가 계속 축적될 뿐 외부로 전혀 분산하지 못 한다.(왜냐하면 외부로 나가는 엣지가 전혀 없으므로.)루프는 일종의 함정을 형성하게 된다. 우린 이것을 랭크 싱크(rank sink)라 부른다. 랭크 싱크로부터 초래되는 문제를해결하기 위해, 우리는 랭크 소스를 도입한다.</p><p>정의 1:<br />
랭크의 소스에 해당하는 웹 페이지의 벡터 중 하나를 E(u)라 하자. 그러면 일군의 웹 페이지들의 페이지랭크는 다음 식을 만족하며 <code>||R||<sub>1</sub> = 1</code>(<code>||R||<sub>1</sub></code>은 R'의 L1 norm)이고 c가 최대값을 가질 때의 R'이다.<span class="fnum">역자주</span></p><div class="imageCenter"><img src="http://www.emh.co.kr/images/pagerank_math_notation.gif" alt="PageRank 페이지랭크"></div><p>E가 모두 다 양수이면 등식의 균형을 위해서 c 값이 줄어들어야만 한다는 것에 주의하자. 그러므로 이 테크닉은 소멸계수(decay factor)에 해당한다. 위 식을 행렬 용어로 표현하면 <code>R' = c(AR' + E)</code>이고, <code>||R||<sub>1</sub> = 1</code>이므로 이 식은 <code>R' = c(A + E x 1)R'</code>로 다시 쓸 수 있다. 여기서 <code>1</code>은 1로만 구성된 벡터다. 그러므로, R'은 <code>(A + Ex1)</code>의 아이겐벡터라고 할 수 있다.</p> <div class="footnote"><span class="fnum">역자주</span> L1 norm은(a,b,c,d,e,..)라는 벡터가 있을 때 (a+b+c+d+e+..)의 값을 의미합니다. '소스'(source)와'싱크'(sink)는 그래프 이론에서 나온 용어로, 아웃엣지가 없는, 즉 밖으로 나가는 링크가 없는 것을 싱크라 하고 반대로인엣지가 없는, 즉 안으로 들어 오는 링크는 없고 밖으로 나가는 것만 있는 것을 소스라 합니다.</div><h4>2.5 랜덤 써퍼 모델(Random Surfer Model)</h4><p>위와 같은 페이지랭크의 정의는 그래프 상의 랜덤 워크(random walks)라는 또 하나의 직관적 기반을 갖고 있는것으로 볼 수 있다. 단순화된 버전의 페이지랭크는 웹 그래프 상에서 랜덤 워크의 확률분포에 해당한다. 직관적으로 생각해 보면이것은 "랜덤 써퍼"의 행동을 모델링한 것으로 볼 수 있다. "랜덤 써퍼"는 무작위로 일련의 링크들을 클릭해 나간다. 하지만실제 웹 써퍼가 작은 루프에 빠져 들었을 때도 계속해서 그 루프 내를 맴돌 가능성은 거의 없다. 대신, 그 써퍼는 다른 페이지로점프하려 할 것이다. 부가적 팩터인 E는 바로 그 행동을 모델링한 것으로 볼 수 있다. 즉, 써퍼는 주기적으로 "지루해지고"E의 분포에 기반해서 선택된 무작위 페이지로 점프하는 것이다.</p><p>지금까지 우리는 E를 사용자 정의 퍼래미터로 생각했다. 대부분의 테스트에서 우리는 E를 모든 웹 페이지에 걸쳐 동일하게α값을 갖는 것으로 했다. 하지만, 섹션 6에서는, E 값이 달라짐에 따라 페이지의 랭크가 어떻게 "사용자화"될 수 있는지를보여줄 것이다.</p><h4>2.6 페이지랭크 계산(Computing PageRank)</h4><p>페이지랭크를 계산하는 것은 규모의 문제를 무시한다면 아주 간단명료하다. S를 웹 페이지의 벡터(E 같은)라 하자. 그러면 페이지랭크는 다음과 같이 계산될 수 있을 것이다.</p><pre><code><br />
R<sub>0</sub> &lt;--- S<br />
loop:<br />
	R<sub>i+1</sub> &lt;--- ARi<br />
		d &lt;--- ||R<sub>i</sub>||<sub>1</sub> - ||R<sub>i+1</sub>||<sub>1</sub><br />
	R<sub>i+1</sub> &lt;--- R<sub>i+1</sub> +dE<br />
		δ&lt;--- ||R<sub>i+1</sub> - R<sub>i</sub>||<sub>1</sub><br />
while δ&gt; ε<br />
</code></pre><p>d 팩터가 수렴속도를 빠르게 하고 ||R||<sub>1</sub>을 유지하는 것에 주목하자. 또 다른 노멀라이제이션 방법은 적절한 팩터를 R에 곱하는 것이다. d의 사용은 E의 영향에 작은 효과만 미칠 것이다.</p><h4>2.7 댕글링 링크(Dangling Links)</h4><p>이 모델과 관계되는 이슈 중 하나는 댕글링 링크 문제다. 댕글링 링크란 외부로 나가는 링크가 없는 페이지를 가리키는 링크를뜻한다. 댕글링 링크가 모델에 영향을 주는 이유는, 이것의 가중치가 어디로 분산되고 있는지가 불분명하고 또 아주 많은 댕글링링크가 존재하기 때문이다. 종종 댕글링 링크가 가리키고 있는 페이지는 다운로드되지 않은 페이지일 수도 있다. 웹을 통째로샘플링하는 것은 어렵기 때문이다.(현재 우리가 다운로드한 2400만 페이지에는 아직 URL이 가리키는 문서가 다운로드되지 않은5100만 개의 URL이 있는 상태다. 즉, 5100만 개의 댕글링 링크가 있는 것이다.) 댕글링 링크는 다른 페이지의 순위에직접적으로 영향을 주지는 않기 때문에, 우리는 모든 페이지랭크가 계산될 때까지 댕글링 링크를 그냥 제거했다. 페이지랭크 계산이다 끝난 뒤에, 즉 큰 문제를 일으키지 않게 되었을 때, 댕글링 링크를 다시 첨가할 수 있다. 링크가 제거됨으로써 그 페이지에있는 다른 링크의 노멀라이제이션이 영향받을 수는 있지만 크게 변화되는 건 아니다.</p><h3>3 임플리멘테이션(Implementation)</h3><p>스탠포드 웹 베이스 프로젝트(Stanford WebBase project)의 일환으로, 우리는 현재 총 2400만 페이지의리파지터리(repository)를 갖고 있는 완전한 크롤링 &amp; 인덱싱 시스템을 구축했다. 웹에 있는 모든 URL을 찾을수 있게 하기 위해서는 모든 웹 크롤러가 URL 데이타베이스를 유지하고 있어야 한다. 웹 크롤러는 페이지랭크의 임플리멘테이션을위해, 크롤링하면서 만나는 링크의 인덱스만 구축하면 된다. 작업 자체는 단순한 것이지만 볼륨이 거대하기 때문에 쉽지 않다. 예를들어, 현재 우리가 구축한 2400만 페이지의 데이타베이스를 5일 안에 인덱싱하기 위해서는, 초당 50 페이지를 프로세싱해야한다. 보통의 페이지 하나에 통상 11개의 링크가 있으므로(무엇을 링크로 셀 것인가에 따라 달라질 수는 있다.) 초당 550개의링크를 프로세싱해야 하는 것이다. 또한, 우리가 구축한 2400만 페이지의 데이타베이스는 7500만 개의 각기 다른 URL을참조하고 있으며, 각각의 링크는 반드시 서로 비교되어야만 하는 것이다. </p><p>웹에 깊숙히 그리고 미묘하게 존재하는 결함들에 유연하게 대응할 수 있는 시스템을 구축하기 위해서 많은 시간이 걸렸다.웹에는 한없이 커다란 싸이트, 페이지, 심지어 끝없이 계속되는 긴 URL들이 있다. 상당수의 웹 페이지가 잘못된 HTML을 담고있기 때문에 파서(parser)를 디자인하는 것이 까다로왔다. 예를 들어, 우리는 URL에 <code>/cgi-bin/</code>이들어 있는 경우 크롤링하지 않았다. 물론, 웹은 계속해서 변하고 있기 때문에 "전체 웹"을 정확하게 샘플링한다는 것은불가능하다. 싸이트가 다운되는 경우도 있고, 어떤 경우는 자신의 싸이트를 인덱싱되지 않도록 해 놓기도 한다. 이런 모든 점에도불구하고, 우리는 공개적으로 접근가능한 웹의 실제 링크 구조를 상당한 수준으로 표현했다고 생각하고 있다.</p><h4>3.1 페이지랭크 임플리멘테이션</h4><p>우리는 각각의 URL을 각기 유니크한 정수로 변환하고, 하이퍼링크의 페이지를 구분할 수 있도록 모든 하이퍼링크를 페이지의 정수 ID를 이용해서 데이타베이스에 저장했다. 임플리멘테이션에 관한 자세한 사항은 <a linkindex="14" href="http://www.emh.co.kr/xhtml/google_search_engine.html">구글 검색엔진의 해부학</a> 논문에서 밝혔다. 보통, 페이지랭크는 다음과 같은 식으로 임플리멘테이션했다.</p><p>먼저, 부모 ID(Parent ID)를 이용해서 링크 구조를 정렬한다. 그 다음, 앞에서 말한 것과 같은 이유로 링크데이타베이스에서 댕글링 링크를 제거한다. (몇 번의 반복 작업만으로도 대부분의 댕글링 링크를 제거할 수 있다.) 그 다음, 랭크값을 초기화한다. 초기화 값을 어떻게 할 것인가는 어떤 전략을 갖고 있느냐에 따라 달라진다. 수렴할 때까지 반복작업을 계속할생각이라면, 일반적으로 초기값은 최종값에 영향을 미치지 않는다. 단지 수렴 속도만 빠르게 할 뿐이다. 하지만 초기값을 잘선택하면 수렴과정의 속도를 높일 수 있다. 우리는 초기 할당값을 신중하게 선택하면 제한적 횟수의 많지 않은 반복 작업만으로도아주 좋은 결과를 얻거나 더 나은 퍼포먼스를 만들어 낼 수 있다고 믿고 있다.</p><p>각 페이지의 가중치에 메모리를 할당한다. 우리는 단정도 부동소수점(single precision floatingpoint) 값을 사용했고, 각각은 4바이트씩 할당했으므로 7500만 개의 URL은 곧 300메가바이트의 크기가 된다. 만약모든 가중치를 담고 있을 만큼 램이 충분치 않으면 여러 번의 패쓰(pass)를 사용해도 된다.(우리가 임플리멘테이션한 것은메모리의 절반과 2개의 패쓰를 사용했다.) 현재 진행 중인 단계의 가중치는 메모리에 저장되고, 전단계의 가중치는 디스크를 통해리니어(linear)하게 억세스한다. 또한, 링크 데이타베이스 - 즉 알고리듬 정의에서의 A - 로의 모든 억세스도 정렬되어있기 때문에 리니어하다. 그러므로 A 역시 디스크에 저장될 수 있다. 이러한 데이타 구조들이 매우 큰 크기임에도 불구하고,리니어 디스크 억세스를 통한 각 반복작업에 걸리는 시간은 보통의 웍스테이션상에서 약 6분 정도면 된다. 가중치들이 수렴하고나면, 다시 댕글링 링크를 추가하고, 랭킹을 재연산한다. 댕글링 링크를 되돌려 넣은 뒤에 필요한 반복 작업 횟수는 댕글링 링크를제거하는 데 요구되었던 횟수와 똑같다는 점에 주의하라. 그렇지 않으면, 댕글링 링크의 일부는 가중치가 0이 될 것이다.</p> <p>이상의 모든 과정은 현재의 임플리멘테이션의 경우 총 5시간이 소요된다. 수렴 조건을 덜 엄격하게 하고, 더 최적화를 한다면계산속도는 더 빨라질 수 있을 것이다. 또는, 아이겐벡터를 추산하는 보다 더 효율적인 테크닉이 사용되어도 퍼포먼스가 더 좋아질것이다. 어쨌든, 페이지랭크를 계산하는 데 필요한 코스트는 풀 텍스트 인덱스를 구축하는 데 필요한 것에 비하자면 아주 사소한것이라 할 수 있다.</p><h3>4 수렴 특성(Convergence Properties)</h3><p>그림 5에서 볼 수 있는 것처럼, 3억 2200만개라는 큰 링크 데이타베이스를 합리적으로 감내할 만한 수준으로 수렴시키는데 필요한 반복작업은 약 52회다. 데이타의 크기가 반이라면 대략 45회면 된다. 이 그래프를 통해서, 극단적으로 큰 크기의컬렉션에서도 페이지랭크가 아주 쉽게 확장될 수 있다는 것을 알 수 있다. 스케일링 팩터가 대략 log<sup>n</sup>과 거의 선형관계를 이룬다.</p><div class="imageCenter"><img src="http://www.emh.co.kr/images/convergence_pagerank.gif" alt="페이지랭크의 수렴" height="441" width="674"><br />
그림 5 페이지랭크 연산의 수렴</div><p>페이지랭크 연산이 아주 빠르게 수렴한다는 사실로부터 파생되는 한 가지 흥미로운 점은 웹이 익스팬더양그래프(expander-like graph)라는 점이다. 이 부분의 이해를 돕기 위해서 그래프 상의 랜덤 워크 이론의 간단한개론을 살펴 보자. 자세한 것은 Motwani-Raghavan이 쓴 페이퍼를 참조하라.</p><p>그래프 상의 랜덤 워크는 스토캐스틱(stochastic)한 과정이다. 즉, 임의의 한 타임스텝에 우리는 그래프 상의 특정노드에 서 있고, 다음 타임스텝에 어떤 노드로 이동할 것인지는 균일하게 무작위적으로 분포하는 아웃엣지 중 하나를 선택해서결정하는 것이다. 만약 모든 (너무 크지는 않은) 서브셋 노드 S가 이웃(neighborhood; S에 속한 노드들로부터아웃엣지를 통해 접근가능한 꼭지점들의 집합)을 가지고 있고, 그 이웃 노드의 크기가 |S|보다 α배 이상 크다면 그 그래프는하나의 익스팬더(expander)라고 할 수 있다. 그리고 만약, 특히 가장 큰 아이겐벨류가 두 번째로 큰 아이겐벨류보다 충분히더 큰 경우, 그 그래프는 좋은 익스팬젼 팩터를 갖고 있다고 볼 수 있다. 랜덤 워크가 빠른 속도로 그래프 상의 노드들의 제한된분포로 수렴해 가면 그 그래프는 래피들리-믹싱(rapidly-mixing)하다. 또한 그래프가 익스팬더이고 아이겐벨류분리(eigenvalue separation)를 갖고 있다면 그 랜덤 워크는 래피들리-믹싱인 경우라 할 수 있다.</p><p>이상의 내용을 페이지랭크 연산과 관련 지어 보자. 페이지랭크란 본질적으로, 웹 그래프 상의 랜덤 워크의 제한된 분포로결정짓는 것이다. 어떤 노드의 중요도 랭킹이란, 본질적으로 충분히 시간이 흐른 뒤에 랜덤 워크가 그 노드에 있을 확률인 것이다.페이지랭크 연산이 로그 시간 내에 종결될 수 있다는 사실은 랜덤 워크가 래피들리 믹싱이거나 그래프가 좋은 익스팬젼 팩터를 갖고있다는 말이 된다. 익스팬더 그래프는 여러 가지 바람직한 특성을 많이 갖고 있기 때문에 웹 그래프와 관계된 연산을 함에 있어서앞으로 다양하게 활용할 수 있을 것이다.</p><h3>5 페이지랭크를 이용한 검색</h3><p>페이지랭크의 주된 적용처는 검색이다. 우리는 페이지랭크를 활용한 두 가지 검색엔진을 임플리멘테이션했다. 하나는 단순한타이틀 기반의 검색엔진이고 다른 하나는 풀 텍스트 검색엔진이다. 후자의 이름은 구글이다. 구글은 표준적인 IR 측정치,근접성(proximity), 앵커 텍스트(웹 페이지를 가리키는 링크의 텍스트), 그리고 페이지랭크 등의 많은 요소를 바탕으로검색 결과를 랭킹한다. 페이지랭크가 어떤 이점을 갖는지에 관한 포괄적인 유져 스터디는 이 논문의 범위를 벗어나지만, 몇 가지비교 실험과 검색 결과 샘플을 이 논문을 통해 얘기해 보려 한다.</p><p>페이지랭크의 이점이 가장 크게 활용될 수 있는 부분은 덜 특화된 질의어(underspecified queries)를처리하는 것이다. 예를 들어, "스탠포드 대학"이라는 질의어를 넣으면, 일반적인 검색엔진은 스탠포드가 들어 간 많은 페이지들을결과로 보여 줄 뿐이다. 하지만 페이지랭크를 활용하면 스탠포드 대학 홈 페이지가 순위의 가장 위로 올라 오는 것이다.</p><h4>5.1 타이틀 검색</h4><p>페이지랭크가 검색에 활용되면 얼마나 유용한지를 시험해 보기 위해 우리는 1600만 페이지의 제목만을 사용하는 검색엔진을만들어 보았다. 그 검색엔진은 질의어를 넣으면 문서 제목에 질의어가 들어 있는 모든 웹 페이지를 찾은 다음, 그 결과를페이지랭크를 이용해서 정렬한다. 이 검색엔진은 아주 단순한 것이고 간단하게 구축할 수 있는데, 비공식적인 시험을 해 본 결과놀랄 만큼 훌륭한 성능을 보여 주었다. 그림 6에서 볼 수 있는 것처럼 "University"라는 검색어에 대해 페이지랭크를이용한 제목 검색엔진은 대표적인 대학들의 목록을 보여 준 것이다. 이 그림은 우리가 만든 MultiQuery 시스템으로, 두개의 검색엔진에 동시에 질의를 할 수 있는 시스템이다. 그림의 왼 편에 있는 것이 페이지랭크를 기반으로 한 타이틀 검색엔진이다.검색 결과에 있는 바 그래프와 퍼센티지는 탑 페이지를 100%로 잡고 페이지의 실제 페이지랭크 값에 로그를 취한 다음노멀라이징한 값이다. 이 논문의 다른 곳에서는 계속 퍼센타일(percentile)을 사용했지만 여기서는 아닌 것이다. 그림의오른 쪽에 있는 것은 알타비스타 검색엔진이다. 알타비스타의 검색 결과를 보면 "University"라는 질의어에 맷칭되는무작위적으로 보이는 웹 페이지들 그리고 여러 써버의 루트 페이지가 보인다. (알타비스타는 퀄리티 휴리스틱으로 URL의 길이를사용하는 것 같다.)</p><div class="imageCenter"><img src="http://www.emh.co.kr/images/multi_search.gif" alt="Multi Search" height="475" width="652"><br />
그림 6 "University" 검색어에 대한 결과 비교</div><h4>5.2 랭크 머징(Rank Merging)</h4><p>타이틀에 기반한 페이지랭크 시스템이 아주 훌륭한 결과를 보여 주는 이유는, 제목을 맷칭하는 것이 페이지의 높은 프리시젼을보장하고, 페이지랭크가 페이지의 높은 품질을 보장하기 때문이다. 웹 검색에서 "University" 같은 질의를 하는 경우,사용자가 살펴 볼 페이지보다 훨씬 많은 페이지들이 존재하기 때문에 리콜은 그다지 중요하지 않다. 리콜이 중요하게 요구되는 특화된검색의 경우는 풀 텍스트에 대한 전통적인 정보검색 점수와 페이지랭크를 함께 적용할 수 있을 것이다. 구글 시스템은 그런 형태의랭크 머징을 사용한다. 랭크 머징은 아주 까다로운 문제로 알려져 있어서 우리는 그런 형태의 질의어를 합리적으로 평가할 수 있게구축하기 위해 상당한 노력을 부가적으로 기울여야만 했다. 하지만, 그런 형태의 질의어에 있어서도 페이지랭크가 상당히 도움이된다고 생각된다.</p><h4>5.3 몇 가지 샘플 결과</h4><p>우리는 페이지랭크를 이용한 풀 텍스트 검색엔진인 구글을 이용해서 상당히 많은 테스트를 해 보았다. 완전한 형태의 유져스터디는 이 논문의 범위를 벗어나지만, 몇 개의 샘플을 이 논문의 부록 A에 수록했다. 더 많은 질의어에 대한 결과를 원하는분은 직접 구글을 테스트 해보면 된다.</p><p>표 1은 페이지랭크에 기반한 탑 15위 페이지 목록이다. 이 리스트는 1996년 7월 시점의 결과다. 최근 다시 페이지랭크를 계산해 보았을 때는 마이크로소프트가 넷스케잎보다 조금 더 큰 페이지랭크를 보여 주었다.</p><div class="imageCenter"><img src="http://www.emh.co.kr/images/top15.gif" alt="Top 15 페이지랭크" height="368" width="621"><br />
표 1</div><h4>5.4 커먼 케이스(Common Case)</h4><p>페이지랭크의 디자인 목표 중 하나가 질의어의 커먼 케이스를 잘 처리하게 한다는 것이었다. 예를 들어, 미시건 대학의 학생관리자 기능 시스템의 이름에 "wolverine"이라는 게 들어 있었던 것으로 기억하고 있는 사람이 "wolverine"이라는검색을 한다고 하자. 우리의 페이지랭크 기반 타이틀 검색엔진은 "Wolverine Access"를 검색 결과의 첫 번째로 보여준다. 이것은 대단히 합리적이다. 왜냐하면 모든 학생들은 Wolverine Access 시스템을 사용하고 있고,"wolverine"이라는 질의를 한 사람이라면 Wolverine Access 페이지를 살펴 보려 할 가능성이 매우 크기때문이다. 그런데 Wolverine Access 싸이트가 좋은 커먼 케이스라는 사실은 그 페이지의 HTML에는 전혀 담겨 있지않다. 심지어 이런 형태의 메타 정보를 페이지 내에 담을 수 있는 방법이 있다고 하더라도, 이런 류의 평가에 있어서는 페이지를만든 사람을 신뢰하기 힘들다는 게 문제가 된다. 웹 페이지를 만드는 많은 사람들이 자신이 만든 페이지가 웹에서 가장 훌륭하고가장 자주 읽힌다고 주장할 것이기 때문이다.</p><p>wolverine이라는 것에 관해서 가장 많은 정보를 담고 있는 페이지를 찾는 것과 wolverine 싸이트의 커먼케이스를 찾는 것은 전혀 다른 일이라는 사실이 중요하다. 웹의 링크구조를 통해 텍스트의 매칭 점수를 전파해 나감으로써 어떤주제를 자세하게 다룬 싸이트를 찾아내는 흥미로운 시스템이 있다.(Massimo Marchiori. The quest forcorrect information on the web: Hyper search engines.) 그 시스템은 그런 과정을 통해가장 중심적인 경로에 포함되는 페이지들을 결과로 보여주는 것이다. 이런 방식은 "flower" 같은 질의어의 경우 좋은 결과를보여 준다. 즉, 그 시스템은 '꽃'이라는 주제를 자세히 다루고 있는 싸이트에 도달할 수 있는 경로 중 가장 좋은 것을 보여주는것이다. 이것과 커먼 케이스를 찾는 접근법을 비교해 보자. 커먼 케이스 접근법은 꽃에 관한 정보대신 꽃을 구입하는 방법만이담긴, 사람들이 가장 많이 찾는 꽃 판매 싸이트를 보여줄 지도 모른다. 두 가지 방식 모두 중요하다는 게 우리의 생각이고,일반적 목적의 웹 검색엔진이라면 마땅히 위의 두 가지 태스크 모두에 있어서 만족스러운 결과를 보여줘야 한다고 생각한다. 이논문에서는, 우리는 커먼 케이스적 접근법에만 집중하고 있다.</p><h4>5.5 커먼 케이스의 하부 구성요소(Subcomponents of Common Case)</h4><p>페이지랭크가 도움이 될 수 있는 커먼 케이스 시나리오가 어떤 성격을 갖는가를 생각해 보는 것은 무척 유익하다. Wolverine Access 싸이트처럼 가장 자주 사용되는 페이지 외에도, 페이지랭크는 <a linkindex="15" href="http://www.emh.co.kr/xhtml/hubs_and_authorities.html">협동적 오쏘리티</a>또는 신뢰할 수 있는 싸이트 역시 표현해 준다. 예를 들어, 사용자는 어떤 뉴스가 단지 뉴욕 타임즈 홈 페이지로부터 직접링크되어 있다는 이유만으로 더 선호할 수 있다. 물론, 그 뉴스 페이지는 뉴욕 타임즈처럼 중요도가 높은 페이지로부터 링크되어있다는 사실만으로 매우 높은 페이지랭크 값을 갖게 된다. 이것은 일종의 협동적 신뢰(collaborative trust)의특성을 잡아내고 있는 것처럼 보인다. 왜냐하면, 신뢰도가 높고 권위 있는 소스로부터 언급된 페이지일수록 그 페이지의 신뢰도와권위가 올라가기 때문이다. 유사하게, 페이지의 품질이나 중요도 역시 이런 류의 순환적 정의에 잘 부합되는 것 같다.</p><h3>6 개인화된 페이지랭크(Personalized PageRank)</h3><p>페이지랭크 연산의 중요한 요소 중 하나가 E이다. E는, 랭크 싱크처럼 아웃엣지가 없는 싸이클을 보충하기 위한 랭크 소스웹 페이지의 벡터다. 한편, E는 랭크 싱크 문제에 대한 해결책으로써뿐만 아니라, 페이지랭크 값을 조정할 수 있는 강력한퍼래미터이기도 하다. 직관적으로 보자면, E 벡터는 랜덤 써퍼가 주기적으로 점프해 가는 웹 페이지의 분포에 해당한다. 밑에서살펴 보겠지만, 이것은 웹을 거시적으로 관찰하거나 특정 부분에 대해 집중적이고 개인화된 관찰을 하는 데 사용될 수 있다.</p> <p>우리가 수행한 실험은 대부분 E 벡터를 모든 웹 페이지에 걸쳐 균일하게 <code>||E||<sub>1</sub> = 0.15</code>로가정했다. 즉, 랜덤 써퍼가 주기적으로 또 다른 랜덤 웹 페이지로 점프하는 것을 가정한 것이다. 이것은 모든 웹 페이지가 단지존재하고 있다는 이유만으로 똑같이 가치를 부여받는 것이므로 E를 무척 민주적으로 선택한 것이다. 이런 테크닉이 상당히성공적이었기는 했지만 중요한 문제점도 갖고 있다. 관련 링크가 많은 어떤 웹 페이지들이 지나치게 높은 랭킹을 받을 수 있는문제다. 예컨데, 저작권 관련 페이지나 상호간에 링크가 많이 된 메일링 리스트 모음 등이 여기에 해당한다.</p><p>또 하나의 극단적 형태로, E를 오직 하나의 웹 페이지로만 구성할 수 있다. 우리는 두 가지로 실험해 보았다. 하나는넷스케잎 홈 페이지로 해 보았고 다른 하나는 유명한 컴퓨터 과학자인 존 맥카씨(John McCarthy)의 홈 페이지로 했다.넷스케잎의 홈 페이지로 한 실험은, 넷스케잎을 기본 홈 페이지로 하고 있는 초보 사용자의 시각에서 페이지의 랭크를 만들어 내려는시도를 한 것이다. 존 맥카씨의 홈 페이지를 이용한 실험은, 그의 홈 페이지에 있는 링크를 바탕으로 우리에게 상당한 문맥적정보를 제공한 개인의 시각에서 페이지랭크를 계산한 것이다.</p><p>두 경우 모두, 위에서 말한 메일링 리스트 문제가 나타나지 않았다. 그리고 두 경우 모두에서, 각각의 홈 페이지가 가장높은 페이지랭크 값을 나타냈으며 그 페이지로부터 직접 연결된 페이지들이 그 뒤를 이엇다. 그 다음 시점부터는 불균형은 줄어들었다. 표 2는 각각의 경우에서 여러 페이지들의 페이지랭크 퍼센타일을 나타낸 것이다. 컴퓨터 사이언스에 관계된 페이지일수록넷스케잎 쪽 랭크보다 매카씨 랭 크쪽이 더 높은 값을 갖고, 특히 스탠포드 대학의 컴퓨터 사이언스 학과와 관계되는 페이지는 더욱높은 매카씨 랭크 값을 갖는 것을 볼 수 있다. 예를 들어 스탠포드 컴퓨터 사이언스 학과의 또 다른 교수의 웹 페이지는 매카씨쪽 랭크가 넷스케잎의 경우보다 6 퍼센타일 더 높다. 그리고 페이지랭크 값을 퍼센타일로 표시한 것에 주의하자. 이렇게 한 것은상위 순위에서 나타나는 페이지랭크 값의 큰 차이를 줄여서 표현하기 위해서다. </p><div class="imageCenter"><img src="http://www.emh.co.kr/images/netscape_vs_mccarthy.gif" alt="Netscape vs McCarthy"><br />
표 2</div><p>위와 같은 개인화된 페이지랭크는 개인화된 검색엔진처럼 다양하게 응용할 수 있을 것이다. 개인화된 검색엔진은, 단순히북마크나 홈 페이지를 입력하는 것만으로 사용자의 취향을 상당 부분 효과적으로 추측해내서 사용자의 수고를 대폭 덜어줄 수 있을것이다. "Mitchell"이라는 질의어로 시행한 예를 부록 A에 수록했다. 그 예를 보면, 웹 상에 "Mitchell"이라는이름을 가진 사람이 아주 많음에도, 존 매카씨 교수의 동료인 존 밋첼 교수의 홈 페이지가 결과의 1위로 나타난 것을 볼 수 있다.</p><h4>6.1 상업적 이익을 위한 조작</h4><p>이런 형태의 개인화된 페이지랭크는 상업적 이익을 위해 조작하는 것을 사실상 완전히 차단할 수 있다. 높은 페이지랭크 값을갖기 위해서는 중요한 페이지로부터 언급되거나 중요하지 않은 많은 페이지로부터 링크되어야만 한다. 최악의 경우, 중요한 싸이트에서광고(링크)를 구입하는 형태의 조작이 있을 수 있겠지만 그건 비용이 소요되므로 충분히 조절 가능하다. 조작에 대한 이런 저항성은정말로 중요한 특성 중 하나다. 왜냐하면 상업적 조작 때문에 많은 검색엔진이 골머리를 앓고 있으며 훌륭한 기능을임플리멘테이션하는 것이 조작 때문에 매우 어려워지기 때문이다. 예컨데, 문서가 자주 업데잇되는 것은 매우 바람직한 특징임에도검색 결과를 조작하고자 하는 사람에 의해 이런 특징이 남용되고 있는 것이다.</p><p>균일한 E로 할 것인지 아니면 단일 페이지 E로 할 것인지의 절충안으로 E를 모든 웹 써버의 루트 수준 페이지로 구성할수도 있다. `이 경우, 어느 정도의 페이지랭크 조작이 가능하다는 것에 주의해야 한다. 많은 루트 레벨 써버를 확보해서 특정싸이트로 링크하면 간단히 조작되기 때문이다.</p><h3>7 적용(Applicaitons)</h3><h4>7.1 웹 트래픽의 추산</h4><p>페이지랭크는 대략 랜덤 웹 써퍼에 해당하기 때문에(섹션 2.5 참조), 페이지랭크가 실제 사용도와 어떻게 대응되는지 알아 보는 것은 아주 흥미로운 일이다. 우리는 NLANR(<a linkindex="16" href="http://ircache.nlanr.net/Cache/">NLANR</a>)의 프록시 캐쉬로부터 얻은 웹 페이지의 접근 횟수를 페이지랭크와 비교해 보았다. NLANR 데이타는 미 전역에 있는 프록시캐쉬에 있는 여러 달에 걸쳐진 기록으로, 11,817,665개의 각기 다른 URL에 관한 자료이다. 그 데이타에 따르면 가장히트가 높은 것은 알타비스타로 638,657 히트다. 그 데이타베이스는 우리가 갖고 있는 7500만 개 URL 데이타베이스와260만 페이지가 중복된다. 이들 데이타셋을 분석, 비교하는 것은 몇 가지 이유에서 대단히 까다로운데, 우선 캐쉬 억세스데이타에 있는 많은 URL들이 무료 이메일 서비스에 있는 개인 메일을 읽기 위해 접근한 것들이라는 점이 있다. 그리고 중복된써버 이름과 페이지 이름도 심각한 문제점이다. 불완전성과 편향됨은 페이지랭크 데이타와 사용도 데이타 모두에서 문제가 된다.하지만, 몇 가지 흥미로운 트렌드를 볼 수 있었다. 캐쉬 데이타에서는 포르노그래프 싸이트들이 높은 사용도를 보였음에도 이들의페이지랭크 값은 대부분 낮았다. 이것은, 사람들이 자신의 웹 페이지에 포르토그래피 싸이트로 링크하는 것을 원하지 않기 때문인것으로 생각된다. 그러므로 페이지랭크와 사용도 데이타 사이의 차이점을 살펴 보는 것을 통해, 사람들이 보고는 싶어하는데 자신의웹 페이지에서는 언급하고 싶어 하지 않는 게 어떤 것이 있는지를 알아낼 수 있을 것이다. 어떤 싸이트는 매우 높은 사용도를갖는데 페이지랭크가 낮은 경우가 있다. netscape.yahoo.com 같은 게 그렇다. 이것은 아마도 우리 데이타베이스에중요한 백 링크가 누락되어 있기 때문인 것 같다. 우리 데이타베이스는 웹 링크 구조이 일부분만을 담고 있기 때문이다. 사용도데이타를 페이지랭크 계산의 시작 벡터로 사용하고 페이지랭크 연산을 몇 차례 반복하는 것도 가능할 것이다. 이렇게 하면 사용도데이타가 채워주지 못 한 부분을 메꿀 수 있을 것이다. 어떤 식이 되었든, 이런 형태의 비교는 향후 연구를 위한 흥미로운주제이다.</p><h4>7.2 백 링크 예측자로써의 페이지랭크</h4><p>페이지랭크는 백 링크의 예측자로써의 의미가 있다. "Efficient crawling through urlordering"(Junghoo Cho, Hector Garcia Molina, and Lawrence Page) 논문에서,우리는 어떻게 웹을 효율적으로 크롤링할 수 있는지, 더 좋은 문서들을 먼저 크롤링할 수 있는지의 문제를 탐색했다. 우리는스탠포드 웹에서 시행한 테스트를 통해서 페이지랭크가 단순히 인용 횟수를 세는 것보다 훨씬 더 좋은 미래 인용 횟수의 예측자라는것을 알게 되었다.</p><p>실험은, 다른 정보 없이 단일 URL에서 출발해서 가급적 최적의 순서에 가깝게 페이지를 크롤링하는 것을 목표로 하고 있다.최적의 순서란 평가함수에 따른 랭크 순서와 정확히 일치하는 순서로 페이지를 크롤링하는 것이다. 이 실험에서의 평가함수는 완전한정보가 주어졌을 때의 인용 횟수 순서로 했다. 문제는, 평가함수를 계산할 정보를 완전히 알게 되는 것은 모든 문서를 크롤링한다음이라는 점이다. 이렇게 불완전한 데이타를 사용해서 크롤링 순서를 정할 때, 단순히 이미 알고 있는 인용 횟수를 활용하는것보다 페이지랭크를 이용하는 쪽이 더 효과적인 것으로 드러났다. 바꿔 얘기하자면, 심지어 측정 기준이 인용횟수를 세는것일지라도, 페이지랭크가 인용회수를 직접 세는 것보다 더 좋은 예측자라는 얘기다! 이것의 이유는 페이지랭크의 경우 인용 횟수를세는 것이 국소적으로만 최대화되는 것을 피할 수 있기 때문인 것 같다. 예를 들어, 인용 횟수를 직접 세는 경우에는 스탠포드CS 웹 페이지들의 컬렉션 속에만 빠져 드는 경향이 있어서 그곳을 벗어나 다른 곳에 있는 인용 회수가 높은 페이지를 찾아 나서는데 오랜 시간이 걸린다. 하지만 페이지랭크는 스탠포드 홈 페이지가 중요하다는 것을 금방 알게 되고, 그 하부 페이지들에게우호적인 점수를 주기 때문에 더 효율적이고 광범위한 검색이 가능한 것이다.</p><p>이러한 인용 횟수의 예측자로써의 페이지랭크의 능력은 페이지랭크를 사용해야 하는 아주 설득력 있는 이유가 된다. 웹의인용구조를 완전히 매핑하는 것은 아주 까다롭기 때문에, 인용 횟수를 직접 세는 것보다 페이지랭크가 훨씬 더 좋은 인용 횟수근사치가 될 수 있는 것이다.</p><h4>7.3 사용자 네비게이션: 페이지랭크 프락시(User Navigation: The PageRank Proxy)</h4><p>우리는 사용자가 각 링크의 페이지랭크와 함께 부가적인 설명을 볼 수 있는 웹 프락시 애플리케이션을 개발했다. 그애플리케이션은 아주 유용했는데, 사용자가 링크를 클릭하기 전에 관련 정보를 미리 알 수 있기 때문이다. 그림 7은 프록시프로그램의 스크린샷이다.빨간 바의 길이는 URL의 페이지랭크 값에 로그를 취한 값이다. 그림을 보면 스탠포드 대학 같은 메이져조직은 매우 높은 랭킹을 받게 되고, 뒤이어 리서치 그룹이, 그 다음으로 개인이 -개인의 경우 스케일의 최상단에는 교수가위치한다 - 나타남을 알 수 있다. 또한 ACM이 스탠포드 대학보다는 높지 않지만 매우 높은 페이지랭크를 갖는 것도 볼 수있다. 재미있는 것은, 아주 지명도가 높은 교수의 페이지가 심할 정도로 낮은 페이지랭크 값을 갖고 있는 것을 찾으면 URL이잘못 되어 있는 것을 찾아낼 수 있다는 점이다. 결과적으로, 프락시 툴은 네비게이션 뿐만 아니라 페이지 제작에도 도움이 될 수있는 것 같다. 이 프락시 애플리케이션은 다른 검색엔진의 결과를 살펴 보는 데에도 아주 유용하다. 그리고 야후의 리스팅 같이링크가 매우 많은 페이지를 파악하는 데도 큰 도움이 된다. 프락시를 통해서 많은 링크 중 어떤 것이 더 흥미로운 것인지를 짐작할수 있기 때문이다. 또는 자신이 찾고 있는 링크가 "중요도" 측면에서 어느 정도인지를 알 수도 있고, 훨씬 더 빠르게 페이지를전체적으로 살펴볼 수 있다.</p><div class="imageCenter"><img src="http://www.emh.co.kr/images/pagerank_proxy.gif" alt="PageRank Proxy" height="531" width="638"><br />
그림 7 페이지랭크 프락시</div><h4>7.4 페이지랭크의 다른 용도</h4><p>페이지랭크의 최초 목표는 백 링크를 정렬해서, 만약 어떤 문서가 많은 백 링크를 갖는다면 그 중 어떤 것이 "최상"의것인지를 찾아서 그걸 가장 먼저 보여주려는 것이었다. 그리고 우리는 그런 시스템을 임플리멘테이션했다. 페이지랭크를 기준으로정렬된 백 링크를 살펴 보는 것은 경쟁을 파악하는 측면에서도 아주 흥미롭다. 예를 들어, 뉴스 싸이트를 운영하는 사람이라면경쟁자가 확보한 중요한 백 링크가 어떤 것인지 지속적으로 관찰하고자 할 것이다. 또한, 페이지랭크는 사용자가 어떤 싸이트가신뢰할 수 있는 것인지 아닌지 판단하는 데 도움을 준다. 예를 들어, 스탠포드 홈 페이지에서 직접 인용된 정보라면 아무래도사용자가 더 신뢰하려 할 것이다.</p><h3>8 결론</h3><p>이 논문에서, 우리는 웰드 와이드 웹 상의 모든 페이지를 페이지랭크라는 단일한 숫자로 압축하고자 하는 담대한 작업을 다루어보았다. 페이지랭크는 페이지의 컨텐트와 상관없이, 오직 웹의 그래프 구조 상의 위치에만 의존하는 모든 웹 페이지의 글로벌랭킹이다. </p><p>페이지랭크를 사용함으로써 우리는 더 중요하고 중심적인 웹 페이지들을 더욱 선호하는 식으로 검색 결과를 정렬할 수 있다.여러 실험을 통해서, 페이지랭크는 고품질의 검색 결과를 보여줌을 알 수 있었다. 페이지랭크의 기반이 되는 직관은 웹 페이지외부에 있는 정보, 즉 일종의 피어 리뷰인, 백 링크를 사용한다는 것이다. 게다가, "중요한" 페이지들로부터의 백 링크는평균적인 페이지들로부터의 백 링크보다 더 중요하며, 이것은 페이지랭크의 재귀적인 정의(섹션 2.4 참조)를 통해 확실히 구현되어있다.</p><p>페이지랭크는 대부분의 질의어에 대한 답변이 될 수 있는 소수의 자주 사용되는 문서들을 분리해 내는 데에도 사용될 수 있다.풀 데이타베이스는 작은 데이타베이스가 질의어에 적절히 응답할 수 없을 때만 참조되면 된다. 마지막으로, 페이지랭크는 클러스터의센터로 사용할 수 있는 대표 페이지를 찾아내는 좋은 방법이 될 수도 있을 것이다.</p><p>페이지랭크는 검색 외에도 트래픽 추산이나 사용자 네비게이션 같은 다른 많은 곳에 적용될 수 있다. 또한, 웹을 특정 시점에서 바라볼 수 있는 사용자화된 페이지랭크 역시 만들어 낼 수 있다.</p><p>종합하자면, 페이지랭크를 이용한 실험은 웹 그래프의 구조가 다양한 정보검색 작업에서 매우 유용하게 사용될 수 있음을 보여 준다고 할 수 있다.</p><br />
<p><br />
</p><br />
<p><br />
</p><div class="urlLink">문서출처: <a set="yes" linkindex="9" href="http://www.emh.co.kr/">이명헌 경영스쿨</a> <a set="yes" linkindex="10" href="http://www.emh.co.kr/xhtml/google_pagerank_citation_ranking.html">http://www.emh.co.kr/xhtml/google_pagerank_citation_ranking.html</a> <br />
 이 문서를 게시하거나 프린트하려면 위 문서출처를 반드시 포함해야 합니다.(참고: <a linkindex="11" rel="license" href="http://creativecommons.org/licenses/by-nc-nd/2.0/kr/deed.kr">저작권정책</a>) </div><!-- main --></div><br/><br/>tag : <a href="/tag/페이지랭크" rel="tag">페이지랭크</a>,&nbsp;<a href="/tag/pagerank" rel="tag">pagerank</a>,&nbsp;<a href="/tag/구글" rel="tag">구글</a>,&nbsp;<a href="/tag/웹페이지" rel="tag">웹페이지</a>,&nbsp;<a href="/tag/검색엔진" rel="tag">검색엔진</a>			 ]]> 
		</description>
		<category>Search Engine</category>
		<category>페이지랭크</category>
		<category>pagerank</category>
		<category>구글</category>
		<category>웹페이지</category>
		<category>검색엔진</category>

		<comments>http://topic.egloos.com/537660#comments</comments>
		<pubDate>Mon, 13 Aug 2007 11:33:16 GMT</pubDate>
		<dc:creator>Hans</dc:creator>
	</item>
	<item>
		<title><![CDATA[ Google Search Engine 해부 - 1 ]]> </title>
		<link>http://topic.egloos.com/536708</link>
		<guid>http://topic.egloos.com/536708</guid>
		<description>
			<![CDATA[ 
  <p class="contentsbox">구글은 처음부터 다른 서비스와는 차별되는 검색엔진과아키텍처, 새로운 개념의 랭킹 모델들을 사용함으로써 그간의 웹 검색에 대한 개념을 크게 바꾸어 놓았다. 구글의 기술은 검색업계에서 일하는 개발자들은 물론 일반 개발자들까지도 관심을 갖게 만드는데, 그 핵심은 탄탄한 기반 기술들과 그것들을 하나로 묶는거대한 프레임워크에 있다. 이번 특집 2부를 통해 구글의 기술이 어떤 그림을 갖고 있는지에 대해 이해할 수 있는 시간이 될것으로 기대한다.</p><br />
<h5 class="sub1"><font size="2"><strong>구글 검색엔진</strong></font>&nbsp;<br />
</h5><p>검색엔진은 대상이 되는 문서들을 수집하고, 수집된 문서들로부터 키워드를 추출하여 키워드-문서간의 역 색인(inverted index)을 생성한 후, 사용자의 질의어(query)를 입력받아 해당 쿼리를 역 색인 구조를찾아, 매칭된 문서를 결과로 반환해 준다. 구글의 검색엔진 역시 이러한 전통적인 검색엔진의 구조와 크게 다르지 않다. 구글의검색엔진은 웹 문서들을 수집하고, 웹 문서들로부터 키워드를 추출하여 역 색인 구조를 생성하고, 생성된 역 색인 구조로부터질의어를 매칭하여 결과를 반환해준다. 그러나 구글의 검색엔진은 기존의 검색 시스템과는 스케일이나 기능 면에서 많은 차이를보여준다.</p>&nbsp;<br />
<p>전통적인 키워드 매칭(keyword matching)을 기반으로 한 자동화된검색엔진(automated search engine)은 몇 가지 약점을 갖고 있었다. 기본적으로 낮은 질의 매칭 결과가 너무빈번하게 나타났다. 게다가 광고주들이 웹 문서에 포함된 키워드들을 조작해 엉뚱한 결과가 노출되도록 하는 것이 가능했다. 구글은이런 문제점을 해결하기 위해 웹 문서의 하이퍼텍스트에 존재하는 부가적인 구조적 정보들을 사용하기 시작했다. 또한 방대한 웹 문서데이터들을 처리하기 위해 매우 거대한 스케일의 검색 아키텍처를 구축했다.</p><p class="sub2"></p><br />
<h5><font size="2">구글 검색엔진의 지향점</font></h5><p>웹을 효율적으로 검색하기 위해서는 몇 가지의 필수적인 기술들이 요구된다. 웹 문서들을 신속하고효율적으로 수집하고, 수집된 데이터들을 최신의 상태로 유지하기 위한 크롤링(crawling) 기술, 대용량 데이터 처리를 위해효율적으로 공간을 사용할 수 있는 색인 구조, 대용량 데이터를 신속하게 처리할 수 있는 색인기(indexer) 기술, 다량의질의어들을 처리할 수 있는 질의어 분석/처리 시스템 등이 그것이다.</p><br />
<p>웹이 성장하면서 이러한 기술들이 감당해야 하는 목표들은 급격하게 상향 조정된다. 게다가 단순히하드웨어의 발전만으로는 웹의 발전 속도를 감당할 수 없다. 하드웨어의 발전이 검색 시스템의 성능을 증가시키지만, 기본적으로디스크 탐색 시간(disk seek time)이나 운영체제의 강력함(robustness)은 그렇게 주목할 만한 요소가 아니다.구글 검색엔진은 극단적으로 큰 데이터 셋(data set)을 커버하기 위한 확장형 구조이며, 효율적인 색인 구조를 사용함으로써데이터에 대한 신속하고 효율적인 액세스가 가능하도록 최적화된 구조이다.</p>&nbsp;<br />
<p>웹 검색의 초창기에 많은 사람들이 검색엔진의 색인이 완전하고 무결성을 갖는다면 어떤 키워드에대해서도 원하는 웹 문서를 검색할 수 있다고 믿었다. 그러나 웹 검색이 발전하면서 색인의 완전성과 무결성이 검색 품질을 좌우하는유일한 요소가 아님이 밝혀졌다. 웹 검색은 일반적으로 입력되는 질의어에 대해 매칭되는 문서의 개수가 대단히 많다. 즉, 검색대상이 되는 색인 내에서 검색 결과로 재현될 수 있는 비율이 대단히 크다. 그러나 일반적인 사용자들은 많은 검색 결과 중에서상위의 일부 결과만을 보고 검색 결과의 모든 품질을 평가하려는 성향이 있다. 관련 있는 검색 결과가 상위에 랭크되어 있지 않고몇 십 페이지 뒤에 랭크되어 있다면, 그것을 찾기 위해 페이지를 클릭할 사용자는 그렇게 많지 않다. 따라서 사용자의 만족감을충족시키기 위해서는 극도로 높은 정확도에 기반한 검색 결과를 제공해야 한다. 정확도는 대용량 데이터의 검색 결과 품질을 좌우하는요소이기 때문에, 재현율을 희생해서라도 정확도를 확보하는 것이 사용자들의 만족감을 위해 가장 중요하다⑴.</p>&nbsp;<br />
<p>구글 검색엔진은 이러한 이유로 정확도 중심의 엔진으로 설계됐다. 구글의 정확도는 극도의 관계성판단(relevance judgement)에 의해 산출되는데, 그 기반에는 링크 구조와 앵커 텍스트(anchor text)를분석한 정보에 의한 질적인 필터링(filtering)이 존재한다. 구글은 이러한 정보들의 정확도를 높이는 두 가지 방법을사용한다. 하나는 개별 웹 페이지의 품질 순위 할당을 위한 페이지 랭크 알고리즘이고, 다른 하나는 검색 결과 개선을 위한 앵커텍스트 사용이다.</p>&nbsp;<br />
<p>참고로, 구글이 검색엔진을 발표했던 초창기에는 또 한 가지 목표를 가지고 있었다. 그것은대용량 웹 문서들과 대용량 트래픽을 감당할 수 있는 거대한 웹 시스템을 만들고, 실제로 많은 사용자들이 그것을 사용하면서 얻는데이터(usage data)를 학술적인 연구에 제공하겠다는 것이었다.</p>&nbsp;<br />
<h5 class="sub2"><font size="4">구글 검색엔진의 특징</font></h5><strong>페이지 랭크의 사용</strong><br />
<br />
<p>웹 문서에 존재하는 레퍼런스(링크) 그래프는 구글 검색엔진이 거의 최초로 주목한 요소이다.페이지 랭크는 이러한 요소들로부터 사용자들이 생각하는 특정 페이지의 중요성(importance)에 부합하는정확도(precision)의 객관적인 척도를 산출해낸다. 사용자들의 생각과 관련을 갖기 때문에 페이지 랭크는 웹 문서에 순위를할당하는데 매우 합리적인 수단이다. 질의어를 문서 제목과 매칭되는지 여부만을 평가하는 단순한 텍스트 검색엔진에는 물론, 풀텍스트(full text, 제목과 내용을 모두 포함) 검색엔진이나 페이지 랭크로 순위를 매기는 경우에도 상당한 성능을 보여주기때문이다.</p>&nbsp;<br />
<p>페이지 랭크는 한 페이지의 인용 횟수(백 링크, back link)를 카운팅하는 방식으로계산된다. 한 페이지가 얼마나 많은 레퍼런스를 받고 있느냐의 수준이 그 페이지의 중요성이나 품질(quality)을 추정할 수있는 요소로 간주된다. 페이지 랭크는 이 기본적인 아이디어를 확장하여 그 링크가 어떤 페이지에서 왔는지를 차별화하고, 링크하는페이지에서 외부로 나가는 총 링크 개수로 노멀라이징(normalizing)을 수행했다.</p>&nbsp;<br />
<p>페이지 랭크를 간략하게 정리하자면 다음과 같다. 페이지 A를 링크하는 다른 페이지들의 set을(T1, T2, T3, ...., Tn)이라고 한다면, 파라미터 d는 0~1 사이의 값을 갖는다. C(A)는 페이지 A에서외부로 나가는 아웃 링크(out link)의 개수이다. 이 때 페이지 A의 페이지 랭크 값 PR(A)은 다음과 같은 수식으로표현된다.</p>&nbsp;<br />
<p>페이지 랭크 PR(A)은 반복 알고리즘(iterative algorithm)으로 계산할 수있으며, 그 값은 웹 링크를 노멀라이징해서 행렬로 바꾸었을 때 주 고유 벡터(principal eigen-vector)에해당한다. 참고로 이것은 약 2600만 페이지의 페이지 랭크를 계산하는데 중급의 워크스테이션으로 수 시간 내에 연산이 가능한수준이다.</p>&nbsp;<br />
<p>페이지 랭크는 또한 사용자의 행동 패턴을 모델링하고 있다. 무작위로 선택한 하나의 웹페이지에서 출발해서 백 버튼을 누르지 않은 상태로 계속 링크를 따라 네비게이션하는 랜덤 서퍼(random surfer)는네비게이션 도중 지루해지면 다시 무작위로 페이지를 선택해서 네비게이션을 시작한다. 한 페이지의 페이지 랭크는 랜덤 서퍼가 그페이지를 방문할 확률을 나타낸다. 페이지 랭크에서 주요 파라미터 중 하나가 댐핑 팩터(damping factor) d이다.페이지 랭크에서는 파라미터 d를 특정 페이지 하나 또는 일련의 페이지에만 선택적으로 적용함으로써개인화(personalization)를 가능하게 하며, 페이지에 대한 랭킹을 올리기 위한 속임수(abusing)를 사실상불가능하게 만들 수 있다.</p>&nbsp;<br />
<p>페이지 랭크의 직관적인 요소 중 또 하나는 페이지 랭크 값이 커지기 위해서는 많은 페이지가어떤 한 페이지를 집중적으로 레퍼런스하고 있거나, 특정 페이지를 레퍼런스하는 페이지 자체의 페이지 랭크 값이 커야 한다는것이다. 예를 들어 많은 페이지로부터 인용되고 있는 페이지는 살펴볼 만한 가치가 있는 것이고, 야후 같은 메이저페이지(major page)에서 링크되고 있는 페이지는 그렇지 않은 페이지보다 중요하다고 간주되는 것이다. 페이지 랭크에 대한더 자세한 내용은 뒤에서 따로 다루겠다.</p>&nbsp;<br />
<br />
<p><strong>앵커 텍스트의 사용</strong></p>&nbsp;<br />
<p>구글 검색엔진은 링크의 텍스트 자체를 특별하게 취급한다. 대부분의 검색엔진들은 링크의텍스트(앵커 텍스트)를 링크를 담고 있는 페이지 자체의 정보 중 일부로만 취급하고 있지만, 구글의 검색엔진은 링크가 가리키고있는 페이지를 링크의 텍스트와 연관시켜 처리한다. 이런 방법은 몇 가지 장점을 가진다. 첫째, 앵커 텍스트는 링크를 담고 있는페이지에 대한 설명보다 링크가 가리키고 있는 페이지에 대해 더 정확한 설명을 담고 있는 경우가 대부분이다. 둘째, 일반적인텍스트 검색엔진이 색인할 수 없는 이미지나 프로그램, 데이터베이스로의 앵커(링크)도 존재할 수 있다. 따라서 앵커를 사용한다면크롤링되지 않는 웹 페이지들까지도 찾아낼 수 있다. 물론 이러한 링크에 걸려있는 대상들은 검색에 유효하지 않은 대상일 수있으므로 사용자에게 보여주기 전에 먼저 유효성 검사를 통과해야 한다. 존재하지 않는 페이지를 가리키는 앵커의 경우에도 유효성검사를 거치면 큰 문제는 없다.</p>&nbsp;<br />
<p>앵커 텍스트를 그 앵커가 가리키는 페이지로 전파시켜 나간다는 아이디어는 World WideWeb Worm(WWWW) 검색엔진에서 먼저 구현됐다. 앵커 텍스트가 텍스트 이외의 데이터에 대한 검색을 용이하게 해 주었고,검색엔진이 크롤링한 웹 문서보다 훨씬 더 많은 영역을 포괄하게 해주는 것에 이 아이디어의 유용성이 있다. 다만, 이를 위해서는대용량 데이터 처리를 위한 구조가 필수적이다.</p><br />
&nbsp;<br />
<p><strong>그 밖의 특징</strong></p>&nbsp;<br />
<p>페이지 랭크와 앵커 텍스트에 대한 접근 방식 외에도 구글 검색엔진은 몇 가지 특징을 갖는다.첫째, 구글 검색엔진은 문서로부터 추출된 모든 키워드들에 대한 위치 정보(positional information)를 저장한다.위치 정보의 저장은 검색 수행 시 근접도의 광범위한 사용을 가능케 한다. 둘째, 구글은 문서 내에서 추출된 키워드의 폰트 크기,대소문자 여부 등에 대한 부수적이고 시각적인 세부 요소들을 추적한다. 폰트 크기가 큰 단어나 볼드체로 된 단어, 대문자로 작성된단어의 경우에는 그렇지 못한 단어에 비해 더 높은 가중치(weight)가 부여된다. 셋째, 구글 검색엔진은 수집된 웹 문서를완전한 HTML 형식으로 압축 저장하기 때문에 이를 활용할 수 있는 여지가 있다.</p>&nbsp;<br />
<p><strong>&lt;그림 1&gt; 구글 검색엔진의 아키텍처</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_01.gif" alt="" border="0"></p><br />
<p>&nbsp;</p><br />
<p style="font-weight: bold;" class="sub2">구글 검색엔진의 전반적인 구조</p>&nbsp;<br />
<p>지금까지 구글 검색엔진의 특징을 살펴보았고, 이제는 구글 검색엔진의 구조에 대해 알아보자.&lt;그림 1&gt;은 구글 검색엔진의 아키텍처를 표현하고 있다. 구글 검색엔진의 구조는 일반 검색엔진과 큰 차이가 없다.구글 검색엔진은 크게 웹 문서를 수집하는 크롤러(crawler) 영역과, 역 색인(inverted index)을 생성하는색인기(indexer) 영역, 그리고 검색을 수행하는 검색기(searcher) 영역으로 구분된다. 구글 검색엔진이 데이터를수집하고 색인을 생성하여 검색을 수행하는 전반적인 시퀀스는 다음과 같다.</p>&nbsp;<br />
<br />
<p>• <strong>크롤링</strong><br />
<br />
- 분산 배치된 크롤러에 의해 웹 페이지들이 다운로드된다.<br />
- 크롤러가 수집한 문서들은 URL server로 보내져서 URL list로 변환된다.<br />
- 크롤러로부터 패치(fetch)된 웹 문서들은 Store server에 저장된다.<br />
- Store server에 저장된 웹 문서들은 압축되어 리파지토리에 저장된다.<br />
- 저장된 웹 문서들은 특정한 docID를 부여받는다.</p><br />
<p>&nbsp;<br />
</p><p>• <strong>색인</strong><br />
<br />
- Indexer가 리파지토리를 읽어 압축된 웹 문서들의 압축을 해제한다.<br />
-Indexer가 압축 해제된 웹 문서를 파싱하여 문서에 포함된 부수적인 정보(위치 정보, 폰트 크기, 대소문자 여부)와 함께추출한 키워드 정보(Hits라고 불린다)의 set을 생성하고, 링크들을 분석하여 링크의 방향성과 앵커 텍스트들을 추출해서anchor file을 생성한다.<br />
- Indexer가 문서 당 추출된 키워드들의 set을 Barrel에 일부분 정렬이 이루어진 forward index 형태로 분산 저장한다.<br />
-URL resolver가 anchor file을 분석하여 상대 URL(relative URL)을 절대 URL(absoluteURL)로 변환하고, 변환된 URL 정보를 Barrel에 저장되어 있는 forward index의 docID와 조합한다.<br />
- Sorter가 Barrel에 docID 순으로 정렬되어 있는 정보를 키워드 별로 정렬하여 wordID를 할당한다.<br />
- Indexer가 wordID 순으로 정렬된 정보를 이용하여 최종적으로 역 색인(inverted index)을 생성하여 Lexicon에 저장한다.</p><br />
<p>&nbsp;<br />
</p><p><strong>&lt;그림 2&gt; 라파지토리의 자료구조</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_02.gif" alt="" border="0"></p><br />
<p>&nbsp;</p><br />
<p>• <strong>검색</strong><br />
<br />
- 입력 받은 질의어를 분석한다.<br />
- Lexicon을 뒤져서 분석을 통해 추출된 키워드에 해당하는 wordID를 찾는다.<br />
- 발견된 wordID에 해당하는 doclist의 시작 위치를 Barrel을 뒤져서 찾는다.<br />
- doclist를 스캔하여 입력된 search term과 매칭되는 도큐먼트들을 찾는다.<br />
- 탐색된 도큐먼트들에 대해서 페이지 랭크를 계산한다.</p><br />
<p>&nbsp;<br />
</p><p style="font-weight: bold;" class="sub2">구글 검색엔진의 자료구조</p>&nbsp;<br />
<p>구글 검색엔진은 기본적으로 대용량 데이터를 다룬다. 기본적인 정보 외에도 부수적인 정보들을충분히 다루고 있는 만큼 모든 색인 구조를 비롯한 자료구조는 매우 효율적이고 최적화돼 있어야 한다. 머신의 성능은 급격하게발전하고 있지만 디스크 I/O 속도는 크게 변함이 없는 현실에서 자료구조는 훨씬 더 중요한 위치를 차지한다. 다음은 구글검색엔진에서 사용하고 있는 자료구조들이다. 구글 검색엔진의 자료구조를 살펴보면, 구글 검색엔진의 내부 프로세스와 구조를 더자세히 볼 수 있다.</p><br />
<br />
<p>• <strong>리파지토리</strong><br />
<br />
리파지토리는크롤러에 의해 수집된 웹 문서의 full HTML을 zlib를 이용해 압축, 저장한다(zlib은 다른 압축 솔루션에 비해 압축과압축 해제 속도가 뛰어나다). 리파지토리에 저장되는 각 웹 문서들은 docID를 prefix로 사용하여, 기타 정보들을 함께묶은 형태의 자료구조로 표현된다. 웹 문서의 consistency 유지나 크롤러의 에러는 리파지토리의 모든 자료구조를재생성(rebuilding)함으로써 해결한다. &lt;그림 2&gt;는 리파지토리의 자료구조를 나타낸 그림이다.</p><br />
&nbsp;<br />
<p>• <strong>도큐먼트 인덱스(Document Index)</strong><br />
<br />
도큐먼트 인덱스는 각 도큐먼트의 정보들을 저장하며, 기본적으로 docID에 의해 정렬된 fixed width ISAM(Indexsequential access mode)이다. 이것은 도큐먼트에 대한 추가적인 정보로 도큐먼트의 상태 정보, 리파지토리내에서의 해당 도큐먼트에 대한 위치, 도큐먼트 체크섬(checksum), 기타 수치적 정보들을 포인터로 담고 있다. 포인터정보만 사용함으로써 콤팩트한 자료구조의 구성이 가능하며, 검색을 수행하는 동안 디스크 탐색 시간을 줄일 수 있다. 추가로,도큐먼트의 정보 중 URL과 docID의 관계를 저장해 두기 위해 URL을 docID로 변환한 관계를 저장하는 파일이 존재한다.이것은 URL 체크섬을 키(key)로 갖고, docID를 데이터로 갖는 자료구조로 일반적인 btree(binary tree)검색과 유사한 방식에 의해, URL 체크섬을 키로 던져 해당 URL의 docID를 찾아내는데 사용된다. 이 방식은URLresolver가 URL을 docID로 변환하는데 사용된다.</p><br />
<p>&nbsp;<br />
</p><p>• <strong>Lexicon</strong><br />
<br />
Lexicon은 실제 검색을 수행할 때 반드시 필요한 역 색인 구조를 만들기 위한 자료구조이다. 검색엔진의 성능과 처리 가능한 용량이 대부분Lexicon과 역 색인 구조에 기반해 결정되기 때문에 Lexicon의 자료구조는 검색엔진의 전체 구조 중 매우 중요한 요소를차지한다. 검색엔진의 속도 향상을 위한 기초적인 접근 방식은 Lexicon을 메모리에 구동 가능한 크기로 쪼개는 것이다. 초기구글 검색엔진의 경우에는 256MB 메인 메모리에 올라갈 수 있는 크기로 설계됐고, 256MB 안에 1,400만 개의 단어를올릴 수 있었다. 구글의 Lexicon은 추출된 단어들의 리스트와 포인터의 해시(hash) 테이블, 두 가지 요소로 구성된다.</p><br />
&nbsp;<br />
<p>• <strong>Hit Lists</strong><br />
<br />
Hit는 하나의 도큐먼트에서 추출된 하나의 단어에 대한 부가적인 위치 정보, 폰트 정보, 대문자 여부 등의 집합이다. HitList는 forward index와 inverted index에서 모두 사용되며 검색엔진 내의 정보 중 상당 부분을 차지하기때문에 가능한 효율적인 구조를 가져야 한다. 구글 검색엔진은 하나의 hit를 2바이트로 인코딩하는 방식을 취한다.<br />
<br />
Hit는 다시 각 도큐먼트에서 URL, title, anchor text, meta tag로부터 추출된 정보를 저장하는 fancyhit, anchor text로부터 정보를 추출된 정보를 저장하는 anchor hit, 그리고 그 밖의 요소들로부터 추출되는plane hit 등 3개의 hit로 구분된다. &lt;표 1&gt;은 인코딩된 fancy hit과 plane hit,anchor hit의 구조를 나타낸다.<br />
<br />
Anchor hit에 포함된 4비트짜리 해시는 해당 anchor가 출현한 웹문서의 docID에 대한 해시 값을 저장한다. 이것은 anchor file에 저장되어, 랭크 산출에 가중치 요소로 사용된다.최종적으로 hit list들은 Barrel에 forward index를 구성하면서 wordID를 기준으로 저장되고,inverted index에 docID를 기준으로 저장된다.</p><br />
&nbsp;<br />
<p>• <strong>Forward Index</strong><br />
<br />
ForwardIndex는 도큐먼트에 대한 docID를 기준으로 추출된 hit list를 wordID와 함께 붙여서 barrel에 분산해놓은구조이다. Barrel 자체가 wordID의 특정 range에 대해 분산되도록 설계되어 있기 때문에 docID가 중복 저장될가능성이 있다. 하지만 inverted index를 구성할 때 Sorter에 의해 wordID를 중심으로 재구성되어야 하기때문에, 실제로는 이와 같은 방식이 조금 더 효율적일 수 있다. Barrel 내에 forward index가 저장될 때는wordID 24비트와 hit list length에 대한 정보가 8비트 추가된다.</p><br />
&nbsp;<br />
<p>• <strong>Inverted Index</strong><br />
<br />
InvertedIndex는 forward index가 Sorter에 의해 wordID 순으로 정렬된 구조이다. 유효한(valid)wordID는 Lexicon에 저장되고, 각 wordID가 속한 도큐먼트에 대한 docID는 Barrel 내에 역 색인으로서저장된다. Lexicon의 각 wordID는 inverted barrel 내의 docID를 가리키는 포인터를 갖는다.</p>&nbsp;<br />
<p>&lt;그림 3&gt;은 Forward Index, Inverted Index,Lexicon의 구조에 대한 그림이다. Forward Barrel에 저장된 docID의 리스트는 최종적으로 Lexicon과Inverted Barrel에 저장되면서 최종적인 역 색인 구조를 구성하게 된다.</p>&nbsp;<br />
<p><strong>&lt;그림 3&gt; Forward/Bcakward Index와 Lexicon의 자료구조</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_03.gif" alt="" border="0"></p><br />
<p><strong>&lt;표 1&gt; 인코딩된 fancy hit과 plane hit, anchor hit의 구조</strong></p><table bgcolor="#cccccc" border="0" cellpadding="3" cellspacing="1" width="589"><tbody><br />
<tr bgcolor="#f4f4f4"><font size="2"><br />
</font><td height="30" width="107"><font size="2">구분</font></td><font size="2"><br />
</font><td colspan="5"><font size="2">내용</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25" width="107"><font size="2">Plane Hit</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="143"><font size="2">capitalization: 1</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="115"><font size="2">font info: 2</font></td><font size="2"><br />
</font><td colspan="3" bgcolor="#ffffff"><font size="2">position: 12</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25" width="107"><font size="2">Fancy Hit</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" height="16" width="143"><font size="2">capitalization: 1</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" height="16" width="115"><font size="2">font info: 7</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" height="16" width="53"><font size="2">type; 4</font></td><font size="2"><br />
</font><td colspan="2" bgcolor="#ffffff" height="16"><font size="2">position: 8</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25" width="107"><font size="2">Anchor Hit</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="143"><font size="2">capitalization: 1</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="115"><font size="2">font info: 7</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="53"><font size="2">type; 4</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="57"><font size="2">hash: 4</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="71"><font size="2">position: 4</font></td><font size="2"><br />
</font></tr><br />
</tbody></table><br />
<p><br />
<br />
<strong>&lt;표 2&gt; 구글 검색엔진의 퍼포먼스 수치 정보</strong></p><br />
<table bgcolor="#cccccc" border="0" cellpadding="3" cellspacing="1" width="589"><tbody><br />
<tr bgcolor="#f4f4f4"><font size="2"><br />
</font><td colspan="2" height="30"><font size="2"><strong>Storage Statistics</strong></font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Total Size of Fetched Pages</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">147.8GB</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Compressed Repository</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">53.5GB</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Short Inverted Index</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">41GB</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Full Inverted Index</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">37.2GB</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Lexicon</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">293MB</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Temporary Anchor Data</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">6.6GB</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Document Index Incl. Variable Width Data</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">9.7GB</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Links Database</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">3.9GB</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Total without Repository</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">55.2GB</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Total with Repository</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">108.7GB</font></td><font size="2"><br />
</font></tr><br />
<tr bgcolor="#f4f4f4"><font size="2"><br />
</font><td colspan="2" height="30"><font size="2"><strong>Web Page Statistics</strong></font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Number of Web pages fetched</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">24 million</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Number of URLs seen</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">76.5 million</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Number of Email Address</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">1.7 million</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="325"><font size="2">Number of 404's</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="249"><font size="2">1.6 million</font></td><font size="2"><br />
</font></tr><br />
<tr bgcolor="#ffffff"><br />
<td colspan="2"><br />
<table bgcolor="#cccccc" border="0" cellpadding="3" cellspacing="1" width="100%"><tbody><br />
<tr bgcolor="#f4f4f4"><font size="2"><br />
</font><td colspan="5" height="30"><font size="2"><strong>Search Times</strong></font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25"><font size="2"><br />
</font></td><font size="2"><br />
</font><td colspan="2" bgcolor="#fafafa"><font size="2"><strong>Initial Query</strong></font></td><font size="2"><br />
</font><td colspan="2" bgcolor="#fafafa"><font size="2"><strong>Same Query Repeated</strong></font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25"><font size="2">Query</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">CPU time</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">Total time</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">CPU time</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">Total time</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25"><font size="2">al gore</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">0.09</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">2.13</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">0.06</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">0.06</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25"><font size="2">vice president</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">1.77</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">3.84</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">1.66</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">1.8</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25"><font size="2">hard dixks</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">0.25</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">4.86</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">0.2</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">0.24</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25"><font size="2">search engine</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">1.31</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">9.63</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">1.16</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">1.16</font></td><font size="2"><br />
</font></tr><br />
</tbody></table><br />
</td><br />
</tr><br />
</tbody></table><br />
<p>&nbsp;</p><br />
<p>지금까지 구글 검색엔진에 대한 특징과 아키텍처, 자료구조에 대해 살펴보았다. 구글이 등장한지많은 시간이 흘렀지만, 구글의 검색엔진은 여전히 최적화된 혁신적인 구조로 개발자들에게 받아들여지고 있다. 많은 검색엔진들은여전히 구글 검색엔진을 벤치마크 대상으로 이용하고 있고, 구글 검색엔진이 갖고 있는 합리적인 랭킹 모델이나 데이터 처리 모델과자료구조는 많은 검색엔진이 닮고 싶어하는 요소들이다.</p>&nbsp;<br />
<h5 class="sub1"><font size="2"><strong>현대적 랭킹 모델, 페이지 랭크 알고리즘</strong></font></h5><p>구글은 처음 등장할 때 대량의 웹 페이지 데이터들에 대한 새로운 개념의 랭킹 모델 적용으로가장 주목받았다. 페이지 랭크라 불리는 이 랭킹 모델(ranking model)은 각 웹 페이지들의 중요성(importance)을 기반으로 계산(scoring)된, 사용자 입장에서 상당히 정확해 보이는 랭킹을 제공한다.</p>&nbsp;<br />
<p>세르게이 브린(Sergey Brin)이 제안한 페이지 랭크 알고리즘은 웹 페이지의 중요성에기반을 둔 일종의 보팅 알고리즘(voting algorithm)으로, 사용자 중심의 주관적 영역에 놓여있던 ‘중요성’을상대적이고 기계적인 관점에서 정량화가 가능한 객관적 영역으로 변환시킨다. 이것은 기존의 야후나 기타 검색엔진들이 제공했던 사람이직접 웹 페이지의 중요도를 등록하여 결과로 제공하는 것이 웹 페이지의 랭크라고 믿어오던 사람들의 생각을 완전히 바꿨다. 구글은모든 페이지들의 중요도를 인터넷에서 웹 페이지를 생산해내는 사람들과 사용자들이 웹 페이지에 접근하는 행태를 분석하여 자동으로랭킹이 계산되는 구조를 만들어 냈다. 인력으로 랭킹을 처리하는 데에는 한계가 있었기 때문에, 비교할 수 없을 정도로 훨씬 더많은 데이터들에 대해 유효해 보이고 자동화된 랭킹을 제공한 구글은 단숨에 검색 사용자들의 이목을 끌 수밖에 없었다.</p>&nbsp;<br />
<p><strong>&lt;그림 4&gt; 역 링크: 링크 A와 링크 B는 페이지 C에 대한 역 링크이다.</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_04.gif" alt="" border="0"></p><br />
<p>&nbsp;</p><br />
<p class="sub2"><strong>랭크를 갖는 링크: 링크를 통한 랭킹의 전파</strong></p>&nbsp;<br />
<p>웹 링크의 중요성에 대한 접근은 구글 이전에도 있었는데 대부분 웹 공간 상에서 링크는 논문에기재되는 학술적 레퍼런스와 유사한 개념으로 보아, 레퍼런스 구조를 분석하고 중요성을 계산하는 테크닉들이 대부분이었다. 예를들어, 학술적으로 자주 인용되는 논문은 그렇지 않은 논문에 비해 중요한 논문일 가능성이 크다고 보는 것이다. 페이지 랭크의기본적인 아이디어는 웹 상의 이러한 레퍼런스 구조를 웹 공간의 링크 구조로 더욱 포괄적으로 확장하는 데 있다.</p>&nbsp;<br />
<p>웹 페이지는 그 페이지에서 밖으로 나가는 순 링크(forward link, outedge)와외부에서 그 페이지를 가르키는 역 링크(back link, inedge)를 포함한다. 기본적으로 페이지 랭크에서 측정되는 웹도큐먼트의 중요성은 웹 도큐먼트의 컨텐트와 상관없이 그 웹 도큐먼트가 갖고 있는 링크 구조를 분석함으로써 측정된다.</p>&nbsp;<br />
<p>페이지 랭크에서 중요성에 대해 가장 주요한 요소로 간주된 것은 링크가 많이 된 페이지가 그렇지못한 페이지보다 대부분 더 중요하다는 가정이었다. 역 링크라 불리는, 외부 페이지로부터의 레퍼런스 횟수는 중요성을 계산하는데기본적인 요소로 사용되었다. &lt;그림 4&gt;는 역 링크의 일반적인 형태를 나타낸다.</p>&nbsp;<br />
<p>하지만 역 링크의 개수를 세는 것만으로 중요성을 매기는 것은 유효하지 않을 수도 있다. 어떤웹 페이지가 달랑 야후 하나에 링크되어 있다면 그 도큐먼트는 단 1개의 역 링크를 갖고 있지만, 그 링크는 중요하지 않은페이지로부터의 역 링크 몇 개보다 훨씬 더 중요한 링크라고 간주될 수 있다. 페이지 랭크는 링크를 통해 랭킹을 전파하는구조이다. 모든 역 링크에는 랭크 값이 있고, 랭크 값이 높은 역 링크의 레퍼런스를 많이 갖는 웹 도큐먼트일수록 웹 도큐먼트의랭크가 올라간다.</p><br />
<br />
<strong>페이지 랭크의 개념</strong><br />
<br />
<p>페이지 랭크를 단순하게 모델링한다면 다음과 같은 간단한 수식으로 표현할 수 있다.</p>&nbsp;<br />
<p>어떤 웹 페이지를 u라고 하고, 웹 페이지 u가 레퍼런스하고 있는 페이지의 집합을 Fu, 웹페이지 u를 역 링크하고 있는 페이지의 집합을 Bu로 표현한다. Nu는 웹 페이지 u로부터 나가는 순 링크의 개수(| Fu|)이다. c는 웹 페이지의 랭크 총합을 일정 레벨로 맞추기 위한 노멀라이징 팩터(normalizing factor)이다.&lt;그림 5&gt;는 페이지 랭크가 계산되는 방식을 간단하게 보여준다.</p>&nbsp;<br />
<p>그러나 웹 공간 상의 복잡한 링크 구조는 이와 같은 수식으로 해결하기 어려운 그래프를구성하기도 하는데, 랭크 싱크(rank sink)와 댕글링 링크(dangling link)가 그것이다 ⑵. 페이지 랭크에서는이런 문제를 해결하기 위해 사용자 정의 파라미터를 하나 더 둔다. 다음은 사용자 정의 파라미터 E가 추가된 페이지 랭크 모델을표현한다.</p>&nbsp;<br />
<p>추가 파라미터 E(u)는 웹 페이지 u로부터 또 다른 특정 페이지로 이탈할 확률 분포에 대한모델이다. 앞서 검색엔진을 설명하면서 잠시 거론되었던 페이지 랭크의 사용자 행동 패턴에 대한 모델링(랜덤 서퍼 모델)이 바로파라미터 E이다. 즉, 파라미터 E는 랜덤 서퍼가 특정 확률 주기에 의해 다른 페이지로 이탈하는 것을 의미하며 이것은 댕글링링크를 이탈하는 행동의 모델링으로 볼 수 있다. 구글 검색엔진은 일반적으로 모든 페이지에 동일한 확률 주기의 E 값을 셋팅하여,모든 서퍼들이 주기적으로 링크의 그래프를 이탈한다고 보지만 E 값을 특정 페이지로 지정함으로써, 개인화된 페이지 랭크 모델을만들 수도 있다.</p>&nbsp;<br />
<p>만약 2개의 페이지 랭크 모델을 만들어서 하나는 E를 일반 포탈 사이트의 홈페이지로, 나머지하나는 E를 컴퓨터 사이언스 관련 커뮤니티의 홈페이지로 셋팅한다면, 일반 포탈 쪽 랭크보다 컴퓨터 사이언스 관련 커뮤니티 쪽의랭크들이 더 큰 값을 가지게 될 것이다.</p><br />
<br />
<strong>페이지 랭크의 구현</strong><br />
<p><br />
</p><p>페이지 랭크는 일반적인 재귀 연산(recursive operation)의 형태이지만, 효율성을위해 컴퓨터 상에서는 벡터의 형태로 변환되어 계산된다. 이에 관련된 정보를 얻고 싶다면 Taher H. Haveliwala가 쓴『Efficient Computation of PageRank(Stanford Technical Report, 1999)』를참조하기 바란다. 페이지 랭크가 컴퓨터 상에서 처리되는 방식은 다음과 같다.</p><br />
<code>R0 ← S loop : Ri + 1 ← ARi d ← ||Ri||1 - ||Ri + 1 ||1 Ri + 1 ← Ri + 1 + dE δ ← ||Ri + 1 - Ri||1 while δ ＞ ∈</code><br />
<br />
<p>• S는 한 웹 페이지의 초기 벡터 값이다.<br />
</p><p>• Ri는 i번째 페이지 랭크 벡터 값을 나타낸다.<br />
• ||R||1은 벡터 R의 노름(norm) 값이다.<br />
• d는 댐핑 팩터(damping factor)이다.<br />
• A는 한 웹 페이지 u에서 다른 웹 페이지 v로 연결되는 포워드 링크의 개수의 역수이다. 만약 서로 연관된 링크가 없다면 0이 된다.</p><br />
<p><strong>&lt;그림 5&gt; 페이지 랭크의<span id="callbacknestchauchau0tistorycom578616" style="float: right; width: 1px; height: 1px;"></span> 계산</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_05.gif" alt="" border="0"></p>&nbsp;<br />
<p>이와 같은 연산은 수렴(convergence)이 이루어질 때까지 반복적으로 이루어진다. 구글 검색엔진 내부에서는 방대한 웹 페이지들의 페이지 랭크 계산을 위해 다음과 같은 방식으로 프로세스를 진행한다.</p>&nbsp;<br />
<p class="sourcebox">① docID를 이용하여 링크 구조를 정렬한다.<br />
② 링크 데이터베이스에서 댕글링 링크를 제거한다.<br />
③ 랭크 값을 초기화한다.<br />
④ 각 페이지의 가중치를 저장하기 위한 메모리를 할당한다.<br />
⑤ 한 단계의 계산이 완료되면 디스크에 가중치를 저장하고, 다음 단계의 계산을 메모리 상에서 진행한다.<br />
⑥ Stet 5를 수렴할 때까지 반복된다.</p><br />
<br />
<strong>페이지 랭크의 의미</strong><br />
<p><br />
</p><p>페이지 랭크는 본질적으로, 웹 링크의 그래프 상에서의 랜덤 서퍼가 갖는 행동 패턴을 제한된분포로 결정짓는 작업이다. 그래프 상의 한 노드의 중요도는 충분한 시간이 흐른 후에 랜덤 서퍼가 그 노드 위에 있을 확률이다.확률이 높다면 웹 상의 서퍼들이 접근할 가능성은 높아진다. 이것은 웹 페이지의 컨텐츠와 상관없이 웹 상에 존재하는 가중치가부여된 링크 구조에 의한 중요성을 산출한다는 의미이다. 이런 특징은 대부분 사용자들의 웹 페이지 접근 의도에 대한 일반적인케이스(common case) 처리가 가능토록 한다.</p>&nbsp;<br />
<p>예를 들어 꽃이라는 키워드를 쳤을 때, 일반적인 케이스는 꽃에 대한 설명이 담긴 페이지들이아니라 꽃 구입이나 배달과 관련된 페이지들이다. 일반적으로 사람들이 특정 질의어를 입력했을 때 특정 페이지가 일반적인 케이스라는정보는 HTML 자체에는 담겨져 있지 않기 때문에, 링크 구조를 분석하는 페이지 랭크는 일반적인 케이스 처리에 매우 효과적이다.또한 페이지 랭크는 사용자에게 자신이 찾고 있는 링크가 중요도 측면에서 어느 정도의 위치를 차지하고 있는지에 대한인디케이터(indicator)가 될 수도 있다.</p>&nbsp;<br />
<p>참고로, 페이지 랭크의 요소들은 지금도 계속해서 튜닝되고 있다. 예를 들면 웹 페이지의 컨텐츠가 얼마나 자주 갱신되는가에 대한 빈도수(frequency) 등이 새롭게 추가되는 요소들 중 하나이다.</p><br />
<br />
<strong>대용량 파일의 분산 처리를 위한 구글 파일 시스템</strong><br />
<p><br />
</p><p>검색엔진의 성능이 검색엔진의 자료구조와 아키텍처에 밀접한 관계가 있는 것은 사실이지만, 어느수준의 성능 이상을 요구하는 경우에는 반드시 최적화된 하부 구조가 필요하다. 앞서 살펴보았던 구글 검색엔진은 대용량의 웹데이터를 다루고, 그에 따른 대용량 데이터와 색인 구조들을 다루고 있다. 대용량 처리를 위해서는 비용 문제를 간과하기 힘들기때문에, 구글은 저 사양의 머신들을 대량 배치하여 분산 처리하는 것으로 대용량 데이터와 대용량 트래픽에 대응하고 있다. 이를가능하게 한 데에는 효율적으로 대용량 파일의 분산 처리와 성능을 위해 자체적으로 개발된 구글 파일 시스템의 역할이 크다.</p>&nbsp;<br />
<p><strong>&lt;그림 6&gt; 구글 파일시스템 아키텍처</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_06.gif" alt="" border="0"></p><p class="sub2"> </p><br />
<span style="font-weight: bold;">구글 파일 시스템의 특징</span><br />
<br />
<p>대용량 분산 파일 시스템이 가져야 하는 요소에는 확장성(scal ability),성능(performance), 신뢰성(reliability), 가용성(avail ability) 등이 있다. 구글 파일 시스템역시 이런 특징적 요소들을 모두 포함하고 있다. 구글 파일 시스템은 리눅스 파일 시스템을 기반으로 개발되었으며, 추가적으로다음과 같은 접근 특성들에 대한 처리 목표를 취하고 있다.</p>&nbsp;<br />
<p>• <strong>분산 처리 서버들의 오류(failure)에 대한 대응</strong><br />
-애플리케이션 버그, 디스크 오류, 메모리 오류, 커넥션 오류, 네트워킹 오류, 파워 서플라이 오류 등에 대해서 모니터링, 오류허용(fault-tolerance), 자동 복구(automatic recovery) 등이 시스템에 포함</p>&nbsp;<br />
<p>• <strong>기존의 파일에 비해 훨씬 더 큰 대용량 파일의 처리</strong><br />
- Multi-GB 파일들이 사용되기 때문에 I/O 오퍼레이션과 블럭 크기(block size)에 대한 파라미터 조정을 통해 효율적으로 관리</p>&nbsp;<br />
<p>• <strong>특징적인 읽기/쓰기 패턴에 대한 최적화</strong><br />
<br />
- Large streaming reads<br />
- Small random reads<br />
- Large, sequential writes<br />
- Small writes</p>&nbsp;<br />
<p>• <strong>Well-defined semantics를 갖는 구조</strong><br />
- 동일 파일에 읽기/쓰기를 하려는 다수의 클라이언트의 오퍼레이션을 처리하기 위해 동기화(synchronization) 처리</p>&nbsp;<br />
<p>• <strong>고속의 대역폭(bandwidth) 유지</strong><br />
- 읽기/쓰기에 대해 엄격한 응답 시간(response time) 유지</p><br />
<p>&nbsp;</p><p style="font-weight: bold;">구글 파일 시스템 아키텍처</p>&nbsp;<br />
<p>구글 파일 시스템은 하나의 마스터 서버(master server)와 다수의 청크서버(chunk server), 그리고 다수의 클라이언트(client)로 구성되어 있다(이러한 서버들은 모두 표준화된 형태인데,구글에서는 표준화된 서버를 pizza server box라고 부른다). &lt;그림 6&gt;은 이러한 구글 파일 시스템의아키텍처에 대한 그림이다.</p>&nbsp;<br />
<p>마스터 서버는 청크 서버에 대한 메타 데이터들을 관리한다. 청크 서버는 정해진 크기의 청크들을 저장하고, 클라이언트는 마스터 서버의 메타 데이터들을 확인하고, 청크 서버에 접근하여 필요한 데이터를 읽고 쓴다.</p>&nbsp;<br />
<p>각 파일들은 정해진 크기의 청크(chunk)로 나뉜다. 각 청크는 생성 시점에 마스터 서버에의해 글로벌하게 유니크한(globally uni que) 청크 핸들(chunk handle)을 할당받는다. 청크 핸들과 바이트레인지(byte range)에 의해 결정된 청크 데이터들은 청크 서버의 로컬 디스크에 저장되는데, 저장되는 청크 데이터는기본적으로 3개의 복제본을 가지게 된다. 하나의 청크 서버에서 청크들을 로컬 파일로 존재하므로 별도의 캐시(cache) 없이리눅스의 버퍼 캐시 효과를 그대로 사용한다. 구글 파일 시스템의 청크 크기는 64MB로 일반적인 리눅스 파일 시스템의 블럭크기보다 크다. 이처럼 큰 청크 크기를 사용함으로써, 클라이언트가 동일한 청크에 접근할 때 불필요하게 마스터 서버와의 통신을줄일 수 있고, 클라이언트의 네트워크 오버헤드와 마스터 서버에 저장되는 메타 데이터의 크기도 줄일 수 있다.</p>&nbsp;<br />
<p>마스터 서버는 모든 파일 시스템의 네임 스페이스(name space), 액세스 컨트롤정보(access control information), 파일-청크 간의 맵핑 정보 등의 메타 데이터를 관리한다. 마스터 서버는이 정보를 이용하여 청크 서버들과 Heart Beat 메시지에 의한 커뮤니케이션을 통해 청크에 대한 가비지 컬렉션(garbagecollection), 청크 서버 간의 마이그레이션(migration)을 수행한다. 마스터 서버의 메타 데이터들은 모두 메모리상에 저장되기 때문에, 마스터 서버의 오퍼레이션이 매우 빠르다. 이는 주기적으로 상태를 스캐닝하여 청크 서버의 오류 상황이발생했을 때 복제본을 재배치한다거나 청크 서버들의 디스크 사용 상태에 따라 청크 마이그레이션을 수행하는데 매우 효율적인 방식이다.</p>&nbsp;<br />
<p>클라이언트는 구글 파일 시스템 API에 의해 구현된 애플리케이션을 담고 있으며, 마스터 서버및 청크 서버와 커뮤니케이션하면서 애플리케이션에 필요한 데이터를 읽고 쓴다. 클라이언트는 마스터 서버와의 메타 데이터와오퍼레이션 내용과 커뮤니케이션하고, 모든 실제 데이터와의 커뮤니케이션을 청크 서버와 직접 하게 된다.</p><br />
<span style="font-weight: bold;">구글 파일 시스템의 일관성 모델(Consistency Model)</span><br />
<br />
<p>클라이언트에 의해 파일이 청크 서버에 저장될 때는 오류 발생에 대비해서 3개의 복제본으로저장된다. 만약, 데이터가 변경/추가된다면 청크 서버 내의 모든 복제본에 대해 동기화가 이루어져야 한다. 파일 쓰기가 이루어졌을때 다음과 같은 순서로 복제본의 동기화가 이루어진다.</p>&nbsp;<br />
<p>① 클라이언트가 마스터 서버에게 현재 사용하고 있는 청크와 또 다른 복제본들의 위치에 대한 정보를 요청한다.<br />
② 마스터 서버가 클라이언트에게 1차 복제본(primary replica)의 ID와 2차 복제본(secondary replica)의 위치 정보를 보내준다.<br />
③ 클라이언트가 모든 복제본에 대해 데이터를 푸시한다. 각 청크 서버는 넘어온 데이터들을 저장한다.<br />
④ 모든 복제본들이 데이터를 받은 것에 대한 완료 여부(acknowledge)가 확인되면 클라이언트는 1차 복제본에 쓰기 요청을 한다.<br />
⑤ 1차 복제본은 모든 2차 복제본에 쓰기 요청을 전달한다.<br />
⑥ 2차 복제본의 오퍼레이션이 완료되면 1차 복제본에 완료 시그널을 보낸다.<br />
⑦ 모든 2차 복제본에서 완료 시그널이 오면 1차 복제본은 쓰기 요청이 완료되었음을 클라이언트에게 회신한다.</p>&nbsp;<br />
<p>&lt;그림 7&gt;은 이와 같은 동작의 흐름을 나타낸 그림이다. 이러한 동작은 기본적으로컨트롤 플로우(control flow)와 데이터 플로우(data flow)가 구분되어 네트워크를 효율적으로 사용하는 방식으로구성되어 있다.</p><br />
&nbsp;<br />
<p style="font-weight: bold;" class="sub2">구글 파일 시스템의 마스터 서버 오퍼레이션</p>&nbsp;<br />
<p>마스터 서버는 구글 파일 시스템 내의 모든 네임 스페이스와 청크들의 복제본에 대한 관리를 처리한다. 마스터 서버에서 진행되는 오퍼레이션들을 간단하게 살펴보면 다음과 같다.</p>&nbsp;<br />
<br />
<p>• <strong>네임 공간에 대한 관리 및 락킹(locking)</strong><br />
- 네임 공간은 풀 패스 명(full path name)의 맵핑 테이블에 의해 관리된다.<br />
- 읽기/쓰기가 발생할 때 lock 처리를 해 conflict가 발생하는 상황을 방지한다.</p>&nbsp;<br />
<p>• <strong>복제본 배치</strong><br />
- 청크의 복제본을 데이터의 신뢰성과 가용성을 최대화하는 방향으로 배치한다.<br />
- 청크의 복제본을 네트워크 사용성(utilization)을 최대화하는 방향으로 배치한다.</p>&nbsp;<br />
<p><strong>&lt;그림 7&gt; Write Control and Data Flow</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_07.gif" alt="" border="0"></p><br />
<p>&nbsp;</p><br />
<p>• <strong>청크와 복제본에 대한 관리</strong><br />
- 새로운 청크를 생성할 때 청크 서버의 디스크 사용 수준이나 최근 영역의 분포 등을 확인하여 생성한다.<br />
- 오류가 발생하여 복제본 간의 내용이 맞지 않다면(corrupted 되었다면) 정상적인 복제본을 재배포한다.<br />
- 청크 서버의 디스크 상태와 부하(load) 상태를 확인하여 좀 더 나은 상태의 청크 서버로 복제본을 재분산(rebalancing)한다.</p><br />
<p><strong>&lt;그림 8&gt; 구글플렉스의 논리적 구조</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_08.gif" alt="" border="0"></p>&nbsp;<br />
<p><strong>&lt;그림 9&gt; 구글의 주요 기술 요소들을 나타내는 다이어그램</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_09.gif" alt="" border="0"></p>&nbsp;<br />
<br />
<p>• <strong>가비지 컬렉션</strong><br />
</p><p><br />
</p><p>- 파일 삭제가 일어나면 마스터 서버에 삭제 시간을 비롯한 정보가 로그로 남는다. 실제 청크 서버에서는 파일 삭제가 바로 이루어지지 않고, 히든 타입으로 리네임(rename) 처리가 된다.<br />
- 마스터 서버에서는 청크 네임 공간 스캔을 통해 3일 이상된 히든 타입의 파일들을 삭제한다.<br />
- 파일이 네임 공간에서 삭제되면 마스터 서버의 메타 데이터가 삭제된다.</p><br />
<br />
<span style="font-weight: bold;">구글 파일 시스템의 오류 복구</span><br />
<p><br />
</p><p>마스터 서버와 청크 서버는 각각 메모리에 올라갈 수 있는 수준의 메타 데이터를 가지고 있다. 서버에 문제가 생겨서 재시작되는 경우 빠른 시간 안에 재동작을 할 수 있는 상황으로 복구될 수 있다.</p>&nbsp;<br />
<p>각 청크는 여러 대의 서로 다른 랙(rack)에 위치한 청크 서버에 복제본을 기본적으로 3개배치한다. 각 청크들은 체크섬 버전 정보를 가지고 관리되며 이에 의해 각 복제본 간의 동기화 작업이 이루어진다. 데이터를 읽기위해 접근한 청크 서버가 문제가 있다면 또 다른 청크 서버에 담겨있는 복제본에 의해 데이터 읽기 작업은 무사히 수행될 수 있다.</p>&nbsp;<br />
<p>마스터 서버 역시 마스터 서버에서 일어나는 모든 오퍼레이션의 로그와 상태(state), 체크포인트들은 여러 대의 머신으로 복제한다(Shadow master라고 불린다). 마스터 서버의 디스크에 오류가 있거나, 외부모니터링 툴에 의해 이상이 발견되는 경우 복제된 마스터 서버에 의해 파일 시스템 오퍼레이션은 정상 수행되도록 조정된다.</p>&nbsp;<br />
<p>구글 파일 시스템은 구글 검색엔진과 서비스에 적합하도록 심플하고 효과적인 파일 시스템으로설계되어 있다. 구글에서 일어나는 대부분의 데이터 액세스는 추가(append) 중심의 쓰기 작업과 빈번한 읽기 중심의작업들이고, 저가의 머신에 의한 클러스터(cluster) 구성이기 때문에 오류 처리 역시 중요한 이슈가 된다.</p>&nbsp;<br />
<p>구글의 파일 시스템은 시스템 내의 중심적인 읽기/쓰기 패턴을 명확하게 정의하고 오류 처리를중심으로 견고하고 효과적으로 설계되어 있다. 검색엔진에서 하부 저장 구조라는 것은 검색엔진 자체의 성능을 뛰어넘도록 하고검색엔진 자체의 안정성을 확장하는 요소로, 구글이 갖고 있는 효율적인 하부 저장 구조는 구글의 기반을 다진 핵심 기술 요소 중매우 중요한 요소로 볼 수 있다.</p><br />
&nbsp;<br />
<p class="sub1"><strong>모든 기술을 아우르는 거대한 프레임워크</strong></p>&nbsp;<br />
<p>지금까지 구글이 갖고 있는 기술들 중에 핵심 기술(core technology)이라고 불릴 수있는 요소들에 대해 간략하게 살펴보았다. 이 기술들은 현재의 구글을 있게 만든 구글만의 독자적인 기술임에 틀림없다. 하지만구글의 기술은 이것이 전부가 아니다. 구글은 모든 애플리케이션과 기능들을 웹 중심(web-centric)으로 흡수하기 위한작업을 하고 있다. 그 기반에는 구글의 기술들을 모두 아우르는 거대한 프레임워크가 존재한다.</p><br />
&nbsp;<br />
<p class="sub2"><strong>구글플렉스</strong></p>&nbsp;<br />
<p>구글플렉스(Googleplex, 구글 본사 건물의 별칭이기도 하다)는 구글의 프레임워크에서매우 중요한 위치를 차지하는 요소이다. 구글플렉스는 동일한 개체들이 모여 거대한 시스템을 구성하는 논리적 구조이다. 하나의서버는 다른 서버들과 기능과 속성들을 공유한다. 이런 서버들이 모여서 클러스터를 구성한다. 클러스터들을 모여서 데이터센터(data center)를 구성한다. 또 다시 데이터 센터들은 다른 애플리케이션 서버들과 모여서 구글의 온라인 시스템을구성한다.</p>&nbsp;<br />
<p>&lt;그림 8&gt;은 구글플렉스의 타이트하고 규칙적으로 조직화된 모습을 보여준다. 그림을살펴보면 구글플렉스 내의 모든 레벨에 걸쳐 동일한 패턴이 반복되고 있음을 알 수 있다. 다시 말해 구글플렉스의 모든 구성요소들은 동형(homogeneous)의 컴퓨팅 시스템이다. 구글 버전의 리눅스 위에서 돌아가는 구글 애플리케이션들의 집합은슈퍼컴퓨터를 이용해 애플리케이션을 돌리는 것과 유사하다.</p>&nbsp;<br />
<p>동형의 컴퓨팅 시스템은 몇 개의 장점을 갖고 있다. 모든 데이터 센터를 구성하고 있는 서버들의구성 역시 동일한 구성이기 때문에, 시스템 규모의 확장시 단순히 서버 랙을 꽂고(plugged-in) 케이블을 연결하는작업만으로도 셋팅과 설정(configuration)을 가능하게 한다. 앞서 살펴보았던 구글 파일 시스템 내에서 마스터가 청크서버에 청크들을 복제하는 작업 역시 동형의 컴퓨팅 시스템에 대한 접근이므로 매우 친숙하고 쉬운 오퍼레이션으로 구현될 수 있다.즉, 구글플렉스는 구글 파일 시스템의 기능과 목적들을 효율적이고 효과적으로 지원할 수 있는 논리적 구조이다.</p><br />
&nbsp;<br />
<p><strong>구글 컴퓨팅 프레임워크</strong></p>&nbsp;<br />
<p>개발자들이 흔히 말하는 ‘구글스럽다’라는 말의 의미는 무엇인가. 검색 영역의 개발자와 일반영역의 개발자가 바라보는 관점이 약간의 차이는 있을 수 있겠지만, 대부분의 경우 구글을 구글스럽게 만드는 것은 검색 기술처럼특화된 기술 자체가 아니라 일반적이고 연구 개발적인 관점에서 접근하는 소프트웨어 공학적이면서 하드웨어 공학적인 솔루션들이일으키는 시너지이다.</p>&nbsp;<br />
<p>&lt;그림 9&gt;는 구글 프레임워크의 전체적인 모습을 나타낸 다이어그램이다. 이 그림을 보면 구글의 프레임워크에 포함되어 있는 중요한 기술들에 대해 알 수 있다.</p>&nbsp;<br />
<p>• <strong>대용량 파일 및 function 가속을 위해 수정된 리눅스</strong><br />
- 기능에 적합하게 튜닝된 리눅스를 사용한다.</p>&nbsp;<br />
<p>• <strong>기능 추가 및 규모 확대에 플러그인 방식에 의해 별도로 손이 가지 않을 정도로 표준화된 분산 구조</strong><br />
- 구글플렉스는 자기 유사 구조를 가지며, 서버의 추가와 오류에 대한 대응이 쉽다.</p>&nbsp;<br />
<p>• <strong>스케일 레벨(scale level)에 관계없이 유사한 기술 구조</strong><br />
- 동형(homogeneous) 구조에 의해 모든 요소들이 구성된다.</p>&nbsp;<br />
<p>• <strong>프로그래밍 언어에 관계없이 기능 구현이 가능한 웹 기반 아키텍처</strong><br />
- 프레임워크의 인터페이스로 WSDL, XML, HTML, POP3, SMTP 등과 같은 플랫폼 독립(platform-independent)적인 프로토콜을 제공한다.</p><br />
<p>&nbsp;<br />
</p><p><strong>&lt;그림 10&gt; Google's fuction: Hardware and Software Innovations</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_10.gif" alt="" border="0"></p><br />
<p>&nbsp;</p><br />
<p><strong>&lt;그림 11&gt; 구글 검색과 LostGoocle을 이용한 검색의 비교</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_11.gif" alt="" border="0"></p><br />
<p>&nbsp;</p><br />
<p>구글의 프레임워크는 구글 파일 시스템에 의해 구성된 데이터 센터와 분석적 방법으로 광고를집행하는 구글 광고 시스템(Ad System), 각종 서비스 시스템(gmail, News 등), 검색엔진 등을 모두 포함한다.구글플렉스의 외부와 내부에는 새로운 서비스 시스템과 애플리케이션들이 추가될 수 있고, 기본적인 인터페이스들을 통해 구글프레임워크로의 접근과 구글 프레임워크의 기능을 사용할 수 있는 확장적이고 오픈된 구조이다(구글의 피카사(Picasa)나 구글어스(Earth)는 로컬 머신에서 수행되는 애플리케이션을 구글 프레임워크로 포괄시키는 좋은 예이다).</p>&nbsp;<br />
<p>조금 다른 관점에서 본다면, 구글 프레임워크는 소프트웨어 공학과 하드웨어 공학의 접점에 놓여있다. 소프트웨어적인 관점에서 성능을 확보하면서 동시에 하드웨어 공학적인 관점에서 비용 절감을 위한 기술들을 모두 포함한다.이는 비용 절감, 저가형 하드웨어, 스마트한 소프트웨어에 대해 집중하는 구글 문화의 주요 부분이다.</p>&nbsp;<br />
<p>구글 프레임워크는 구글을 여타 다른 경쟁업체와 차이를 갖도록 하는 명확한 요소이다.구글플렉스는 구글 파일 시스템과 구글이 지향하는 성능과 비용절감의 측면에서 매우 효율적인 구조이다. 서버 랙이나 데이터 센터가오류를 일으키더라도 데이터의 손실이나 구글플렉스 전체의 다운은 방지된다. 또한, 동형 시스템의 사용으로 인해 머신의 설치과정이나 설정(configuration)의 표준화와 자동화를 가능케 했다. 이는 타 업체가 소프트웨어 중심의 튜닝이나 하드웨어의업그레이드에 의존해 성능과 안정성을 유지하는 모습과는 상당한 차이를 보인다.</p>&nbsp;<br />
<p>구글의 프레임워크는 또한 구글 내의 개발자는 물론, 일반적인 개발자들에게 아주 좋은 장난감꾸러미(toy box)이다. 구글 프레임워크의 인터페이스를 통해 언제 어디서나 웹과 연결된 환경이라면 구글의 강력한 기능을그대로 활용할 수 있는 것이다. 이러한 확장적이고 오픈되어 있는 프레임워크 구조는 많은 개발자들의 호응을 얻고 있다.</p><br />
&nbsp;<br />
<p style="font-weight: bold;" class="sub1"><font size="4">구글 APIs</font></p>&nbsp;<br />
<p>구글은 개발자들이 쉽게 구글 프레임워크에 접근할 수 있는 API set을 제공한다. 구글이갖고 있는 기술에 쉽게 접근하여 방대한 데이터와 강력한 기능들을 사용할 수 있는 구글 API는 개발자들에게 매력적인 요소일수밖에 없다. 앞서 1부에서 소개한 것처럼 구글에서는 다양한 API들을 제공하는데, 여기서는 가장 대표적으로 사용되고 있는 구글웹 검색 API에 대해 살펴보겠다.</p>&nbsp;<br />
<p style="font-weight: bold;" class="sub1">구글 웹 검색 APIs</p>&nbsp;<br />
<p>구글 웹 검색 API는 SOAP과 WSDL 표준을 기반으로 구글과 통신할 수 있는 방식을제공한다. 개발자는 어떤 프로그래밍 언어를 사용하든 상관없이 구글과의 프로토콜만 맞춰줌으로써 구글의 기능을 그대로 사용할 수있다. 구글 웹 검색 APIs 페이지(http://www.google. com/apis/)에는 다음과 같은 프로그래밍아이디어들이 기재되어 있다.</p>&nbsp;<br />
<p class="sourcebox">- 주제에 맞는 새로운 정보에 대한 자동 모니터링<br />
- 시간의 흐름에 따른 마켓 분석과 트렌드 분석<br />
- 온라인 게임의 개발 - 새로운 검색 UI의 개발<br />
- 구글의 스펠 체크 기능을 애플리케이션에 추가</p>&nbsp;<br />
<p><strong>&lt;표 3&gt; 구글 웹 검색 APls를 통한 검색 요청에 사용되는 기본적인 파라미터</strong></p><br />
<table style="width: 650px; height: 271px;" bgcolor="#cccccc" border="0" cellpadding="3" cellspacing="1" width="650"><tbody><br />
<tr><font size="2"><br />
</font><td bgcolor="#f4f4f4" height="30"><font size="2"><strong>파라미터 명</strong></font></td><font size="2"><br />
</font><td bgcolor="#f4f4f4"><font size="2"><strong>설명</strong></font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25"><font size="2">key</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">구글 인증키. APls를 다운받은 후 구글로부터 메일로 인증 키를 받아야 한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25"><font size="2">q</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">질의어</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25"><font size="2">start</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">검색 결과 중 불러올 index 번호. 0부터 시작</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25"><font size="2">maxResults</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">한 페이지에 최대로 불러올 검색 결과의 건 수</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25"><font size="2">filter</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">검색 결과 중 특정 결과들을 필터하기 위한 조건</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25"><font size="2">restricts</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">구글 웹 색인 중 서브 셋을 검색하기 위한 조건</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25"><font size="2">safeSearch</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">성인 필터링을 위한 Boolean 파라미터</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25"><font size="2">lr</font></td><font size="2"><br />
</font><td bgcolor="#ffffff"><font size="2">언어 제한. 특정 나랏말로 된 문서만을 검색하기 위한 조건</font></td><font size="2"><br />
</font></tr></tbody><br />
</table><br />
<p>&nbsp;<br />
</p><p>구글 웹 검색 APIs는 SOAP을 사용하는 웹 서비스 모델과 만나면 굉장한 효과를 발휘할 수있다. LostGoogle(http://lostgoggles.com) 은 구글 API를 이용하여 웹 검색 결과에 해당 페이지의스크린샷을 썸네일로 제공한다. 만약 LostGoogle을 이용하여 아마존닷컴(http:// www.amazon.com)의 내용을검색하고자 하면 아마존닷컴에서 웹 서비스로 제공하고 있는 요소들과 합쳐져 도서에 관련된 훨씬 더 풍부한 정보 도서의 형태,가격, 인기도 등을 볼 수 있다.</p>&nbsp;<br />
<p><br />
</p><p style="font-weight: bold;">구글 웹 검색 APIs를 통한 검색 요청</p>&nbsp;<br />
<p>구글 웹 검색 APIs를 통해 구글로 검색 요청을 보내기 위해 사용하는 기본적인 파라미터는 &lt;표 3&gt;과 같다. 질의어 파라미터에 해당되는 <q>는&lt;표 4&gt;와 같은 형식으로 기술할 수 있다. 부수적인 qualifier들을 사용함으로써 검색 결과를 특정 조건에 맞게필터링할 수 있다. 파라미터들을 이용하여 SOAP을 구성한다면 &lt;화면 2&gt;와 같은 형식으로 구글에 리퀘스트를 날리게될 것이다.</q></p><br />
<p><q><strong>&lt;화면 2&gt; SOAP으로 구성된 구글 검색 요청</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_12.gif" alt="" border="0"></q></p><br />
<p><q><strong>&lt;화면 3&gt; SOAP으로 구성된 구글 검색 결과 포맷</strong><br />
<br />
<img src="http://www.dbguide.net/images/know/tech/051026_go_13.gif" alt="" border="0"></q></p><br />
<p><q><strong>&lt;표 4&gt; 질의어 파라미터의 기술 형식</strong><br />
</q></p><br />
<table bgcolor="#cccccc" border="0" cellpadding="3" cellspacing="1" width="589"><tbody><br />
<tr align="center" bgcolor="#f4f4f4" valign="center"><font size="2"><br />
</font><td height="30" width="128"><font size="2"><strong>쿼리의 성격</strong></font></td><font size="2"><br />
</font><td width="222"><font size="2"><strong>예제</strong></font></td><font size="2"><br />
</font><td width="217"><font size="2"><strong>설명</strong></font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25" width="128"><font size="2">특정 질의어를 포함</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="222"><font size="2">Star Wars Episode +1</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="217"><font size="2">일번적인 질의어에 "+ 특정 질의어"를 붙여 일반적인 질의어와 특정 질의어가 모두 출현한 검색 결과만을 출력한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="128"><font size="2">특정 질의어를 제외</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="222"><font size="2">bass-music</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="217"><font size="2">일반적인 질의어에 "- 특정 질의어"를 붙여 일반적인 질의어는 출현하지만 특정 질의어가 출현하지 않는 검색 결과만을 출력한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25" width="128"><font size="2">특정 어구 검색</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="222"><font size="2">"yellow pages"</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="217"><font size="2">특정 어구가 출현한 검색 결과만을 출력한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="128"><font size="2">Boolean or 검색</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="222"><font size="2">vacation london OR paris</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="217"><font size="2">"word A OR word b" 는 word A 와 word B에 대해 Boolean or 검색 결과만을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25" width="128"><font size="2">사이트 제한 검색</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="222"><font size="2">admission site: www.stanford.edu</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="217"><font size="2">특정 domain에 포함되어 있는 도큐먼트에 대한 결과만을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="128"><font size="2">날짜 제한 검색</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="222"><font size="2">Star Wars datarange:2452122-2452234</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="217"><font size="2">Jullian Date 포맷으로 입력된 날짜 기간동안 생성된 웹 페이지드에 대한 검색 결과만을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25" width="128"><font size="2">제목 검색(팀)</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="222"><font size="2">intitle:Google search</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="217"><font size="2">"intitle:" 바로 뒤에 명시된 질의어가 제목에 출현한 검색 결과만을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="128"><font size="2">제목 검색(전체)</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="222"><font size="2">allintitle:Google search</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="217"><font size="2">"alltitle:" 뒤에 명시된 모든 쿼리 팀들이 제목에 출현한 검색 결과만을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="128"><font size="2">URL 검색(팀)</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="222"><font size="2">inurl: Google search</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="217"><font size="2">"inurl:" 바로 뒤에 명시된 질의어가 URL에 포함되어 있는 웹 문서만을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="128"><font size="2">URL 검색(전체)</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="222"><font size="2">allinurl: Google search</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="217"><font size="2">"allinurl:" 로 시작되는 질의어의 경우 명시된 모든 질의어가 URL에 포함되어 있는 웹 문서만을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25" width="128"><font size="2">텍스트만 검색</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="222"><font size="2">allintext: Google search</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="217"><font size="2">"alltext:"로 시작되는 질의어의 경우, 명시된 질의어가 웹 문서의 body text 부분에서 출현한 문서만을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="128"><font size="2">링크만 검색</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="222"><font size="2">allinlinks: Google search</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="217"><font size="2">"allinlinks:"로 시작되는 질의어의 경우, 명시된 모든 질의어가 앵커 텍스트에서 출현한 문서만을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25" width="128"><font size="2">파일 타입 포함 필터링</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="222"><font size="2">Google filetype: doc OR filetype:pdf</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="217"><font size="2">"filetype:" 뒤에 명시된 파일 타입을 포함하고 있는 문서만을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="128"><font size="2">파일 타입 제외 필터링</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="222"><font size="2">Google filetype: doc-filetype:pdf</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="217"><font size="2">"-filetype:" 뒤에 명시된 파일 타입을 포함하지 않는 문서만을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25" width="128"><font size="2">웹 문서 정보</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="222"><font size="2">info:www.google.com</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="217"><font size="2">특정 URL에 해당되는 페이지 하나만을 검색 결과로 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="128"><font size="2">역 링크</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="222"><font size="2">link:www.google.com</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="217"><font size="2">특정 URL에 역 링크하고 있는 페이지들을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#ffffff" height="25" width="128"><font size="2">관련 링크</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="222"><font size="2">related:www.google.com</font></td><font size="2"><br />
</font><td bgcolor="#ffffff" width="217"><font size="2">특정 URL의 페이지와 유사한 페이지들을 노출한다.</font></td><font size="2"><br />
</font></tr><br />
<tr><font size="2"><br />
</font><td bgcolor="#fafafa" height="25" width="128"><font size="2">캐시된 결과 페이지</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="222"><font size="2">cache:www.google.com web</font></td><font size="2"><br />
</font><td bgcolor="#fafafa" width="217"><font size="2">구글이 수집하여 캐시해 놓은 페이지를 보여준다. 특정 질의어와 함께 입력되면 해당 질의어에 하이라이팅 처리를 해준다.</font></td><font size="2"><br />
</font></tr></tbody><br />
</table><br />
<p><q>구글 웹 검색 API를 이용한 검색 결과의 수신</q></p><br />
<p><q>SOAP을 이용하여 리퀘스트를 날리면, 구글은 SOAP으로 검색 결과를 회신한다. 회신되는 결과에 포함되는 주요 정보들은 다음과 같다.</q></p><br />
<pre class="sourcebox"><code><q><strong>&lt;summary&gt;</strong> - 검색결과가 ODP 디렉토리 내의 리스트의 경우, ODP 서머리에 해당되는 텍스트 스트링<br />
<br />
 <strong>&lt;URL&gt;</strong> - 검색 결과의 URL path<br />
<br />
 <strong>&lt;snippet&gt;</strong> - 검색 결과 웹 페이지 중 입력된 질의어가 출현한 부분을 볼드 처리하여 추출한 웹 페이지 컨텐츠의 일부 스트링<br />
<br />
 <strong>&lt;title&gt;</strong> - 검색 결과의 타이틀 - 캐시된 페이지의 KB 크기<br />
<br />
 <strong>&lt;relatedInformationPresent&gt;</strong> - related: 요청에 대한 true/false 값<br />
<br />
 <strong>&lt;hostName&gt;</strong> - 필터링이 수행되어 한 호스트에서 두 개의 결과가 노출되는 경우, 두 번째 결과에 추가적으로 호스트 네임이 기술된다.</q></code><br />
</pre><br />
<p><q>SOAP에 의해 넘어온 검색 결과는 &lt;화면 3&gt;과 같은 형태가 될 것이다.구글 웹 검색 APIs를 다운로드하면 자바로 작성된 간단한 패키지가 포함되어 있다. 이것은 자바를 통해 SOAP 메시지를 구성해구글과 간단하게 통신할 수 있는 환경을 제공한다. 굳이 자바뿐 아니라 SOAP 처리를 위한 기타 프로그래밍 언어의 라이브러리도다수 공개되어 있으니 개발자가 편의에 맞는 언어를 선택해 SOAP 프로토콜을 처리하는 데에는 그리 큰 어려움이 없다.</q></p><br />
<br />
<p style="font-weight: bold;" class="sub1"><q>구글만이 가진 튼튼한 인프라 구조</q></p><br />
<p><q>지금까지 구글의 핵심 기술이라고 불릴 수 있는 요소들에 대해서 간략하게나마 살펴보았다.검색에 대한 기술들이 상당 부분 오픈되어 있는 현재 상황으로 볼 때, 검색 기술에 대한 진입 장벽은 많이 높은 편이 아니다.그럼에도 불구하고 구글이 검색 업계에서 독보적인 위치를 차지할 수 있는 것은 구글만이 갖고 있는 핵심 기술들이 선구적이고 핵심에집중하며 멈추지 않고 성장하고 있기 때문이다. 게다가 그 기술들은 숨겨져 있는 것이 아니라 많은 개발자들을 위해 개방되어 있다.구글의 기술이 개발자들에게 전파되고 전파된 기술들이 역으로 다시 구글을 발전시킨다.</q></p><br />
<p><q>사용자들이 흔히 말하는 바와 같이, 구글의 서비스가 구글스러울 수밖에 없는 것은 구글만이갖고 있는 인프라 구조들이 버티고 있기 때문이다. 최하단의 인프라 구조들과 그것을 아우르는 프레임워크, 그리고 구글이 기술을바라보는 철학이 최상단의 서비스에 영향을 미치고 있는 것이다.</q></p><br />
&nbsp;<br />
<p>출처: <a href="http://chauchau0.tistory.com/entry/%ED%8A%B9%EC%A7%91-2%EB%B6%80-%EC%84%B1%EA%B3%B5%EC%9D%98-%EC%9B%90%EC%B2%9C-%ED%83%84%ED%83%84%ED%95%9C-%EA%B8%B0%EC%88%A0-%EC%9D%B8%ED%94%84%EB%9D%BC-%EB%8C%80%ED%95%B4%EB%B6%80-%EA%B5%AC%EA%B8%80" title="동우리's rants" class="external" linkindex="10">동우리's rants</a></p><br/><br/>tag : <a href="/tag/구글" rel="tag">구글</a>,&nbsp;<a href="/tag/google" rel="tag">google</a>,&nbsp;<a href="/tag/검색엔진" rel="tag">검색엔진</a>,&nbsp;<a href="/tag/search" rel="tag">search</a>,&nbsp;<a href="/tag/engine" rel="tag">engine</a>,&nbsp;<a href="/tag/기술" rel="tag">기술</a>,&nbsp;<a href="/tag/웹" rel="tag">웹</a>,&nbsp;<a href="/tag/pagerank" rel="tag">pagerank</a>,&nbsp;<a href="/tag/검색" rel="tag">검색</a>			 ]]> 
		</description>
		<category>Search Engine</category>
		<category>구글</category>
		<category>google</category>
		<category>검색엔진</category>
		<category>search</category>
		<category>engine</category>
		<category>기술</category>
		<category>웹</category>
		<category>pagerank</category>
		<category>검색</category>

		<comments>http://topic.egloos.com/536708#comments</comments>
		<pubDate>Mon, 13 Aug 2007 07:30:12 GMT</pubDate>
		<dc:creator>Hans</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 액티브X 대체기술 5부 - MS가 내놓은 액티브X 컨트롤의 대안 실버라이트 활용법 ]]> </title>
		<link>http://topic.egloos.com/508868</link>
		<guid>http://topic.egloos.com/508868</guid>
		<description>
			<![CDATA[ 
  <p class="title1"><span style="font-weight: bold;">더 큰 세상으로 가는 문</span><br style="font-weight: bold;"><span style="font-weight: bold;">액티브X 대체기술</span> </p><br />
<p class="author">기획/정리 l 전희용 기자 flytgr@imaso.co.kr</p><br />
<p class="contentsbox">마소 독자치고 액티브X 문제와 무관하다고 할 수 있는 사람은 별로 없을 것이다. 그런데, 참 이상한 일은 액티브X 이야기만 나오면 문제의 원인이나 해결책을 이야기하기 보단 목에 핏대부터 세운다. 누군가를 탓하기 위함이다. 하지만 막상 따지고 보면 누구의 잘못이라고 하기는 어려운 일이다. 워낙 오랫동안 쌓아온 일이기 때문이다. 그렇다고 곪을 대로 곪은 상처를 그냥 놓아둘 수도 없는 일. 이번 달 특집에서는 이 상처의 원인에 대해 알아보고, 그 치료방법인 액티브X의 대체 기술들에 대해서도 함께 알아본다. 다들 잘 알다시피 아직 액티브X를 1대1로 대신해 줄 수 있는 기술은 없다. 하지만, 여러 기술들을 이용하여 산적한 문제들을 보완하며 차츰 치료해 나갈 수는 있을 것이다. 깊이 박힌 상처가 하루아침에 낫는 걸 보았는가?</p><br />
<table bgcolor="#999999" border="0" cellpadding="5" cellspacing="1" width="100%"><tbody><tr bgcolor="#ffffff"><td height="20"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3187" target="_blank">1부 | 백조에서 미운오리로 전락한 액티브X 문제와 해결방안 | 정희용</a></td></tr><tr bgcolor="#ffffff"><td height="20"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3188" target="_blank">2부 | 발등의 불끄기 공인인증서 대체기술 | 최상훈</a></td></tr><tr bgcolor="#ffffff"><td height="20"><a href="http://www.dbguide.net/comb/common/edit/1%BA%CE%20%7C%20%B9%E9%C1%B6%BF%A1%BC%AD%20%B9%CC%BF%EE%BF%C0%B8%AE%B7%CE%20%C0%FC%B6%F4%C7%D1%20%BE%D7%C6%BC%BA%EAX%20%B9%AE%C1%A6%BF%CD%20%C7%D8%B0%E1%B9%E6%BE%C8%20%7C%20%C1%A4%C8%F1%BF%EB" target="_blank">3부 | UI 대체는 내게 맡겨라 Ajax를 이용한 UI 개발 | 박영록</a></td></tr><tr bgcolor="#ffffff"><td height="20"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3190" target="_blank">4부 | 액티브X 뛰어넘는 기능과 호환성 XPCOM 개발전략 | 김민수</a></td></tr><tr bgcolor="#ffffff"><td height="20"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3191" target="_blank"><b>5부 | MS가 내놓은 액티브X의 대안 실버라이트 활용법 | 한용희</b></a></td></tr></tbody></table><br />
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr></tr></tbody></table><br />
<p class="title1">MS가 내놓은 액티브X 컨트롤의 대안<br />
실버라이트 활용법</p><br />
<p class="contentsbox">최근 정부기관들이 앞장서서 액티브X의 배제에 노력하면서 사회 전반에서도 액티브X에 대한 관심이 뜨겁다. 정부기관의 노력으로는 신규 발주 사업의 제안 요청서에 특정 제품을 지원하지 않도록 명시하여 표준을 따르지 않는 기술의 제안을 차단하는 것 등이다. <br />
5부에서는 액티브X 컨트롤의 대안으로 MS가 내놓은 실버라이트 활용법에 대해 알아보자.</p><br />
<p class="author">한용희 | woom33@korea.com | 롯데정보통신 정보기술연구소에 재직 중</p><br />
<p>요즘은 브라우저 하나만 있으면 거의 모든 작업을 할 수 있다. 기업 내에서 사용하는 ERP 애플리케이션도 브라우저 하나로 돌아가고 은행 거래나 쇼핑, 공공기관 증명서 발급 등 모든 작업을 브라우저 안에서 할 수 있다. 하지만 이는 브라우저가 가진 기본적인 기능에서 액티브X 컨트롤을 이용하여 그 능력을 확장했기에 가능한 기능들이다. </p><p>이에 따라 이제는 기존 브라우저가 가진 단순 정보 표현 기능 말고도 사용자의 새롭고 다양한 욕구를 충족시켜줄 수 있는 새로운 프레임워크가 필요하다. 시대는 그러한 기능을 요구했고, 사람들은 그러한 기능을 수행할 수 있는 새로운 대안을 찾아 다녔다. 그렇다고 기존에 웹이라는 세상이 만들어 놓은 네트워크 구조를 무너뜨릴 생각은 없었다. 오히려 이를 그대로 이용하면서 그 위에서 다양한 기능을 수행 할 수 있는 무엇인가가 필요했다. </p><p>그래서 찾은 것이 단순 애니메이션 기능으로 사용하였던 플래시였다. 플래시는 브라우저 위에 액티브X 컨트롤로 만들어진 별도의 플러그인을 한 번만 설치하면 플래시로 만든 모든 응용 프로그램을 구동할 수 있다. 즉, 새로운 기능을 제공하는 새 프레임워크를 발견한 것이다. 사람들은 이 플래시를 단순 애니메이션 도구가 아닌 새로운 응용 프로그램을 만들 수 있는 도구로 재평가하기 시작했고, 플래시는 그러한 기능을 하나 둘씩 추가해 나갔다. </p><p>플래시는 본격적인 응용프로그램 개발 툴로 끌어올린 플랙스(FLEX)라는 제품을 발표하면서 본격적으로 리치 인터넷 애플리케이션(Rich Internet Application) 서비스를 하게 된 것이다. </p><p>액티브X 컨트롤을 대체하려면 무엇보다 브라우저가 가진 기능을 확장할 수 있어야 하며, 웹이 만들어 놓은 네트워크라는 세상 안에서 그 기능을 수행해야만 한다. 또한 특정 OS나 특정 브라우저가 아닌 모든 환경에서 사용가능 해야만 한다. 이러한 조건을 충족시키기 위해서는 기존 브라우저 위에서 플래시처럼 한 번의 플러그인을 설치하면 모든 응용 프로그램을 구동시킬 수 있는 기술이 필요했던 것이다. 그래서 탄생한 것이 바로 실버라이트(코드명: WPF/e)이다. </p><p>플래시와 비슷한 개념이고 기능도 비슷하지만 내부를 들여다보면 그 개발 환경은 사뭇 다르다. 플래시는 태생이 애니메이션을 위한 도구로 출발한 것인 반면에 실버라이트는 출발부터 디자이너와 개발자를 위한 새로운 플랫폼으로 출발한 기술이다. </p><br />
<br />
<p class="sub1">개발자와 디자이너를 위한 협업</p><br />
<p>개발자와 디자이너는 서로 다른 세계를 살아가는 사람들이다. 개발자가 숲 보다는 나무를 보고 일하는 사람이라면 디자이너는 나무 보다는 숲을 보고 일하는 사람들이다. 서로의 보는 관점 자체가 다르다. 이렇게 서로 다른 시각을 가진 사람들이 일을 하다보면 서로 의사소통이나 표현의 문제로 서로 대립되는 경우도 비일비재하다.</p><p>이러한 문제가 가장 크게 대두 되면서 만연했던 시기가 바로 ASP 시절이다. 일면 스파게티 코드로 유명한 ASP 코드는 디자이너의 코드와 개발자의 코드가 뒤섞여 있다. 자고 일어나면 상대방이 수정을 해서 디자인이 헝클어지거나 기능이 제대로 동작하지 않는 경우가 있었다. 이럴 때면 서로 네 탓이니 내 탓이니 하면서 싸우기 일쑤였다. </p><p>이러한 문제는 ASP.NET 기술이 디자이너의 코드와 개발자의 코드를 분리하면서 어느 정도 해결되었다. 하지만 사용자의 편의성을 높이기 위한 기능들은 클라이언트 쪽에서 구동되어야 하는데, 이는 별도의 스크립트라는 언어로 개발을 해야만 했다. 디자이너는 자신의 상상 속에서 사용자의 편의성을 높이기 위한 디자인을 내 놓지만 개발자가 디자이너의 그러한 상상의 세상을 스크립트로 구현하기란 좀처럼 쉽지 않았다. 그래서 디자이너와 개발자의 중간에 위치한 UI 개발자라는 별도의 직업까지 생길 정도였다.</p><p>사용자의 요구사항은 이제 점점 웹을 단순한 정보를 표현하는 도구가 아닌 사용자와 서로 편하게 대화할 수 있는 환경으로 만들어 주기를 원했다. 이제 웹은 정보를 보여주는 도구가 아닌 정보를 생산하는 도구가 된 것이다. 따라서 사용자의 UI를 편하게 만드는 것이 보다 좋은 웹사이트를 만드는 척도가 되었다. </p><p>이제는 디자이너가 꿈꾸고 있는 상상속의 이미지를 그대로 표현해 주는 새로운 기술이 필요해 졌다. 기존의 HTML은 정보를 보여주는 데 적절한 언어이지 정보를 생산하는 데에는 적합하지 않았다. 따라서 HTML이 아닌 다른 새로운 표준이 필요했고 그래서 나온 것이 바로 XAML(eXtensible Application Markup Language, 재믈)이다. 이를 통해서 디자이너가 생각하는 기능과 표현을 XML 기반의 새로운 태그 언어로 표시한 것이다. XAML에 대해서는 자세히 설명하지는 않을 것이다. 이미 여러 차례 마이크로소프트웨어에서 소개되었기 때문이다(2007년 1월호 특집 기사 참조).</p><p>이제 디자이너는 XAML을 생성해 주는 새로운 도구를 이용해서 디자인을 해야만 한다. 그래서 MS에서는 익스프레션 제품군을 새로 만들어 판매하고 있다. &lt;표 1&gt;은 2007년 1월호 특집 기사에 실린 익스프레션 제품군과 어도비의 디자인 프로그램 비교표이다.</p><div align="center"><table bgcolor="#666666" border="0" cellpadding="0" cellspacing="1" width="100%"><tbody><tr bgcolor="#ffffff"><td height="25"><div align="center"><b>Microsoft</b></div></td><td height="25"><div align="center"><b>Adobe</b></div></td></tr><tr bgcolor="#ffffff"><td height="25"><div align="center">익스프레션 디자인</div></td><td height="25"><div align="center">일러스트레이터<br />
포토샵 </div></td></tr><tr bgcolor="#ffffff"><td height="25"><div align="center">익스프레션 블랜드</div></td><td height="25"><div align="center">플래시<br />
플렉스 </div></td></tr><tr bgcolor="#ffffff"><td height="25"><div align="center">익스프레션 웹</div></td><td height="25"><div align="center">드림위버</div></td></tr><tr bgcolor="#ffffff"><td height="25"><div align="center">익스프레션 미디어</div></td><td height="25"><div align="center">프리미어</div></td></tr></tbody></table><br />
&lt;표 1&gt; MS와 어도비의 디자인 제품 비교표 </div><p>새로운 툴로 전향하기 싫은 사람들을 위해서도 별도의 변환 툴을 제공한다. 현재는 다음과 같은 두 가지 변환 도구가 출시되어 있다.</p><p class="sourcebox">· SWF to XAML Converter(http://www.mikeswanson.com/ swf2xaml)<br />
: 플래시 SWF 파일을 XAML 파일로 변환<br />
<br />
· Adobe Illustrator to WPF/XAML Export Plug-In(http://www.mike swanson.com/xamlexport)<br />
: Illustrator에서 XAML 파일로 저장해주는 플러그 인</p><p>MS에서는 이렇게 사용자의 편의성을 높여주는 일련의 활동을 UX(User Experience, 사용자 경험)라고 정의하고 있다. 이제 디자이너는 마음껏 사용자의 편의성을 향상시키기 위하여 자신만의 언어를 사용할 수 있게 되었으며, 개발자도 자연스럽게 이를 수용할 수 있는 준비가 된 것이다.</p><br />
<br />
<p class="sub1">웹을 위한 종합선물세트, 실버라이트</p><br />
<p>요즘 기술 트렌드를 대변 하는 말 중에 유행하는 말이 한 가지 있다. 그것은 바로 ‘종합선물세트’라는 것이다. 요즘 기술의 추세는 특정한 기능에 편중되지 않고 모든 기능을 포함하는 것이 유행이다. 필자가 처음 실버라이트의 아키텍처를 보고 제일 먼저 머리에 떠오른 단어도 ‘종합선물세트’이었다. 실버라이트는 요즘 유행하는 모든 기술을 거의 다 담았다고 해도 과언이 아니다. 실버라이트는 현재 두 가지 버전이 있다. 1.0 베타와 1.1 알파 버전이다. 1.0 버전은 올 여름에 출시될 예정이고, 1.1 버전은 아직 미정이다. 1.0과 1.1의 가장 큰 차이점은 1.1에서는 닷넷 프레임워크 프로그래밍 모델을 지원한다는 것이다. 즉, C#이나 비주얼 베이직을 이용하여 관리코드(Managed Code)를 작성할 수 있다. 닷넷 프로그래밍 모델을 지원하면 앞으로 실버라이트의 개발이 훨씬 용이해 질 것이다. 1.0 버전에서는 자바 스크립트만 지원한다. 이제 실버라이트의 주요 특징을 차례로 알아보자.</p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246704" localfile="yes" postid="38905412" height="382" width="600"><br />
&lt;그림 1&gt; 실버라이트 Application structure</p><p>● <b>크로스 브라우저(Cross-browser), 크로스 플랫폼(Cross-platform)</b><br />
실버라이트의 가장 큰 특징은 한 마디로 크로스 브라우저와 크로스 플랫폼이다. 현재 지원 가능한 브라우저는 IE와 모질라, 파이어폭스, 애플 사파리와 오페라다. 운영체제는 윈도우와 애플의 Mac OSX를 지원한다. </p><p>● <b>경량화(Lightweight browser plug-in)</b><br />
이름에서도 알 수 있듯이 실버라이트의 브라우저 플러그인은 경량화를 지향한다. 현재 실버라이트 1.0 베타 버전의 런타임은 1.38MB정도 한다. 최종 런타임도 3MB를 넘지 않을 것이라고 한다. 참고로 플래시 9.0의 런타임은 현재 2.2MB이다.</p><p>● <b>멀티미디어 지원</b><br />
실버 라이트는 오디오와 비디오 재생을 위한 자체적인 스트리밍 플레이 기능을 가지고 있는 덕분에 별도의 플레이어 없이 자체적으로 재생할 수 있다. 비디오는 윈도우 미디어 콘텐츠인 WMV와 WMA 포맷을 지원하며, HDTV 수준의 비디오 해상도도 지원한다. 오디오로는 MP3 포맷을 지원한다. 현재 www. Silverlight.net 사이트에 가면 폭스 무비(Fox Movie)의 영화 예고편을 실버라이트로 만들어 놓은 것을 확인해 볼 수 있다. 상당한 수준의 해상도를 지원하는 영화 예고편을 감상 할 수 있다.</p><p>● <b>WPF, XAML 지원</b><br />
실버라이트는 프레젠테이션 기술로 WPF(Windows Presentation Foundation)를 채택하였다. WPF는 윈도우 비스타의 닷넷 프레임워크 3.0에 포함된 기술인데, 디자인을 표현하는데 있어 XAML을 이용한다. 이에 대한 자세한 내용 역시 2007년 1월호 특집 기사를 참고하길 바란다. 실버라이트의 초창기 코드명은 WPF/e였다. 여기서 e는 Everywhere 즉, 어디서나 WPF 응용프로그램을 사용하자는 취지로 만들어진 코드명이다. 때문에 실버라이트는 3D 기능을 제외한 대부분의 WPF 기능을 제공한다. 플래시와 마찬가지로 벡터 기반이기 때문에 확대하거나 축소를 하더라도 이미지의 손실 없이 부드럽게 표현되는 것도 빼놓을 수 없는 특징이다.</p><p>● <b>닷넷 프로그래밍 모델 지원</b><br />
실버라이트 1.1버전부터는 닷넷 프로그래밍 모델도 지원한다. CLR 전부를 지원하는 것은 아니지만, CLR 대부분의 기능을 지원할 예정이다. 사용 할 수 있는 언어로는 C#과 비주얼 베이직, IronPython, Ruby, Managed JScript 등이 있다. 이중에 C#과 비주얼 베이직은 기존에 있던 언어이지만 새롭게 동적 언어인 IronPython, Ruby, Managed JScript 지원을 추가했다. 스크립트 언어가 가진 높은 생산성을 더 이상 무시할 수 없었던 것이다. 현재 ASP.NET도 IronPython과 같은 동적언어를 추가할 예정이다(http://www.asp.net/downloads/futures/default. aspx?tabid=62).</p><p>● <b>기존 응용프로그램 지원</b><br />
실버라이트는 자바스크립트와 서로 연동할 수 있다. 자바 스크립트 뿐만 아니라 ASP.NET AJAX와도 쉽게 연동할 수 있다. 한 예로 http://www.thewpfblog.com/examples/wpfe/microbe /Default.html에 가면 WPF/e와 플래시가 서로 연동되는 데모를 볼 수 있다. 공이 튀는 하나의 화면에서 움직이는 것 같지만 사실 왼쪽은 WPF/e로 만든 것이고, 오른쪽은 플래시로 만든 것이다. 서로 데이터를 주고받으면서도 부드러운 움직임을 보여준다.</p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246705" localfile="yes" postid="38905412" height="296" width="600"><br />
&lt;화면 1&gt; WPF/e와 플래시가 서로 연동한 데모</p><p>● <b>압축 지원</b><br />
XAML 파일은 텍스트 기반이기 때문에 그 용량이 상당히 크다. 따라서 이를 그대로 웹에 올리려면 용량이 문제가 된다. 플래시의 경우도 개발 시에는 FLA 파일 포맷을 사용하지만 실제 배포할 때에는 압축된 SWF 포맷을 사용한다. 실버라이트도 이러한 압축 기술을 지원할 예정이다.</p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246706" localfile="yes" postid="38905412" height="124" width="309"><br />
&lt;그림 2&gt; 실버라이트의 압축 패키징</p><br />
<br />
<p class="sub1">실버라이트와의 조우, Hello World!</p><br />
<p>새로운 언어를 배울 때 언제나 등장하는 것이 바로 ‘Hello World’를 출력하는 예제일 것이다. 실제로 이 예제를 만들어 봄으로써 실버라이트의 개발 환경을 느껴보자. 실버라이트를 개발하는데 있어 여기에서는 1.1 알파 버전을 사용할 것이다. 1.0 버전 버전은 닷넷 프레임워크를 아직 지원하지 않기 때문에 다양한 기능을 보여주기에는 부족한 점이 있다. </p><p>1.1 알파 버전은 http://msdn2.microsoft.com/en-us/asp. net/bb187452.aspx에서 다운로드 받아서 설치하면 된다. 웹 페이지에 접속하면 다음과 같은 프로그램들 목록이 표시된다.</p><p class="sourcebox">· Microsoft Silverlight 1.1 Alpha.브라우저 플러그 인<br />
· Microsoft Silverlight 1.1 Alpha Software Development Kit(SDK)개발 툴 킷<br />
· Microsoft Expression! Blend 2 PreviewXAML 디자인을 위한 디자인 툴<br />
· Microsoft Visual Studio Code Name “Orcas” Beta 1.비주얼 스튜디오 차기 버전인 Orcas Beta1 버전<br />
· Microsoft Silverlight Tools Alpha for Visual Studio Code Name “Orcas” Beta 1.Orcas Beta1 버전에서 실버라이트를 개발하기 위한 프로젝트 템플릿</p><p>설치할 프로그램이 많은 편이다. 이 프로그램들은 모두 무료로 다운로드 받을 수 있으므로 전부다 다운로드 받아서 설치를 한다. <br />
먼저 C# 기반의 실버라이트 응용 프로그램을 만들어 보자. 비주얼 스튜디오를 실행하고 새 프로젝트에서 C# 밑에 있는 실버라이트 프로젝트를 선택한다. </p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246707" localfile="yes" postid="38905412" height="329" width="600"><br />
&lt;화면 2&gt; 실버라이트 프로젝트 선택하는 화면</p><p>프로젝트를 생성하면 &lt;화면3&gt;과 같은 프로젝트가 만들어 진다.</p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246708" localfile="yes" postid="38905412" height="261" width="249"><br />
&lt;화면 3&gt; C# 기반의 실버라이트 프로젝트</p><p>화면을 표시하는 페이지는 TestPage.html이다. 기존의 MS 방식대로라면 확장자를 htm으로 사용하겠지만, html을 사용한 것으로 봐서는 크로스 브라우저를 지향하려는 의도가 엿보인다. TestPage.html 코드를 보면 별다른 코드가 없다. </p><p><b>&lt;리스트 1&gt; TestPage.html의 일부</b></p><p class="sourcebox"><br />
<br />
...<br />
<br />
<br />
</p><div id="SilverlightControlHost"><br />
<br />
</div><br />
<p>실버라이트의 런타임 자체도 액티브X 컨트롤로 만들어져 있는데, 작년에 이올라스 패치 문제가 있었듯이 한 파일 안에서 같이 실행하면 액티브X 컨트롤이 활성화되지 않는 탓에 별도의 파일로 분리하는 것이 좋다. Silverlight.js 파일은 모든 브라우저에서 실버라이트가 동작하도록 만들어 놓은 자바스크립트 라이브러리다. TestPage.html.js는 Silverlight.js에 있는 실버라이트 생성 컨트롤을 호출하면서 XAML 파일을 연동시켜주는 역할을 한다. </p><p><b>&lt;리스트 2&gt; TestPage.html.js</b></p><p class="sourcebox">function createSilverlight()<br />
{<br />
Sys.Silverlight.createObjectEx({<br />
source: "Page.xaml",<br />
parentElement: document.getElementById("SilverlightControlHost"),<br />
id: "SilverlightControl",<br />
properties: {<br />
width: "100%",<br />
height: "100%",<br />
version: "0.95",<br />
enableHtmlAccess: true<br />
},<br />
events: {}<br />
});<br />
}</p><p>Page.xaml 파일을 보면 단순히 Canvas 하나를 그리는 구문만이 존재 한다.</p><p><b>&lt;리스트 3&gt; Page.xaml</b></p><p class="sourcebox"><canvas><br x:name="parentCanvas">xmlns="http://schemas.microsoft.com/client/2007" <br />
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" <br />
Loaded="Page_Loaded" <br />
x:Class="HelloWorld_CS.Page;assembly= ClientBin/HelloWorld_CS.dll"<br />
Width="640"<br />
Height="480"<br />
Background="White"<br />
&gt;<br />
</canvas></p><p>이 구문에서 x:Class라는 부분이 바로 닷넷 프로그래밍 모델로 만든 어셈블리를 연동하는 부분이다. 클래스명과 경로를 적어주어야 한다. DLL로 만든 클래스의 네임스페이스와 이름을 표기하고 실제 DLL 파일의 경로를 적어 준다. Loaded에는 초기에 로드 되면서 호출할 메소드 이름을 적어준다. </p><p>디자이너는 이 XAML 파일을 수정하고 개발자는 이 XAML에 연동된 파일(여기에서는 xaml.cs)을 각각 수정하면 된다. </p><p><b>&lt;리스트 4&gt;Page.xaml.cs</b></p><p class="sourcebox">namespace HelloWorld_CS<br />
{<br />
public partial class Page : Canvas<br />
{<br />
public void Page_Loaded(object o, EventArgs e)<br />
{<br />
// Required to initialize variables<br />
InitializeComponent();<br />
}<br />
}<br />
}</p><p>현재까지는 각각의 코드가 아무런 일도 하지 않는다. 이제 익스프레션 블랜드를 이용해서 Hello World! 텍스트 박스 하나를 그려보자.<br />
&lt;화면 4&gt;처럼 비주얼 스튜디오에서 바로 블랜드를 호출할 수 있다.</p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246709" localfile="yes" postid="38905412" height="445" width="297"><br />
&lt;화면 4&gt; Blend를 여는 메뉴</p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246710" localfile="yes" postid="38905412" height="332" width="600"><br />
&lt;화면 5&gt; Hello World! 텍스트 박스를 추가한 모습</p><p>&lt;화면 5&gt;를 보면 Hello World! 텍스트 박스를 추가한 모습을 볼 수 있다. 블랜드에서는 비주얼 스튜디오와 마찬가지로 옆에 프로젝트 리스트가 나오며 블랜드에서 아예 프로젝트를 새로 만들 수도 있다. 이러한 기능은 개발자와 디자이너가 보다 긴밀하고 효과적인 협업을 할 수 있도록 만들어진 기능이라고 할 수 있다.</p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246711" localfile="yes" postid="38905412" height="423" width="600"><br />
&lt;화면 6&gt; 블랜드에서 프로젝트 만들기</p><p>이제 저장을 하고 비주얼 스튜디오로 돌아와서 실행을 하면 Hello World! 텍스트가 잘 나올 것이다. 단 아직 한글 지원이 미비한 관계로 블랜드에서 언어 관련 코드는 삭제해 주어야만 한다. </p><p><b>&lt;리스트 5&gt; Page.xaml에 Hello World! 텍스트 박스 추가한 결과</b></p><p class="sourcebox"><textblock width="156" height="37" canvas.left="133" canvas.top="23" textwrapping="Wrap"><br />
Hello World!<br />
</textblock></p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246712" localfile="yes" postid="38905412" height="303" width="600"><br />
&lt;화면 7&gt; Hello World!를 실행한 화면</p><p>이번에는 디자이너 부분이 아닌 개발자 부분에서 코드를 수정해 보자. 위의 TextBlock에 이름을 다음과 같이 지정한다.</p><p class="sourcebox"><textblock x:name="“block”" width="“156”" height="“37”" canvas.left="“133”" canvas.top="“23”" textwrapping="“Wrap”"><br />
Hello World!<br />
</textblock></p><p>이를 Page.xaml.cs 코드에서 다음과 같이 수정해 보자.</p><p class="sourcebox">block.Text = “Welcome to the Silverlight”;</p><p>즉, Page_Loaded 이벤트에서 block이라는 이름의 TextBlock의 내용을 바꾸었다. 이를 실행해 보면 Hello World!에서 ‘Welcom to the Silverlight’로 바뀐 것을 볼 수 있을 것이다.</p><p>이번에는 IronPython을 이용해서 똑같은 결과물을 만들어 보자. 위의 Page.xaml에서 동적언어에 대한 내용을 &lt;리스트 6&gt;과 같이 추가한다.</p><p><br />
</p><p><b>&lt;리스트 6&gt; 동적언어 지원을 위한 Page.xaml</b></p><p class="sourcebox"><canvas><br x:name="parentCanvas">xmlns="http://schemas.microsoft.com/client/2007" <br />
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" <br />
Width="640"<br />
Height="480"<br />
Background="White"<br />
&gt;<br />
<x:CODE source="Page.xaml.py" type="text/ironpython"></x:CODE><br />
<textblock><br x:name="block" width="156" height="37" canvas.left="133" loaded="OnLoad">Canvas.Top="23" TextWrapping="Wrap"&gt;<br />
Hello World!<br />
</textblock><br />
</canvas></p><p>이번에는 닷넷 프레임워크 어셈블리가 필요 없으므로 x:Class도 선언할 필요가 없다. 대신 x:Code라는 태그를 통해서 동적언어를 설정한다. 기능은 앞의 예제와 동일하게 텍스트의 내용을 바꾼다.</p><p><br />
</p><p><b>&lt;리스트 7&gt; Page.xaml.py</b></p><p class="sourcebox">def OnLoad(sender, e):<br />
block.Text = "Welcome to the Silverlight"</p><p class="sourcebox"><br />
</p><p>결과를 보면 파이썬으로 만들어도 동일한 결과를 볼 수 있다. 그렇다면 ASP.NET처럼 이러한 관리코드나 동적코드는 서버 사이드에서 실행되는 것일까? 우리가 어떤 버튼을 클릭하면 서버에 가서 그 이벤트를 처리하고 결과를 돌려주는 방식일까? 그것은 아니다. 실버라이트는 어셈블리나 동적언어 코드를 직접 클라이언트에 모두 로딩 한다. 따라서 서버에 특정 네트워크 통신을 따로 하지 않는 이상 라운드 트립은 없다.</p><br />
<br />
<p style="font-weight: bold;" class="sub1">실버라이트의 추가적인 특징들</p><br />
<p>실버라이트의 주요 특징과 간단한 샘플 프로그램도 만들어 보았다. 이번에는 실버라이트의 추가적인 특징들에 대해 알아보자.</p><p><br />
</p><p>● <b>DRM(Digital Right Management)</b><br />
콘텐츠에 대하여 DRM 기능을 쉽게 적용할 수 있도록 지원되는 기능이다. 이를 이용하면 자신의 실버라이트의 콘텐츠에 대하여 저작권 보호 기능을 사용할 수 있다. 아직 구체적인 예제는 없지만, 예를 들면 복사를 제한하는 등의 기능이 추가될 것으로 예상된다.</p><p><br />
</p><p>● <b>LINQ(Language Integrated Query)</b><br />
LINQ에 대해서는 2006년 1월호 ‘C#의 미래’라는 글을 참고하길 바란다. 간단히 설명하자면 DB나 XML과 같은 데이터의 쿼리 구문을 수행하는데 있어 기존에는 문자열을 조합하여 쿼리 구문을 만들거나 별도의 객체를 이용해서 쿼리 구문을 수행하였다. 쿼리 구문이 언어와 독립적인 탓에 통일성 있는 개발이 어려웠던 반면에, 이제는 이러한 쿼리 구문 자체를 언어에 포함시켰다. 따라서 이제는 쿼리 구문을 언어 차원에서 보다 쉽게 만들 수 있는 것이다. 현재 이 기능은 C#3.0에 포함될 예정이다. 비주얼 스튜디오 Orcas에는 이 기능이 이미 들어있다.</p><p><br />
</p><p>● <b>격리된 스토리지(Isolated storage)</b><br />
로컬 파일 시스템에 어떤 데이터를 저장해야 할 경우가 있을 것이다. 이때 아무 폴더나 접근 가능하게 하면 기존 액티브X 컨트롤의 보안 문제와 같은 위험을 내포하게 된다. 따라서 안전하게 격리된 별도의 저장 공간을 사용함으로써 이에 따른 보안 이슈를 해결할 수 있다. 실버라이트에서는 이러한 별도의 독립적인 저장 공간인 Isolated storage를 지원한다. Isolated storage에 대해서는 http://msdn2.microsoft.com/en-us/library/ ffbfac6a-5c25-41de-830b-b7d0c1225f83.aspx을 참조하거나 2006년 7월호 ‘Enterprise Library2.0’기사를 참고하기 바란다.</p><p><br />
</p><p>● <b>파일 관리</b><br />
안전한 파일 열기 다이얼로그 박스를 지원한다. 실버라이트는 HTTP POST를 이용한 웹서비스도 지원하므로 파일 업로드/다운로드 기능을 구현할 수 있다. 실제로 실버라이트 1.1 Quick Starts 샘플에 보면 파일 업로드 다운로드 샘플이 있다. 기존에 많은 파일 업로드/다운로드 기능들이 액티브X 컨트롤로 구현이 되어 있는데, 앞으로 실버라이트를 이용한 업로드/다운로드 컨트롤의 가능성에 대해서도 검토해 볼 수 있을 것이다.</p><p><br />
 </p><p>● <b>JSON 지원</b><br />
JSON은 JavaScript Object Notation의 약자이다. 한마디로 자바스크립트에서 사용하는 객체 기술 방법이다. XML과 비슷하게 텍스트 기반의 트리형식으로 데이터를 표시한다. XML은 범용 적이긴 하지만 파싱을 하기 위한 부하가 있고 수많은 꺽쇠 기호‘&lt;’, ‘&gt;’로 인하여 사이즈가 크다. 그래서 등장한 것이 경량화 되고 자바스크립트에서 바로 객체로 인식 가능한 데이터 형식인 JSON이다. 플랫폼에 종속적이지 않기 때문에 어디에서나 자유롭게 사용할 수 있다. 보다 자세한 내용은 http://www.ietf.org/ rfc/rfc4627.txt?number=4627을 참조하길 바란다.</p><p><br />
</p><p>● <b>POX 지원</b><br />
POX는 Plain Old XML의 약자이다. XML 데이터를 주고받는데 있어 일반적으로는 SOAP 프로토콜을 이용한 방식이 권장된다. 하지만 SOAP 프로토콜은 부가적인 정보를 많이 포함해야 하므로 상당히 무겁다. POX는 단순한 XML 데이터를 전송하므로 상대적으로 가벼워지는 효과가 있다. 따라서 SOAP 프로토콜이나 WS-* 표준에 해당하는 기능을 사용하지 않을 거라면 단순한 POX 방식의 메시지가 유용할 것이다.</p><p><br />
</p><p>● <b>XML 라이브러리</b><br />
스크립트에서 XML DOM 객체를 이용해서 XML 데이터를 처리하는 것은 쉬운 일이 아니다. 실버라이트는 닷넷 프레임워크를 그대로 사용할 수 있으므로 닷넷 프레임워크에 있는 XMLReader나 XMLWriter 클래스를 바로 사용할 수 있다. 또한 XLinQ 기능을 이용하면 보다 쉬운 쿼리 구문도 만들 수 있다.</p><br />
<br />
<p style="font-weight: bold;" class="sub1">실버라이트의 성능</p><br />
<p>실버라이트의 그래픽 렌더링 성능에 대해 벤치마크 할 수 있는 재미있는 사이트가 있다. 바로 http://bubblemark.com다.</p><p>여러 개의 공을 표시하고 렌더링 하면서 초당 몇 프레임이 나오는지 계산하는 프로그램이다. 동일한 프로그램을 DHTML이나 플래시, 실버라이트를 이용해서 테스트를 수행할 수 있다. 실제로 사용자가 직접 할 수 있으므로 상당히 흥미로운 사이트다. 필자가 직접 테스트한 결과도 있는데 &lt;표 2&gt;는 올해 2월에 WPF /e로 수행한 결과이다.</p><p><br />
</p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246713" localfile="yes" postid="38905412" height="436" width="600"><br />
&lt;화면 8&gt; 실버라이트, DHTML, Flex 그래픽 렌더링 성능 테스트</p><p align="center"><br />
</p><p>결과를 보면 실버라이트의 렌더링 성능이 플렉스 못지않음을 확인할 수 있을 것이다. 이 결과 외에 여러 사람들이 테스트한 결과를 댓글로 올려놓았다. 관심 있는 독자들은 참고하길 바란다.</p><br />
<br />
<p style="font-weight: bold;" class="sub1">실버라이트의 미래</p><br />
<p>WPF의 부분 집합 기능을 가지는 실버라이트는 점점 더 그 기능을 추가해 나갈 것이다. 현재 1.1 알파 버전에서 사용할 수 있는 컨트롤이 다양하지는 않지만 앞으로 많이 추가될 것이다. 아래는 WPF와 실버라이트의 특징을 비교한 표이다. 아래 표 내용은 미국 라스베가스에서 열린 MIX07에서 발표한 내용의 일부이다.</p><p>&lt;표 3&gt;~&lt;표 5&gt;를 보면 정식 1.1 버전이 나올 때쯤이면 상당히 유용한 기능들이 추가될 것으로 예상된다. 위의 기능들 중 한 가지 아쉬운 것은 1.1 버전에서도 DataGrid 기능은 고려되고 있지 않다는 점이다. 일반적인 응용 프로그램을 만드는데 있어 그리드 기능은 상당히 많이 사용된다. 그리드 기능만 있어도 웬만한 게시판 프로그램도 쉽게 만들 수 있을 것이다. WPF에서는 그리드 컨트롤을 써드파티 제품으로 제공하는데 실버라이트에서는 사용자 정의 컨트롤 기능을 지원하므로 다른 업체들이 이러한 그리드 컨트롤을 만들어서 제공할 수 있을 것으로 예상된다.</p><p>실버라이트의 발전 과정을 보고 있으면 마치 영화에서나 보았던 꿈에 그리던 미래의 컴퓨팅 환경이 상상이 되곤 한다. 기존 브라우저의 한계를 뛰어 넘는 자유로운 사용자 인터페이스는 새로운 웹 환경을 만들어 나갈 수 있을 것이다.</p><p><br />
</p><p><a href="http://www.dbguide.net/" target="_blank"><b><font color="midnightblue">제공 : DB포탈사이트 DBguide.net </font></b></a></p><br/><br/>tag : <a href="/tag/ajax" rel="tag">ajax</a>,&nbsp;<a href="/tag/실버라이트" rel="tag">실버라이트</a>,&nbsp;<a href="/tag/플래시" rel="tag">플래시</a>,&nbsp;<a href="/tag/ui" rel="tag">ui</a>,&nbsp;<a href="/tag/웹" rel="tag">웹</a>,&nbsp;<a href="/tag/애플리케이션" rel="tag">애플리케이션</a>,&nbsp;<a href="/tag/호환성" rel="tag">호환성</a>,&nbsp;<a href="/tag/표준" rel="tag">표준</a>			 ]]> 
		</description>
		<category>Trend</category>
		<category>ajax</category>
		<category>실버라이트</category>
		<category>플래시</category>
		<category>ui</category>
		<category>웹</category>
		<category>애플리케이션</category>
		<category>호환성</category>
		<category>표준</category>

		<comments>http://topic.egloos.com/508868#comments</comments>
		<pubDate>Mon, 06 Aug 2007 06:24:25 GMT</pubDate>
		<dc:creator>Hans</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 액티브X 대체기술 4부 - 액티브X를 뛰어넘는 기능과 호환성 XPCOM 개발 테크닉 ]]> </title>
		<link>http://topic.egloos.com/508843</link>
		<guid>http://topic.egloos.com/508843</guid>
		<description>
			<![CDATA[ 
  <h4 class="title1">더 큰 세상으로 가는 문 - 액티브X 대체기술 </h4><p><br />
</p><p class="author">기획/정리 l 전희용 기자 flytgr@imaso.co.kr</p><p><br />
</p><p class="contentsbox">마소 독자치고 액티브X 문제와 무관하다고 할 수 있는 사람은 별로 없을 것이다. 그런데, 참 이상한 일은 액티브X 이야기만 나오면 문제의 원인이나 해결책을 이야기하기 보단 목에 핏대부터 세운다. 누군가를 탓하기 위함이다. 하지만 막상 따지고 보면 누구의 잘못이라고 하기는 어려운 일이다. 워낙 오랫동안 쌓아온 일이기 때문이다. 그렇다고 곪을 대로 곪은 상처를 그냥 놓아둘 수도 없는 일. 이번 달 특집에서는 이 상처의 원인에 대해 알아보고, 그 치료방법인 액티브X의 대체 기술들에 대해서도 함께 알아본다. 다들 잘 알다시피 아직 액티브X를 1대1로 대신해 줄 수 있는 기술은 없다. 하지만, 여러 기술들을 이용하여 산적한 문제들을 보완하며 차츰 치료해 나갈 수는 있을 것이다. 깊이 박힌 상처가 하루아침에 낫는 걸 보았는가?</p><br />
<table bgcolor="#999999" border="0" cellpadding="5" cellspacing="1" width="100%"><tbody><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3187" target="_blank">1부 | 백조에서 미운오리로 전락한 액티브X 문제와 해결방안 | 정희용</a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3188" target="_blank">2부 | 발등의 불끄기 공인인증서 대체기술 | 최상훈</a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/comb/common/edit/1%BA%CE%20%7C%20%B9%E9%C1%B6%BF%A1%BC%AD%20%B9%CC%BF%EE%BF%C0%B8%AE%B7%CE%20%C0%FC%B6%F4%C7%D1%20%BE%D7%C6%BC%BA%EAX%20%B9%AE%C1%A6%BF%CD%20%C7%D8%B0%E1%B9%E6%BE%C8%20%7C%20%C1%A4%C8%F1%BF%EB" target="_blank">3부 | UI 대체는 내게 맡겨라 Ajax를 이용한 UI 개발 | 박영록</a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3190" target="_blank"><b>4부 | 액티브X 뛰어넘는 기능과 호환성 XPCOM 개발전략 | 김민수</b></a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3191" target="_blank">5부 | MS가 내놓은 액티브X의 대안 실버라이트 활용법 | 한용희</a></font></td></tr></tbody></table><br />
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr></tr></tbody></table><br />
<p class="title1"><b>액티브X를 뛰어넘는 기능과 호환성<br />
XPCOM 개발 테크닉</b></p><br />
<p class="contentsbox">액티브X 문제로 때 아닌 진통을 겪고 있는 나라는 놀랍게도 우리나라뿐이다. 미국이나 유럽 대부분의 국가들은 https 프로토콜 하나로 ID만으로 인증하면 그걸로 끝인 탓이다. 보안 능력을 높이기 위해 사용자에게 그 이상의 요구를 하지 않는다. 그들의 보안 의식이 낮은 탓일까? 필자는 그렇게 생각하지 않는다. MS의 조국인 미국에서 조차 선호하지 않고 있는 액티브X의 지나친 사용을 이제는 되돌아보고 바로잡을 때다. 특집 4부에서는 XPCOM을 통해 기존의 액티브X를 어떻게 대체할 수 있는지에 대해 알아본다.</p><br />
<p class="author">김민수 | mskim@transware.co.jp | 일본 웹 애플리케이션 개발회사 한국 지사 개발팀 근무</p><br />
<p>XPCOM, 앞에 두 글자 XP와 뒤에 COM를 보면 Windows XP와 무슨 관련이 있는 기술처럼 보인다. 그도 그럴 것이 COM와 COM+로 대표되는 액티브X를 위시한 마이크로소프트(이하 MS)의 컴포넌트 기술과 비슷한 단어인 Cross Platform Compo nent Object Model의 약자이기 때문이다. 그래서 어느 정도 관련이 있다고도 볼 수 있는 기술이다. 하지만, 결정적으로 MS는 수익을 추구하는 회사란 집단이고 XPCOM을 만든 모질라 재단은 비영리단체라는 것이다. 물론, 수익 추구라는 차이를 내세워 표준인지 아닌지를 가름 할 수는 없다. 하지만 MS의 브라우저 IE는 리눅스용이 없다. 하지만 모질라재단의 파이어폭스는 윈도우는 물론 리눅스와 유닉스, 맥OS, OS/2 등등 현존하는 거의 모든 OS를 지원하고 있다. 즉, 지원하는 플랫폼이 다양하기 때문에 더욱 범용적으로 사용할 수 있고 액티브X를 대체하는 것에 더하여 표준으로 자리 잡기에 충분하다고 얘기할 수 있겠다.</p><br />
<p>이번 특집에서는 기존에 마소를 통해 소개된 적 있는 XPCOM의 소개 기사는 최대한 배제하고, 다양한 플랫폼에 XPCOM을 어떻게 적용하면 좋을 지에 대한 활용 기사 위주로 다룰 것이다. XPCOM에 대해 더 궁금한 독자들은 원고 중에 제시된 링크를 참조하길 바란다.</p><p><br />
</p><p class="sub1"><b>SDK 다운로드와 설치하기</b></p><br />
<p>XPCOM으로 개발하려면 SDK를 다운로드 받아 설치해야 한다. 다음의 링크를 통해 필요한 파일을 다운로드 받을 수 있다.</p><p>Mozilla Gecko SDK 다운로드</p><p>● Branch<br />
- 윈도우즈 환경의 Visual C++ 컴파일러 버전<br />
ftp://ftp.mozilla.org/pub/mozilla.org/mozilla/nightly/latest-1.7/gecko-sdk-i586-pc-msvc.zip<br />
- 윈도우즈 환경의 Cygwin GCC 컴파일러 버전<br />
ftp://ftp.mozilla.org/pub/mozilla.org/mozilla/nightly/latest-1.7/gecko-sdk-i686-pc-cygwin.zip<br />
- 리눅스 환경의 GCC 컴파일러 버전<br />
ftp://ftp.mozilla.org/pub/mozilla.org/mozilla/nightly/latest-1.7/gecko-sdk-i686-pc-linux-gnu.tar.gz<br />
- 리눅스 환경의 GCC 컴파일러 GTK2+XFT 버전 <br />
ftp://ftp.mozilla.org/pub/mozilla.org/mozilla/nightly/latest-1.7/gecko-sdk-i686-pc-linux-gnu-gtk2+xft.tar.gz</p><p>● Trunk<br />
- 윈도우즈 환경의 Visual C++ 컴파일러 버전<br />
ftp://ftp.mozilla.org/pub/mozilla.org/mozilla/nightly/latest-trunk/gecko-sdk-i586-pc-msvc.zip<br />
- 리눅스 환경의 GCC 컴파일러 버전<br />
ftp://ftp.mozilla.org/pub/mozilla.org/mozilla/nightly/latest-trunk/gecko-sdk-i686-pc-linux-gnu.tar.gz<br />
- 리눅스 환경의 GCC 컴파일러 GTK2+XFT 버전<br />
ftp://ftp.mozilla.org/pub/mozilla.org/mozilla/nightly/latest-trunk/gecko-sdk-i686-pc-linux-gnu-gtk2+xft.tar.gz<br />
</p><br />
<p class="sub1"><b>C++로 작성하는 XPCOM</b></p><p><br />
</p><p>먼저 각각의 과정을 살펴보면 가장 먼저 xxIxxx.idl를 만들고, 그 뒤에 xpidl를 이용하여 xxIxxx.xpt와 xxIxxx.h를 작성한다. 또, xxIxxx.h로부터 xxxxx.h, xxxxx.cpp와 xxxxxModule.cpp를 작성하고 나서 Makefile.in를 작성하고 파이어폭스와 함께 빌드하면 된다.</p><p><br />
</p><p><b>&lt;리스트 1&gt; xxIxxx.idl</b></p><div><p>#include "nsISupports.idl"<br />
[scriptable, uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)]<br />
interface xxIxxx : nsISupports<br />
{<br />
long add(in long a, in long b);<br />
};</p></div><p class="sourcebox"><br />
</p><p>&lt;리스트 1&gt;은 두 개의 숫자를 입력받아 더하는 역할을 하는 xxlxxx.idl 코드다. 이제 다음과 같이 xpidl를 이용하여 xxIxxx.xpt 와 xxIxxx.h를 작성해 보자.</p><div><p>xpidl -m typelib -I c:xxx_gecko_sdk xxIxxx.idl<br />
xpidl -m header -I c:xxx_gecko_sdk xxIxxx.idl</p></div><p class="sourcebox"><br />
</p><p>다음으로 해야 할 일은 xxxxx.ccp를 작성하기 위해 xxIxxx.h에 있는 /* Header file */ 부터 /* Implementation file */ 의 앞까지를 xxxxx.h에 복사한 뒤에 xxxxx()를 virtual xxxxx()로 바꾸는 것이다.</p><p>&lt;리스트 2&gt; xxxxx.h 작성</p><div><p>#ifndef _XX_XXX_H_<br />
#define _XX_XXX_H_<br />
<br />
#include "xxIxxx.h"<br />
<br />
#define XX_XXX_CONTRACTID "@xxx.xxx.kr/xx_ext/xxx;1"<br />
#define XX_XXX_CLASSNAME "This is Sample"<br />
#define XX_XXX_CID {0x00000000, 0x0000, 0x0000, <br />
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}<br />
<br />
// 위의 내용을 앞에 추가한다. XX_XXX_CID 는 xxIxxx.h 의 XXXXX_IID 를 복사한다.<br />
<br />
#endif //_XX_XXX_H_</p></div><p class="sourcebox"><br />
</p><p>xxxxx.cpp는 xxIxxx.h에 있는 /* Implementation file */부터 /* End of implementation class template. */ 까지를 복사하여 만들면 된다.</p><p><br />
</p><p><b>&lt;리스트 3&gt; xxxxx.cpp 작성</b></p><div><p class="sourcebox">#include "xxxxx.h"</p></div><p class="sourcebox"><br />
// 위의 헤더를 추가</p><p>이번에는 모듈 등록을 위해 &lt;리스트 4&gt;와 같이 xxxxxModule. cpp 파일을 만든다.</p><p><br />
</p><p><b>&lt;리스트 4&gt; xxxxxModule.cpp</b></p><div><p>#include "nsIGenericFactory.h"<br />
#include "xxxxx.h"<br />
<br />
NS_GENERIC_FACTORY_CONSTRUCTOR(xxxxx)<br />
<br />
static nsModuleComponentInfo components[] =<br />
{<br />
{<br />
XX_XXX_CLASSNAME, <br />
XX_XXX_CID,<br />
XX_XXX_CONTRACTID,<br />
xxxxxConstructor,<br />
},<br />
};<br />
<br />
NS_IMPL_NSGETMODULE(xxxxxModule, components)</p></div><p class="sourcebox"><br />
</p><p class="sub1"><b>C++ 의 XPCOM on Linux</b></p><p><br />
</p><p>이번에는 리눅스에 C++ XPCOM을 적용하는 방법에 대해 알아볼 것이다. 여기에서는 Debian GNU/Linux를 기준으로 하여 진행한다. 리눅스에서는 .so 형식의 셰어드 라이브러리로 만들어야 한다.</p><p>가장 먼저 다음과 같은 방법으로 작업용 디렉토리를 만든다.</p><p><br />
</p><div><p class="sourcebox">% mkdir -p xpcom-sample/{content/xpcom-sample,components}<br />
% cd xpcom-sample</p></div><p><br />
</p><p>코드를 작성하기 전에 일단 XPCOM을 인스톨 하는 확장 기능을 만들어 보자.</p><p><b>&lt;리스트 5&gt; install.rdf</b></p><div><p class="sourcebox"><rdf xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#">xmlns:em="http://www.mozilla.org/2004/em-rdf#"&gt;<br />
<description about="urn:mozilla:install-manifest"><em:ID>xpcom-sample@imaso.co.kr</em:ID><br />
<em:NAME>XPCOM sample</em:NAME><br />
<em:VERSION>0.1</em:VERSION><br />
<em:DESCRIPTION>XPCOM sample</em:DESCRIPTION><br />
<em:CREATOR>Min-su Kim</em:CREATOR><br />
<br />
<em:TARGETAPPLICATION><br />
<description><br />
<em:ID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:ID><br />
<em:MINVERSION>2.0</em:MINVERSION><br />
<em:MAXVERSION>2.0.0.*</em:MAXVERSION></description></em:TARGETAPPLICATION></description></rdf></p></div><p>파이어폭스의 사용자 유저 인터페이스의 환경을 저장하는 chrome 파일을 확인한다.</p><p><b>&lt;리스트 6&gt; chrome.manifest</b></p><div><p class="sourcebox">content xpcom_sample content/<br />
overlay chrome://browser/content/browser.xul chrome://xpcom_sample/content/overlay.xul<br />
</p></div><p>인스톨러 작성 스크립트도 만든다.</p><p><br />
</p><p><b>&lt;리스트 7&gt; dist.sh</b></p><div><p class="sourcebox">#!/bin/sh<br />
<br />
cd `dirname $0`<br />
<br />
#basename=`basename $PWD`<br />
basename=xpcom-sample<br />
version=`grep '<em:VERSION>' install.rdf | sed -e 's,<!--?EM:VERSION-->,,g'`<br />
version=`echo $version | sed -e 's/[[:space:]]//g'`<br />
<br />
xpi=$basename-$version.xpi<br />
<br />
if [ -f components/Makefile ]; then<br />
(cd components &amp;&amp; make) || exit 1<br />
component_shared="components/myCalc.so"<br />
<br />
component_xpt="components/myICalc.xpt"<br />
components="$component_xpt $component_shared"<br />
fi<br />
xpi_contents="content $components chrome.manifest install.rdf"<br />
<br />
rm -f $xpi<br />
zip -q -r -9 $xpi $xpi_contents -x */.svn/* || exit 1</em:VERSION></p></div><p>&lt;리스트 7&gt;처럼 dist.sh가 만들어졌으면 다음과 같이 입력하여 .xpi를 작성한다.</p><div><p class="sourcebox">% ./dist.sh</p></div><p>현재 디렉토리에 xpcom-sample-0.1.xpi을 인스톨하기 위해 다음과 같이 입력한다.</p><div><p class="sourcebox">% iceweasel xpcom-sample-0.1.xpi</p></div><p>파이어폭스에서 [툴] - [애드 온(add-on)] 메뉴를 선택하여 ‘XPCOM sample’이 인스톨 되어 있는지 확인한다.<br />
자 이제 XPCOM을 사용할 모든 준비가 끝났으니 실제 코드들을 만들어보자.</p><br />
<p class="sub2"><b>IDL의 작성 편집</b></p><br />
<p>가장 먼저 할 일은 components 디렉토리에 myICalc.idl를 작성하는 것이다. components 디렉토리 아래에 작성하여 파이어폭스가 자동으로 XPCOM를 검출해 읽어 들일 수 있도록 해 준다. 그렇게 하지 않으면 수동으로 등록하지 않으면 안 된다.</p><p>IDL 안의 uuid를 uuidgen(참고링크3)로 생성한다. </p><div><p class="sourcebox">% uuidgen<br />
c95498ae-16f5-4b46-8713-2cf79e30d4ef</p></div><p><b>&lt;리스트 8&gt; compornts/myICalc.idl</b></p><div><p class="sourcebox">#include "nsISupports.idl"<br />
[scriptable, uuid(c95498ae-16f5-4b46-8713-2cf79e30d4ef)]<br />
interface myICalc : nsISupports<br />
{<br />
long add(in long a, in long b);<br />
};</p></div><br />
<p class="sub2"><b>.xpt와 .h 생성하기와 편집하기</b></p><br />
<p>IDL이 다 만들어졌다면 이번에는 만들어 놓은 IDL 로부터 .xpt와 .h를 생성할 차례다. xpidl를 사용하여 .xpi와 .h를 만든다. 이 두 파일은 .idl 를 수정할 때마다 만들어야 하므로 Makefile로 만들어 두는 것이 좋다.</p><p>여기에서는 XULRunner를 사용하고 있는데 데비안 이외의 리눅스 환경에서는 GECKO_PATH나 GECKO_XXX_PATH를 변경 할 필요가 있을 것이다.</p><p><b>&lt;리스트 9&gt; components/Makefile</b></p><div><p class="sourcebox">GECKO_PATH = /usr/lib/xulrunner<br />
GECKO_SDK_PATH = $(GECKO_PATH)/sdk<br />
<br />
GECKO_IDL_PATH = $(GECKO_SDK_PATH)/idl<br />
<br />
XPIDL = $(GECKO_PATH)/xpidl<br />
<br />
IDL = myICalc.idl<br />
XPT = myICalc.xpt<br />
IHEADER = myICalc.h<br />
<br />
all: $(XPT) $(IHEADER)<br />
<br />
$(XPT): $(IDL)<br />
$(XPIDL) -m typelib -I$(GECKO_IDL_PATH) $(IDL)<br />
<br />
$(IHEADER): $(IDL)<br />
$(XPIDL) -m header -I$(GECKO_IDL_PATH) $(IDL)<br />
<br />
clean:<br />
rm -f $(XPT) $(IHEADER)</p></div><p>dist.sh를 실행해 .xpi 를 생성한 후에 다시 인스톨한다.</p><div><p class="sourcebox">% ./dist.sh<br />
/usr/lib/xulrunner/xpidl -m typelib -I/usr/lib/xulrunner/sdk/idl myICalc.idl<br />
/usr/lib/xulrunner/xpidl -m header -I/usr/lib/xulrunner/sdk/idl myICalc.idl<br />
% iceweasel xpcom-sample-0.1.xpi</p></div><p>.xpt가 인식되고 있는지 확인하려면 다음과 같이 입력해 보자.</p><div><p class="sourcebox">% grep xpcom-sample /.mozilla/firefox/*/xpti.dat</p></div><p>다음과 같은 결과가 출력되면 .xpt가 정상적으로 인식된 것이다.</p><div><p class="sourcebox">4,.../extentions/xpcom-sample@imaso.co.kr/components</p></div><br />
<p class="sub2"><b>XPCOM의 설치하기</b></p><br />
<p>우선은 myCalc.h를 작성해야 하는데 여기에서도 UUID가 필요하다. 다음과 같이 입력하여 사전에 UUID를 만들어 둔다.</p><div><p class="sourcebox">% uuidgen<br />
8931dfd3-edf3-4b7d-bd44-1da72064f0dc</p></div><p>이렇게 만들어진 uuid를 16진수로 나누어 코드에 적용하기 위해 다음과 같이 포맷을 변환해 두어야 한다.</p><div><p class="sourcebox">8931dfd3-edf3-4b7d-bd44-1da72064f0dc<br />
↓<br />
8931dfd3 edf3 4b7d bd 44 1d a7 20 64 f0 dc<br />
↓<br />
0x8931dfd3 0xedf3 0x4b7d 0xbd 0x44 0x1d 0xa7 0x20 0x64 0xf0 0xdc<br />
↓<br />
{0x8931dfd3, 0xedf3, 0x4b7d, {0xbd, 0x44, 0x1d, 0xa7, 0x20, 0x64, 0xf0, 0xdc}}</p></div><p>이것을 요즘 유행하는 스크립트 언어인 루비를 이용해서 만들어 보자.</p><p><b>&lt;리스트 10&gt; split-uuid.rb</b></p><div><p class="sourcebox">#!/usr/bin/env ruby<br />
<br />
ARGV.each do |uuid|<br />
uuid_components = uuid.split(/-/)<br />
first_components = uuid_components.slice!(0, 3)<br />
second_components = []<br />
uuid_components.each do |uuid_component|<br />
second_components.concat(uuid_component.scan(/../))<br />
end<br />
first_components = first_components.collect do |component|<br />
"0x#{component}"<br />
end.join(", ")<br />
second_components = second_components.collect do |component|<br />
"0x#{component}"<br />
end.join(", ")<br />
puts "{#{first_components}, {#{second_components}}}"<br />
end</p></div><p>혹은 이렇게 한다.</p><p><b>&lt;리스트 11&gt; split-uuid2.rb</b></p><div><p class="sourcebox">#!/usr/bin/env ruby<br />
<br />
ARGV.each do |uuid|<br />
uuid_components = uuid.split(/-/)<br />
first_components = uuid_components.slice!(0, 3)<br />
second_components = uuid_components.inject([]) do |result, component|<br />
result + component.scan(/../)<br />
end<br />
first, second = [first_components, second_components].collect do |components|<br />
components.collect do |component|<br />
"0x#{component}"<br />
end.join(", ")<br />
end<br />
puts "{#{first}, {#{second}}}"<br />
end<br />
</p></div><p>&lt;리스트 10&gt;이나 &lt;리스트 11&gt;과 같이 하면 다음과 같은 두 형식의 UUID가 만들어진다.</p><div><p class="sourcebox">8931dfd3-edf3-4b7d-bd44-1da72064f0dc<br />
{0x8931dfd3, 0xedf3, 0x4b7d, {0xbd, 0x44, 0x1d, 0xa7, 0x20, 0x64, 0xf0, 0xdc}}</p></div><p>헤더 파일은 components/myICalc.h에 있는 것을 카피하여 사용한다.</p><p><b>&lt;리스트 12&gt; components/myCalc.h</b></p><div><p class="sourcebox">#ifndef __MYCALC_H__<br />
#define __MYCALC_H__<br />
<br />
#include "myICalc.h"<br />
<br />
#define MY_CALC_CONTRACT_ID "@imaso.co.kr/xpcom-sample/Calc;1"<br />
#define MY_CALC_CLASS_NAME "Calculator"<br />
#define MY_CALC_CID_STR "8931dfd3-edf3-4b7d-bd44-1da72064f0dc"<br />
#define MY_CALC_CID <br />
{0x8931dfd3, 0xedf3, 0x4b7d, <br />
{0xbd, 0x44, 0x1d, 0xa7, 0x20, 0x64, 0xf0, 0xdc}}<br />
<br />
class myCalc : public myICalc<br />
{<br />
public:<br />
NS_DECL_ISUPPORTS<br />
NS_DECL_MYICALC<br />
<br />
myCalc();<br />
<br />
private:<br />
myCalc();<br />
<br />
protected:<br />
/* additional members */<br />
};<br />
<br />
#endif</p></div><p>cpp도 components/myICalc.cpp에 있으므로 그것을 복사하고 add를 추가한다.</p><p><b>&lt;리스트 13&gt; components/myCalc.cpp</b></p><div><p class="sourcebox">#include "mozilla-config.h"<br />
#include "myCalc.h"<br />
<br />
NS_IMPL_ISUPPORTS1(myCalc, myICalc)<br />
<br />
myCalc::myCalc()<br />
{<br />
/* member initializers and constructor code */<br />
}<br />
<br />
myCalc::myCalc()<br />
{<br />
/* destructor code */<br />
}<br />
<br />
/* long add (in long a, in long b); */<br />
NS_IMETHODIMP myCalc::Add(PRInt32 a, PRInt32 b, PRInt32 *_retval)<br />
{<br />
*_retval = a + b;<br />
return NS_OK;<br />
}<br />
<br />
#include "mozilla-config.h"<br />
#include "myCalc.h"<br />
<br />
NS_IMPL_ISUPPORTS1(myCalc, myICalc)<br />
<br />
myCalc::myCalc()<br />
{<br />
/* member initializers and constructor code */<br />
}<br />
<br />
myCalc::myCalc()<br />
{<br />
/* destructor code */<br />
}<br />
<br />
/* long add (in long a, in long b); */<br />
NS_IMETHODIMP myCalc::Add(PRInt32 a, PRInt32 b, PRInt32 *_retval)<br />
{<br />
*_retval = a + b;<br />
return NS_OK;<br />
}</p></div><p>components/Makefile를 수정하여 컴파일 할 수 있도록 한다.</p><p><b>&lt;리스트 14&gt; components/Makefile</b></p><div><p class="sourcebox">CXX = c++<br />
CXXFLAGS = -g -Wall -fno-rtti -fno-exceptions -shared<br />
<br />
GECKO_PATH = /usr/lib/xulrunner<br />
GECKO_SDK_PATH = $(GECKO_PATH)/sdk<br />
<br />
GECKO_IDL_PATH = $(GECKO_SDK_PATH)/idl<br />
GECKO_INCLUDE_PATH = $(GECKO_SDK_PATH)/include<br />
GECKO_LIB_PATH = $(GECKO_SDK_PATH)/lib<br />
<br />
XPIDL = $(GECKO_PATH)/xpidl<br />
<br />
GECKO_INCLUDES = -I$(GECKO_INCLUDE_PATH)<br />
GECKO_CFLAGS = -DXPCOM_GLUE $(GECKO_INCLUDES)<br />
<br />
GECKO_LDFLAGS = -L$(GECKO_LIB_PATH)<br />
GECKO_LIBS = -lxpcomglue <br />
-lnspr4 <br />
-lplds4<br />
<br />
OBJS = myCalc.o<br />
<br />
IDL = myICalc.idl<br />
XPT = myICalc.xpt<br />
IHEADER = myICalc.h<br />
SHARED = myCalc.so<br />
<br />
all: $(XPT) $(IHEADER) $(SHARED)<br />
<br />
$(XPT): $(IDL)<br />
$(XPIDL) -m typelib -I$(GECKO_IDL_PATH) $(IDL)<br />
<br />
$(IHEADER): $(IDL)<br />
$(XPIDL) -m header -I$(GECKO_IDL_PATH) $(IDL)<br />
<br />
$(SHARED): $(IHEADER) $(OBJS)<br />
$(CXX) $(CXXFLAGS) $(GECKO_LDFLAGS) -o $(SHARED) $(OBJS) $(GECKO_LIBS)<br />
<br />
clean:<br />
rm -f $(XPT) $(IHEADER) $(OBJS) $(SHARED)<br />
<br />
.cpp.o:<br />
$(CXX) $(CXXFLAGS) $(GECKO_CFLAGS) -c $&lt;<br />
</p></div><p><br />
</p><p>dist.sh를 실행해 컴파일 할 때 모질라의 헤더 파일에 warning 메시지가 표시되지만 큰 문제는 없다.</p><p><br />
</p><p class="sub2">컴파일 시 warning 메시지들</p><br />
<div><p class="sourcebox">% ./dist.sh<br />
c++ -g -Wall -fno-rtti -fno-exceptions -shared -DXPCOM_GLUE -I/usr/lib/xulrunner/sdk/include -c myCalc.cpp<br />
/usr/lib/xulrunner/sdk/include/nsISupportsBase.h:80: warning: <br />
‘class nsISupports<br />
＇ has virtual functions but non-virtual destructor<br />
/usr/lib/xulrunner/sdk/include/nsIProgrammingLanguage.h:32: warning: <br />
‘class nsIProgrammingLanguage<br />
＇ has virtual functions but non-virtual destructor<br />
/usr/lib/xulrunner/sdk/include/nsIClassInfo.h:33: warning: <br />
‘class nsIClassInfo<br />
＇ has virtual functions but non-virtual destructor<br />
myICalc.h:25: warning: <br />
‘class myICalc<br />
＇ has virtual functions but non-virtual destructor<br />
c++ -g -Wall -fno-rtti -fno-exceptions -shared -L/usr/lib/ xulrunner/sdk/lib -o myCalc.so myCalc.o -lxpcomglue -lnspr4 -lplds4</p></div><p>이것으로 components/myCalc.so를 만들어 사용 할 수 있다. 하지만, 이것만으로는 아직 부족하다.</p><br />
<p class="sub2"><b>XPCOM 등록하기</b></p><br />
<p>공유 라이브러리가 읽혔을 때에 XPCOM을 등록하는 기능이 필요하다면 그 기능은 &lt;리스트 15&gt;와 같이 components/my CalcModule.cpp로 구현하면 된다.</p><p><b>&lt;리스트 15&gt; components/myCalcModule.cpp</b></p><div><p class="sourcebox">#include "nsIGenericFactory.h"<br />
#include "myCalc.h"<br />
<br />
NS_GENERIC_FACTORY_CONSTRUCTOR(myCalc)<br />
<br />
static nsModuleComponentInfo components[] =<br />
{<br />
{<br />
MY_CALC_CLASS_NAME,<br />
MY_CALC_CID,<br />
MY_CALC_CONTRACT_ID,<br />
myCalcConstructor,<br />
}<br />
};<br />
<br />
NS_IMPL_NSGETMODULE("myCalcModule", components)<br />
</p></div><p>또한 components/Makefile의 OBJS에도 추가한다.</p><p><b>&lt;리스트 16&gt; components/Makefile</b></p><div><p class="sourcebox">...<br />
OBJS = myCalc.o myCalcModule.o<br />
...</p></div><p>예제에서는 myCalc 하나만을 등록하고 있지만 복수의 XPCOM이 하나의 공유 라이브러리에 들어갈 수도 있다. 프로그램 패키지를 묶어서 인스톨하기 위해 다음과 같이 스크립트를 입력한다.</p><div><p class="sourcebox">% ./dist.sh<br />
...<br />
% iceweasel xpcom-sample-0.1.xpi</p></div><p>myCalc가 등록되었는지 확인하려면 다음과 같이 입력한다.</p><div><p class="sourcebox">% grep myCalc /.mozilla/firefox/*/compreg.dat</p></div><p>이렇게 입력한 결과가 다음과 같이 나오면 제대로 등록된 것이다.</p><div><p class="sourcebox">abs:/.../xpcom-sample@imaso.co.kr/components/myCalc. so,1173322260000<br />
{8931dfd3-edf3-4b7d-bd44-1da72064f0dc},,,,abs: /.../myCalc.so</p></div><br />
<p class="sub2">테스트용 인터페이스</p><br />
<p>대화형으로 xul을 사용하여 팝업의 인터페이스를 만들어 자바스크립트의 식을 테스트하는 인터페이스를 만들어 보자.</p><p><b>&lt;리스트 17&gt; content/overlay.xul</b></p><div><p class="sourcebox"><br />
<overlay><br />
id="test-overlay"<br />
xmlns="http://www.mozilla.org/keymaster/gatekeeper/ there.is.only.xul"&gt;<br />
<br />
</overlay></p><p class="sourcebox">oncommand=”<br />
(function () {<br />
var obj;<br />
try {<br />
const cid = '@imaso.co.kr/xpcom-sample/Calc;1';<br />
obj = Components.classes[cid].createInstance();<br />
obj = obj.QueryInterface(Components.interfaces.myICalc);<br />
} catch (err) {<br />
alert!(err);<br />
return;<br />
}<br />
alert!('3 + 4 = ' + obj.add(3, 4));<br />
})();<br />
"/&gt;</p></div><br />
<p>역시 .xpi 를 다시 인스톨 한다.</p><div><p class="sourcebox">% ./dist.sh<br />
% iceweasel xpcom-sample-0.1.xpi</p></div><p>[XPCOM sample] 메뉴에서 [Call sample XPCOM]를 실현한 뒤에 ‘3 + 4 = 7’라는 메시지가 표시되면 성공이다.</p><p><br />
</p><p class="sub1"><b>C++ 의 XPCOM on Mac OS X</b></p><p><br />
</p><p>이번에는 Mac OS X에서 실행되는 C++ XPCOM을 만들어보자. </p><p>Mac OS X에서는 GCC 대신 Xcode를 사용하여 컴파일 한다. Mac에서 라이브러리는 dylib 형식으로 만들기 때문에 리눅스용 Makefile을 사용할 수 없을 뿐 아니라 dist.sh도 변경해야 한다.</p><p>Xcode의 프로젝트는 components/myCalc.xcodeproj/ 에 위치한다.</p><p>가장 먼저 &lt;리스트 18&gt;과 같이 dist.sh를 수정해 보자.</p><p><b>&lt;리스트 18&gt; Mac OS X 환경에 맞게 인스톨 패스와 파일 확장자를 수정한 dist.sh</b></p><div><p class="sourcebox">#!/bin/sh<br />
<br />
cd dirname $0<br />
<br />
if [ -x "which gnused" ]; then<br />
SED=gnused<br />
else<br />
SED=sed<br />
fi<br />
<br />
#basename=basename $PWD<br />
basename=xpcom-sample<br />
version=grep '<em:VERSION>' install.rdf | $SED -e 's,<!--?EM:VERSION-->,,g'<br />
version=echo $version | $SED -e 's/[[:space:]]//g'<br />
<br />
xpi=$basename-$version.xpi<br />
<br />
case uname in<br />
Linux)<br />
(cd components &amp;&amp; make) || exit 1<br />
component_shared="components/myCalc.so"<br />
;;<br />
Darwin)<br />
build_type=Release<br />
xcodebuild_args="-project myCalc.xcodeproj -configuration $build_type"<br />
(cd components &amp;&amp; xcodebuild $xcodebuild_args) || exit 1<br />
component_shared="components/libmyCalc.dylib"<br />
cp components/build/$build_type/libmyCalc.dylib $component_shared<br />
;;<br />
*)<br />
echo "Unknown environment"<br />
exit 1<br />
;;<br />
esac<br />
<br />
component_xpt="components/myICalc.xpt"<br />
components="$component_xpt $component_shared"<br />
<br />
xpi_contents="content $components chrome.manifest install.rdf"<br />
<br />
rm -f $xpi<br />
zip -q -r -9 $xpi $xpi_contents -x */.svn/* || exit 1</em:VERSION></p></div><p>Mac OS X의 gecko-sdk에는 xpidl이 들어있는데, 여기에는 요즘은 오래된 버전의 glib와 libIDL이 포함되어 있다. 이 정도의 버전은 최근의 MacPorts로는 가져오기가 어렵기 때문에 Linux에서 생성한 .xpt와 .h를 불러와서 사용해야 한다.</p><p>다음과 같이 dist.sh를 실행하여 .xpi를 작성한다.</p><div><p class="sourcebox">% ./dist.sh</p></div><p>만들어진 xpcom-sample-0.1.xpi를 파이어폭스에 마우스로 드래그앤드롭하면 인스톨 되고 메뉴에 [XPCOM sample]이 표시된다. [Call sample XPCOM]를 선택하여 ‘3 + 4 = 7’라는 메시지가 표시되면 성공이다.</p><p>커맨드 라인으로부터 확인하려면 리눅스에서와 마찬가지로 다음과 같이 입력하면 된다.</p><div><p class="sourcebox">% grep myICalc /Library/Application Support/Firefox/Profiles/ */xpti.dat</p></div><p><br />
</p><p class="sub1"><b>Xcode 프로젝트 작성하기</b></p><p><br />
</p><p>다음은 Xcode 프로젝트를 작성하는 과정을 간략하게 설명한 것이다. 지면 관계상 각 단계들을 일일이 설명할 수 없는 탓이다. 어려운 과정이 아니므로 다음 과정들을 참고하여 Xcode 프로젝트를 만들어보자.</p><blockquote><div><p>1. 파일 → 신규 프로젝트</p><p>2. 프로젝트<br />
· 프로젝트명: myCalc<br />
· 디렉토리: .../xpcom-sample/components/</p><p>3. 왼쪽의 myCalc 라는 곳에서 오른쪽 클릭<br />
· 추가 → 신규 타깃<br />
· BSD/Dynamic Library<br />
- 타깃 명: myCalc</p><p>4. [타깃 myCalc의 정보] 대화상자가 나타나면 지운다.</p><p>5. 왼쪽의 myCalc라는 곳에서 오른쪽 클릭<br />
· 추가 → 기존의 파일<br />
· myCalc.cpp, myCalc.h myCalcModule.cpp, myCalc.h를 선택, 정리하여 추가<br />
· prompt가 나오면 디폴트 추가(타깃으로 추가한 조금 전 만든 myCalc에 체크가 있는 것을 확인)</p><p>6. 왼쪽의 myCalc라는 곳에서 더블 클릭<br />
· [프로젝트 myCalc의 정보] 대화상자가 표시된다<br />
· [일반] 탭 → [타깃 SDK를 사용한 크로스 개발]: [Mac OS X 10.4 (Universal)]<br />
· [빌드] 탭 → [구성]: [모든 구성]<br />
· [아키텍처] → 아래쪽에 있는 [편집] 버튼: [PowerPC]와 [Intel]에 체크<br />
· [헤더 검색 패스] → 아래쪽에 있는 [편집]버튼: 아래에 있는 [+] 버튼을 누르고 항목을 늘려 gecko-sdk/include에 패스를 정한다<br />
- 상대 패스로 하는 경우에는 소스 중에서 components/ 디렉토리로부터 지정<br />
- 샘플 소스 중에서는 톱 디렉토리(xpcom-sample)와 같은 디렉토리에 gecko-sdk로 있다<br />
· [라이브러리 검색 패스] → 아래쪽에 있는 [편집] 버튼: 아래에 있는 [+] 버튼을 누르고 항목을 늘려 Firefox.app/Contents/Mac OS에 패스워드를 정한다<br />
- 샘플 소스 중에서는 /Applications/ 이하에 Firefox.app 하지만 인스톨 되어 있다<br />
· [다른 링커 옵션] → 아래쪽에 있는 [편집] 버튼: 아래에 있는 [+] 버튼을 5회 누르고 항목을 늘려, 각각 [-lxpcom_core]와 [-lxpcom], [-lnspr4], [-lplds4], [-lplc4] 추가</p><p>7. 메뉴로부터 [빌드] → [모든 타깃을 클리닝]</p><p>8. 메뉴로부터 [빌드] → [빌드]</p><p>9. 메인 윈도우의 왼쪽의 [에러와 경고]를 보고 경고·에러가 나와 있지 않은 것을 확인</p></div></blockquote><br />
<p class="sub2"><b>비주얼 스튜디오의 솔루션 작성 방법</b></p><br />
<p>다음은 비주얼 스튜디오에서 솔루션을 작성하는 방법을 간단히 정리한 것이다. 만약 비주얼 스튜디오의 사용법이 익숙지 않다면 다음 내용을 참조하여 솔루션을 작성해 보자.</p><blockquote><div><p>1. 파일 → 신규 작성 → 프로젝트</p><p>2. Visual C++ → 프로젝트<br />
· 프로젝트명: myCalc<br />
· 장소: .../xpcom-sample/components/<br />
· 솔루션의 디렉토리를 작성: 체크 하지 않음</p><p>3. 완료</p><p>4. 왼쪽의 myCalc → 원시 파일로 오른쪽 클릭<br />
· 추가 → 기존의 항목 → 상의 폴더에 말해 myCalc.cpp와 myCalcModule.cpp 선택 → 추가</p><p>5. 왼쪽의 myCalc → 헤더 파일로 오른쪽 클릭<br />
· 추가 → 기존의 항목 → 상위 폴더에서 myCalc.h와 myICalc.h를 선택 → 추가</p><p>6. 프로젝트 → myCalc 의 프롭퍼티<br />
· 왼쪽 위의 드롭다운 리스트의 구성: 모든 구성<br />
· 구성 프로퍼티 → C/C++ → 전반 → 추가의 인클루드 디렉토리<br />
- ......gecko-sdkinclude(xpcom-sample와 같은 레벨의 gecko-sdk)<br />
· 구성 프롭퍼티 → 링커 → 전반 → 추가의 라이브러리 디렉토리<br />
- ......gecko-sdklib(xpcom-sample와 같은 레벨에 gecko-sdk)<br />
· 구성 프롭퍼티 → 링커 → 입력 → 추가의 의존 파일<br />
- xpcomglue_s.lib xpcom.lib nspr4.lib<br />
- Rlease로 구성하여 libcmt.lib 추가<br />
- 구성을 모든 구성에 되돌린다<br />
· 구성 프롭퍼티 → 링커 → 입력 → 특정의 라이브러리의 무시<br />
- MSVCRT<br />
· 구성 프롭퍼티 → 링커 → 마니페스트 → 마니페스트의 생성<br />
- 아니오<br />
</p></div></blockquote><br />
<p>다음과 같이 나오면 .xpt의 인스톨은 성공한 것이다.</p><br />
<div><p class="sourcebox">142,myICalc.xpt,6,134,1173341340000<br />
1294,myICalc,{c95498ae-16f5-4b46-8713-2cf79e30d4ef},142,-1,1</p></div><p>이번에는 XPCOM이 정상적으로 인스톨 되었는지 확인하기 위해 다음과 같이 입력해 본다.</p><div><p class="sourcebox">% grep myCalc /Library/Application Support/Firefox/Profiles/*/ compreg.dat</p></div><p>입력한 내용의 성공 메시지는 다음과 같다.</p><div><p class="sourcebox">abs:/.../xpcom-sample@imaso.co.kr/components/libmyCalc. dylib,1173345060000<br />
{8931dfd3-edf3-4b7d-bd44-1da72064f0dc},,,,abs:/.../ libmyCalc.dylib</p></div><p><br />
</p><p class="sub1"><b>C++ 의 XPCOM on 윈도우</b></p><p><br />
</p><p>윈도우에서의 XPCOM 확장자(extension)는 .dll이다. 또, 비주얼 스튜디오는 Makefile이 아니라, 솔루션 파일을 사용해 컴파일 한다. 이런 특징에 유연하게 대처하려면 dist.sh를 변경해야 한다.</p><p>비주얼 스튜디오 8의 솔루션 파일은 components/myCalc/my Calc.sln에 배치하기로 한다. 또, devenv.exe(비주얼 스튜디오 8의 커맨드 명)에 패스워드가 걸리지 않은 경우는 C:Program Files\Microsoft Visual Studio 8\Common7IDE\devenv.exe 에 있다고 가정한다.</p><p><b>&lt;리스트 19&gt; 윈도우 환경에 맞게 인스톨 패스와 파일 확장자를 수정한 dist.sh</b></p><div><p class="sourcebox">#!/bin/sh<br />
cd dirname $0<br />
if [ -x "which gnused 2&gt;&amp;1 /dev/null" ]; then<br />
SED=gnused<br />
else<br />
SED=sed<br />
fi<br />
#basename=basename $PWD<br />
basename=xpcom-sample<br />
version=grep '<em:VERSION>' install.rdf | $SED -e 's,<!--?EM:VERSION-->,,g'<br />
version=echo $version | $SED -e 's/[[:space:]]//g'<br />
xpi=$basename-$version.xpi<br />
case uname in<br />
Linux)<br />
(cd components &amp;&amp; make) || exit 1<br />
component_shared="components/myCalc.so"<br />
;;<br />
Darwin)<br />
build_type=Release<br />
xcodebuild_args="-project myCalc.xcodeproj -configuration $build_type"<br />
(cd components &amp;&amp; xcodebuild $xcodebuild_args) || exit 1<br />
component_shared="components/libmyCalc.dylib"<br />
cp components/build/$build_type/libmyCalc.dylib $component_shared<br />
;;<br />
CYGWIN*)<br />
build_type=Release<br />
if which devenv &gt; /dev/null; then<br />
DEVENV="devenv"<br />
else<br />
DEVENV="/cygdrive/c/Program Files/Microsoft Visual Studio 8/Common7/IDE/devenv.exe"<br />
fi<br />
"$DEVENV" /Build $build_type components/myCalc/myCalc.sln || exit 1<br />
component_shared="components/myCalc.dll"<br />
cp components/myCalc/$build_type/myCalc.dll $component_shared<br />
;;<br />
*)<br />
echo "Unknown environment"<br />
exit 1<br />
;;<br />
esac<br />
<br />
component_xpt="components/myICalc.xpt"<br />
components="$component_xpt $component_shared"<br />
<br />
xpi_contents="content $components chrome.manifest install.rdf"<br />
<br />
rm -f $xpi<br />
zip -q -r -9 $xpi $xpi_contents -x */.svn/* || exit 1<br />
</em:VERSION></p></div><br />
<p class="sub2"><b>.xpt 와 .h 의 생성</b></p><br />
<p>윈도우용의 gecko-sdk에 들어 있는 xpidl은 오래된 버전의 glib와 libIDL이 컴파일 되어 있다. 이것은 다음과 같이 하면 확인할 수 있다.</p><div><p class="sourcebox">% objdump -p ../gecko-sdk/bin/xpidl.exe | grep -i dll<br />
DllCharacteristics 00000000<br />
vma: Hint Time Forward DLL First<br />
DLL Name: libIDL-0.6.dll<br />
DLL Name: glib-1.2.dll<br />
DLL Name: MSVCRT.dll</p><p>xpidl의 옵션은 리눅스와 같아서 생략한다.</p></div><br />
<p class="sub2"><b>인스톨 편집</b></p><br />
<p>다른 OS에서와 마찬가지로 다음과 같이 dist.sh를 실행해하여 .xpi를 작성한다.</p><div><p class="sourcebox">% ./dist.sh</p></div><p>인스톨 하려면 다른 플랫폼과 똑같이 xpcom-sample-0.1.xpi를 파이어폭스에 드래그앤드롭하면 인스톨 된다. 메뉴에 [XP COM sample]이 표시되면 [Call sample XPCOM]를 실행시켜 ‘3 + 4 = 7’라는 메시지가 표시되는지 확인한다.</p><p>인스톨 여부를 커맨드 라인에서 확인하려면 다음과 같이 입력한다.</p><div><p class="sourcebox">% grep myICalc /cygdrive/c/Documents and Settings/$USER/ Application Data/Mozilla/Firefox/Profiles/*/xpti.dat</p></div><p>다음과 같은 결과가 표시되면 .xpt의 인스톨은 성공이다.</p><div><p class="sourcebox">4,myICalc.xpt,3,134,1173668700000<br />
587,myICalc,{c95498ae-16f5-4b46-8713-2cf79e30d4ef},4,-1,1</p></div><p>마지막으로 XPCOM이 인스톨 되었는지 확인하기 위해 다음과 같이 입력하면 된다.</p><div><p class="sourcebox">% grep myCalc /cygdrive/c/Documents and Settings/$USER /Application Data/Mozilla/Firefox/Profiles/*/compreg.dat</p></div><p>XPCOM 인스톨 확인 메시지는 다음과 같다.</p><div><p class="sourcebox">abs:C:\...\xpcom-sample@imaso.co.kr\components\ myCalc.dll,1173763800000<br />
{8931dfd3-edf3-4b7d-bd44-1da72064f0dc},,,,abs:C:\ ...\myCalc.dll</p></div><p>지금까지 각 운영체제별 XPCOM 개발 예제에 대해 간단히 알아보았다. 지면 한계상 의도했던 내용의 절반 정도 밖에는 소개하지 못하여 아쉬움이 남는다. 하지만 우리에겐 인터넷과 커뮤니티가 있다. 아직 한국의 모질라 개발자 커뮤니티 등에는 다양한 자료와 질문, 답변들이 준비되어 있다. 특집 4부의 내용을 기반으로 커뮤니티의 자료들을 참고하면 XPCOM에 대해 좀 더 다양한 지식들을 얻을 수 있을 것이다. </p><br />
<a href="http://www.dbguide.net/" target="_blank"><b><font color="midnightblue">제공 : DB포탈사이트 DBguide.net </font></b></a><br/><br/>tag : <a href="/tag/ajax" rel="tag">ajax</a>,&nbsp;<a href="/tag/표준" rel="tag">표준</a>,&nbsp;<a href="/tag/mozilla" rel="tag">mozilla</a>,&nbsp;<a href="/tag/파이어폭스" rel="tag">파이어폭스</a>,&nbsp;<a href="/tag/xpt" rel="tag">xpt</a>,&nbsp;<a href="/tag/호환성" rel="tag">호환성</a>,&nbsp;<a href="/tag/ui" rel="tag">ui</a>,&nbsp;<a href="/tag/웹" rel="tag">웹</a>			 ]]> 
		</description>
		<category>Trend</category>
		<category>ajax</category>
		<category>표준</category>
		<category>mozilla</category>
		<category>파이어폭스</category>
		<category>xpt</category>
		<category>호환성</category>
		<category>ui</category>
		<category>웹</category>

		<comments>http://topic.egloos.com/508843#comments</comments>
		<pubDate>Mon, 06 Aug 2007 06:15:12 GMT</pubDate>
		<dc:creator>Hans</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 액티브X 대체기술 3부 - Ajax를 이용한 UI개발 ]]> </title>
		<link>http://topic.egloos.com/508713</link>
		<guid>http://topic.egloos.com/508713</guid>
		<description>
			<![CDATA[ 
  <p class="title1">더 큰 세상으로 가는 문<br />
액티브X 대체기술 </p><br />
<p class="author">기획/정리 l 전희용 기자 flytgr@imaso.co.kr</p><br />
<p class="contentsbox">마소 독자치고 액티브X 문제와 무관하다고 할 수 있는 사람은 별로 없을 것이다. 그런데, 참 이상한 일은 액티브X 이야기만 나오면 문제의 원인이나 해결책을 이야기하기 보단 목에 핏대부터 세운다. 누군가를 탓하기 위함이다. 하지만 막상 따지고 보면 누구의 잘못이라고 하기는 어려운 일이다. 워낙 오랫동안 쌓아온 일이기 때문이다. 그렇다고 곪을 대로 곪은 상처를 그냥 놓아둘 수도 없는 일. 이번 달 특집에서는 이 상처의 원인에 대해 알아보고, 그 치료방법인 액티브X의 대체 기술들에 대해서도 함께 알아본다. 다들 잘 알다시피 아직 액티브X를 1대1로 대신해 줄 수 있는 기술은 없다. 하지만, 여러 기술들을 이용하여 산적한 문제들을 보완하며 차츰 치료해 나갈 수는 있을 것이다. 깊이 박힌 상처가 하루아침에 낫는 걸 보았는가?</p><br />
<table bgcolor="#999999" border="0" cellpadding="5" cellspacing="1" width="100%"><tbody><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3187" target="_blank">1부 | 백조에서 미운오리로 전락한 액티브X 문제와 해결방안 | 정희용</a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3188" target="_blank">2부 | 발등의 불끄기 공인인증서 대체기술 | 최상훈</a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/comb/common/edit/1%BA%CE%20%7C%20%B9%E9%C1%B6%BF%A1%BC%AD%20%B9%CC%BF%EE%BF%C0%B8%AE%B7%CE%20%C0%FC%B6%F4%C7%D1%20%BE%D7%C6%BC%BA%EAX%20%B9%AE%C1%A6%BF%CD%20%C7%D8%B0%E1%B9%E6%BE%C8%20%7C%20%C1%A4%C8%F1%BF%EB" target="_blank"><b>3부 | UI 대체는 내게 맡겨라 Ajax를 이용한 UI 개발 | 박영록</b></a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3190" target="_blank">4부 | 액티브X 뛰어넘는 기능과 호환성 XPCOM 개발전략 | 김민수</a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3191" target="_blank">5부 | MS가 내놓은 액티브X의 대안 실버라이트 활용법 | 한용희</a></font></td></tr></tbody></table><br />
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr></tr></tbody></table><br />
<p style="font-weight: bold;" class="title1">UI 대체는 내게 맡겨라<br />
Ajax를 이용한 UI 개발</p><br />
<p class="contentsbox">액티브X를 사용하는 가장 큰 이유 두 가지는 클라이언트 자원을 이용할 수 있다는 점과 윈도우의 UI 컴포넌트를 쉽게 사용할 수 있다는 점이다. Ajax는 이 두 가지 용도를 모두 만족시킬 수는 없지만 고급 UI를 필요로 하는 애플리케이션까지 Ajax로 만들 수 있을 정도로 강력한 UI 기능을 지원한다. 특집 3부에서는 이점에 포커싱하여 Ajax로 액티브X를 대체하는 방법들에 대해 알아본다.</p><br />
<p class="author">박영록 | poci@ncsoft.net | 오픈마루 개발자</p><br />
<br />
<p>먼저 액티브X가 할 수 있는 일에 대해서 알아보자. 크게 두 가지로 분류할 수 있을 것 같다. 하나는 클라이언트의 자원을 이용하는 일이다. 웹 브라우저의 보안 모델에서는 클라이언트의 자원 중 일부분만 접근할 수 있는데 액티브X를 사용하면 클라이언트의 거의 모든 자원을 이용할 수 있다. 인터넷 뱅킹을 할 때 뜨는 키보드 보안 모듈은 하드웨어 제어를 통해 키보드의 입력을 다른 프로그램이 해킹하지 않는지 감시하는 것이다. 바이러스 검사 프로그램 같은 건 클라이언트의 파일 시스템에 접근할 수 있기 때문에 가능한 것이고 자신의 PC를 다른 사설 네트워크(주로 회사 네트워크)에 소속된 것처럼 만들어주는 VPN(가상 사설 네트워크) 프로그램도 클라이언트의 네트워크 자원을 이용할 수 있기 때문에 가능한 것이다. 물론 게임도 가능하다. 이처럼 클라이언트의 자원을 마음대로 활용할 수 있기 때문에 강력한 도구가 되기도 하지만 스파이웨어 같은 도구로 악용되기도 한다. </p><p>또 다른 하나는 윈도우의 UI 컴포넌트들을 쉽게 활용할 수 있다는 것이다. 기본적인 컴포넌트 외에는 모두 직접 만들어야 하는 HTML과는 달리 윈도우의 UI 컴포넌트는 종류도 많고 완성도가 높은데다 GUI 생성 툴도 좋기 때문에 기능성이 높은 UI를 쉽게 만들 수 있다. 그래서 고객이 제한된 SI(시스템 통합) 프로젝트에서는 복잡한 요구사항을 처리하기 위해 액티브X를 선택하는 경우가 많다. 간혹 더 화려하고 막강한 UI를 위해서 액티브X를 쓴다고 하기도 하는데 실상 HTML과 CSS, 자바스크립트로도 고수준 UI를 만드는 일이 그리 어려운 일은 아니다. 그보다 이미 준비되고 검증된 UI 컴포넌트가 많고 겉보기 UI만 만들 수 있는 HTML 위지윅 도구에 비해 동작까지 세밀하게 조정할 수 있는 비주얼 스튜디오가 더 편리하다는 점이 중요하게 작용하는 것 같다. </p><p>그럼 Ajax가 할 수 있는 일은 무엇일까. Ajax는 원래는 웹에서 비동기 통신을 하는 기술을 일컫는 말이었다. 하지만 요즘은 의미가 확장되어 DHTML, CSS, 자바스크립트를 포괄하는 개념으로 이야기되기도 한다. 여기서도 이런 넓은 의미의 개념을 Ajax에 적용하는 것이 적절할 듯하다. 이런 측면에서 본다면 Ajax가 대체할 수 있는 것은 앞의 두 가지 중 후자다. Ajax 역시 웹 브라우저 보안 모델을 넘어서진 못하기 때문에 전자의 문제는 전혀 해결할 수 없다. 그런 면에서 Ajax는 액티브X의 완전한 대안은 아닌 셈이다. 하지만 후자의 경우는 상당히 많은 부분을 대체할 수 있다. 요즘에는 워드프로세서나 스프레드시트처럼 고급 UI를 필요로 하는 애플리케이션도 액티브X를 전혀 쓰지 않고 만들어내는 경우도 볼 수 있을 정도다.</p><p><br />
 </p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246685" localfile="yes" postid="38905412"><br />
&lt;화면 1&gt; 위키 기반 웹노트 서비스 : 스프링노트</p><p align="center"><br />
</p><p>특집 3부에서는 Ajax로 액티브X를 대체하는 몇 가지 사례들에 대해 알아볼 것이다. 가급적 추상적인 이야기들보다는 코드로 이야기하면서 자바스크립트와 HTML/CSS로 UI를 만들어 나가는 것이 생각보다 쉽고 재미있다는 사실을 보여주고 싶다. </p><br />
<br style="font-weight: bold;"><p style="font-weight: bold;" class="sub1">HTML WYSIWYG 에디터 만들기</p><br />
<br />
<p>과거 단순 텍스트만 저장하던 게시판이 점점 진화하여 다양한 스타일을 표현하려는 욕구가 강해지면서 카페나 블로그 등에도 액티브X나 자바 애플릿으로 만든 에디터가 많이 채용되었다. 그런데 요즘에는 액티브X 에디터들이 순수 HTML/자바스크립트 에디터가 점차 늘어나는 추세다. 최신 웹 브라우저들에 위지윅(WYSIWYG) 에디터가 탑재되면서 액티브X 없이 구현할 수 있게 된 것이다. 웹 브라우저에 내장된 위지윅 에디터를 사용하면 게시판 등에 위지윅 에디터를 붙이는 일은 별로 어렵지 않다. 이미 오픈소스로 완성도 높은 에디터도 많이 나와 있지만 여기서는 직접 만들어보자. 파이어폭스와 IE의 API가 조금씩 다르기 때문에 그 차이점도 조금 살펴볼 것이다. </p><br />
<br />
<br />
<p style="font-weight: bold;" class="sub2">HTML 편집 모드</p><br />
<p>위지윅 에디터를 이용하는 방법은 두 가지다. 하나는 자바스크립트에서 document.designMode에 ‘on’ 값을 주는 것이다. 그러면 페이지 전체가 에디팅 할 수 있는 모드로 바뀌게 된다. 이 방법은 파이어폭스와 IE 모두 동작한다. &lt;리스트 1&gt;을 보자. </p><p><b>&lt;리스트 1&gt; Hello World</b></p><p class="sourcebox"><br />
</p><h2>Hello</h2>World<br />
<br />
<p>&lt;리스트 1&gt;을 브라우저로 열면 &lt;화면 2&gt;와 같이 보인다. </p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246686" localfile="yes" postid="38905412"><br />
&lt;화면 2&gt; &lt;리스트1&gt;의 실행 결과</p><p align="center"><br />
</p><p>겉보기론 별 다를 바 없어 보이지만 이 페이지는 브라우저상에서 편집이 가능하다. 만약 e와 l 사이에 커서가 있는 상태에서 a를 입력하면 Heallo가 보일 것이다. 물론 스타일은 주변 스타일을 그대로 유지한다. 화살표 키로 이동하는 것도 일반 에디터와 비슷하고 글자를 입력하거나 지우는 것도 비슷하다. 웹 브라우저 자체에서 키 입력을 받아서 HTML 문서의 DOM 객체를 수정하는 것이다. 그래서 DOM Inspector 등으로 보면 <br />
</p><font size="2">엘리먼트의 내용이 Heallo로 바뀌는 것을 볼 수 있다.<br />
<br />
 </font><p><font size="2">IE에는 designMode와는 별개로 또 contentEditable이라는 속성이 있다. designMode가 HTML 문서 전체를 편집할 수 있도록 하는데 반해 contentEditable 속성은 document 객체의 속성이 아니라 엘리먼트의 속성으로 HTML 문서의 일부분만 편집할 수 있도록 할 수 있다. div나 span, a 등의 엘리먼트에 적용할 수 있다. 그래서 웹 에디터를 만들기는 파이어폭스보다 IE가 조금 더 쉽다. 반면 designMode는 문서 전체를 편집할 수 있도록 만들기 때문에 메뉴나 내비게이션까지 지워버릴 수도 있고 또 designMode에서는 링크를 클릭해도 이동하지 않기 때문에 지우지 않더라도 동작하지 않는다. 그래서 designMode만 지원하는 브라우저에서는 위지윅 에디터를 만들 때 iframe을 사용한다. iframe 안에 designMode를 켠 문서를 넣고 바깥에 메뉴나 내비게이션이 있는 문서는 designMode를 끈 상태로 놔두는 것이다. 그러면 iframe 영역만 자유롭게 편집할 수 있다. &lt;리스트 2&gt;와 비슷한 식으로 만들면 된다.</font></p><p><font size="2"><br />
 </font></p><p><font size="2"><b>&lt;리스트 2&gt; 에디터 기본 틀</b></font></p><p class="sourcebox"><font size="2"><br />
</font></p><div><font size="2"><br />
<a href="http://www.dbguide.net/com/..." target="_blank">메뉴1</a><br />
<a href="http://www.dbguide.net/com/..." target="_blank">메뉴2</a><br />
<a href="http://www.dbguide.net/com/..." target="_blank">메뉴3</a><br />
</font></div><font size="2"><br />
<br />
</font><p><font size="2">&lt;리스트 2&gt;를 실행하면 &lt;화면 3&gt;과 같이 표시된다. 이때, 박스 바깥은 일반 웹페이지처럼 동작하고 박스 안의 영역은 편집 가능한 상태가 된다. 윈도우 프로그래밍으로 비유한다면 RichEdit 컨트롤을 사용할 수 있게 된 셈이다. 하지만 이것만으로는 완전한 에디터가 될 수 없다. 위지윅 상태의 문서를 그 스타일 그대로 글을 쓰거나 지우거나 할 수는 있지만 새로운 스타일로 글을 쓰지는 못하기 때문이다. 예를 들어 World에서 첫 번째 예제 코드의 </font></p><p><font size="2">World</font></p><font size="2">부분을 편집할 때 or 부분을 지우거나 다른 글자로 바꿀 수는 있어도 이 부분만 강조하기 위해 </font><p><font size="2">W<strong> or</strong>ld</font></p><font size="2">와 같이 만들 수는 없다. 쉽게 말하면 새로운 태그를 삽입할 수단이 없다. 엔터키를 누르면</font> <p><font size="2">태그나 <br />
태그가 삽입되는 게 전부이다. </font></p><p align="center"><font size="2"><img src="http://tfile.nate.com/download.asp?FileID=32246687" localfile="yes" postid="38905412"><br />
&lt;화면 3&gt; &lt;리스트 2&gt;의 결과화면</font></p><p align="center"><font size="2"><img src="http://tfile.nate.com/download.asp?FileID=32246688" localfile="yes" postid="38905412"><br />
&lt;화면 4&gt; tinyMCE</font></p><p align="center"><font size="2"><br />
</font></p><p><font size="2">그래서 에디터를 완성하기 위해서는 여러 가지 버튼들을 붙이고 단축키를 할당해서 새로운 태그를 삽입할 수 있게 해야 한다. 다음은 오픈소스 에디터인 tinyMCE의 화면 중 하나인데 이처럼 만들어야 완성된 에디터가 되는 것이다. </font></p><font size="2"><br />
</font><p style="font-weight: bold;" class="sub2"><font size="2">Bold 버튼 만들기</font></p><font size="2"><br />
</font><p><font size="2">여기서는 간단하게 선택된 부분을 Bold로 강조하는 버튼을 만들어서 붙여보자. 먼저, 윈도우 프로그래밍에서 RichEdit 컨트롤을 쓰려면 갖다 붙이는 것뿐만 아니라 RichEdit 컨트롤의 API를 알아야 하듯이 웹 에디터에서도 웹 브라우저에서 제공하는 에디터의 API를 알아야 한다. 이것도 파이어폭스와 IE가 약간 다르긴 하지만 상당히 비슷한 편이다. 둘 다 document 객체에서 execCommand라는 메소드를 사용할 수 있다. execCommand의 사용법은 다음과 같다.</font></p><p><font size="2"><br />
 </font></p><p><font size="2">bSuccess = object.execCommand(sCommand [, bUserInterface] [, vValue])</font></p><p><font size="2"><br />
</font></p><p><font size="2">IE에서는 selection 객체나 range 객체에도 이 메소드를 사용할 수 있다. 첫 번째 sCommand는 실행할 명령의 종류, 두 번째는 UI가 붙느냐 아니냐인데 일단은 무조건 false를 준다고 생각하면 된다. 세 번째는 명령을 실행하는데 부가적으로 필요한 값들을 넘겨주는 것이다. 대부분의 편집 API는 이 execCommand 메소드 하나에서 sCommand를 다양하게 바꿔가면서 실행하게 된다. sCommand의 종류로는 bold, createlink, fontname, fore color, formatblock 등 에디터에 필요한 다양한 것들이 있으며 자세한 내용은 파이어폭스 사이트나 MSDN에서 찾아볼 수 있다. </font></p><p><font size="2">여기서는 강조하는 버튼을 붙일 것이므로 필요한 커맨드는 bold다. 바로 앞의 예제 코드에서 div 태그 안에 &lt;리스트 3&gt;과 같은 코드를 삽입해보자.</font></p><p><font size="2"><br />
 </font></p><p><font size="2"><b>&lt;리스트 3&gt; 강조 버튼</b></font></p><p class="sourcebox"><font size="2"><br />
<a href="http://www.dbguide.net/com/#" target="_blank">강조</a></font></p><p class="sourcebox"><font size="2"><a href="http://www.dbguide.net/com/#" target="_blank"><br />
</a></font></p><p><font size="2">그리고 웹 브라우저에서 다시 html 파일을 열어보자. 링크가 하나 더 생겼다. 이제 편집을 하다가 강조 링크를 누르면 그 다음부터 입력하는 글자는 진하게 표시될 것이다. 일부분을 선택하고 강조 링크를 누르면 그 부분만 강조된다. 이런 식으로 에디터에 필요한 다양한 기능들을 추가하면 앞서 본 tinyMCE와 같은 웹 에디터를 만들 수 있다.</font></p><p><br />
</p><p><font size="2"><br />
</font></p><p align="center"><font size="2"><img src="http://tfile.nate.com/download.asp?FileID=32246689" localfile="yes" postid="38905412"><br />
&lt;화면 5&gt; &lt;리스트 3&gt;의 결과화면</font></p><p><font size="2">이처럼 생각보다 웹 에디터를 만드는 일이 어렵지 않음을 알 수 있다. 하지만 그렇다고 또 쉬기만 한 일도 아니다. 브라우저마다 동작이 조금씩 다르고 웹 브라우저에 내장된 에디터에 버그가 많기 때문이다. 그래서 tinyMCE 같은 에디터에서는 이런 부분을 많이 수정해 놓았고 필자가 개발에 참여했던 스프링노트에서도 처음에는 tinyMCE를 쓰다가 수많은 버그를 견디지 못하고 에디터를 처음부터 다시 만들기도 했다. 아무튼 이제 사용자들에게 액티브X를 설치하도록 강요하지 않고도 꽤 괜찮은 수준의 위지윅 에디터를 제공할 수 있다는 것은 희망적인 일이다. </font></p><font size="2"><br />
</font><p style="font-weight: bold;" class="sub1"><font size="2">드래그 앤 드롭 기능 만들기</font></p><font size="2"><br />
<br />
</font><p><font size="2">웹 페이지 내에서의 드래그 앤 드롭도 자바스크립트와 CSS만으로 구현할 수 있다. 드래그 앤 드롭은 윈도우처럼 웹 브라우저 내의 대화상자를 끌어서 움직인다든지, 트리에서 항목을 끌어서 옮기는 등 다양한 응용이 가능하기 때문에 직관적인 UI를 만드는데 유용하다. 만드는 방법도 어렵지 않다. 우선 CSS에는 절대 좌표로 특정 엘리먼트의 위치를 지정할 수 있는 기능이 있다. 자바스크립트에서는 다음과 같은 코드로 CSS style을 지정할 수 있다.</font></p><p><font size="2"><br />
 </font></p><p class="sourcebox"><font size="2">element.style.top = ‘200px’<br />
element.style.left = ‘150px’</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">이것은 element를 위에서 200 픽셀, 왼쪽에서 150 픽셀의 위치에 놓으라는 것이다. 이 기능을 이용하면 특정 엘리먼트의 위치를 마음대로 조정할 수 있다. 또, 자바스크립트에서는 마우스 이벤트를 잡아내서 그 지점의 좌표를 알아낼 수 있다. 마우스를 누를 때 mousedown, 움직일 때 mousemove, 뗄 때 mouseup 이벤트가 발생하는데 이것을 이용하면 된다. 좌표는 프로토타입의 이벤트 객체를 통해서 쉽게 가져올 수 있다. 그리고 엘리먼트의 현재 위치도 자바스크립트에서 element.offsetLeft, elem ent.offsetTop 속성으로 알 수 있다. 엘리먼트의 좌표를 읽을 때는 자바스크립트로, 수정할 때는 CSS의 style 속성으로 쓴다는 점에 주의해야 한다. 이 정도만 알면 나머지는 산수만 하면 된다. </font></p><font size="2"><br />
<br />
</font><p style="font-weight: bold;" class="sub2"><font size="2">대화상자 만들기</font></p><font size="2"><br />
</font><p><font size="2">먼저 문서에 대화상자 하나를 그려보자. 이번 예제부터는 프로토타입 라이브러리를 사용할 것이다. </font></p><p><font size="2"><b>&lt;리스트 4&gt; 대화상자 만들기</b></font></p><p class="sourcebox"><font size="2"><br />
</font><style>UNKNOWN { BR: } </style></p><div id="dialog"><font size="2"><br />
Hello<br />
</font></div><font size="2"><br />
<br />
</font><p><font size="2">&lt;리스트 4&gt;를 실행시키면 &lt;화면 6&gt;과 같은 화면이 표시될 것이다. 팝업 윈도우가 아니라 HTML 문서 안에 div 태그를 띄워서 마치 대화상자처럼 보이게 만든다. </font></p><p align="center"><font size="2"><img src="http://tfile.nate.com/download.asp?FileID=32246690" localfile="yes" postid="38905412"><br />
&lt;화면 6&gt; &lt;리스트 4&gt;의 결과화면</font></p><font size="2"><br />
<br />
</font><p style="font-weight: bold;"><font size="2">이벤트 핸들러 설정하기</font></p><font size="2"><br />
</font><p><font size="2">우리는 여기서 Hello가 있는 대화상자를 마우스로 누르고 움직이면 대화상자가 따라 움직이도록 만들 것이다. 먼저 HTML 문서에 이벤트를 걸어야 한다. Hello가 있는 div 태그에서 마우스를 누르면 드래그가 시작되므로 div 태그에 onmousedown 이벤트 핸들러를 설정한다. 그리고 마우스가 이동하는 범위는 문서 전체이므로 문서 전체에 onmousemove 이벤트 핸들러를 걸고 드래그 종료를 확인하기 위해 onmouseup 이벤트도 문서 전체에 걸어준다. 위의 코드를 다음과 같이 수정하면 된다. </font></p><p class="sourcebox"><font size="2"><br />
</font></p><div id="“dialog”" event)”=""><p><font size="2">이벤트 핸들러에서 함수를 실행하면서 두 개의 인자를 넘긴다. 첫 번째 인자는 div 태그의 DOM 객체이고 두 번째 인자는 이벤트의 속성을 담고 있는 객체이다. 이벤트 핸들러에서는 이 두 가지 인자를 가지고 조작하게 된다. </font></p><font size="2"><br />
<br />
</font><p style="font-weight: bold;" class="sub2"><font size="2">드래그 이벤트 핸들러 만들기</font></p><font size="2"><br />
</font><p><font size="2">그럼 이제 각 이벤트에 따라 동작하는 실제 이벤트 핸들러 함수를 만들어보자. 먼저 dragBegin에서 해야 할 일은 드래그를 시작한 지점의 좌표를 기억하고 드래그 시작을 알려주는 것이다. 다음과 같은 코드면 충분하다.</font></p><p><font size="2"><br />
 </font></p><p><font size="2"><b>&lt;리스트 5&gt; 드래그 시작 알리기</b></font></p><p><font size="2"><b><br />
</b></font></p><p class="sourcebox"><font size="2">function dragBegin(element, event) {<br />
&nbsp;&nbsp;&nbsp; element.dragging = true<br />
&nbsp;&nbsp;&nbsp; element.startx = Event.pointerX(event)<br />
&nbsp;&nbsp;&nbsp; element.starty = Event.pointerY(event)<br />
}</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">element 객체에 바로 우리가 정의한 속성을 대입하는 것이 특이해보일 수도 있을 것이다. DOM 객체도 일반 자바스크립트 객체와 똑같이 다룰 수 있고 자바스크립트는 속성을 동적으로 할당할 수 있기 때문에 &lt;리스트 5&gt;와 같은 코드가 가능하다. 보통 DOM 객체에 대응하는 자바스크립트 객체를 proxy 객체로 만들어서 쓰는 경우가 많은데 DOM 객체 자체에 메소드와 속성을 부여해서 실제로 드래그할 수 있는 객체인 것처럼 다룰 수도 있다. 지금은 드래그 앤 드롭의 원리를 보여주는 것이 목적이기 때문에 간편한 이 방법을 선택했지만 상황에 따라 다른 선택이 가능할 것이다. </font></p><p><font size="2">이제 처음 드래그한 지점은 저장했으니 drag 함수에서는 마우스가 이동한 거리를 계산해서 그만큼 div 태그를 이동시키면 된다. &lt;리스트 6&gt;과 같은 코드가 될 것이다.</font></p><p><font size="2"><br />
 </font></p><p><font size="2"><b>&lt;리스트 6&gt; 드래그 함수 적용</b></font></p><p><font size="2"><b><br />
</b></font></p><p class="sourcebox"><font size="2">function drag(element, event) {<br />
&nbsp;&nbsp;&nbsp; if (!dragging) return</font></p><p class="sourcebox"><font size="2">&nbsp;&nbsp;&nbsp; element.style.left = element.offsetLeft + Event.pointerX(event) - element.startx + 'px'<br />
&nbsp;&nbsp;&nbsp; element.style.top = element.offsetTop + Event.pointerY(event) - element.starty + 'px'<br />
&nbsp;&nbsp;&nbsp; element.startx = Event.pointerX(event)<br />
&nbsp;&nbsp;&nbsp; element.starty = Event.pointerY(event)<br />
}</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">여기까지 하고 실행해보면 이제 Hello가 마우스를 따라다니는 것을 확인할 수 있을 것이다. 이제 마우스 버튼에서 손을 뗐을 때 드래그 안 되도록 하는 코드만 넣으면 된다.</font></p><p><font size="2"><br />
</font></p><p class="sourcebox"><font size="2">function dragEnd(element, event) {<br />
&nbsp;&nbsp;&nbsp; element.dragging = false<br />
}</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">이걸로 드래그 앤 드롭의 완성이다. 불과 함수 세 개를 사용한 열 몇 줄의 코드로 드래그 앤 드롭이 구현되는 것이다. </font></p><font size="2"><br />
</font><p style="font-weight: bold;" class="sub2"><font size="2">드래그 앤 드롭 코드 줄이기</font></p><font size="2"><br />
</font><p><font size="2">산수만 잘한다면 좀 더 줄일 수도 있다. 사실 마우스를 클릭한 지점과 대화상자의 좌상단과의 거리는 늘 일정하게 유지된다. 그렇다면 이 차이만 처음에 구해두면 중간에 변하는 값을 매번 저장하지 않아도 된다. 즉, 다음처럼 코드를 줄일 수 있다. </font></p><p><br />
</p><p><font size="2"><b><br />
</b></font></p><p><font size="2"><b>&lt;리스트 7&gt; 개선된 드래그 앤 드롭 코드</b></font></p><p><font size="2"><b><br />
</b></font></p><p class="sourcebox"><font size="2">function dragBegin(element, event) {<br />
&nbsp;&nbsp;&nbsp; element.dragging = true<br />
&nbsp;&nbsp;&nbsp; element.diffx = Event.pointerX(event) - $('dialog').offsetLeft<br />
&nbsp;&nbsp;&nbsp; element.diffy = Event.pointerY(event) - $('dialog').offsetTop<br />
}<br />
function drag(element, event) {<br />
&nbsp;&nbsp;&nbsp; if (!element.dragging) return<br />
&nbsp;&nbsp;&nbsp; element.style.left = Event.pointerX(event) - element.diffx + 'px'<br />
&nbsp;&nbsp;&nbsp; element.style.top = Event.pointerY(event) - element.diffy + 'px'<br />
}</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p class="sourcebox"><font size="2">function dragEnd(element, event) {<br />
&nbsp;&nbsp;&nbsp; element.dragging = false<br />
}</font></p><p class="sourcebox"><br />
</p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">드래그가 어려운 기술일 것 같지만 의외로 이렇게 간단하게 구현된다. 드롭은 dragEnd에서 다른 함수를 호출할 수 있도록 하는 코드만 조금 추가하면 된다. 이것은 독자의 몫으로 남겨둔다. </font></p><p><font size="2">또 하나 신경 써야 할 것은 이벤트 핸들러다. 여기서는 간단하게 구현하기 위해 엘리먼트에 직접 이벤트 핸들러를 달았지만 실전에서는 이벤트 핸들러도 동적으로 할당한다. body 엘리먼트처럼 넓은 범위에 mousemove처럼 자주 발생하는 이벤트를 걸어두는 것은 바람직하지 않기 때문이다. 그래서 body에 이벤트를 거는 것은 대화상자에 mousedown 이벤트가 발생한 시점에 걸고 mouseup 이벤트가 발생했을 때 이벤트 핸들러를 제거하는 것이 좋다. dragBegin, dragEnd 함수를 조금만 수정하면 쉽게 할 수 있을 것이다. script.aculo.us 같은 프레임워크에서 드래그 앤 드롭을 구현하는 방법도 크게 다르지 않다. 다만 좀 더 기능이 많기 때문에 코드는 훨씬 긴데 여기 있는 정도의 원리만 이해하면 script.aculo.us의 드래그 앤 드롭 코드도 쉽게 이해하고 활용할 수 있을 것이다. </font></p><p><font size="2">한 가지 짚고 넘어가야 할 것은 모든 종류의 드래그 앤 드롭이 가능한 것은 아니라는 사실이다. 웹 브라우저의 내장 에디터가 어느 정도 기본 드래그 앤 드롭을 지원하기도 하고 HTML 문서 안에서도 위와 같은 방식으로 드래그 앤 드롭이 가능하지만 클라이언트에 있는 파일의 드래그 앤 드롭과 연계하는 것은 불가능하다. 탐색기에서 이미지를 끌어서 웹 브라우저에 올려놓는다고 이미지가 업로드 되도록 할 수는 없다는 얘기다. 앞서 언급한 것처럼 클라이언트의 자원에는 접근할 수 없기 때문이다. 이런 부분은 역시 클라이언트의 자원에 접근하는 일이기 때문에 액티브X든 자바 애플릿이든 다른 기술을 사용해야한다.</font></p><font size="2"><br />
<br />
</font><p style="font-weight: bold;" class="sub1"><font size="2">동적으로 로딩 하는 트리 만들기</font></p><font size="2"><br />
</font><p><font size="2">이번에는 좁은 의미의 Ajax인 비동기 통신까지 활용하는 사례를 살펴보자. 트리 컨트롤은 이미 꽤 오래 전부터 액티브X가 아니라 자바스크립트로 구현되어 왔다. 하지만 기존에는 그냥 데이터를 미리 다 로딩해 놓고 보여주는 식이었다. 하지만 Ajax의 등장으로 좀 더 동적인 트리가 가능해졌다. 윈도우에서 탐색기를 열면 처음부터 다 보여주는 것이 아니라 디스크에서 읽은 만큼만 보여주고 다 읽기 전에도 트리를 이용할 수 있다. 이와 같은 동작이 웹에서도 가능하다. </font></p><font size="2"><br />
</font><p style="font-weight: bold;" class="sub2"><font size="2">트리 만들기</font></p><font size="2"><br />
</font><p><font size="2">먼저 트리부터 만들어보자. 이번에도 프로토타입을 사용한다. 다음과 같은 코드로 최상위 노드로 구성된 트리를 그릴 수 있을 것이다. <br />
일종의 웹사이트 분류 트리를 예제 데이터로 사용해보자. 그리고 각 노드의 하위 노드들도 다음과 같이 샘플 데이터를 만든다.</font></p><p><font size="2"><br />
 </font></p><p><font size="2"><b>&lt;리스트 8&gt; 최상위 트리<br />
</b></font></p><ul id="tree"><font size="2"></font><li id="search"><font size="2"><span>+ </span>검색<br />
</font></li><li id="community"><font size="2"><span>+ </span>커뮤니티<br />
</font></li><li id="shopping"><font size="2"><span>+ </span>쇼핑<br />
</font></li></ul><p><font size="2"><b>&lt;리스트 9&gt; 트리의 하위 노드</b></font></p><p><font size="2"><b><br />
</b></font></p><p><font size="2">treeData 변수에 값들을 넣고 있는데 여기서 사용한 문법이 JSON(JavaScript Object Notation)이다. {}로 둘러싼 부분은 하나의 객체가 되는데 사전과 같은 구조다. {key:’google’, name: ‘구글’}은 key, name이라는 두 개의 속성을 가지며 그 값은 각각 ‘google’과 ‘구글’이 되는 것이다. 자바스크립트는 객체 자체가 다른 언어의 사전 객체나 해시 테이블, 맵 등과 비슷한 역할을 한다. Ajax에서 응답의 자료구조로 흔히 쓰이는 형식이다. </font></p><p><font size="2">treeData의 내용은 트리 구조를 테이블 형태로 풀어 놓은 것이다. 검색 카테고리는 search라는 id를 갖고 있고 이 아래에는 id가 google, naver, yahoo인 항목들이 있다. 마찬가지로 commu nity도 있고 shopping은 한 단계가 더 있는데 openmarket이 있고 shoppingmall이 있는데 각각은 또 하위 엘리먼트를 가진다. </font></p><font size="2"><br />
</font><p style="font-weight: bold;" class="sub2"><font size="2">트리 펼치기와 접기</font></p><font size="2"><br />
</font><p><font size="2">그리고 이제 li 엘리먼트 안에 +가 그려진 span 엘리먼트에 클릭 이벤트를 달면 된다. 다음처럼 달면 된다.</font></p><p><font size="2"><br />
 </font></p><p class="sourcebox"><font size="2">$$(‘#tree span’).each(function(element) {<br />
&nbsp;&nbsp;&nbsp; Event.observe(element, ‘click’, toggle)<br />
})</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">이 코드는 프로토타입이 제공하는 라이브러리를 사용한 것이다. id가 tree인 엘리먼트 밑에 있는 엘리먼트 중 span 엘리먼트를 모두 찾아서 그 각각에 대해서 이벤트를 할당하는 것이다. Event.observe의 의미는 element에 ‘click’ 이벤트가 발생했을 때 toggle 함수를 실행하라는 뜻이다. toggle은 트리의 하위 노드가 접혀 있으면 펼치고, 펼쳐져 있으면 접는 기능을 하면 된다. 이런 기능은 &lt;리스트 10&gt;이면 충분하다.</font></p><p><font size="2"><br />
</font> </p><p><font size="2"><b>&lt;리스트 10&gt; toggle 이벤트</b></font></p><p><font size="2"><b><br />
</b></font></p><p class="sourcebox"><font size="2">function toggle(event) {<br />
&nbsp;&nbsp;&nbsp; var element = Event.element(event).parentNode<br />
&nbsp;&nbsp;&nbsp; if (element.expanded) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fold(element)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.expanded = false<br />
&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; expand(element)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.expanded = true<br />
&nbsp;&nbsp;&nbsp; }<br />
}</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">이제 펼치는 expand 함수와 접는 fold 함수만 남았다. expand는 &lt;리스트 11&gt;과 같다.</font></p><p><font size="2"><br />
</font></p><p><font size="2"><b>&lt;리스트 11&gt; expand 함수</b></font></p><p><font size="2"><b><br />
</b></font></p><p class="sourcebox"><font size="2">function expand(element) {<br />
&nbsp;&nbsp;&nbsp; var ul = document.createElement('ul')</font></p><p class="sourcebox"><font size="2">&nbsp;&nbsp;&nbsp; element.appendChild(ul)</font></p><p class="sourcebox"><font size="2">&nbsp;&nbsp;&nbsp; var children = treeData[element.id]<br />
&nbsp;&nbsp;&nbsp; children.each(function(child) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var li = document.createElement('li')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ul.appendChild(li)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; li.id = child.key<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; li.innerHTML = '<span>+ </span>' + child.name<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Event.observe(li.firstChild, ‘click’, toggle)<br />
&nbsp;&nbsp;&nbsp; })<br />
&nbsp;&nbsp;&nbsp; element.firstChild.innerHTML = '- '<br />
}</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">데이터를 가져와서 document.createElement 함수로 엘리먼트를 생성한 후 현재 노드에 appendChild로 갖다 붙이면 된다. 접는 것은 간단하다. 다음과 같이 expand에서 붙였던 엘리먼트들을 죄다 지우면 된다.</font></p><p><font size="2"><br />
 </font></p><p class="sourcebox"><font size="2">function fold(element) {<br />
&nbsp;&nbsp;&nbsp; element.removeChild(element.getElementsByTagName (‘ul’)[0])<br />
&nbsp;&nbsp;&nbsp; element.firstChild.innerHTML = ‘+ ’<br />
}</font></p><font size="2"><br />
</font><p style="font-weight: bold;" class="sub2"><font size="2">동적 로딩 기능 만들기</font></p><font size="2"><br />
</font><p><font size="2">여기까지만 하면 데이터를 처음에 다 가져와서 트리 구조로 표현하는 것이 되는 것이다. 이제 동적으로 데이터 로딩하는 부분을 추가해보자. expand 함수를 보면 중간에 treeDataelement. id를 통해서 자식 노드들을 배열 형태로 가져오는 코드가 있다. 이 부분에서 Ajax를 통해서 데이터를 가져오게 하면 된다. 다만 비동기로 통신하는 코드는 데이터를 가져오도록 요청하는 부분과 가져온 데이터를 처리하는 부분이 분리가 되어야 한다. expand 함수에서는 데이터를 가져오도록 요청만 하고 데이터를 가져오고 나면 addChildren 함수를 호출되도록 하면 된다. 그럼 &lt;리스트 12&gt;와 같은 코드가 될 것이다.</font></p><p><font size="2"><br />
</font> </p><p><font size="2"><b>&lt;리스트 12&gt; addChildren 함수를 이용한 동적 로딩 코드</b></font></p><p><font size="2"><b><br />
</b></font></p><p class="sourcebox"><font size="2">function expand(element) {<br />
&nbsp;&nbsp;&nbsp; new Ajax.Request('/treeData?id=' + element.id, {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; method: get,<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; onSuccess: addChildren<br />
&nbsp;&nbsp;&nbsp; })<br />
}<br />
<br />
function addChildren(request) {<br />
&nbsp;&nbsp;&nbsp; var children = eval!(request.responseText)<br />
&nbsp;&nbsp;&nbsp; var ul = document.createElement('ul')<br />
&nbsp;&nbsp;&nbsp; children.each(function(child) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var li = document.createElement('li')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ul.appendChild(li)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; li.id = child.key<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; li.innerHTML = '<span>+ </span>' + child.name<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Event.observe(li.firstChild, 'click', toggle)<br />
&nbsp;&nbsp;&nbsp; })<br />
&nbsp;&nbsp;&nbsp; element.firstChild.innerHTML = '- '<br />
}</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">Ajax.Request도 프로토타입에서 제공하는 기능이다. 브라우저별로 호출방법이 다른 XMLHttpReqeust 객체를 wrapping 해서 쓰기 편하게 해준다. 여기서 첫 번째 인자가 호출할 URL인데 이 코드가 제대로 동작하려면 서버 사이드의 코드도 필요하다. 하지만 간단하게 텍스트 파일을 만들어서 텍스트 파일 URL을 써 넣고 텍스트 파일 내용에는 JSON 타입으로 내용을 써 놓아서 테스트해볼 수는 있을 것이다. </font></p><font size="2"><br />
<br />
</font><p style="font-weight: bold;" class="sub1"><font size="2">재미 있는 Ajax UI 프로그래밍</font></p><font size="2"><br />
<br />
</font><p><font size="2">몇 가지 예제를 통해 살펴본 것처럼 웹에서 자바스크립트로 기능성 높은 UI를 만드는 일은 그리 어려운 일이 아니다. 게다가 이미 이런 UI 컴포넌트들을 만들어서 모아 놓은 오픈소스 라이브러리도 있다. Dojo같은 프레임워크는 윈도우 프로그래밍 하는 느낌으로 사용할 수 있고 script.aculo.us 같은 프레임워크는 UI 관련된 컴포넌트들을 모아서 제공하고 있다. jQuery는 앞서 살펴본 프로토타입과 script.aculo.us를 합친 기능을 제공한다. 대부분 커스터마이즈하기 쉽게 되어 있기 때문에 별다른 노력 없이 가져다 쓸 수 있을 것이다. <br />
그럼에도 불구하고 이런 UI 컴포넌트를 만드는 방법은 알아둘 필요가 있다. 프레임워크들이 제공하는 것과 비슷하지만 다른 컴포넌트를 만들어야 하는 경우가 많기 때문이다. 예를 들면 스프링노트에서는 트리 목록을 보여주는 사이드 바가 있는데 이 부분의 크기를 마우스 드래그로 조정하는 기능이 있다. 이런 기능은 일반적인 드래그 앤 드롭 컴포넌트로는 붙이기 어렵다. 그럴 때 드래그 앤 드롭의 구현 방법을 알고 있다면 손쉽게 구현할 수 있다. </font></p><p><font size="2">이미 완성된 컴포넌트를 조립하는 액티브X가 개발이 빠른 측면도 있지만 배포 면에서는 아무래도 개발자나 사용자나 모두에게 불편하다. 반면에 Ajax UI 컴포넌트는 개발이 액티브X에 비해 크게 느리지 않고 배포에는 월등히 유리하다. 접근성의 측면에서도 액티브X나 플래시, 자바 애플릿 등의 다른 기술에 비해 브라우저만 있으면 되는 Ajax 기술이 가장 좋다고 할 수 있다. </font></p><p><font size="2">하지만 필자가 그보다 더 중요한 장점으로 꼽고 싶은 것은 Ajax 개발은 좀 더 재미있다는 것이다. 자바스크립트는 현재 널리 사용되는 언어 중 가장 다이내믹한 언어이다. 그 덕분에 코드와 생각의 거리가 비교적 짧아서 좋은 코드를 만들 수 있고 다른 UI 개발에 비해 결과를 빨리 확인할 수 있다는 점도 매력적이다. 자바스크립트가 한때는 스파게티 소스의 온상인 것처럼 이야기되기도 했지만 프로그래머가 아닌 사람들도 쉽게 가져다 쓰고 응용할 수 있는 언어임은 부인할 수 없을 것이다. 그리고 동적인 언어는 지저분해질 수 있는 한계도 크지만 더 좋은 코드를 만들 수 있는 한계도 크다. 개발자에게 더 많은 권한을 부여해주는 것이다. </font></p><p><font size="2">자바스크립트와 CSS 기술의 발전 덕분에 이제 UI 때문에 액티브X를 쓸 필요는 거의 없어졌다. 그럼에도 불구하고 아직 그룹웨어나 SI 분야에서는 액티브X가 많이 쓰이고 있다. 웹 접근성도 해치고 사용자도 귀찮게 만드는 액티브X, UI에서 사용하는 것만이라도 줄여야 하지 않을까. 필자가 이 글을 쓰고 있는 PC의 OS도 리눅스인데 액티브X 때문에 사내 그룹웨어에 접속도 못하는 불편을 겪고 있다. 최근 PC를 새로 구입한 사람들도 윈도우 비스타에서 제대로 사용할 수 없는 사이트가 많아서 어려움을 겪고 있을 것이다. 말도 많고 탈도 많은 액티브X, UI 부분만이라도 Ajax로 대체해 보자. Ajax 프로그래밍이 생각보다 쉽고 재미있다는 것을 독자 여러분도 느끼게 되기를 바란다. </font></p><font size="2"><br />
<br />
</font><p style="font-weight: bold;" class="sub1"><font size="2">자바스크립트 개발 도구</font></p><font size="2"><br />
</font><p><font size="2">자바스크립트에도 다양한 프레임워크와 개발도구가 있는데 여기서는 프로토타입(prototype)과 파이어버그(Firebug)를 소개해보려고 한다. 프로토타입은 요즘 가장 널리 쓰이는 자바스크립트 프레임워크이다. Ajax 애플리케이션에서 많이 사용하는 패턴 중 언어의 기본적인 부분들을 쉽게 해주는 라이브러리이다. 대표적으로 $() 함수가 있다. 앞선 예제에서 사용했던 코드 중에 다음과 같은 부분은</font></p><p><font size="2"><br />
 </font></p><p class="sourcebox"><font size="2">document.getElementById(‘editor’)</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">아래와 같이 바꿀 수 있다.</font></p><p><font size="2"><br />
 </font></p><p class="sourcebox"><font size="2">$(‘editor’)</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">단순한 축약에 불과하지만 실제 개발 과정에서는 정말 큰 편의를 제공한다. 이외에 CSS Selector와 같은 문법으로 엘리먼트의 목록을 가져올 수 있는 $$ 함수도 있고 Event 객체나 Array 객체를 편리하게 다룰 수 있는 방법도 제공한다. 예제를 통해 살펴보자.</font></p><p><font size="2"><br />
</font> </p><p class="sourcebox"><font size="2">var list = [1, 4, 6, 3, 11, 8, 4, 7, 8]<br />
var uniqList = list.uniq() // 중복 원소 제거 [1, 4, 6, 3, 11, 8, 7]</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">루비에서 많이 사용하는 방식으로 closure를 활용해서 for 루프를 대체할 수도 있다.</font></p><p><font size="2"><br />
</font> </p><p class="sourcebox"><font size="2">list.each(function(element) {<br />
&nbsp;&nbsp;&nbsp; sum = sum + element<br />
})</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">Event 객체의 경우는 브라우저 호환성을 걱정하지 않고 사용할 수 있는 도구들을 많이 제공한다.</font></p><p><font size="2"><br />
 </font></p><p class="sourcebox"><font size="2">Event.pointerX(event) // IE, 파이어폭스에 상관없이 event가 발생한 마우스 좌표를 가져오면서 스크롤 보정도 해준다.<br />
Event.element(event) // IE의 event.srcElement, Firefox의 event.targetElement</font></p><p class="sourcebox"><font size="2"><br />
</font></p><p><font size="2">자세한 내용은 prototypejs.org에서 볼 수 있다. 요즘은 jQuery라는 프레임워크도 뜨고 있지만 프로토타입이 워낙 빠른 속도로 대중화되어서 많은 다른 라이브러리가 프로토타입 기반으로 되어 있기 때문에 알아두면 좋을 것이다. </font></p><p><font size="2">일반적으로 복잡한 Ajax 애플리케이션을 개발할 때는 디버깅 도구가 좀 더 많고 표준 지원이 좋은 파이어폭스 기준으로 개발하는 경우가 많다. 파이어폭스에는 자바스크립트 콘솔, Web Developer 툴바, DOM Inspector 등 개발에 편리한 도구가 많다. 그 중 가장 중요한 도구는 아마 파이어버그일 것이다. DOM 구조를 실시간으로 보면서 각종 속성들을 쉽게 볼 수 있고 내용을 바꿀 수도 있기 때문이다. 자바스크립트도 자동완성이 지원되는 shell이 제공되며 간단한 디버깅도 가능하고 에러가 났을 때 정확한 지점을 표시해 주기도 한다. IE에도 최근 MS가 내놓은 IE Dev Toolbar가 있긴 하지만 파이어버그의 기능이 압도적이다.</font></p><p><font size="2"><br />
</font> </p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246691" localfile="yes" postid="38905412"></p><p><br />
</p><p>파이어버그의 DOM Inspector</p><p><br />
</p><br />
<p><font size="2"><a href="http://www.dbguide.net/" target="_blank"><b><font color="midnightblue">제공 : DB포탈사이트 DBguide.net </font></b></a></font><br />
</p></div><br />
<br/><br/>tag : <a href="/tag/ajax" rel="tag">ajax</a>,&nbsp;<a href="/tag/표준" rel="tag">표준</a>,&nbsp;<a href="/tag/호환성" rel="tag">호환성</a>,&nbsp;<a href="/tag/ui" rel="tag">ui</a>,&nbsp;<a href="/tag/자바스크립트" rel="tag">자바스크립트</a>,&nbsp;<a href="/tag/html" rel="tag">html</a>			 ]]> 
		</description>
		<category>Trend</category>
		<category>ajax</category>
		<category>표준</category>
		<category>호환성</category>
		<category>ui</category>
		<category>자바스크립트</category>
		<category>html</category>

		<comments>http://topic.egloos.com/508713#comments</comments>
		<pubDate>Mon, 06 Aug 2007 05:29:40 GMT</pubDate>
		<dc:creator>Hans</dc:creator>
	</item>
	<item>
		<title><![CDATA[ 액티브X 대체기술 2부 - 발등의 불끄기 공인인증서 대체 기술 ]]> </title>
		<link>http://topic.egloos.com/508703</link>
		<guid>http://topic.egloos.com/508703</guid>
		<description>
			<![CDATA[ 
  <p class="title1">더 큰 세상으로 가는 문<br />
액티브X 대체기술 </p><br />
<p class="author">기획/정리 l 전희용 기자 flytgr@imaso.co.kr</p><br />
<p class="contentsbox">마소 독자치고 액티브X 문제와 무관하다고 할 수 있는 사람은 별로 없을 것이다. 그런데, 참 이상한 일은 액티브X 이야기만 나오면 문제의 원인이나 해결책을 이야기하기 보단 목에 핏대부터 세운다. 누군가를 탓하기 위함이다. 하지만 막상 따지고 보면 누구의 잘못이라고 하기는 어려운 일이다. 워낙 오랫동안 쌓아온 일이기 때문이다. 그렇다고 곪을 대로 곪은 상처를 그냥 놓아둘 수도 없는 일. 이번 달 특집에서는 이 상처의 원인에 대해 알아보고, 그 치료방법인 액티브X의 대체 기술들에 대해서도 함께 알아본다. 다들 잘 알다시피 아직 액티브X를 1대1로 대신해 줄 수 있는 기술은 없다. 하지만, 여러 기술들을 이용하여 산적한 문제들을 보완하며 차츰 치료해 나갈 수는 있을 것이다. 깊이 박힌 상처가 하루아침에 낫는 걸 보았는가?</p><br />
<table bgcolor="#999999" border="0" cellpadding="5" cellspacing="1" width="100%"><tbody><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3187" target="_blank">1부 | 백조에서 미운오리로 전락한 액티브X 문제와 해결방안 | 정희용</a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3188" target="_blank"><b>2부 | 발등의 불끄기 공인인증서 대체기술 | 최상훈</b></a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/comb/common/edit/1%BA%CE%20%7C%20%B9%E9%C1%B6%BF%A1%BC%AD%20%B9%CC%BF%EE%BF%C0%B8%AE%B7%CE%20%C0%FC%B6%F4%C7%D1%20%BE%D7%C6%BC%BA%EAX%20%B9%AE%C1%A6%BF%CD%20%C7%D8%B0%E1%B9%E6%BE%C8%20%7C%20%C1%A4%C8%F1%BF%EB" target="_blank">3부 | UI 대체는 내게 맡겨라 Ajax를 이용한 UI 개발 | 박영록</a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3190" target="_blank">4부 | 액티브X 뛰어넘는 기능과 호환성 XPCOM 개발전략 | 김민수</a></font></td></tr><tr bgcolor="#ffffff"><td height="20"><font size="2"><a href="http://www.dbguide.net/know/know102001.jsp?mode=view&amp;pg=1&amp;idx=3191" target="_blank">5부 | MS가 내놓은 액티브X의 대안 실버라이트 활용법 | 한용희</a></font></td></tr></tbody></table><br />
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr></tr></tbody></table><br />
<p class="title1">발등의 불끄기<br />
공인인증서 대체 기술</p><br />
<p class="contentsbox">액티브X 문제는 공인인증서에서 특히 심각하다. 직접 돈을 거래하는데 사용될뿐 아니라 이미 너무 많이 사용하고 있기 때문이다. 게다가 웹 표준화 단체인 오픈 웹의 금융결제원을 상대로 한 거액 소송 덕분에 액티브X로 만든 공인인증서를 다른 기술로 대체하자는 목소리 또한 높아졌다. 특집 2부에서는 공인인증서 대체 기술로 거론되고 있는 기술 중 자바 공인인증서에 대해 간단히 알아본다.</p><br />
<p class="author">최상훈 | vicdev@magicn.com | 다날㈜ 해외개발팀 팀장</p><br />
<p>어느 날 부터인가 액티브X 문제가 여기저기서 터져 나오기 시작하더니, 이제는 일반인들조차도 이 문제에 관심을 가지는 상황이 되었다. 문제는 그렇게 열을 올리고 있으면서도 대체 왜 문제인지 잘 모르는 사람들도 있다는 데 있다. 심지어 그저 반MS 감정의 연장쯤으로 생각하는 사람들도 있기에 1부에서는 먼저 액티브X 문제가 불거지게 된 배경과 그 해결 방법으로 제시되는 기술들에 대해 알아볼 것이다.</p><br />
<p>지금까지 전자결제나 공인인증서 처리에는 액티브X 기술이 독점적으로 사용되어 왔다. 하지만 마이크로소프트(이하 MS)의 독점 기술인 액티브X는 다른 기종의 웹브라우저나 다른 OS 플랫폼에서는 전혀 동작하지 않는다. 예전부터 리눅스나 매킨토시 등 다른 운영체제를 사용하는 사용자 모임에서는 이 문제를 끊임없이 제기해왔다. 급기야 노무현 대통령에게 리눅스 선물하기 모임(줄여서 ‘노리추’라고도 함)이 결성되기 까지 했다. 이 모임은 액티브X 일변도인 인터넷 환경에서 다른 플랫폼을 사용하는 것이 얼마나 불편한지를 정부에 호소하기 위해 2005년 4월 22일 국민 참여 수석을 통해 리눅스가 설치된 컴퓨터를 대통령에게 전달하기도 했다. 이런 노력들이 있었음에도 불구하고 대다수의 윈도우 사용자와 정부는 큰 반응을 보이지 않았다.</p><br />
<br />
<p class="sub1">공인인증서 구현 기술들에 대한 고찰</p><br />
<br />
<p>그런데, 왜 최근 들어서 갑자기 액티브X 이외의 다른 기술로 공인인증서를 처리하는 것에 대한 관심이 급부상하고 있는 것일까? 그 이유는 MS가 윈도우 비스타를 출시하면서 스스로가 제안한 액티브X를 부정했기 때문이다. 더 정확히 말하면 IE7에서 제공하는 보호모드 기능 때문이다. IE7의 보호모드 기능은 [Win dows]나 [Program Files] 등의 시스템 폴더에 파일이 저장되지 않도록 차단하는 기능이다. 그렇다고 시스템 폴더로의 접근이 완전히 차단된 것은 아니다. 일단 IE7을 실행하면 표준 사용자 권한에서 실행된다. 만약 사용자가 IE7을 통해 합법적 시스템 폴더의 접근을 시도할 경우 관리자 권한을 획득하기 위해 윈도우에 권한 상승을 요청하여 사용자의 확인을 받게 하면 접근할 수 있다.</p><p>MS에서 보호모드 기능을 제공하는 이유는 액티브X가 상당히 편리한 웹 클라이언트 환경이지만, 보안상 취약한 부분을 내제하고 있기 때문이다. 액티브X를 악용하면 PC에 개인 정보가 노출될 수 있다. 바이러스가 유포되고 원하지 않는 플러그인들이 설치되기도 하며, 컴퓨터 속도를 떨어뜨리는 ‘그레이웨어’의 유포 등 액티브X의 사용자에게 정신적, 물리적, 경제적 피해를 주는 사례가 많았다. 이러한 이유들 때문에 윈도우 비스타(IE 7)의 개발 스펙에 보호모드 기능을 추가한 것이다. </p><p>또 다른 이유로 비 MS나 비 IE 사용자들의 불편함이 주무부처에 공감대를 얻은 것으로 해석된다. 물론 그 동안 이런 민원들에 대한 적극적인 응대는 없었다. 앞서 언급한 노리추 사건과 지난 2007년 1월 23일 대한민국 전자정부 웹페이지 국제 표준화 운동을 주도하고 있는 오픈웹(http://openweb.or.kr)이 금융결제원을 상대로 4억 1,500만원의 손해배상 청구한 사건도 있었다.</p><p>이러한 일련의 사건과 현상들이 종합되어 개발자가 아닌 사람들까지도 액티브X에 대한 관심을 가지게 되었다. 그 결과 운영체제나 브라우저에 독립적인 공인인증서 처리 애플리케이션이 시대적인 요구로 자리 잡게 된 것이다. 한국정보보호진흥원(이하 KISA)에서는 여러 대안 플랫폼 중 자바 플랫폼을 이용하여 공인인증서를 만드는데 대한 기술을 검토하고 있다.</p><br />
<br />
<p class="sub1">기술적 쟁점</p><br />
<br />
<p>사실 자바 공인인증서 처리 애플리케이션은 스페인과 미국, 독일, 덴마크, 핀란드, 대만 등 많은 국가에서 채택하고 있다. 하지만 국가마다 환경이 다르고, 무엇보다도 공인인증서 처리는 주로 금융 결제 및 인증과 같이 중요하고 민감한 거래에 사용된다. 때문에 개인의 권익을 최대한 보장 받을 수 있도록 안정성을 보장하는 기술검토가 필요하다.</p><p>여기에서는 자바로 공인인증서 처리 애플리케이션을 만들기 위해 고려해야 하는 기술 쟁점들에 대해 알아본다.</p><br />
<p class="sub2">기술적 쟁점 1 - JRE의 비용</p><br />
<p>자바는 반 컴파일 + 반 인터프리터(half-compiled and half-interpreted) 언어다. 때문에 런타임에 자바의 실행을 지원하는 환경이 갖추어져 있어야 한다. 이 환경을 JRE(Java Runtime Environment)라고 하는데, 자바 공인인증서를 처리하려면 JRE가 반드시 설치되어 있어야 한다. 그렇다면 JRE를 설치하면 될 문제다. 하지만 JRE는 몇 가지 문제점을 가지고 있다. </p><p>● 설치비용<br />
네트워크로 JRE 설치 파일을 다운 받아 설치가 완료되기까지 작게는 수분 길게는 수십 분 이상의 시간적 비용이 따른다. 물론 이 설치는 한번만 해주면 된다. 또한, 설치 시 엔드 유저에게 낯선 몇 번의 클릭을 해야만 한다. </p><p>● JRE의 호환성<br />
호환성은 다시 버전 별 호환성과 운영체제별 호환성으로 나눌 수 있다. 버전 별 호환성은 특정 상위 버전으로 설치를 권장하면 된다. 문제는 운영체제 별 호환성이다. 현재 썬마이크로시스템즈(이하 썬)에서 제공하는 공식 JRE(http://java.sun.com/)는 윈도우와 솔라리스, 리눅스 밖에 없다. 물론 IBM이나 애플 등 여러 OS 벤더들은 각자의 운영체제에 동작하는 JRE를 개발하고 배포한다. 하지만, 운영체제의 JRE 지원은 반드시 보장되는 것이 아니며, 운영체제에서 동작하는 JRE의 호환성도 확보되어야 한다. 하지만 애초에 자바는 WORA(Write Once, Run Anywhere)를 모토로 하는 언어이기 때문에 문제될 게 없으나 벤더의 표준화에 대한 보증이 담보되어야한다.</p><br />
<p class="sub2">기술적 쟁점 2 - 자바 역공학의 문제</p><br />
<p>앞서 설명한대로 자바는 반 컴파일과 반 인터프리터 언어이기 때문에 자바는 컴파일 하기도 인터프리트하기도 용이한 언어다. 대부분의 경우 이런 자바의 특징은 장점이다. 그런데 이 장점은 반대로 역공학 하기 쉽다는 단점이 되기도 한다. 소스코드를 컴파일하면 곧바로 기계어로 실행할 수 있는 바이너리코드가 생성되는 것이 아니라, JVM이 실행하기 쉬운 바이트코드로 생성되기 때문이다. </p><p>현재 바이트 코드 to 소스코드로 역컴파일할 수 있는 툴들은 많이 나와 있는 상태다. 상황이 이러하니 자바 공인인증서 처리 모듈을 만들더라도 쉽게 그 소스를 볼 수 있게 되는 셈이다. 그렇다고 자바로 만들면 전부 역컴파일 된다고 생각할 필요는 없다. 암호화/복호화를 처리하는 코드는 조금의 노력만 투자한다면 쉽게 찾아볼 수 있기 때문이다. 또한, 우리나라에서 사용하는 공식 암호화 알고리즘이 SEED와 3-DES라는 것도 쉽게 알 수 있다(이 문서만 봐도 알 수 있지 않은가?). 문제는 암호화 알고리즘이 무엇이고 코드가 어떻다는데 있지 않다. </p><p>일단 PKI(Public Key Infrastructure) 기반의 암호화 및 인증 처리는 알고리즘이 중요한 게 아니라 개인키가 보호되는데 있다. 개인키 정보가 있는 인증서를 확보하지 못 한다면 알고리즘을 알아도 아무런 소용이 없다. 뿐만 아니라 자바 기술에서 역컴파일러의 발전만 있었던 게 아니라 난독기(obfuscator)도 발전했다. 그 덕분에 문자열 인코딩이나 제어흐름을 변경하는 정도의 기능으로도 충분히 역컴파일된 코드를 읽기 힘든 수준의 난독성으로 보장할 수 있다(물론 인내심이 강한 사람에겐 못 당하지만 말이다). </p><p>또, 역 컴파일의 문제가 자바만의 문제는 아니다. 액티브X도 역 컴파일의 위험에서 자유로울 수 없는 탓이다. 컴파일되어 배포되는 액티브X 코드도 어셈블리어로 역 컴파일 될 수 있기 때문이다. 어셈블리어를 가독성 높은 고급언어인 자바처럼 쉽게 읽는 사람은 많지 않지만 액티브X도 완벽히 로직을 은닉한다고 할 수 없는 셈이다. </p><br />
<p class="sub2">기술적 쟁점 3 - 클래스 바꿔치기</p><br />
<p>지금까지의 문제는 나름대로 심각하지 않거나 대안이 있다. 하지만 이제부터의 문제는 좀 더 심각한 편이다. </p><p>자바 애플릿은 수행속도를 높이기 위해 매번 실행 시 마다 서버에서 jar 파일을 다운 받아 실행하지 않고 다운받은 jar 파일을 로컬 캐시에 저장해둔다. 캐시 된 jar가 저장될 위치는 Windows의 경우 [제어판] → [자바] → [일반] → [임시 인터넷 파일] → [설정]에서 확인할 수 있다. 물론 실행 시 마다 서버에서 다운로드를 받을 수도 있지만 인증서 처리 같이 사이즈가 큰 코드는 이 방식을 채택할 경우 시간적 비용 부담이 커진다.</p><p>캐시 디렉토리에 있는 jar 파일의 압축을 풀면 공격자가 주요 클래스를 자신이 만든 다른 클래스로 바꿔치기 할 수 있다. 만일 바꿔치기한 클래스가 동일한 로직을 수행하면서 아이디와 패스워드, 인증서 텍스트, 주민등록 번호 등을 공격자의 컴퓨터로 저장한다면 그 원래 사용자가 경제적으로 막대한 피해를 입게 될 것은 당연한 일이다.</p><p>이때 보안을 위해 Signed Applet!을 사용한다 하더라도 큰 도움이 되지 않는다. Signed Applet!은 Applet!을 실행할 때 인증처리만 할 뿐이지 jar 파일의 변경을 감지하지는 못 하기 때문에 바꿔치기 된 클래스를 그대로 실행할 수 있다. 참고로, 이 사실은 금융결제원 전자인증센터에서 증명되었다.</p><p>이 취약점은 자바 자체로는 해결하기 어려운 문제이다. CRC 처리를 한다던가, jar 파일에 변조를 감지하도록 sign을 한다던가, 특정 주요 클래스를 캐시하지 않고 동적 로딩 하는 방법도 생각해봤다. 하지만 ‘클래스 바꿔 치기’ 공격은 자바로 구현된 어떤 클래스에서도 시도할 수 있기 때문에 자바의 문제를 해결하는 자바 클래스는 동일한 문제를 해결할 수 없었다. 이 문제도 약간의 테크닉을 통해 해결할 수 있을 것 같다. 필자가 생각해둔 테크닉이 있지만 이 글에서 표현할 수는 없어 이 정도로 밝혀두겠다.</p><p>앞에서도 설명했지만, 이 부분도 액티브X에서 완벽히 해결된 사항이 아니다. 필자는 윈도우 실행파일을 역 어셈블하여 사용 기간이 제한된 셰어웨어의 만료일을 체크하지 않도록 해당 코드를 JUMP 시켰던 동료를 본 적이 있다. 액티브X도 변조가 가능하다는 얘기다. 문제는 자바 클래스를 변조해 바꿀 수 있는 사람보다 액티브X의 바이너리를 변조할 수 있는 사람이 압도적으로 적다는데 있다.</p><br />
<p class="sub2">기술적 쟁점 4 - PKCS#11 지원 문제</p><br />
<p>자바에서는 암/복호화 처리를 위해 JCA(Java Cryptography Architecture)와 JCE(Java Cryptography Extension)를 정의하고 있다. JCA는 java.security 패키지에 있으며, 암호화 처리를 위한 메커니즘과 구조, 인터페이스, 팩토리 등을 정의하고 있다. 암호화 처리는 상당히 다양한 알고리즘을 사용할 수 있어서(혹은 어떠한 알고리즘을 사용하는지 알 수 없어서) SPI(Service Provider Interface)를 이용하고 있다. 왜냐하면 자바는 사용자가 사용할 알고리즘을 알 수 없고 사용자가 사용할 수 있는 모든 알고리즘을 제공할 수 없기 때문이다. 그래서 JCA는 SPI의 프로바이더를 이용하여 사용자가 사용할 암호화 방식을 등록/선택하게 하므로 어떤 알고리즘이던지 사용할 수 있는 틀을 제공한다.</p><p>JCE는 java.crypto 패키지에 있으며, JCA의 확장으로 1.2 버전까지는 미국의 수출제약법령(U.S. export control regulat ions)에 의해 미국과 캐나다 내에서만 사용할 수 있었다. 그러나 JCE 1.2.2 부터는 제한적인 상황에서 미국과 캐나 다 이외 지역에서도 사용할 수 있게 되었다.</p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246675" localfile="yes" postid="38905412" height="216" width="458"></p><p>여하튼, JCE는 Cipher와 MAC(Message Authentication Code), Key Generation, Key Agreement 등 실제적인 암호화 처리를 제공한다. 보다 자세한 설명은 자바서비스넷의 이인영님이 게시한 Java Security와 Cryptography Architecture 문서(http://www.javastudy.co.kr/docs/lec_java/security/JAVASecurity.html)를 참조하길 바란다. 따라서 JCA와 JCE의 기능은 각각 &lt;그림 2&gt;와 같다.</p><p>PKCS는 RSA 사의 연구실에서 주관하여 정의한 공개키 암호화 표준(Public Key Crpytography Standard)이다. 이 표준은 공개키 암호화를 위한 각종 방식을 정의하고 있는데 PKCS#1 부터 PKCS#15 까지 15 종류의 표준이 있다. PKCS#11은 11번째 표준으로서 암호화 토큰 인터페이스 표준을 정의하고 있다.</p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246676" localfile="yes" postid="38905412" height="258" width="425"></p><p>자바SE 5.0에서 자바 플랫폼에서 네이티브 PKCS#11 토큰의 통합을 편리하게 하기 위해 Sun PKCS#11 프로바이더를 추가하였다. 이 프로바이더는 JCA와 JCE API로 작성된 기존의 응용프로그램이 네이티브 PKCS#11 토큰에 접근할 수 있도록 해준다. 자세한 정보는 http://java.sun.com/javase/6/docs/ technotes/guides/security/p11guide.html을 참조하길 바란다.</p><p>● HSM 보안 토큰<br />
공인인증서의 해킹 사고를 막기 위해 이를 별도의 하드웨어에 저장할 목적으로 HSM(Hardware Security Module) 보안 토큰을 이용한다. 왜냐하면 HSM은 하드웨어 암호 가속기나 스마트카드 같은 암호 토큰과의 네이티브 프로그래밍 인터페이스를 제공하기 때문이다. 따라서 여러 종류의 디바이스에 대한 하드웨어 암호화를 이용하기 위해 HSM을 사용해야 하는데, 이때 PKCS#11 프로바이더를 이용한다. 따라서 자바 5.0 이상에서는 기본적으로 PKCS#11 프로바이더를 사용할 수 있다.</p><p>PKCS#11 지원은 디바이스 업체에서 PKCS#11 라이브러리를 제공하면 자바에서는 해당 프로바이더를 이용하여 기능호출이 가능하다. 하지만, PKCS#11 프로바이더 이용 시 SEED 알고리즘을 지원하지 않기 때문에 이에 대한 처리방안을 고려해야 한다. </p><p>왜냐하면, SEED 알고리즘은 1999년 한국정보보호센터(현 한국정보보호진흥원)에서 개발한 우리나 라 고유의 알고리즘이기 때문이다. 따라서 SEED 알고리즘을 별도로 Cipher클래스를 상속하여 구현하고 PKCS#11 프로바이더에 등록해주면 문제는 해결될 것이다.</p><br />
<p class="sub2">기술적 쟁점 5 - 윈도우 비스타 환경에서의 공인인증서 저장위치 문제</p><br />
<p>현재 우리나라에서 공인인증서를 저장하는 위치는 PC에서 시스템 폴더 밑에 특정 폴더로 지정되어 있다. 그렇다면 앞서 윈도우 비스타의 IE 7에서 발생한 문제와 동일한 문제가 발생한다. 필자가 가능성 검증을 하지는 못 했지만 이 문제는 자바에서 권한상승 방법을 그대로 이용하면 되지 않을까 싶다. 자바에 기본적으로 내장된 CORBA를 사용해 COM/CORBA Bridge 기술을 적용하는 것도 좋은 방법일 듯하다. 이 방법은 CORBA와 COM의 상호 운용성을 제공한다.<br />
자바가 공인인증서 플랫폼으로 쓰인다면?</p><p>이상에서 밝혀졌다시피 자바는 공인인증서 처리 플랫폼으로 사용하는데 장/단점을 자기고 있다. 하지만, 자바가 공인인증서를 처리하는데 충분히 적합하며, 결함이 없다는 데에는 이견이 없을 것이다. 단지 JRE를 엔드유저가 다운 받아야 하고 수행속도도 느릴 수 있다. </p><p>파업의 천국 프랑스에서 대중교통 노동자들에 의해 파리에서 3주 동안 지하철과 기차, 시내버스가 단 한 대도 다니지 않았다고 한다. 이때 불편함을 묻는 기자의 질문에 과반수가 넘는 파리 시민이 “불편하지요. 하지만 나는 파업 노동자들을 100% 지지하고 있습니다”라고 답했다고 한다. 자바를 공인인증서 처리 모듈로 사용하기 위해서는 최초 한번 JRE를 깔고 또다시 애플릿을 다운로드해야 하는 부담이 따른다. 하지만 액티브X가 지원되지 않으므로 고생하는 윈도우가 아닌 운영체제, IE가 아닌 웹브라우저 사용자들까지 공인인증서를 사용할 수 있다면 충분히 감내할 수 있는 부담이 아닐까 한다. </p><br />
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr></tr></tbody></table><p>Cover Story Plus</p><br />
<p class="sub1">오픈웹 소송과 자바 공인인증서</p><br />
<p>특집 2부는 자바로 공인인증서를 만들기 위해 필요한 기술과 해결 과제 등의 기술 쟁점을 소개하고 있다. 대체 왜 이런 복잡하고 어려운 기술에 대해 설명하고 있는 것일까? 그것에 대해 이해하기 위해 먼저 오픈웹 소송 과정부터 살펴보자.<br />
액티브X 문제가 지속적으로 제기되어 왔지만 오랜 시간동안 그저 산발적이고 미약한 목소리들 탓에 큰 성과를 거둔 적은 별로 없었다. 그러다가 비스타 발표와 맞물려 웹 표준화 단체인 오픈웹(www.openweb.or.kr)이 심지에 불을 붙이며 액티브X, 그중에서도 공인인증서 문제에 불이 붙었다.</p><p>오픈웹의 소송 내용은 금융결제원(이하 금결원)이 특정 운영체제와 브라우저에서만 실행할 수 있는 공인인증서를 제공함으로써 윈도우와 IE를 사용하지 않는 사용자들을 차별했다는 내용이 주였다. 액티브X로 만들어진 공인인증서를 사용하고 있는 탓이다. 이러한 차별을 통해 그동안 피해를 입었다고 주장하는 83명의 원고인단과 함께 금결원을 상대로 손해배상 청구 소송을 한 것이다. 3%를 밑도는 소수 운영체제나 브라우저를 쓰는 사람들은 대한민국에서 인터넷 뱅킹조차 할 수 없도록 만들었으니 당연한 일일 터다.</p><br />
<p class="sub1">잇따른 소송과 반발</p><br />
<p>그런데 오픈웹이 깃발을 들어 올리자 여기저기서 또 다른 목소리들이 터져 나왔다. 금결원이 그동안 특정 OS와 브라우저만 지원하는 인증서를 강요한 탓에 자신들이 범용적으로 사용할 수 있도록 개발한 공인인증서 소프트웨어를 사용하지 못하여 경제적 손실을 입었다며 한 결제 대행 서비스 업체도 소송 의사를 밝혔다. 더불어 오픈웹 소송 결과가 긍정적으로 진행되어가자 이번에는 아예 금결원은 공인인증 기관으로서의 자격이 없다며 공인인증기관 지정 취소 요구 소송을 준비하고 있다. 금결원이 은행들의 필요에 따라 만들어졌으며 은행의 임원들이 이사진으로 구성된 금결원이 공인인증 기관으로 활동하는 것에 문제가 있다는 것이 오픈웹의 주장이다. 또, 소송 과정에서 금결원은 은행의 추가비용 발생 등을 이유로 IE 이외의 브라우저 사용자를 위한 공인인증 소프트웨어 제공을 거부하는 등 공인인증기관으로서의 역할을 충실히 하지 않고 있다는 점도 이유로 들고 있다. 이런 이유로 오픈웹은 6월경에 공인인증기관 지정을 담당하는 정보통신부를 상대로 금결원에 대한 공인인증 기관 지정의 취소를 요구하는 행정 소송을 제기할 방침이란다. </p><br />
<p class="sub1">공인인증서 문제 자바로 해결하자 </p><br />
<p>오픈웹 소송으로 액티브X 공인인증서 문제가 주목을 받자 한국정보보호진흥원(이하 KISA)이 발 벗고 나섰다. KISA는 지난 2월부터 관련 전문가들과 함께 범용적으로 사용할 수 있는 공인인증서를 만들기 위한 방안을 모색하고 있다.</p><p>이미 몇 차례 회의를 가진 끝에 내린 결론은 여러 방법 중 해외에서도 오픈소스를 통해 서비스를 구현하고 있는 자바가 가장 유력한 기술로 인정되고 있다. 자바는 JRE(Java runtime environment)만 설치되어 있는 환경이면 OS와 브라우저를 가리지 않고 지원한다. 반면에 기존의 액티브X 윈도우 계열의 OS와 IE에서만 작동하는 기술이기 때문에 비MS 계열의 PC 환경에서는 사용이 불가능한 상태이다.</p><p>물론, 자바를 이용한 공인인증 서비스 구현이 하루아침에 될 일은 아니다. 이런 서비스가 구현되려면 먼저 다양한 사용자 환경에 대한 지원과 국제 표준을 준용한 인증서 관리 기능 지원 여부, 국제 및 국내 표준 알고리즘(SEED 알고리즘)을 이용한 전자서명 생성과 검증, 암복호화 기능 지원, 스마트카드와 USB 보안토큰 장치 지원 등이 필요하다.</p><p>최근 KISA와 관련 전문가들은 자바의 보안성과 확장성을 중심으로 기술적인 검토를 하고 있으며, 비스타와의 호환성 등 여러 가지 문제에 대한 해결책도 모색 중이다.</p><p align="center"><img src="http://tfile.nate.com/download.asp?FileID=32246677" localfile="yes" postid="38905412" height="360" width="517"></p><p>이미 해외의 몇 개 나라에서는 자바를 이용하여 공인인증 서비스를 구현하고 있기도 하다. KISA와 전문가들의 노력, 사회의 관심 그리고 금융기관의 바른 의식이 하나가 되어 조만간 자바 공인인증 서비스를 만날 수 있게 되기를 바란다. </p><p>정희용 기자 | flytgr@imaso.co.kr</p><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr></tr></tbody></table><p>Cover Story Plus</p><br />
<p class="sub1">공인인증서 문제 해결을 위한 방법들</p><br />
<p>특집 2부에서는 공인인증서 문제를 해결하기 위해 자바를 활용하는 방법 위주로 설명하고 있지만, 이 밖에도 여러 가지 방법들이 제안되고 있다. 특히, 오픈웹은 상당히 다양한 방법들에 대해 체계적으로 제시하고 있으며, 이는 다시 단기적인 방법과 장기적인 방법으로 나누어서 설명되고 있다. 오픈웹이 제시하고 있는 단기적 해결 방법과 장기적인 해결 방법은 다음 링크를 통해 확인할 수 있다.</p><p>● 단기적 해결 방안 : http://korea.gnu.org/openweb/1/sterm.html <br />
● 장기적 해결 방안 : http://open.unfix.net/%EC%A0%84%EC%9E %90%EC%84%9C%EB%AA%85%EB%B2%95%EA%B3%BC-%EA%B3%B5%EC%9D%B8%EC%9D%B8%EC%A6%9D%EC%84%9Cin-progress/#c9</p><p>여기에서는 오픈웹이 제안하고 있는 해결 방법들에 대해 간단히 알아본다. 먼저 단기적인 해결 방안으로 제시하고 있는 기술들은 자바 애플릿과 특집 4부에서 다루고 있는 XPCOM, 플래시(플랙스)와 자바 애플릿의 병행, 플래시, 모질라나 넷스케이프의 플러그인 기능 등이다. 이 중에서 가장 빨리 적용할 수 있는 방법으로는 자바 애플릿과 플래시를 들고 있다. </p><p>자바 애플릿에 대해서는 본문에서 설명하고 있지만 다시 간단히 설명하자면, 자바는 높은 수준의 보안을 확보할 수 있을 뿐 아니라 플랫폼에 구애받지 않으면서 인증서를 구현할 수 있다. 또 한 가지 빼놓을 수 없는 장점은 사용자가 컴퓨터에 관리자 권한으로 어떤 프로그램도 설치할 필요가 없기 때문에, 네트워크 관리 기준이 높은 외국에서도 쉽게 사용할 수 있다는 점이다. 물론, 자바 애플릿에도 단점은 있다. 컴퓨터가 자바 애플릿을 다운 받는데 약간의 시간이 걸린다는 점과 가상머신이 마련되는 동안 좀 더 기다려야 한다는 점이다.</p><p>다음은 플래시다. 플래시는 자바 애플릿에 비해 내려 받아야 하는 파일의 크기가 작고 플래시 플레이어 자체가 가상머신의 역할을 하기 때문에 자바 애플릿을 쓸 때보다는 시간이 덜 걸린다는 장점이 있다. 또, 높은 안정성을 가지고 있을 뿐 아니라 플래시 플레이어만 설치되어 있다면 매킨토시와 리눅스 등의 운영체제에서도 사용할 수 있다. 관리자 권한이 없는 일반 사용자가 자신의 개인용 파일 시스템에 플래시 플레이어를 설치하는 구조이기 때문에, 보안 위험을 줄이면서도 추가 설치나 업그레이드가 가능하다는 점도 장점이다. 오픈웹에 따르면 이미 국내 보안 업체 중에 플래시와 자바 애플릿을 이용한 공인인증서 처리 솔루션의 개발을 완료한 곳도 있단다. </p><p>한 가지를 더 살펴보자. 이번 방법은 브라우저의 확장 플러그인을 사용하는 것이다. 플러그인은 애플릿처럼 어떤 응용프로그램의 이용에 도움이 되는 특정한 부가 기능을 제공하는 보조 프로그램이다. 여기에서 주프로그램과 보조 프로그램 간의 통신과 리소스 호출 방법 등을 제시하는 API는 오픈소스 형태로 공개되어 있다. 대표적인 브라우저로는 파이어폭스가 있으며 플러그인 기반의 인증 기술 또한 국내 기술진에 의해 개발되어 있다고 한다. </p><p>다음 표는 오픈웹에서 제안하고 있는 공인인증서 문제의 단기적인 해결 방법들을 비교 정리한 것이다. </p><p align="center"><a href="http://www.dbguide.net/images/know/tech/070621_t2_4.jpg" target="_blank"><img src="http://tfile.nate.com/download.asp?FileID=32246678" localfile="yes" postid="38905412" border="0" height="411" width="556"></a></p><p align="center">(자세히 보기 - 이미지를 클릭 하십시오.)</p><p>정희용 기자 | flytgr@imaso.co.kr</p><br />
<br />
<br />
<p><a href="http://www.dbguide.net/" target="_blank"><b><font color="midnightblue">제공 : DB포탈사이트 DBguide.net </font></b></a><br />
</p><br/><br/>tag : <a href="/tag/ajax" rel="tag">ajax</a>,&nbsp;<a href="/tag/기술" rel="tag">기술</a>,&nbsp;<a href="/tag/브라우저" rel="tag">브라우저</a>,&nbsp;<a href="/tag/웹" rel="tag">웹</a>,&nbsp;<a href="/tag/표준" rel="tag">표준</a>,&nbsp;<a href="/tag/호환성" rel="tag">호환성</a>,&nbsp;<a href="/tag/액티브" rel="tag">액티브</a>,&nbsp;<a href="/tag/운영체제" rel="tag">운영체제</a>			 ]]> 
		</description>
		<category>Trend</category>
		<category>ajax</category>
		<category>기술</category>
		<category>브라우저</category>
		<category>웹</category>
		<category>표준</category>
		<category>호환성</category>
		<category>액티브</category>
		<category>운영체제</category>

		<comments>http://topic.egloos.com/508703#comments</comments>
		<pubDate>Mon, 06 Aug 2007 05:25:05 GMT</pubDate>
		<dc:creator>Hans</dc:creator>
	</item>
</channel>
</rss>
