<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
	<channel>
		<title>HARDWORKER</title>
		<link>http://hardworker.tistory.com/</link>
		<description>웹개발자가 관심갖는 것</description>
		<language>ko</language>
		<pubDate>Sat, 28 Jan 2012 00:47:08 +0900</pubDate>
		<generator>Tistory 1.1 (http://www.tistory.com/)</generator>
		<managingEditor>sh.</managingEditor>
		<image>
		<title>HARDWORKER</title>
		<url><![CDATA[http://cfile7.uf.tistory.com/image/193ABB384E4009A92A3C84]]></url>
		<link>http://hardworker.tistory.com/</link>
		<description>웹개발자가 관심갖는 것</description>
		</image>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Hardworker" /><feedburner:info uri="hardworker" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2FHardworker" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/Hardworker" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FHardworker" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><item>
			<title>자바스크립트 JavaScript 학습자료 추천</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/cNbkrgn2Cz8/30</link>
			<description>&lt;div&gt;
&lt;div class="txc-textbox" style="border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(243, 197, 52); border-right-color: rgb(243, 197, 52); border-bottom-color: rgb(243, 197, 52); border-left-color: rgb(243, 197, 52); background-color: rgb(254, 254, 184); padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; "&gt;
&lt;p&gt;&lt;i&gt;&lt;b&gt;2011년 7월 31일 추가.&lt;/b&gt;&lt;/i&gt;&amp;nbsp;이 글이 본 블로그에서 가장 많이 방문되는 글이라는 사실에 충격받아 글을 갈아엎고 싶은 마음이 굴뚝같지만 밑천도 시간도 부족해 간단한 업데이트로 대신하려 한다.&lt;/p&gt;
&lt;p&gt;부족한 밑천은 StackOverflow에 올라온 &lt;a href="http://stackoverflow.com/questions/11246/best-resources-to-learn-javascript" target="_blank" title="[http://stackoverflow.com/questions/11246/best-resources-to-learn-javascript]로 이동합니다."&gt;Best Resources to learn JavaScript&lt;/a&gt;의 종결자적 답변으로 때워볼까 한다. &amp;nbsp;많은 사람이 추천하는 &amp;nbsp;더글라스 크락포드(Douglas Crockford)의 웹사이트와 그의 책 &lt;a href="http://www.amazon.com/dp/0596517742/?tag=stackoverfl08-20" target="_blank" title="[http://www.amazon.com/dp/0596517742/?tag=stackoverfl08-20]로 이동합니다."&gt;JavaScript: The Good Parts&lt;/a&gt;을 참고하자. 다행히&lt;a href="http://www.aladin.co.kr/shop/wproduct.aspx?ISBN=8979145985" target="_blank" title="[http://www.aladin.co.kr/shop/wproduct.aspx?ISBN=8979145985]로 이동합니다."&gt;번역서&lt;/a&gt;가 출간되었으니 참고.&lt;/p&gt;
&lt;p&gt;이 글을 쓴게 3년 전인데 그 사이 자바스크립트는 &lt;a href="http://www.crockford.com/javascript/javascript.html" target="_blank" title="[http://www.crockford.com/javascript/javascript.html]로 이동합니다."&gt;세상에서 가장 오해받는 언어&lt;/a&gt;에서 가장 핫한 언어가 되었다. 늘 "이 말랑말랑한 언어로 서버사이드 개발을 하면 재밌겠다"고 생각해왔는데, Node.js, Backbone 등 서버사이드의 다양한 솔루션이 나오고 있다. PhoneGap이나 Titanium 등 하이브리드 모바일 앱 개발에도 자바스크립트는 굉장히 중요한 역할을 한다. 웹브라우저의 속도 개선, HTML5의 저변 확대 등의 영향으로 게임 등 전통적으로 JS의 영역이 아니라 여겨지던 부분에서도 활발한 움직임이 있다. &lt;a href="https://github.com/bebraw/jswiki/wiki/Game-Engines" target="_blank" title="[https://github.com/bebraw/jswiki/wiki/Game-Engines]로 이동합니다."&gt;JavaScript Game Engine 목록&lt;/a&gt;을 보라.&lt;/p&gt;
&lt;p&gt;요즘 쏟아져나오는 .js 라이브러리의 양은 상상 초월이다.&amp;nbsp;http://paperjs.org/,&amp;nbsp;http://popcornjs.org/,&amp;nbsp;http://kolber.github.com/audiojs/,&amp;nbsp;http://processingjs.org/,&amp;nbsp;http://impactjs.com/ ... The World's Most Active Programming Language가 되어버린 자바스크립트의 최신 동향을 제대로 훑는 건 내 능력을 벗어나는 일인 것 같다. 나도 따라가기 버거웁다 ㅠㅠ &amp;nbsp;여기서 이만 부족하나마 오래된 글의 애프터서비스를 마친다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
(원래 글 쓴 날 : 2008년 8월 15일) 몇 년 사이 자바스크립트가 다시 전성기를 맞고 있군요. 이를 증명하듯 한동안 한빛-O'relly의 '자바스크립트 핵심 가이드'하고 정보문화사-Wrox의 'Professional Javascript'외엔 프로그래머가 볼 만한 책이 없었는데 요즘 좋은 책이 많이 나왔네요.&lt;br /&gt;
&lt;br /&gt;
얼마전 후배 개발자가 자바스크립트 책을 추천해달라고 한걸 계기로, 자바스크립트 학습자료를 정리해보기로 했어요.&lt;br /&gt;
&lt;br /&gt;
우선 제가 최고의 자바스크립트 책으로 치는 '자바스크립트 핵심 가이드'의 원서 최신판, 'JavaScript, The Definitive Guide 5/E'가 번역되어 나왔어요. 한빛에서 나온 3/E의 번역서는 애초에 품절이라 아쉬웠는데 이번에 인사이트가 좋은 일을 했네요^^ &lt;span style="text-decoration: line-through;"&gt;저는 구판만 읽어봤지만, 최신판이니만큼 더욱 좋아졌을거라 생각해요.&lt;/span&gt; 팀원이 책을 샀길래 잠깐 훑어봤더니 굉장히 좋아졌네요! 예제 코드도 최신 스타일(?)이고, 레퍼런스 부분이 분책되있는 점도 아주 좋고요. 구판은 버려야겠어요^^&lt;br /&gt;
&lt;div class="ttbReview"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;a href="http://www.aladdin.co.kr/shop/wproduct.aspx?ISBN=8991268412&amp;amp;ttbkey=ttbbs00481101006&amp;amp;COPYPaper=1"&gt;&lt;img src="http://image.aladdin.co.kr/coveretc/book/coversum/8991268412_1.jpg" alt="" border="0" style="display: none !important; visibility: hidden !important; opacity: 0 !important; " width="0" height="0"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="vertical-align: top;" align="left"&gt;&lt;a href="http://www.aladdin.co.kr/shop/wproduct.aspx?ISBN=8991268412&amp;amp;ttbkey=ttbbs00481101006&amp;amp;COPYPaper=1" class="aladdin_title"&gt;자바스크립트 완벽 가이드 - 전2권&lt;/a&gt; - &lt;img src="http://image.aladdin.co.kr/img/common/star_s10.gif" alt="10점" border="0" style="display: none !important; visibility: hidden !important; opacity: 0 !important; " width="0" height="0"&gt;&lt;br /&gt;
데이비드 플래너건 지음, 송인철 외 옮김/인사이트&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;br /&gt;
제가 사랑하는 '헤드 퍼스트Head First' 시리즈에서 JavaScript도 나왔군요! 이 책도 읽어보진 않았습니다만, 헤드퍼스트 시리즈 중에는 실망스러운게 없었어요. 전 헤드퍼스트를 믿어요ㅎ 차근차근 친절하게 배우고픈 초보자는 이 책을 고려해보세요!&lt;br /&gt;
&lt;div class="ttbReview"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;a href="http://www.aladdin.co.kr/shop/wproduct.aspx?ISBN=8979145829&amp;amp;ttbkey=ttbbs00481101006&amp;amp;COPYPaper=1"&gt;&lt;img src="http://image.aladdin.co.kr/coveretc/book/coversum/8979145829_1.jpg" alt="" border="0" style="display: none !important; visibility: hidden !important; opacity: 0 !important; " width="0" height="0"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="vertical-align: top;" align="left"&gt;&lt;a href="http://www.aladdin.co.kr/shop/wproduct.aspx?ISBN=8979145829&amp;amp;ttbkey=ttbbs00481101006&amp;amp;COPYPaper=1" class="aladdin_title"&gt;Head First JavaScript&lt;/a&gt; - &lt;img src="http://image.aladdin.co.kr/img/common/star_s10.gif" alt="10점" border="0" style="display: none !important; visibility: hidden !important; opacity: 0 !important; " width="0" height="0"&gt;&lt;br /&gt;
마이클 모리슨 지음, 홍형경 옮김/한빛미디어&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;br /&gt;
이건 번역서 나오기 전에 원서를 후루룩 넘겨본 수준이지만.... 책의 저자가 엄청 유명한 웹사이트인 www.quirksmode.org의 주인장 피터 폴 콕이란 이유만으로 추천이에요. www.quirksmode.org에서 배운게 고마워서라도 그냥 책 한권 사주고 싶다는.. 최근 이슈인 '웹표준'과 관련된 내용이 많이 있고, 자바스크립트 초심자를 위한 책은 아니에요.&lt;br /&gt;
&lt;div class="ttbReview"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;a href="http://www.aladdin.co.kr/shop/wproduct.aspx?ISBN=8960770442&amp;amp;ttbkey=ttbbs00481101006&amp;amp;COPYPaper=1"&gt;&lt;img src="http://image.aladdin.co.kr/coveretc/book/coversum/8960770442_1.jpg" alt="" border="0" style="display: none !important; visibility: hidden !important; opacity: 0 !important; " width="0" height="0"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="vertical-align: top;" align="left"&gt;&lt;a href="http://www.aladdin.co.kr/shop/wproduct.aspx?ISBN=8960770442&amp;amp;ttbkey=ttbbs00481101006&amp;amp;COPYPaper=1" class="aladdin_title"&gt;PPK 자바스크립트&lt;/a&gt; - &lt;img src="http://image.aladdin.co.kr/img/common/star_s10.gif" alt="10점" border="0" style="display: none !important; visibility: hidden !important; opacity: 0 !important; " width="0" height="0"&gt;&lt;br /&gt;
피터 폴 콕 지음, 전정환.정문식 옮김/에이콘출판&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;br /&gt;
경량 데이터 교환형식으로 널리 쓰이는 JSON을 고안한 Douglas crockford의 웹사이트 먼저.&lt;br /&gt;
&lt;a href="http://www.crockford.com/javascript/javascript.html" target="_blank"&gt;The World's Most Misunderstood Programming Language&lt;/a&gt;는 자바스크립트에 대해 이런저런 편견을 가진 분들을 위한 글이에요. &lt;a href="http://home.postech.ac.kr/%7Eskyul/javascript.html" target="_blank"&gt;한글로 번역&lt;/a&gt;된 것도 있으니 부담갖지 마시고요ㅎ&lt;br /&gt;
&lt;a href="http://www.json.org/" target="_blank"&gt;JSON&lt;/a&gt;에 대해서도 곧 알아두셔야 할거에요. Ajax시대를 맞아 서로 다른 플랫폼간의 경량 데이터 통신에 아주 많이 쓰이는 형식이거든요. 그 외에도 자바스크립트 코드 압축기라던가 여러가지 참고할 자료가 많아요.&lt;br /&gt;
&lt;br /&gt;
앞에도 잠깐 언급한 http://www.quirksmode.org/는 정말정말 중요한 곳이에요. 웹브라우저에 내장된 클라이언트-사이드 자바스크립트에 대한 정보는 여기 다 있어요. 여기 있는 글을 다 읽어봐야됩니다ㅎ 특히 이벤트 모델에 대한 부분(&lt;a href="http://www.quirksmode.org/js/introevents.html" target="_blank"&gt;http://www.quirksmode.org/js/introevents.html&lt;/a&gt;)은 이벤트 모델 (.onclick과 addEventHandler/attachEvent)의 차이, 역사, 브라우저별 특성 등 모든게 정리되어 있어요!&lt;br /&gt;
&lt;br /&gt;
Ajax의 등장으로 자바스크립트계가 활발해지면서 각종 라이브러리가 등장했는데, 가장 유명해진 것이 바로 &lt;a href="http://prototypejs.org/" target="_blank"&gt;프로토타입prototype.js&lt;/a&gt;가 아닐까 합니다. 이 외에도 jQuery라던가 Dojo toolkit, YUI 등 좋은게 많습니다만 저는 prototype.js를 분석해볼 것을 권해드려요. 일단은 제가 라인단위로 분석해본게 이것 뿐이라^^ 관련서적이 나와있기도 하고요, RoR과 함께 엄청 성장을 해서 사용자층이 많은 것도 장점이고요.&lt;br /&gt;
김영보님이 prototype.js를 분석한 서적이 출간되기도 했습니다만 지금은 절판이라 구할 수 없어요. 저는 책도 샀고 저자직강도 들었었는데, 인터넷에서 자료찾는게 익숙한 분이면 절판된 사실에 아쉬워하지 않아도 될거에요. 자세한 구현원리까지 설명되어있진 않아서요. prototype.js와 찰떡궁합인 scriptaculous를 같이 설명한 책이 시중에 나왔으니 참고하시구요. (분석서는 아니고, 활용서들이에요)&lt;br /&gt;
&lt;br /&gt;
당장 prototype.js같은 큰 라이브러리를 분석하기 부담스럽다면, 한 때 인기를 끌었던 이 글을 읽어보세요.&lt;br /&gt;
&lt;a href="http://www.dustindiaz.com/top-ten-javascript/" target="_blank"&gt;http://www.dustindiaz.com/top-ten-javascript/&lt;/a&gt;&lt;br /&gt;
유용한 자바스크립트 함수 10개만 꼽아본다면? 이라는 질문으로 시작하는 이 글은 prototype.js와 같은 라이브러리가 유행하기 직전에 쓰여진거라는 점을 감안하고 보면 아주 재미있어요. 많은 개발자들이 생각하는 자바스크립트의 아쉬운 점도 엿볼 수 있고, 여기에 있는 함수중에 prototype.js 안에 구현되어 있는 것들도 많아서 나중에 prototype.js를 분석할 때 도움이 되요.&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
자바스크립트 초보자에겐 &lt;a href="http://www.slash7.com/articles/2006/07/26/javascript-boot-camp-tutorial" target="_blank"&gt;Javascript Bootcamp tutorial&lt;/a&gt;을 추천하고 싶네요! 짧은 코드가 나오는 여러장의 슬라이드인데, 차례대로 넘기면서 보면 '아하!'할 수 있게 구성됐어요. 필수 추천자료에요.&lt;br /&gt;
&lt;br /&gt;
생각나는대로 막 적어내려봤는데, 생각보다 가진 자료가 별로 없네요^^ 레퍼런스와 다른 분들이 모아둔 자료를 아래 참고에 링크하면서 마치겠습니다. 더 생각이 날때마다 업데이트 하도록 하지요.&lt;br /&gt;
&lt;br /&gt;
참고&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.w3schools.com/jsref/default.asp" target="_blank"&gt;http://www.w3schools.com/jsref/default.asp&lt;/a&gt; w3schools의 js reference&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.mozilla.org/ko/docs/Core_JavaScript_1.5_Reference" target="_blank"&gt;http://developer.mozilla.org/ko/docs/Core_JavaScript_1.5_Reference&lt;/a&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jania.pe.kr/aw/moin.cgi/JavaScriptTips" target="_blank"&gt;http://jania.pe.kr/aw/moin.cgi/JavaScriptTips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://seye2.egloos.com/1932494" target="_blank"&gt;http://seye2.egloos.com/1932494&lt;/a&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div id="csscan-wrapper" style="display: none; "&gt;
&lt;h2 id="csscan-header"&gt;element&lt;/h2&gt;&lt;table id="csscan-table"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-font" class="csscan-header"&gt;Font&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-font-family"&gt;
&lt;td id="csscan-property-font-family" class="csscan-property"&gt;font-family&lt;/td&gt;
&lt;td id="csscan-value-font-family" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-size"&gt;
&lt;td id="csscan-property-font-size" class="csscan-property"&gt;font-size&lt;/td&gt;
&lt;td id="csscan-value-font-size" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-style"&gt;
&lt;td id="csscan-property-font-style" class="csscan-property"&gt;font-style&lt;/td&gt;
&lt;td id="csscan-value-font-style" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-variant"&gt;
&lt;td id="csscan-property-font-variant" class="csscan-property"&gt;font-variant&lt;/td&gt;
&lt;td id="csscan-value-font-variant" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-weight"&gt;
&lt;td id="csscan-property-font-weight" class="csscan-property"&gt;font-weight&lt;/td&gt;
&lt;td id="csscan-value-font-weight" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-letter-spacing"&gt;
&lt;td id="csscan-property-letter-spacing" class="csscan-property"&gt;letter-spacing&lt;/td&gt;
&lt;td id="csscan-value-letter-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-line-height"&gt;
&lt;td id="csscan-property-line-height" class="csscan-property"&gt;line-height&lt;/td&gt;
&lt;td id="csscan-value-line-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-decoration"&gt;
&lt;td id="csscan-property-text-decoration" class="csscan-property"&gt;text-decoration&lt;/td&gt;
&lt;td id="csscan-value-text-decoration" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-align"&gt;
&lt;td id="csscan-property-text-align" class="csscan-property"&gt;text-align&lt;/td&gt;
&lt;td id="csscan-value-text-align" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-indent"&gt;
&lt;td id="csscan-property-text-indent" class="csscan-property"&gt;text-indent&lt;/td&gt;
&lt;td id="csscan-value-text-indent" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-transform"&gt;
&lt;td id="csscan-property-text-transform" class="csscan-property"&gt;text-transform&lt;/td&gt;
&lt;td id="csscan-value-text-transform" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-white-space"&gt;
&lt;td id="csscan-property-white-space" class="csscan-property"&gt;white-space&lt;/td&gt;
&lt;td id="csscan-value-white-space" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-word-spacing"&gt;
&lt;td id="csscan-property-word-spacing" class="csscan-property"&gt;word-spacing&lt;/td&gt;
&lt;td id="csscan-value-word-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-color"&gt;
&lt;td id="csscan-property-color" class="csscan-property"&gt;color&lt;/td&gt;
&lt;td id="csscan-value-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-background" class="csscan-header"&gt;Background&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-background-attachment"&gt;
&lt;td id="csscan-property-background-attachment" class="csscan-property"&gt;bg-attachment&lt;/td&gt;
&lt;td id="csscan-value-background-attachment" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-color"&gt;
&lt;td id="csscan-property-background-color" class="csscan-property"&gt;bg-color&lt;/td&gt;
&lt;td id="csscan-value-background-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-image"&gt;
&lt;td id="csscan-property-background-image" class="csscan-property"&gt;bg-image&lt;/td&gt;
&lt;td id="csscan-value-background-image" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-position"&gt;
&lt;td id="csscan-property-background-position" class="csscan-property"&gt;bg-position&lt;/td&gt;
&lt;td id="csscan-value-background-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-repeat"&gt;
&lt;td id="csscan-property-background-repeat" class="csscan-property"&gt;bg-repeat&lt;/td&gt;
&lt;td id="csscan-value-background-repeat" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-size" class="csscan-header"&gt;Box&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-width"&gt;
&lt;td id="csscan-property-width" class="csscan-property"&gt;width&lt;/td&gt;
&lt;td id="csscan-value-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-height"&gt;
&lt;td id="csscan-property-height" class="csscan-property"&gt;height&lt;/td&gt;
&lt;td id="csscan-value-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-top"&gt;
&lt;td id="csscan-property-border-top" class="csscan-property"&gt;border-top&lt;/td&gt;
&lt;td id="csscan-value-border-top" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-right"&gt;
&lt;td id="csscan-property-border-right" class="csscan-property"&gt;border-right&lt;/td&gt;
&lt;td id="csscan-value-border-right" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-bottom"&gt;
&lt;td id="csscan-property-border-bottom" class="csscan-property"&gt;border-bottom&lt;/td&gt;
&lt;td id="csscan-value-border-bottom" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-left"&gt;
&lt;td id="csscan-property-border-left" class="csscan-property"&gt;border-left&lt;/td&gt;
&lt;td id="csscan-value-border-left" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-margin"&gt;
&lt;td id="csscan-property-margin" class="csscan-property"&gt;margin&lt;/td&gt;
&lt;td id="csscan-value-margin" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-padding"&gt;
&lt;td id="csscan-property-padding" class="csscan-property"&gt;padding&lt;/td&gt;
&lt;td id="csscan-value-padding" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-max-height"&gt;
&lt;td id="csscan-property-max-height" class="csscan-property"&gt;max-height&lt;/td&gt;
&lt;td id="csscan-value-max-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-min-height"&gt;
&lt;td id="csscan-property-min-height" class="csscan-property"&gt;min-height&lt;/td&gt;
&lt;td id="csscan-value-min-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-max-width"&gt;
&lt;td id="csscan-property-max-width" class="csscan-property"&gt;max-width&lt;/td&gt;
&lt;td id="csscan-value-max-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-min-width"&gt;
&lt;td id="csscan-property-min-width" class="csscan-property"&gt;min-width&lt;/td&gt;
&lt;td id="csscan-value-min-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-outline-color"&gt;
&lt;td id="csscan-property-outline-color" class="csscan-property"&gt;outline-color&lt;/td&gt;
&lt;td id="csscan-value-outline-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-outline-style"&gt;
&lt;td id="csscan-property-outline-style" class="csscan-property"&gt;outline-style&lt;/td&gt;
&lt;td id="csscan-value-outline-style" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-outline-width"&gt;
&lt;td id="csscan-property-outline-width" class="csscan-property"&gt;outline-width&lt;/td&gt;
&lt;td id="csscan-value-outline-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-position" class="csscan-header"&gt;Positioning&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-position"&gt;
&lt;td id="csscan-property-position" class="csscan-property"&gt;position&lt;/td&gt;
&lt;td id="csscan-value-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-top"&gt;
&lt;td id="csscan-property-top" class="csscan-property"&gt;top&lt;/td&gt;
&lt;td id="csscan-value-top" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-bottom"&gt;
&lt;td id="csscan-property-bottom" class="csscan-property"&gt;bottom&lt;/td&gt;
&lt;td id="csscan-value-bottom" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-right"&gt;
&lt;td id="csscan-property-right" class="csscan-property"&gt;right&lt;/td&gt;
&lt;td id="csscan-value-right" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-left"&gt;
&lt;td id="csscan-property-left" class="csscan-property"&gt;left&lt;/td&gt;
&lt;td id="csscan-value-left" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-float"&gt;
&lt;td id="csscan-property-float" class="csscan-property"&gt;float&lt;/td&gt;
&lt;td id="csscan-value-float" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-display"&gt;
&lt;td id="csscan-property-display" class="csscan-property"&gt;display&lt;/td&gt;
&lt;td id="csscan-value-display" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-clear"&gt;
&lt;td id="csscan-property-clear" class="csscan-property"&gt;clear&lt;/td&gt;
&lt;td id="csscan-value-clear" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-z-index"&gt;
&lt;td id="csscan-property-z-index" class="csscan-property"&gt;z-index&lt;/td&gt;
&lt;td id="csscan-value-z-index" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-list" class="csscan-header"&gt;List&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-list-style-image"&gt;
&lt;td id="csscan-property-list-style-image" class="csscan-property"&gt;list-style-image&lt;/td&gt;
&lt;td id="csscan-value-list-style-image" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-list-style-type"&gt;
&lt;td id="csscan-property-list-style-type" class="csscan-property"&gt;list-style-type&lt;/td&gt;
&lt;td id="csscan-value-list-style-type" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-list-style-position"&gt;
&lt;td id="csscan-property-list-style-position" class="csscan-property"&gt;list-style-position&lt;/td&gt;
&lt;td id="csscan-value-list-style-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-table" class="csscan-header"&gt;Table&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-vertical-align"&gt;
&lt;td id="csscan-property-vertical-align" class="csscan-property"&gt;vertical-align&lt;/td&gt;
&lt;td id="csscan-value-vertical-align" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-collapse"&gt;
&lt;td id="csscan-property-border-collapse" class="csscan-property"&gt;border-collapse&lt;/td&gt;
&lt;td id="csscan-value-border-collapse" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-spacing"&gt;
&lt;td id="csscan-property-border-spacing" class="csscan-property"&gt;border-spacing&lt;/td&gt;
&lt;td id="csscan-value-border-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-caption-side"&gt;
&lt;td id="csscan-property-caption-side" class="csscan-property"&gt;caption-side&lt;/td&gt;
&lt;td id="csscan-value-caption-side" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-empty-cells"&gt;
&lt;td id="csscan-property-empty-cells" class="csscan-property"&gt;empty-cells&lt;/td&gt;
&lt;td id="csscan-value-empty-cells" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-table-layout"&gt;
&lt;td id="csscan-property-table-layout" class="csscan-property"&gt;table-layout&lt;/td&gt;
&lt;td id="csscan-value-table-layout" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-effects" class="csscan-header"&gt;Effects&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-text-shadow"&gt;
&lt;td id="csscan-property-text-shadow" class="csscan-property"&gt;text-shadow&lt;/td&gt;
&lt;td id="csscan-value-text-shadow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row--webkit-box-shadow"&gt;
&lt;td id="csscan-property--webkit-box-shadow" class="csscan-property"&gt;-webkit-box-shadow&lt;/td&gt;
&lt;td id="csscan-value--webkit-box-shadow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-radius"&gt;
&lt;td id="csscan-property-border-radius" class="csscan-property"&gt;border-radius&lt;/td&gt;
&lt;td id="csscan-value-border-radius" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-other" class="csscan-header"&gt;Other&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-overflow"&gt;
&lt;td id="csscan-property-overflow" class="csscan-property"&gt;overflow&lt;/td&gt;
&lt;td id="csscan-value-overflow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-cursor"&gt;
&lt;td id="csscan-property-cursor" class="csscan-property"&gt;cursor&lt;/td&gt;
&lt;td id="csscan-value-cursor" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-visibility"&gt;
&lt;td id="csscan-property-visibility" class="csscan-property"&gt;visibility&lt;/td&gt;
&lt;td id="csscan-value-visibility" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  					&lt;embed src="http://api.v.daum.net/static/recombox1.swf" quality="high" flashvars="nid=19130954" allowscriptaccess="always" allowfullscreen="false" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash" wmode="transparent"&gt;&lt;/embed&gt;
						&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=cNbkrgn2Cz8:PJSxA17Qamw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=cNbkrgn2Cz8:PJSxA17Qamw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=cNbkrgn2Cz8:PJSxA17Qamw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/cNbkrgn2Cz8" height="1" width="1"/&gt;</description>
			<category>Javascript</category>
			<category>prototype.js</category>
			<category>책추천</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/30</guid>
			<comments>http://hardworker.tistory.com/30#entry30comment</comments>
			<pubDate>Sun, 31 Jul 2011 22:53:24 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/30</feedburner:origLink></item>
		<item>
			<title>웹폰트(@font-face)에 관해 / About Web Fonts</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/2h_c-n_T62s/113</link>
			<description>&lt;p&gt;예전에도 한 번 웹폰트에 대해서&amp;nbsp;&lt;a href="http://hardworker.tistory.com/98" target="_blank" title="[http://hardworker.tistory.com/98]로 이동합니다."&gt;쓴 적이 있는데&lt;/a&gt;&amp;nbsp;그 후로 참 이쪽 업계에 많은 발전이 있었다. 주요 웹브라우저가 웹폰트 지원을 강화했고, iOS4.2부터 모바일 사파리가 웹폰트를 지원한다. Typekit도 빠르게 성장하는 것 같고, 구글도 &lt;a href="http://www.google.com/webfonts" target="_blank" title="[http://www.google.com/webfonts]로 이동합니다."&gt;웹폰트 서비스&lt;/a&gt;를 오픈한 후 신경을 많이 쓰는 것 같다. 구글에서 제공하는 폰트 패밀리가 지금 197개에 달하고, &lt;a href="http://twitter.com/#!/googlefonts" target="_blank" title="[http://twitter.com/#!/googlefonts]로 이동합니다."&gt;빠르게 추가되고 있다&lt;/a&gt;. 국내에서도 미투데이가 한동안 나눔고딕을 웹폰트로 제공했는데 &lt;a href="http://me2day.net/me2/blog/posts/py0j0ze-1xf" target="_blank" title="[http://me2day.net/me2/blog/posts/py0j0ze-1xf]로 이동합니다."&gt;성능을 이유로 제거&lt;/a&gt;했다. 한국어 폰트는 글자수가 많아 용량이 큰데, 적극 도입하는데 큰 장벽이 되는 것이 사실이다. 하지만 웹폰트는 앞으로 대세 내지는 상당히 일반적으로 쓰일 것으로 생각한다. 내가 개발하고 있는 서비스에서도 웹폰트를 쓰고 있는데, 관련 자료를 정리하기 위해 이 글을 쓴다. 약간의 구글링만으로 찾을 수 있는 자료들이지만... 나이를 먹어감에 따라 자꾸 헷갈려서 원.&lt;/p&gt;
&lt;p&gt;쉬운 방법부터. 구글이나 타입킷같은 웹폰트 호스팅을 이용하면 정말 쉽다.&amp;nbsp;&lt;a href="http://www.google.com/webfonts" target="_blank" title="[http://www.google.com/webfonts]로 이동합니다."&gt;Google Webfonts&lt;/a&gt;나 &lt;a href="http://typekit.com" target="_blank" title="[http://typekit.com]로 이동합니다."&gt;Typekit&lt;/a&gt;에서 마음에 드는 폰트를 고르고&amp;nbsp;코드 몇 줄 복사해 넣으면 바로 적용된다. 구글은 Open/Free 폰트만 제공하지만 쓸만한 것들이 많다. 타입킷은 무료부터 유명 상용 폰트까지 다양하다. &lt;a href="http://alternativeto.net/software/typekit/" target="_blank" title="[http://alternativeto.net/software/typekit/]로 이동합니다."&gt;비슷한 서비스가 많으니&lt;/a&gt;&amp;nbsp;고려해보자. 한글 폰트가 필요하다면&amp;nbsp;&lt;a href="http://fontface.kr/" target="_blank" title="[http://fontface.kr/]로 이동합니다."&gt;fontface.kr&lt;/a&gt;(무료, 비상업, 나눔 패밀리만 제공)이 우선 시도해보기 좋고, 더 본격적으로 상업적 지원까지 고려한다면&amp;nbsp;&lt;a href="http://api.mobilis.co.kr/webfonts/" target="_blank" title="[http://api.mobilis.co.kr/webfonts/]로 이동합니다."&gt;모빌리스의 웹폰트 서비스&lt;/a&gt;(나눔, 은, 백묵 등 공개글꼴 제공)에 관심을 가져보자.&lt;/p&gt;
&lt;p&gt;좀 더 기술적인 것들을 알고 싶다면 계속 읽어주세요. 일반인은 여기까지.&lt;/p&gt;
&lt;p&gt;@font-face로 웹폰트를 쓸 때 성가신 점은, 바로 브라우저 호환성이다. IE은 EOT, Firefox는 WOFF(3.5 이하는 TTF/OTF), Safari는 TTF 포멧을 지원한다(IE9와 OS X Lion의 사파리는 WOFF 지원한다고. 5년 후엔 WOFF로 대동단결 가능하겠다.). 즉 한 가지 웹폰트를 사용하려면 세 가지 포멧을 서버에 올려두어야 한다. Google Web fonts나 Typekit같은 서비스는 이걸 알아서 해주니 편하다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;브라우저 호환성을 고려해 CSS 작성하는 방법은 &lt;a href="http://paulirish.com/2009/bulletproof-font-face-implementation-syntax/" target="_blank" title="[http://paulirish.com/2009/bulletproof-font-face-implementation-syntax/]로 이동합니다."&gt;Bulletproof @font-face syntax&lt;/a&gt;&amp;nbsp;참고. 그리고 웹폰트를 임베딩 할 때 CSS파일에 직접 써줘도 되지만 &lt;a href="http://code.google.com/apis/webfonts/docs/getting_started.html" target="_blank" title="[http://code.google.com/apis/webfonts/docs/getting_started.html]로 이동합니다."&gt;Google Font API의 WebFont Loader 라이브러리(JavaScript)&lt;/a&gt;를 고려해보자. 폰트를 비동기적으로 불러올 수도 있고, 유용한 이벤트도 제공한다. 꼭 구글 웹폰트에 등록된 폰트가 아니라도 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;영문 폰트는 유/무료로 선택의 폭이 넓다. 한글의 경우 자유롭게 사용할 수 있는 폰트가 많지 않은 실정이다. GPL 혹은 OFL을 채택한 폰트는 모빌리스 웹폰트 서비스에서 제공하는 것들의 거의 다라고 생각하면 되겠다. &lt;a href="http://rubis.tistory.com/183" target="_blank" title="[http://rubis.tistory.com/183]로 이동합니다."&gt;무료로 공개된 한글 폰트&lt;/a&gt;가 꽤 있지만 웹폰트 형태로 자유롭게 쓸 수 있는 것은 거의 없다. 예를 들어 포탈 다음도 네이버와 마찬가지로 '다음체'라는 글꼴을 무료 공개했지만 '나눔글꼴'처럼 수정과 재배포가 자유로운 OFL을 채택하지도 않아 웹폰트로 활용은 어렵다. &lt;a href="http://info.daum.net/Daum/info/introduceOfCI.do" target="_blank" title="[http://info.daum.net/Daum/info/introduceOfCI.do]로 이동합니다."&gt;공식 페이지의 사용가이드란&lt;/a&gt;에 (그것도 이미지로) "배포되는 형태 그대로 사용해야 합니다"라는 조항이 있더라. (정말 안되는지 궁금하면 다음에 문의해보세요.) 한겨레라던가 조선일보, 엠비씨 등 언론기관에서도 글꼴을 공개했지만 개인 용도에 한한다던가 하는 단서가 있으니 역시 웹폰트로 사용하는 것은 어렵겠다.&lt;/p&gt;
&lt;p&gt;나의 경우는 서울시에서 배포하는 서울 남산/한강체를 웹폰트로 활용하기 위해 이 글에 적고 있는 내용들을 조사한건데, 서울체의 경우 서울시에 전화로 문의해서 웹페이지에 사용해도 좋다는 답을 얻었다. 담당자가 기술적인 사항을 제대로 이해했는지는 확실하지 않지만, 공공기관에서 만들었고 되도록 널리 사용되기를 바라는 것 같았다.&lt;/p&gt;
&lt;p&gt;&lt;meta charset="utf-8"&gt;아래는 폰트파일을 웹폰트 포멧으로 바꾸는 방법이다. 그런데, 바꾸기 전에 꼭 기억하자 - 폰트도 소프트웨어로서 저작권을 보호받는다. 웹에 올릴 수 있는 권리가 있는지 꼭 확인하자. 당신의 컴퓨터에 깔린 폰트라고 해서 웹에 올려도 되는건 아니다. 돈주고 샀을지라도 말이다.&lt;/p&gt;
&lt;p&gt;TTF를 EOT/WOFF로 변환해주는 웹서비스가 있다. 폰트를 업로드하면 필요한 모든 작업을 해줘서 너무너무 편하다. 단 두 곳 모두 2Mb 업로드 용량 제한이 있어 아쉽다.&lt;/p&gt;
&lt;ul style="list-style-type: square; "&gt;
&lt;li&gt;&lt;meta charset="utf-8"&gt;&lt;a href="http://www.kirsle.net/wizards/ttf2eot.cgi" target="_blank" title="[http://www.kirsle.net/wizards/ttf2eot.cgi]로 이동합니다."&gt;http://www.kirsle.net/wizards/ttf2eot.cgi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;meta charset="utf-8"&gt;&lt;a href="http://www.fontsquirrel.com/fontface/generator" target="_blank" title="[http://www.fontsquirrel.com/fontface/generator]로 이동합니다."&gt;http://www.fontsquirrel.com/fontface/generator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;한글 폰트의 용량이라는 것은 예사로 2Mb를 넘기 때문에 직접 변환해야 하는데 TTF to EOT는&amp;nbsp;&lt;a href="http://www.eotfast.com/" target="_blank" title="[http://www.eotfast.com/]로 이동합니다."&gt;http://www.eotfast.com/&lt;/a&gt;가 괜찮은 것 같다. &lt;a href="http://code.google.com/p/ttf2eot/" target="_blank" title="[http://code.google.com/p/ttf2eot/]로 이동합니다."&gt;http://code.google.com/p/ttf2eot/&lt;/a&gt;도 같은 일을 해주는 프로그램인데 나의 경우는 잘 작동하지 않았다. MS에서 윈도우 95시절에 만들었다던가 하는 &lt;a href="http://www.microsoft.com/typography/weft.mspx" target="_blank" title="[http://www.microsoft.com/typography/weft.mspx]로 이동합니다."&gt;WEFT&lt;/a&gt;라는 툴이 있는데, 나는 제대로 써보질 못했다.&lt;/p&gt;
&lt;meta charset="utf-8"&gt;&lt;p&gt;WOFF로 바꿀 땐 &amp;nbsp;&lt;a href="http://people.mozilla.org/~jkew/woff/" target="_blank" title="[http://code.google.com/p/ttf2eot/]로 이동합니다."&gt;http://people.mozilla.org/~jkew/woff/&lt;/a&gt;를 쓰면 된다. OTF나 TTF를 변환해준다는데, 내 경우 OTF는 변환이 안되고 TTF만 되더라.&lt;/p&gt;
&lt;p&gt;&lt;meta charset="utf-8"&gt;변환한 폰트 파일들은 위의 @font-face 설명이나 Google Web Font Loader 등을 이용해서 웹사이트에 넣으면 되겠다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;참고로 나도 아직 잘 모르는 부분들이긴 하지만 몇 가지를 더 소개하자면... EOT는 특정 도메인에서만 사용할 수 있도록 만들 수 있다. 이걸로 수익모델을 만든 회사도 좀 있더라. 그리고 구글 웹폰트는 &lt;a href="http://code.google.com/apis/webfonts/docs/getting_started.html#Optimizing_Requests" target="_blank" title="[http://code.google.com/apis/webfonts/docs/getting_started.html#Optimizing_Requests]로 이동합니다."&gt;필요한 글자의 폰트만 다운로드하는 옵션&lt;/a&gt;이 있어 전송량을 줄이도록 도와준다. 한글 폰트야말로 이런 기법을 적용하면 큰 효과를 볼 수 있을테다.&lt;/p&gt;
&lt;p&gt;웹폰트에 대해 더 알고싶다면 위키피디아의 &lt;a href="http://en.wikipedia.org/wiki/Web_typography" target="_blank" title="[http://en.wikipedia.org/wiki/Web_typography]로 이동합니다."&gt;Web Typography&lt;/a&gt; 항목이 좋은 시작점이 될거고, &lt;a href="http://blog.typekit.com/" target="_blank" title="[http://blog.typekit.com/]로 이동합니다."&gt;Typekit Blog&lt;/a&gt;에서도 좋은 글을 많이 올라와있으니 체키라웃.&lt;/p&gt;
&lt;div id="csscan-wrapper" style="display: none; "&gt;
&lt;h2 id="csscan-header"&gt;element&lt;/h2&gt;&lt;table id="csscan-table"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-font" class="csscan-header"&gt;Font&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-font-family"&gt;
&lt;td id="csscan-property-font-family" class="csscan-property"&gt;font-family&lt;/td&gt;
&lt;td id="csscan-value-font-family" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-size"&gt;
&lt;td id="csscan-property-font-size" class="csscan-property"&gt;font-size&lt;/td&gt;
&lt;td id="csscan-value-font-size" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-style"&gt;
&lt;td id="csscan-property-font-style" class="csscan-property"&gt;font-style&lt;/td&gt;
&lt;td id="csscan-value-font-style" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-variant"&gt;
&lt;td id="csscan-property-font-variant" class="csscan-property"&gt;font-variant&lt;/td&gt;
&lt;td id="csscan-value-font-variant" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-weight"&gt;
&lt;td id="csscan-property-font-weight" class="csscan-property"&gt;font-weight&lt;/td&gt;
&lt;td id="csscan-value-font-weight" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-letter-spacing"&gt;
&lt;td id="csscan-property-letter-spacing" class="csscan-property"&gt;letter-spacing&lt;/td&gt;
&lt;td id="csscan-value-letter-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-line-height"&gt;
&lt;td id="csscan-property-line-height" class="csscan-property"&gt;line-height&lt;/td&gt;
&lt;td id="csscan-value-line-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-decoration"&gt;
&lt;td id="csscan-property-text-decoration" class="csscan-property"&gt;text-decoration&lt;/td&gt;
&lt;td id="csscan-value-text-decoration" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-align"&gt;
&lt;td id="csscan-property-text-align" class="csscan-property"&gt;text-align&lt;/td&gt;
&lt;td id="csscan-value-text-align" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-indent"&gt;
&lt;td id="csscan-property-text-indent" class="csscan-property"&gt;text-indent&lt;/td&gt;
&lt;td id="csscan-value-text-indent" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-transform"&gt;
&lt;td id="csscan-property-text-transform" class="csscan-property"&gt;text-transform&lt;/td&gt;
&lt;td id="csscan-value-text-transform" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-white-space"&gt;
&lt;td id="csscan-property-white-space" class="csscan-property"&gt;white-space&lt;/td&gt;
&lt;td id="csscan-value-white-space" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-word-spacing"&gt;
&lt;td id="csscan-property-word-spacing" class="csscan-property"&gt;word-spacing&lt;/td&gt;
&lt;td id="csscan-value-word-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-color"&gt;
&lt;td id="csscan-property-color" class="csscan-property"&gt;color&lt;/td&gt;
&lt;td id="csscan-value-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-background" class="csscan-header"&gt;Background&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-background-attachment"&gt;
&lt;td id="csscan-property-background-attachment" class="csscan-property"&gt;bg-attachment&lt;/td&gt;
&lt;td id="csscan-value-background-attachment" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-color"&gt;
&lt;td id="csscan-property-background-color" class="csscan-property"&gt;bg-color&lt;/td&gt;
&lt;td id="csscan-value-background-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-image"&gt;
&lt;td id="csscan-property-background-image" class="csscan-property"&gt;bg-image&lt;/td&gt;
&lt;td id="csscan-value-background-image" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-position"&gt;
&lt;td id="csscan-property-background-position" class="csscan-property"&gt;bg-position&lt;/td&gt;
&lt;td id="csscan-value-background-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-repeat"&gt;
&lt;td id="csscan-property-background-repeat" class="csscan-property"&gt;bg-repeat&lt;/td&gt;
&lt;td id="csscan-value-background-repeat" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-size" class="csscan-header"&gt;Box&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-width"&gt;
&lt;td id="csscan-property-width" class="csscan-property"&gt;width&lt;/td&gt;
&lt;td id="csscan-value-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-height"&gt;
&lt;td id="csscan-property-height" class="csscan-property"&gt;height&lt;/td&gt;
&lt;td id="csscan-value-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-top"&gt;
&lt;td id="csscan-property-border-top" class="csscan-property"&gt;border-top&lt;/td&gt;
&lt;td id="csscan-value-border-top" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-right"&gt;
&lt;td id="csscan-property-border-right" class="csscan-property"&gt;border-right&lt;/td&gt;
&lt;td id="csscan-value-border-right" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-bottom"&gt;
&lt;td id="csscan-property-border-bottom" class="csscan-property"&gt;border-bottom&lt;/td&gt;
&lt;td id="csscan-value-border-bottom" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-left"&gt;
&lt;td id="csscan-property-border-left" class="csscan-property"&gt;border-left&lt;/td&gt;
&lt;td id="csscan-value-border-left" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-margin"&gt;
&lt;td id="csscan-property-margin" class="csscan-property"&gt;margin&lt;/td&gt;
&lt;td id="csscan-value-margin" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-padding"&gt;
&lt;td id="csscan-property-padding" class="csscan-property"&gt;padding&lt;/td&gt;
&lt;td id="csscan-value-padding" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-max-height"&gt;
&lt;td id="csscan-property-max-height" class="csscan-property"&gt;max-height&lt;/td&gt;
&lt;td id="csscan-value-max-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-min-height"&gt;
&lt;td id="csscan-property-min-height" class="csscan-property"&gt;min-height&lt;/td&gt;
&lt;td id="csscan-value-min-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-max-width"&gt;
&lt;td id="csscan-property-max-width" class="csscan-property"&gt;max-width&lt;/td&gt;
&lt;td id="csscan-value-max-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-min-width"&gt;
&lt;td id="csscan-property-min-width" class="csscan-property"&gt;min-width&lt;/td&gt;
&lt;td id="csscan-value-min-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-outline-color"&gt;
&lt;td id="csscan-property-outline-color" class="csscan-property"&gt;outline-color&lt;/td&gt;
&lt;td id="csscan-value-outline-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-outline-style"&gt;
&lt;td id="csscan-property-outline-style" class="csscan-property"&gt;outline-style&lt;/td&gt;
&lt;td id="csscan-value-outline-style" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-outline-width"&gt;
&lt;td id="csscan-property-outline-width" class="csscan-property"&gt;outline-width&lt;/td&gt;
&lt;td id="csscan-value-outline-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-position" class="csscan-header"&gt;Positioning&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-position"&gt;
&lt;td id="csscan-property-position" class="csscan-property"&gt;position&lt;/td&gt;
&lt;td id="csscan-value-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-top"&gt;
&lt;td id="csscan-property-top" class="csscan-property"&gt;top&lt;/td&gt;
&lt;td id="csscan-value-top" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-bottom"&gt;
&lt;td id="csscan-property-bottom" class="csscan-property"&gt;bottom&lt;/td&gt;
&lt;td id="csscan-value-bottom" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-right"&gt;
&lt;td id="csscan-property-right" class="csscan-property"&gt;right&lt;/td&gt;
&lt;td id="csscan-value-right" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-left"&gt;
&lt;td id="csscan-property-left" class="csscan-property"&gt;left&lt;/td&gt;
&lt;td id="csscan-value-left" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-float"&gt;
&lt;td id="csscan-property-float" class="csscan-property"&gt;float&lt;/td&gt;
&lt;td id="csscan-value-float" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-display"&gt;
&lt;td id="csscan-property-display" class="csscan-property"&gt;display&lt;/td&gt;
&lt;td id="csscan-value-display" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-clear"&gt;
&lt;td id="csscan-property-clear" class="csscan-property"&gt;clear&lt;/td&gt;
&lt;td id="csscan-value-clear" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-z-index"&gt;
&lt;td id="csscan-property-z-index" class="csscan-property"&gt;z-index&lt;/td&gt;
&lt;td id="csscan-value-z-index" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-list" class="csscan-header"&gt;List&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-list-style-image"&gt;
&lt;td id="csscan-property-list-style-image" class="csscan-property"&gt;list-style-image&lt;/td&gt;
&lt;td id="csscan-value-list-style-image" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-list-style-type"&gt;
&lt;td id="csscan-property-list-style-type" class="csscan-property"&gt;list-style-type&lt;/td&gt;
&lt;td id="csscan-value-list-style-type" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-list-style-position"&gt;
&lt;td id="csscan-property-list-style-position" class="csscan-property"&gt;list-style-position&lt;/td&gt;
&lt;td id="csscan-value-list-style-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-table" class="csscan-header"&gt;Table&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-vertical-align"&gt;
&lt;td id="csscan-property-vertical-align" class="csscan-property"&gt;vertical-align&lt;/td&gt;
&lt;td id="csscan-value-vertical-align" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-collapse"&gt;
&lt;td id="csscan-property-border-collapse" class="csscan-property"&gt;border-collapse&lt;/td&gt;
&lt;td id="csscan-value-border-collapse" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-spacing"&gt;
&lt;td id="csscan-property-border-spacing" class="csscan-property"&gt;border-spacing&lt;/td&gt;
&lt;td id="csscan-value-border-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-caption-side"&gt;
&lt;td id="csscan-property-caption-side" class="csscan-property"&gt;caption-side&lt;/td&gt;
&lt;td id="csscan-value-caption-side" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-empty-cells"&gt;
&lt;td id="csscan-property-empty-cells" class="csscan-property"&gt;empty-cells&lt;/td&gt;
&lt;td id="csscan-value-empty-cells" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-table-layout"&gt;
&lt;td id="csscan-property-table-layout" class="csscan-property"&gt;table-layout&lt;/td&gt;
&lt;td id="csscan-value-table-layout" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-effects" class="csscan-header"&gt;Effects&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-text-shadow"&gt;
&lt;td id="csscan-property-text-shadow" class="csscan-property"&gt;text-shadow&lt;/td&gt;
&lt;td id="csscan-value-text-shadow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row--webkit-box-shadow"&gt;
&lt;td id="csscan-property--webkit-box-shadow" class="csscan-property"&gt;-webkit-box-shadow&lt;/td&gt;
&lt;td id="csscan-value--webkit-box-shadow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-radius"&gt;
&lt;td id="csscan-property-border-radius" class="csscan-property"&gt;border-radius&lt;/td&gt;
&lt;td id="csscan-value-border-radius" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-other" class="csscan-header"&gt;Other&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-overflow"&gt;
&lt;td id="csscan-property-overflow" class="csscan-property"&gt;overflow&lt;/td&gt;
&lt;td id="csscan-value-overflow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-cursor"&gt;
&lt;td id="csscan-property-cursor" class="csscan-property"&gt;cursor&lt;/td&gt;
&lt;td id="csscan-value-cursor" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-visibility"&gt;
&lt;td id="csscan-property-visibility" class="csscan-property"&gt;visibility&lt;/td&gt;
&lt;td id="csscan-value-visibility" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;p.s : 또 다른 &lt;a href="http://vimeo.com/26188365" target="_blank" title="[http://vimeo.com/26188365]로 이동합니다."&gt;font-face&lt;/a&gt;&amp;nbsp;;)&lt;/p&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-113-0" class="entry-ccl-by" src="http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-fr/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-fr/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  					&lt;embed src="http://api.v.daum.net/static/recombox1.swf" quality="high" flashvars="nid=18618692" allowscriptaccess="always" allowfullscreen="false" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash" wmode="transparent"&gt;&lt;/embed&gt;
						&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=2h_c-n_T62s:RQz4rLCCiIc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=2h_c-n_T62s:RQz4rLCCiIc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=2h_c-n_T62s:RQz4rLCCiIc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/2h_c-n_T62s" height="1" width="1"/&gt;</description>
			<category>학습자료, 추천사이트</category>
			<category>font-face</category>
			<category>web fonts</category>
			<category>웹폰트</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/113</guid>
			<comments>http://hardworker.tistory.com/113#entry113comment</comments>
			<pubDate>Thu, 14 Jul 2011 23:23:02 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/113</feedburner:origLink></item>
		<item>
			<title>백악관 웹사이트 개발에 쓰였던 Drupal 코드가 공개됐다.</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/g8PAL6b1CRc/111</link>
			<description>&lt;p style="color: rgb(51, 51, 51); font-family: 굴림; font-size: 9pt; line-height: 1.5; "&gt;사실 이 소식 좀 뒷북인데, 작년 4월에 이미 몇 개의 모듈이 공개됐었단다. 작년 4월로 말씀드리자면 본인이 뉴질랜드 남섬을 방문하여 낮에는 여행을 밤에는 코딩을 하며 알찬 시간을 보내느라 뉴스를 따라잡을 시간이 없었다.&lt;/p&gt;
&lt;p style="color: rgb(51, 51, 51); font-family: 굴림; font-size: 9pt; line-height: 1.5; "&gt;다행스럽게도 백악관이 두 번째 코드 릴리스를 해주신 덕분에 놓쳤던 소식을 건져올릴 수 있었다. 지나간 소식부터 보자면...&lt;/p&gt;
&lt;p style="color: rgb(51, 51, 51); font-family: 굴림; font-size: 9pt; line-height: 1.5; "&gt;2010년 4월&amp;nbsp;&lt;a href="http://www.whitehouse.gov/blog/2010/04/21/whitehousegov-releases-open-source-code" target="_blank" title="[http://www.whitehouse.gov/blog/2010/04/21/whitehousegov-releases-open-source-code]로 이동합니다."&gt;WhiteHouse.gov releases Open Source Code&lt;/a&gt;를 통해&amp;nbsp;다음 4개 모듈을 공개했다.&amp;nbsp;&lt;br /&gt;
&lt;/p&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;&lt;font class="Apple-style-span" color="#333333" face="굴림"&gt;http://drupal.org/project/context_http_headers&lt;/font&gt;&lt;/li&gt;
&lt;li&gt;&lt;font class="Apple-style-span" color="#333333" face="굴림"&gt;&lt;/font&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51); font-family: 굴림; "&gt;http://drupal.org/project/akamai&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51); font-family: 굴림; "&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51); font-family: 굴림; "&gt;http://drupal.org/project/govdelivery&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51); font-family: 굴림; "&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51); font-family: 굴림; "&gt;http://drupal.org/project/node_embed&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#333333" face="굴림"&gt;그리고 몇 일 전&amp;nbsp;&lt;a href="http://www.whitehouse.gov/blog/2011/02/11/whitehousegov-releases-second-set-open-source-code" target="_blank" title="[http://www.whitehouse.gov/blog/2011/02/11/whitehousegov-releases-second-set-open-source-code]로 이동합니다."&gt;WhiteHouse.gov Releases Second Set of Open Source Code&lt;/a&gt;를 통해 IMCE Tools 등 몇 가지 모듈을 추가로 공개했다.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
공개된 모듈들을 써본게 아니라 이렇다 저렇다 평가는 못 하겠다. 다만 정부기관의 웹사이트를 오픈소스 소프트웨어로 구축하고, 그 결과물을 다시 커뮤니티에 되돌리는 모습이 보기 좋다.&lt;/div&gt;
&lt;div id="csscan-wrapper" style="display: none; "&gt;
&lt;h2 id="csscan-header"&gt;element&lt;/h2&gt;&lt;table id="csscan-table"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-font" class="csscan-header"&gt;Font&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-font-family"&gt;
&lt;td id="csscan-property-font-family" class="csscan-property"&gt;font-family&lt;/td&gt;
&lt;td id="csscan-value-font-family" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-size"&gt;
&lt;td id="csscan-property-font-size" class="csscan-property"&gt;font-size&lt;/td&gt;
&lt;td id="csscan-value-font-size" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-style"&gt;
&lt;td id="csscan-property-font-style" class="csscan-property"&gt;font-style&lt;/td&gt;
&lt;td id="csscan-value-font-style" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-variant"&gt;
&lt;td id="csscan-property-font-variant" class="csscan-property"&gt;font-variant&lt;/td&gt;
&lt;td id="csscan-value-font-variant" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-font-weight"&gt;
&lt;td id="csscan-property-font-weight" class="csscan-property"&gt;font-weight&lt;/td&gt;
&lt;td id="csscan-value-font-weight" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-letter-spacing"&gt;
&lt;td id="csscan-property-letter-spacing" class="csscan-property"&gt;letter-spacing&lt;/td&gt;
&lt;td id="csscan-value-letter-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-line-height"&gt;
&lt;td id="csscan-property-line-height" class="csscan-property"&gt;line-height&lt;/td&gt;
&lt;td id="csscan-value-line-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-decoration"&gt;
&lt;td id="csscan-property-text-decoration" class="csscan-property"&gt;text-decoration&lt;/td&gt;
&lt;td id="csscan-value-text-decoration" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-align"&gt;
&lt;td id="csscan-property-text-align" class="csscan-property"&gt;text-align&lt;/td&gt;
&lt;td id="csscan-value-text-align" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-indent"&gt;
&lt;td id="csscan-property-text-indent" class="csscan-property"&gt;text-indent&lt;/td&gt;
&lt;td id="csscan-value-text-indent" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-text-transform"&gt;
&lt;td id="csscan-property-text-transform" class="csscan-property"&gt;text-transform&lt;/td&gt;
&lt;td id="csscan-value-text-transform" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-white-space"&gt;
&lt;td id="csscan-property-white-space" class="csscan-property"&gt;white-space&lt;/td&gt;
&lt;td id="csscan-value-white-space" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-word-spacing"&gt;
&lt;td id="csscan-property-word-spacing" class="csscan-property"&gt;word-spacing&lt;/td&gt;
&lt;td id="csscan-value-word-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-color"&gt;
&lt;td id="csscan-property-color" class="csscan-property"&gt;color&lt;/td&gt;
&lt;td id="csscan-value-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-background" class="csscan-header"&gt;Background&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-background-attachment"&gt;
&lt;td id="csscan-property-background-attachment" class="csscan-property"&gt;bg-attachment&lt;/td&gt;
&lt;td id="csscan-value-background-attachment" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-color"&gt;
&lt;td id="csscan-property-background-color" class="csscan-property"&gt;bg-color&lt;/td&gt;
&lt;td id="csscan-value-background-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-image"&gt;
&lt;td id="csscan-property-background-image" class="csscan-property"&gt;bg-image&lt;/td&gt;
&lt;td id="csscan-value-background-image" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-position"&gt;
&lt;td id="csscan-property-background-position" class="csscan-property"&gt;bg-position&lt;/td&gt;
&lt;td id="csscan-value-background-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-background-repeat"&gt;
&lt;td id="csscan-property-background-repeat" class="csscan-property"&gt;bg-repeat&lt;/td&gt;
&lt;td id="csscan-value-background-repeat" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-size" class="csscan-header"&gt;Box&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-width"&gt;
&lt;td id="csscan-property-width" class="csscan-property"&gt;width&lt;/td&gt;
&lt;td id="csscan-value-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-height"&gt;
&lt;td id="csscan-property-height" class="csscan-property"&gt;height&lt;/td&gt;
&lt;td id="csscan-value-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-top"&gt;
&lt;td id="csscan-property-border-top" class="csscan-property"&gt;border-top&lt;/td&gt;
&lt;td id="csscan-value-border-top" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-right"&gt;
&lt;td id="csscan-property-border-right" class="csscan-property"&gt;border-right&lt;/td&gt;
&lt;td id="csscan-value-border-right" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-bottom"&gt;
&lt;td id="csscan-property-border-bottom" class="csscan-property"&gt;border-bottom&lt;/td&gt;
&lt;td id="csscan-value-border-bottom" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-left"&gt;
&lt;td id="csscan-property-border-left" class="csscan-property"&gt;border-left&lt;/td&gt;
&lt;td id="csscan-value-border-left" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-margin"&gt;
&lt;td id="csscan-property-margin" class="csscan-property"&gt;margin&lt;/td&gt;
&lt;td id="csscan-value-margin" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-padding"&gt;
&lt;td id="csscan-property-padding" class="csscan-property"&gt;padding&lt;/td&gt;
&lt;td id="csscan-value-padding" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-max-height"&gt;
&lt;td id="csscan-property-max-height" class="csscan-property"&gt;max-height&lt;/td&gt;
&lt;td id="csscan-value-max-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-min-height"&gt;
&lt;td id="csscan-property-min-height" class="csscan-property"&gt;min-height&lt;/td&gt;
&lt;td id="csscan-value-min-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-max-width"&gt;
&lt;td id="csscan-property-max-width" class="csscan-property"&gt;max-width&lt;/td&gt;
&lt;td id="csscan-value-max-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-min-width"&gt;
&lt;td id="csscan-property-min-width" class="csscan-property"&gt;min-width&lt;/td&gt;
&lt;td id="csscan-value-min-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-outline-color"&gt;
&lt;td id="csscan-property-outline-color" class="csscan-property"&gt;outline-color&lt;/td&gt;
&lt;td id="csscan-value-outline-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-outline-style"&gt;
&lt;td id="csscan-property-outline-style" class="csscan-property"&gt;outline-style&lt;/td&gt;
&lt;td id="csscan-value-outline-style" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-outline-width"&gt;
&lt;td id="csscan-property-outline-width" class="csscan-property"&gt;outline-width&lt;/td&gt;
&lt;td id="csscan-value-outline-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-position" class="csscan-header"&gt;Positioning&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-position"&gt;
&lt;td id="csscan-property-position" class="csscan-property"&gt;position&lt;/td&gt;
&lt;td id="csscan-value-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-top"&gt;
&lt;td id="csscan-property-top" class="csscan-property"&gt;top&lt;/td&gt;
&lt;td id="csscan-value-top" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-bottom"&gt;
&lt;td id="csscan-property-bottom" class="csscan-property"&gt;bottom&lt;/td&gt;
&lt;td id="csscan-value-bottom" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-right"&gt;
&lt;td id="csscan-property-right" class="csscan-property"&gt;right&lt;/td&gt;
&lt;td id="csscan-value-right" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-left"&gt;
&lt;td id="csscan-property-left" class="csscan-property"&gt;left&lt;/td&gt;
&lt;td id="csscan-value-left" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-float"&gt;
&lt;td id="csscan-property-float" class="csscan-property"&gt;float&lt;/td&gt;
&lt;td id="csscan-value-float" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-display"&gt;
&lt;td id="csscan-property-display" class="csscan-property"&gt;display&lt;/td&gt;
&lt;td id="csscan-value-display" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-clear"&gt;
&lt;td id="csscan-property-clear" class="csscan-property"&gt;clear&lt;/td&gt;
&lt;td id="csscan-value-clear" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-z-index"&gt;
&lt;td id="csscan-property-z-index" class="csscan-property"&gt;z-index&lt;/td&gt;
&lt;td id="csscan-value-z-index" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-list" class="csscan-header"&gt;List&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-list-style-image"&gt;
&lt;td id="csscan-property-list-style-image" class="csscan-property"&gt;list-style-image&lt;/td&gt;
&lt;td id="csscan-value-list-style-image" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-list-style-type"&gt;
&lt;td id="csscan-property-list-style-type" class="csscan-property"&gt;list-style-type&lt;/td&gt;
&lt;td id="csscan-value-list-style-type" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-list-style-position"&gt;
&lt;td id="csscan-property-list-style-position" class="csscan-property"&gt;list-style-position&lt;/td&gt;
&lt;td id="csscan-value-list-style-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-table" class="csscan-header"&gt;Table&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-vertical-align"&gt;
&lt;td id="csscan-property-vertical-align" class="csscan-property"&gt;vertical-align&lt;/td&gt;
&lt;td id="csscan-value-vertical-align" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-collapse"&gt;
&lt;td id="csscan-property-border-collapse" class="csscan-property"&gt;border-collapse&lt;/td&gt;
&lt;td id="csscan-value-border-collapse" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-spacing"&gt;
&lt;td id="csscan-property-border-spacing" class="csscan-property"&gt;border-spacing&lt;/td&gt;
&lt;td id="csscan-value-border-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-caption-side"&gt;
&lt;td id="csscan-property-caption-side" class="csscan-property"&gt;caption-side&lt;/td&gt;
&lt;td id="csscan-value-caption-side" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-empty-cells"&gt;
&lt;td id="csscan-property-empty-cells" class="csscan-property"&gt;empty-cells&lt;/td&gt;
&lt;td id="csscan-value-empty-cells" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-table-layout"&gt;
&lt;td id="csscan-property-table-layout" class="csscan-property"&gt;table-layout&lt;/td&gt;
&lt;td id="csscan-value-table-layout" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-effects" class="csscan-header"&gt;Effects&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-text-shadow"&gt;
&lt;td id="csscan-property-text-shadow" class="csscan-property"&gt;text-shadow&lt;/td&gt;
&lt;td id="csscan-value-text-shadow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row--webkit-box-shadow"&gt;
&lt;td id="csscan-property--webkit-box-shadow" class="csscan-property"&gt;-webkit-box-shadow&lt;/td&gt;
&lt;td id="csscan-value--webkit-box-shadow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-border-radius"&gt;
&lt;td id="csscan-property-border-radius" class="csscan-property"&gt;border-radius&lt;/td&gt;
&lt;td id="csscan-value-border-radius" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-other" class="csscan-header"&gt;Other&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-overflow"&gt;
&lt;td id="csscan-property-overflow" class="csscan-property"&gt;overflow&lt;/td&gt;
&lt;td id="csscan-value-overflow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-cursor"&gt;
&lt;td id="csscan-property-cursor" class="csscan-property"&gt;cursor&lt;/td&gt;
&lt;td id="csscan-value-cursor" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id="csscan-row-visibility"&gt;
&lt;td id="csscan-property-visibility" class="csscan-property"&gt;visibility&lt;/td&gt;
&lt;td id="csscan-value-visibility" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div id="csscan-wrapper" style="display: none; "&gt;&lt;h2 id="csscan-header"&gt;element&lt;/h2&gt;&lt;table id="csscan-table"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-font" class="csscan-header"&gt;Font&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-font-family"&gt;&lt;td id="csscan-property-font-family" class="csscan-property"&gt;font-family&lt;/td&gt;
&lt;td id="csscan-value-font-family" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-font-size"&gt;
&lt;td id="csscan-property-font-size" class="csscan-property"&gt;font-size&lt;/td&gt;
&lt;td id="csscan-value-font-size" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-font-style"&gt;
&lt;td id="csscan-property-font-style" class="csscan-property"&gt;font-style&lt;/td&gt;
&lt;td id="csscan-value-font-style" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-font-variant"&gt;
&lt;td id="csscan-property-font-variant" class="csscan-property"&gt;font-variant&lt;/td&gt;
&lt;td id="csscan-value-font-variant" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-font-weight"&gt;
&lt;td id="csscan-property-font-weight" class="csscan-property"&gt;font-weight&lt;/td&gt;
&lt;td id="csscan-value-font-weight" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-letter-spacing"&gt;
&lt;td id="csscan-property-letter-spacing" class="csscan-property"&gt;letter-spacing&lt;/td&gt;
&lt;td id="csscan-value-letter-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-line-height"&gt;
&lt;td id="csscan-property-line-height" class="csscan-property"&gt;line-height&lt;/td&gt;
&lt;td id="csscan-value-line-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-text-decoration"&gt;
&lt;td id="csscan-property-text-decoration" class="csscan-property"&gt;text-decoration&lt;/td&gt;
&lt;td id="csscan-value-text-decoration" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-text-align"&gt;
&lt;td id="csscan-property-text-align" class="csscan-property"&gt;text-align&lt;/td&gt;
&lt;td id="csscan-value-text-align" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-text-indent"&gt;
&lt;td id="csscan-property-text-indent" class="csscan-property"&gt;text-indent&lt;/td&gt;
&lt;td id="csscan-value-text-indent" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-text-transform"&gt;
&lt;td id="csscan-property-text-transform" class="csscan-property"&gt;text-transform&lt;/td&gt;
&lt;td id="csscan-value-text-transform" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-white-space"&gt;
&lt;td id="csscan-property-white-space" class="csscan-property"&gt;white-space&lt;/td&gt;
&lt;td id="csscan-value-white-space" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-word-spacing"&gt;
&lt;td id="csscan-property-word-spacing" class="csscan-property"&gt;word-spacing&lt;/td&gt;
&lt;td id="csscan-value-word-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-color"&gt;
&lt;td id="csscan-property-color" class="csscan-property"&gt;color&lt;/td&gt;
&lt;td id="csscan-value-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-background" class="csscan-header"&gt;Background&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-background-attachment"&gt;&lt;td id="csscan-property-background-attachment" class="csscan-property"&gt;bg-attachment&lt;/td&gt;
&lt;td id="csscan-value-background-attachment" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-background-color"&gt;
&lt;td id="csscan-property-background-color" class="csscan-property"&gt;bg-color&lt;/td&gt;
&lt;td id="csscan-value-background-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-background-image"&gt;
&lt;td id="csscan-property-background-image" class="csscan-property"&gt;bg-image&lt;/td&gt;
&lt;td id="csscan-value-background-image" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-background-position"&gt;
&lt;td id="csscan-property-background-position" class="csscan-property"&gt;bg-position&lt;/td&gt;
&lt;td id="csscan-value-background-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-background-repeat"&gt;
&lt;td id="csscan-property-background-repeat" class="csscan-property"&gt;bg-repeat&lt;/td&gt;
&lt;td id="csscan-value-background-repeat" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-size" class="csscan-header"&gt;Box&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-width"&gt;&lt;td id="csscan-property-width" class="csscan-property"&gt;width&lt;/td&gt;
&lt;td id="csscan-value-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-height"&gt;
&lt;td id="csscan-property-height" class="csscan-property"&gt;height&lt;/td&gt;
&lt;td id="csscan-value-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-border-top"&gt;
&lt;td id="csscan-property-border-top" class="csscan-property"&gt;border-top&lt;/td&gt;
&lt;td id="csscan-value-border-top" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-border-right"&gt;
&lt;td id="csscan-property-border-right" class="csscan-property"&gt;border-right&lt;/td&gt;
&lt;td id="csscan-value-border-right" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-border-bottom"&gt;
&lt;td id="csscan-property-border-bottom" class="csscan-property"&gt;border-bottom&lt;/td&gt;
&lt;td id="csscan-value-border-bottom" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-border-left"&gt;
&lt;td id="csscan-property-border-left" class="csscan-property"&gt;border-left&lt;/td&gt;
&lt;td id="csscan-value-border-left" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-margin"&gt;
&lt;td id="csscan-property-margin" class="csscan-property"&gt;margin&lt;/td&gt;
&lt;td id="csscan-value-margin" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-padding"&gt;
&lt;td id="csscan-property-padding" class="csscan-property"&gt;padding&lt;/td&gt;
&lt;td id="csscan-value-padding" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-max-height"&gt;
&lt;td id="csscan-property-max-height" class="csscan-property"&gt;max-height&lt;/td&gt;
&lt;td id="csscan-value-max-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-min-height"&gt;
&lt;td id="csscan-property-min-height" class="csscan-property"&gt;min-height&lt;/td&gt;
&lt;td id="csscan-value-min-height" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-max-width"&gt;
&lt;td id="csscan-property-max-width" class="csscan-property"&gt;max-width&lt;/td&gt;
&lt;td id="csscan-value-max-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-min-width"&gt;
&lt;td id="csscan-property-min-width" class="csscan-property"&gt;min-width&lt;/td&gt;
&lt;td id="csscan-value-min-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-outline-color"&gt;
&lt;td id="csscan-property-outline-color" class="csscan-property"&gt;outline-color&lt;/td&gt;
&lt;td id="csscan-value-outline-color" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-outline-style"&gt;
&lt;td id="csscan-property-outline-style" class="csscan-property"&gt;outline-style&lt;/td&gt;
&lt;td id="csscan-value-outline-style" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-outline-width"&gt;
&lt;td id="csscan-property-outline-width" class="csscan-property"&gt;outline-width&lt;/td&gt;
&lt;td id="csscan-value-outline-width" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-position" class="csscan-header"&gt;Positioning&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-position"&gt;&lt;td id="csscan-property-position" class="csscan-property"&gt;position&lt;/td&gt;
&lt;td id="csscan-value-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-top"&gt;
&lt;td id="csscan-property-top" class="csscan-property"&gt;top&lt;/td&gt;
&lt;td id="csscan-value-top" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-bottom"&gt;
&lt;td id="csscan-property-bottom" class="csscan-property"&gt;bottom&lt;/td&gt;
&lt;td id="csscan-value-bottom" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-right"&gt;
&lt;td id="csscan-property-right" class="csscan-property"&gt;right&lt;/td&gt;
&lt;td id="csscan-value-right" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-left"&gt;
&lt;td id="csscan-property-left" class="csscan-property"&gt;left&lt;/td&gt;
&lt;td id="csscan-value-left" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-float"&gt;
&lt;td id="csscan-property-float" class="csscan-property"&gt;float&lt;/td&gt;
&lt;td id="csscan-value-float" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-display"&gt;
&lt;td id="csscan-property-display" class="csscan-property"&gt;display&lt;/td&gt;
&lt;td id="csscan-value-display" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-clear"&gt;
&lt;td id="csscan-property-clear" class="csscan-property"&gt;clear&lt;/td&gt;
&lt;td id="csscan-value-clear" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-z-index"&gt;
&lt;td id="csscan-property-z-index" class="csscan-property"&gt;z-index&lt;/td&gt;
&lt;td id="csscan-value-z-index" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-list" class="csscan-header"&gt;List&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-list-style-image"&gt;&lt;td id="csscan-property-list-style-image" class="csscan-property"&gt;list-style-image&lt;/td&gt;
&lt;td id="csscan-value-list-style-image" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-list-style-type"&gt;
&lt;td id="csscan-property-list-style-type" class="csscan-property"&gt;list-style-type&lt;/td&gt;
&lt;td id="csscan-value-list-style-type" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-list-style-position"&gt;
&lt;td id="csscan-property-list-style-position" class="csscan-property"&gt;list-style-position&lt;/td&gt;
&lt;td id="csscan-value-list-style-position" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-table" class="csscan-header"&gt;Table&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-vertical-align"&gt;&lt;td id="csscan-property-vertical-align" class="csscan-property"&gt;vertical-align&lt;/td&gt;
&lt;td id="csscan-value-vertical-align" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-border-collapse"&gt;
&lt;td id="csscan-property-border-collapse" class="csscan-property"&gt;border-collapse&lt;/td&gt;
&lt;td id="csscan-value-border-collapse" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-border-spacing"&gt;
&lt;td id="csscan-property-border-spacing" class="csscan-property"&gt;border-spacing&lt;/td&gt;
&lt;td id="csscan-value-border-spacing" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-caption-side"&gt;
&lt;td id="csscan-property-caption-side" class="csscan-property"&gt;caption-side&lt;/td&gt;
&lt;td id="csscan-value-caption-side" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-empty-cells"&gt;
&lt;td id="csscan-property-empty-cells" class="csscan-property"&gt;empty-cells&lt;/td&gt;
&lt;td id="csscan-value-empty-cells" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-table-layout"&gt;
&lt;td id="csscan-property-table-layout" class="csscan-property"&gt;table-layout&lt;/td&gt;
&lt;td id="csscan-value-table-layout" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-effects" class="csscan-header"&gt;Effects&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-text-shadow"&gt;&lt;td id="csscan-property-text-shadow" class="csscan-property"&gt;text-shadow&lt;/td&gt;
&lt;td id="csscan-value-text-shadow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row--webkit-box-shadow"&gt;
&lt;td id="csscan-property--webkit-box-shadow" class="csscan-property"&gt;-webkit-box-shadow&lt;/td&gt;
&lt;td id="csscan-value--webkit-box-shadow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-border-radius"&gt;
&lt;td id="csscan-property-border-radius" class="csscan-property"&gt;border-radius&lt;/td&gt;
&lt;td id="csscan-value-border-radius" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;
&lt;th colspan="2" id="csscan-header-other" class="csscan-header"&gt;Other&lt;/th&gt;&lt;/tr&gt;
&lt;tr id="csscan-row-overflow"&gt;&lt;td id="csscan-property-overflow" class="csscan-property"&gt;overflow&lt;/td&gt;
&lt;td id="csscan-value-overflow" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-cursor"&gt;
&lt;td id="csscan-property-cursor" class="csscan-property"&gt;cursor&lt;/td&gt;
&lt;td id="csscan-value-cursor" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;tr id="csscan-row-visibility"&gt;
&lt;td id="csscan-property-visibility" class="csscan-property"&gt;visibility&lt;/td&gt;
&lt;td id="csscan-value-visibility" class="csscan-value"&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-111-0" class="entry-ccl-by" src="http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-fr/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-fr/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  					&lt;embed src="http://api.v.daum.net/static/recombox1.swf" quality="high" flashvars="nid=13956385" allowscriptaccess="always" allowfullscreen="false" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash" wmode="transparent"&gt;&lt;/embed&gt;
						&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=g8PAL6b1CRc:fwj65g0sF8g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=g8PAL6b1CRc:fwj65g0sF8g:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=g8PAL6b1CRc:fwj65g0sF8g:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/g8PAL6b1CRc" height="1" width="1"/&gt;</description>
			<category>Drupal / 드루팔</category>
			<category>drupal</category>
			<category>드루팔</category>
			<category>백악관</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/111</guid>
			<comments>http://hardworker.tistory.com/111#entry111comment</comments>
			<pubDate>Tue, 15 Feb 2011 12:03:13 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/111</feedburner:origLink></item>
		<item>
			<title>저장소의 파일이름 한꺼번에 바꾸기 Rename multiple files in svn repository</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/6J7T0em1nO8/107</link>
			<description>&lt;font class="Apple-style-span" color="#333333" face="굴림" size="3"&gt;&lt;span class="Apple-style-span" style="font-size: 9pt; line-height: 1.5;"&gt;저장소에 같은 이름의 파일이 여러 개 있다. 그런데 이름을 한꺼번에 바꿔야 할 때, 일일이 바꿔야 한다면 끔찍.&lt;/span&gt;&lt;/font&gt;&lt;div style="color: rgb(51, 51, 51); font-family: 굴림; font-size: 9pt; line-height: 1.5; "&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div style="color: rgb(51, 51, 51); font-family: 굴림; font-size: 9pt; line-height: 1.5; "&gt;
만약 저장소의 "공격.png"를 모두 "Attack.png"로 바꿔야 한다면&lt;/div&gt;
&lt;div style="color: rgb(51, 51, 51); font-family: 굴림; font-size: 9pt; line-height: 1.5; "&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#333333" face="굴림"&gt;&lt;span style="font-family: Terminal; "&gt;$ find . -name "공격.png" | awk '{print $1, $1}' | sed 's/공격.png/Attack.png/2' | awk '{print "svn rename", $1, $2}' | sh&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-107-0" class="entry-ccl-by" src="http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-fr/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-fr/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=6J7T0em1nO8:HHbNWU7EAaU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=6J7T0em1nO8:HHbNWU7EAaU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=6J7T0em1nO8:HHbNWU7EAaU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/6J7T0em1nO8" height="1" width="1"/&gt;</description>
			<category>awk</category>
			<category>find</category>
			<category>sed</category>
			<category>shell</category>
			<category>svn</category>
			<category>unix</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/107</guid>
			<comments>http://hardworker.tistory.com/107#entry107comment</comments>
			<pubDate>Sun, 24 Oct 2010 18:05:46 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/107</feedburner:origLink></item>
		<item>
			<title>빠른 것이 미덕, Rasmus Lerdorf의 Simple is Hard 리뷰</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/OD0X7ZUFp7g/102</link>
			<description>&lt;p&gt;&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile5.uf.tistory.com/original/131EA00C4B74B1E51AE6BA" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile5.uf.tistory.com/image/131EA00C4B74B1E51AE6BA" alt="" filemime="image/png" filename="sih-00.png" height="341" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Rasmus 아저씨의 "Simple is Hard"라는 PT 중 PHP 성능에 관한 내용 일부를 소개해볼까 한다. 이 아저씨의 Simple is Hard라는 PT가 좀 &lt;a href="http://talks.php.net/index.php/PHP" target="_blank" title="[http://talks.php.net/index.php/PHP]로 이동합니다."&gt;여러 버전&lt;/a&gt;이 있는데, &lt;a href="http://talks.php.net/show/drupal08" target="_blank" title="[http://talks.php.net/show/drupal08]로 이동합니다."&gt;2008년 DrupalCon 발표자료&lt;/a&gt;를 참고했다.&amp;nbsp;예전에 &amp;nbsp;&lt;a href="http://hardworker.tistory.com/16" target="_blank" title="[http://hardworker.tistory.com/16]로 이동합니다."&gt;소개했던&lt;/a&gt;&amp;nbsp;자료랑 거의 비슷하긴 한데 좀 추가된 내용이 있어서 재탕을 해볼까 한다.&lt;/p&gt;
&lt;meta charset="utf-8"&gt;&lt;p&gt;그나저나, 참 뭐 하나 만들고 운영하고 하는데 신경 쓸 일이 한두 가지가 아니다. 설계도 중요하고, 보안도 생각해야되고, 성능도 빼놓을 수 없고 ... 잘 한답시고 주구장창 붙잡고 있어도 안 된다. 인생은 타이밍이니까. 그런데 요즘 HipHop도 공개되고 그러는 분위기니까 '성능'이란 주제에 대해 좀 더 생각해보는 시간을 갖도록 하자. 안그래도 &lt;a href="http://www.google.com/search?hl=en&amp;amp;q=google+site+fast+a+little+bit+of+bonus+ranking&amp;amp;aq=f&amp;amp;aqi=&amp;amp;oq=" target="_blank" title="[http://www.google.com/search?hl=en&amp;amp;q=google+site+fast+a+little+bit+of+bonus+ranking&amp;amp;aq=f&amp;amp;aqi=&amp;amp;oq=]로 이동합니다."&gt;구글이 빠른 웹사이트에 랭킹 보너스를 줄지도 모른다는 얘기&lt;/a&gt;도 있고. 빠른 웹사이트가 빠르면 좋은거다.&lt;/p&gt;
&lt;p&gt;오늘은 잡설은 짧게 끝내고 본론 바로 갑니다. 이 PT는 Scalability, Performance, Security 이렇게 세 부분으로 나뉜다. Scalability는 한국말로 옮기기가 참 애매한데, 확장성이라고 주로 옮기기는 하는 모양이지만 꼭 그 뜻은 아니고, 간혹 가용성 이렇게 옮기기도 하는데 꼭 그 뜻도 아닌 것 같다. 아.. 이것도 본론은 아닌데. 다음 문단부터 본론 나갑니다.&lt;/p&gt;
&lt;p&gt;이 자료에서 Rasmus 아저씨는 "PHP가 성능상의 병목이 되는 경우는 흔치 않지만, 몇 가지 도구를 써서 성능을 향상하는 기법을 소개합니다.&lt;/p&gt;
&lt;p&gt;8페이지부터 시작합니다. 우선 Laconica, Habari, Wordpress, Magento를 차례대로 Siege로 테스트합니다. 표 안의 숫자는 높을수록 빠른거에요. 1초에 몇 번의 트랜잭션(즉 페이지뷰)을 처리하는지. (Siege는 Apache ab랑 비슷한 벤치마킹 툴)&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;table width="580" bgcolor="#ffffff" style="border-collapse:collapse" cellpadding="1" cellspacing="1"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;normal&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;with APC enabled&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;Laconica - PHP 5.2.7-dev&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;18.71&amp;nbsp;&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;&amp;nbsp;45.37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;Laconica - PHP 5.3.0-dev&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;20.58&amp;nbsp;&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;&amp;nbsp;46.14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;Habari - PHP 5.2.10-dev&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;11.41&amp;nbsp;&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;&amp;nbsp;26.69&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;Wordpress&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;7.27&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;&amp;nbsp;33.08&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;Magento&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;2.33&lt;/td&gt;
&lt;td style="border:1px solid #dadada" width="33%"&gt;4.10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;p&gt;일단 &lt;a href="http://pecl.php.net/package/APC" target="_blank" title="[http://pecl.php.net/package/APC]로 이동합니다."&gt;APC&lt;/a&gt;를 안 쓸 이유가 없다는 걸 알 수가 있다. APC는 eAccelerator같은 OP Code Cache의 하나다. Rasmus 본인이 개발한거고. 보통은 eAccelerator를 많이들 쓰던데 특별한 이유는 모르겠다. 내 경우 APC나 eAccelerator에서 문제가 있던 부분을 &lt;a href="http://xcache.lighttpd.net/" target="_blank" title="[http://xcache.lighttpd.net/]로 이동합니다."&gt;xCache&lt;/a&gt;(lighttpd 개발자가 만든 OPCode cacher)를 써서 해결본 경험이 있기는 하다. 자세하게 분석하거나 벤치마킹 해본 건 아니니 그냥 참고하시라고.&lt;/p&gt;
&lt;p&gt;이어서&amp;nbsp;&lt;a href="http://talks.php.net/show/drupal08/10" target="_blank" title="[http://talks.php.net/show/drupal08/10]로 이동합니다."&gt;10페이지&lt;/a&gt;부터는 System call overhead를 줄여서 성능상의 이득을 얻는 과정이 나온다. 이를테면 Apache httpd.conf에 DirectoryIndex index.php를 명시해줘서 index.html index.cgi index.pl index.php를 차례대로 찾는 수고를 줄이는 것 만으로도 시스템콜을 절약할 수 있다는 얘기다. 개발자로서는 놓치기 쉬운 부분 되겠다.&lt;/p&gt;
&lt;p&gt;다음은 include_path다.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;;include_path = ".:/usr/local/lib/php"&lt;br /&gt;
include_path = "/usr/local/lib/php:."&lt;/p&gt;
&lt;p&gt;현재 디렉토리(.)를 먼저 찾은 다음에 /usr/local/lib/php를 찾도록 되어있던 걸 순서만 바꿔준건데 이것만으로 시스템콜이 많이 줄어든 걸 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;span id="tx_left_marker"&gt;&lt;/span&gt;&lt;span style="font-family: Terminal; "&gt;수정하기전:&lt;br /&gt;
close(10) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = 0&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;getcwd("/var/www/laconica", 4096) &amp;nbsp; &amp;nbsp; &amp;nbsp; = 18&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;time(NULL) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= 1216449985&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;lstat64("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;lstat64("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;lstat64("/var/www/laconica", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;lstat64("/var/www/laconica/PEAR.php", 0xbffcf5fc) = -1 ENOENT (No such file or directory)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;open("/var/www/laconica/PEAR.php", O_RDONLY) = -1 ENOENT (No such file or directory)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;time(NULL) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= 1216449985&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;open("/usr/local/lib/php/PEAR.php", O_RDONLY) = 10&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;fstat64(10, {st_mode=S_IFREG|0644, st_size=34813, ...}) = 0&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;stat64("./PEAR.php", 0xbffd1654) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= -1 ENOENT (No such file or directory)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Terminal; "&gt;stat64("/usr/local/lib/php/PEAR.php", {st_mode=S_IFREG|0644, st_size=34813, ...}) = 0&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 굴림; "&gt;close(10) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = 0&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;수정한다음:&lt;br /&gt;
close(10) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = 0&lt;br /&gt;
time(NULL) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;= 1216450700&lt;br /&gt;
open("/usr/local/lib/php/PEAR.php", O_RDONLY) = 10&lt;br /&gt;
fstat64(10, {st_mode=S_IFREG|0644, st_size=34813, ...}) = 0&lt;br /&gt;
stat64("/usr/local/lib/php/PEAR.php", {st_mode=S_IFREG|0644, st_size=34813, ...}) = 0&lt;br /&gt;
close(10) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; = 0&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;각각이 뭐하는건지 자세히는 모르더라도, 여러 디렉토리에서 파일이 있나없나 찾아보는데 시간을 많이 썼었다는 걸 짐작해볼 수 있다. 이렇게 고치고 나니 45.37 trans/sec 나오던 것이 46.63 trans/sec으로 빨라졌다. 2.7% 빨라진건데, 큰 수치가 아니라 생각할지도 모르지만 소스코드 한 줄 안 고치고 이정도면 대단한거다. 시스템이 크고 바쁠수록 더.&lt;/p&gt;
&lt;p&gt;그런데 혹시나 해서 부연 설명하는건데, 무조건 저렇게 고친다고 빨라지는게 아니라, 로그를 남기고 그걸 분석해서 뭘 할지 정해야된다. "아, include_path에 .를 무조건 마지막에 넣는구나."와 같은 결론을 내리면 곤란하다.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://talks.php.net/show/drupal08/13" target="_blank" title="[http://talks.php.net/show/drupal08/13]로 이동합니다."&gt;다음&lt;/a&gt;은 apc.stat값을 0으로 바꾸는 것이 어떤 영향을 미치는지를 보여주고 있다. apc.stst은 APC OP cache의 설정값 중 하나인데 소스코드가 거의 바뀌지 않는 상황(예를들어 실제 운영중인 서버)에서 유용하게 쓸 수 있다. 이 값은 기본이 켜진(1) 상태인데, 이 상태에서는 APC가 혹시 소스코드에 바뀐게 있나 계속 검사를 한다. 그런데 이걸 꺼버리면(apc.stat=0) 웹서버를 재시작하거나 강제로 캐시를 비우지 않는 한 계속 캐시된 OP Code를 쓴다. &lt;a href="http://www.php.net/manual/en/apc.configuration.php#ini.apc.stat" target="_blank" title="[http://www.php.net/manual/en/apc.configuration.php#ini.apc.stat]로 이동합니다."&gt;메뉴얼에 다 나온 내용&lt;/a&gt;이니 RTFM하시기 바란다. 이런류의 설정은 굉장히 유용하긴 한데 정확한 의미를 모르고 쓰거나, apc.stat=0으로 해놓고 까먹거나 하게되면 "왜 고쳤는데 반영이 안 되는거야!?" 따위의 어이없는 혼선을 빚을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile7.uf.tistory.com/original/12229A054B749D0C432520" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile7.uf.tistory.com/image/12229A054B749D0C432520" alt="" filemime="" filename="cfile7.uf@12229A054B749D0C432520.png" height="385" width="590"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;왼쪽이 apc.stat 고치기 전, 오른쪽이 후.&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;왼쪽에는 있는 것들 중에 오른쪽에는 안보이는 것들이 좀 있다. 그만큼은 절약이 된거라고 보면 되겠다. 벤치마크 결과를 확인해보면 46.15 trans/sec. 큰 의미는 없는 수치로 보인다. 하지만 로그에서 보았듯이 실제로는 절약되고 있기 때문에 아주 바쁜 상황에서라면 고려해볼 수 있는 방법이다.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://talks.php.net/show/drupal08/14" target="_blank" title="[http://talks.php.net/show/drupal08/14]로 이동합니다."&gt;14&lt;/a&gt;, &lt;a href="http://talks.php.net/show/drupal08/15" target="_blank" title="[http://talks.php.net/show/drupal08/15]로 이동합니다."&gt;15&lt;/a&gt;장에서는 include hierarchy를 고쳐 성능상의 이득을 보는 방법을 설명한다. include 계층이 어떻게 되는지 조사하는데 &lt;a href="http://pecl.php.net/package/inclued" target="_blank" title="[http://pecl.php.net/package/inclued]로 이동합니다."&gt;PECL/Inclued&lt;/a&gt;(스펠링 주의. 오타아님)를 쓴다. 쪼고만 모니터에서 비교해보느라 눈 빠지는 줄 알았다.&lt;/p&gt;
&lt;p&gt;&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile3.uf.tistory.com/original/130481224B74A722428447" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile3.uf.tistory.com/image/130481224B74A722428447" alt="" filemime="image/png" filename="sih-04.png" height="384" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;위가 시술전 아래가 시술후다. 이 아저씨가 뭘 어떻게 고쳤는가 모르겠다만, 내가 이해한 건 이렇다. 시술전에는 common.php가 DataObject.php를 require_once함에도 불구하고, common.php가 불러들이는 다른 여러 파일들이 DataObject.php를 또 불러댄다. 즉 점선으로 표시된 의존관계 중 어떤 것들은 군더더기라는 뜻이다. 이런식으로 몇 군데를 고친 것 같은데 다들 숨은그림 찾듯이 찾아보시고 저도 좀 알려주세요. 30인치 모니터가 있으면 저도 볼 수 있는데....&lt;/p&gt;
&lt;p&gt;중요한게, 그래서 얼마나 효과를 봤느냐? 46.15 에서 49.84로 뛰었다. 1%에 조금 못 미치지만 괜찮지 않습니까?&lt;/p&gt;
&lt;p&gt;지금까지는 주로 설정이나 순서 이런걸 바꿔서 효과를 보는, 상대적으로 쉬운 방법들이었다. 이번에는 프로파일링을 해 본다. 프로파일링 툴로 valgrind나 xdebug를 쓴다. 프로파일링 결과를 여기서 보는것처럼 그래프로 그려서 볼 수도 있는데, 꼭 그래프로 안 봐도 되기는 하지만 이렇게 보면 멋있기는 하다. 암튼 결과를 보고 어느 함수가 자원을 많이 잡아먹는지를 확인할 수 있다. 확인했는게 그 루틴이 너무 중요한거면 어쩔 수 없지만 만약 대안이 있다면 .....&lt;/p&gt;
&lt;p&gt;첫 번째 사례로 &lt;a href="http://talks.php.net/show/drupal08/18" target="_blank" title="[http://talks.php.net/show/drupal08/18]로 이동합니다."&gt;Remove some XMLWriter code&lt;/a&gt;라는걸 소개했는데, 아마 꼭 필요하지 않은 코드였거나 좀 더 가벼운 (자원 덜 먹는) 코드로 대체했다는 뜻인 것 같다. 특히 XML하고 관련된 것들이 메모리나 자원을 엄청 잡아먹는 경향이 있는데 간단한 XML이라면 DOM이나 OO스타일의 라이브러리 안 쓰고 그냥 문자열로 만들어도 된다는게 내 생각이다.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://talks.php.net/show/drupal08/23" target="_blank" title="[http://talks.php.net/show/drupal08/23]로 이동합니다."&gt;두 번째 케이스&lt;/a&gt;에서는 PHP가 시스템의 기본 Timezone을 쓰느라 헛짓하는 걸 간단하게 php.ini파일에 date.timezone 설정을 추가해서 정리해준다. 이렇게만 해줘도 160 trans/sec정도였던 것이 180으로 향상되었다.&lt;/p&gt;
&lt;p&gt;다음이 진짜 재밌는데, 내가 이걸 보면서 "앗 정리해서 포스팅해봐야겠다"고 생각했었다. 간단하게 "Hello World"만 출력하는 루틴의 성능을 비교해보는건데 Plain HTML부터 CakePHP, CodeIgniter, Zend Framework 등 널리 쓰이는 프레임웍에다 .. 두둥 .. Drupal 6.4도 같이 비교를 해놔서 아주 재밌었다. (DrupalCon에서 발표한거니까 ㅋㅋ) &lt;a href="http://talks.php.net/show/drupal08/24" target="_blank" title="[http://talks.php.net/show/drupal08/24]로 이동합니다."&gt;이 페이지&lt;/a&gt;부터 차례로 넘겨보면 되겠다. 행여나 이런 단순 벤치마크를 가지고 확대해석하는 분들은 없었으면 하는게 나의 작은 소망이자 바램이다.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;table width="580" bgcolor="#ffffff" style="border-collapse:collapse" cellpadding="1" cellspacing="1"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;Method&lt;/td&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;transactions / sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;Plain HTML&lt;/td&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;611.78&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;Trivial PHP&lt;/td&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;606.77&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;CakePHP 1.2.0.rc2&lt;/td&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;25.88&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;Symfony 1.1&lt;/td&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;100.63&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;Solar 1.0.0alpha1&lt;/td&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;271.18&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;Agavi 1.0-beta1 (production)&lt;/td&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;126.91&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;Zend Framework 1.6.0-rc1(with include_path tweak)&lt;/td&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;130.08&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;CodeIgniter 1.6.3&lt;/td&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;305.90&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;Prado 3.1.2&lt;/td&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;76.95&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;&amp;nbsp;Drupal 6.4&lt;/td&gt;
&lt;td style="border:2px solid #dadada" width="50%"&gt;51.37&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;참 가지각색이죠? 2년차 드루팔러로서 변호를 좀 해보자면, 드루팔은 다른 MVC 웹프레임웍하곤 좀 다르죠. 그것들보다는 좀 더 상위에 있다고 보는게 맞고, 아무리 Hello World만 출력하는 모듈을 짜넣었다고 해도 기본적으로 권한이라던가 캐시라던가 DB연결 이런게 다 돌아가고 있다는겁니다. 그러니까 단순비교는 무리.
&lt;/p&gt;
&lt;p&gt;자 지금까지 Simple is Hard라는 라스무스 아저씨의 발표자료를 살펴봤다. 직접 발표장에 간 것도 아니고 동영상을 본 것도 아니라 내가 잘못 이해한게 있을지도 모르겠지만 손가락을 보지 말고 달을 보는 지혜를 발휘해보도록 하자.&lt;/p&gt;
&lt;/div&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-102-0" class="entry-ccl-by" src="http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-fr/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-fr/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=OD0X7ZUFp7g:3GKtMBLVjl4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=OD0X7ZUFp7g:3GKtMBLVjl4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=OD0X7ZUFp7g:3GKtMBLVjl4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/OD0X7ZUFp7g" height="1" width="1"/&gt;</description>
			<category>학습자료, 추천사이트</category>
			<category>optimization</category>
			<category>Performance</category>
			<category>php</category>
			<category>profiling</category>
			<category>rasmus lerdorf</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/102</guid>
			<comments>http://hardworker.tistory.com/102#entry102comment</comments>
			<pubDate>Fri, 12 Feb 2010 10:43:05 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/102</feedburner:origLink></item>
		<item>
			<title>HipHop for PHP 소식 조금 더.</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/xH-rrUwC3Qo/101</link>
			<description>&lt;p&gt;몇 일 인터넷이 안됐다. 시간이 천천히 가더라. 그 사이에 HipHop이 공개됐나 봤더니 아직이다. &lt;a href="http://github.com/facebook/hiphop-php" target="_blank" title="[http://github.com/facebook/hiphop-php]로 이동합니다."&gt;GitHub&lt;/a&gt;에 위키&amp;nbsp;몇 페이지가 올라오긴 했지만 소스코드는 &lt;a href="http://github.com/facebook/hiphop-php/tree/344ad7dcb05b8afed0825fb1ddd9b4c5f76b3235" target="_blank" title="[http://github.com/facebook/hiphop-php/tree/344ad7dcb05b8afed0825fb1ddd9b4c5f76b3235]로 이동합니다."&gt;몇 일 더 기다려 달란다&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Within the next few days (and maybe even sooner) we'll release an initial copy of the source code that you can build on CentOS, but doesn't have a lot of commit history and has some workarounds for these build issues.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;몇 일 내에(어쩌면 더 빨리) CentOS에서 빌드할 수 있는 첫 번째 소스코드를 내놓을 겁니다. 하지만 커밋 히스토리가 별로 없고 지금 겪고있는 빌드관련 문제를 피하기 위한 코드가 있을겁니다. (즉, 완전하지 않을거란 말)&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;힙합에 관심을 갖고 찾아보신 분들은 알겠지만, 이게 얼른 가져다 쓸 수 있는 물건이 아니다. 최소한 아직은 아니다. 힙합이 어떤 의미를 가져다주는가에 대해 잘 정리한 글이 있어 허락도 안 받고 옮겨본다.&lt;/p&gt;
&lt;p&gt;원문은 굉장히 길어서 일부분만 옮긴다. 원문은 &lt;a href="http://terrychay.com/article/hiphop-for-faster-php.shtml" target="_blank" title="[http://terrychay.com/article/hiphop-for-faster-php.shtml]로 이동합니다."&gt;http://terrychay.com/article/hiphop-for-faster-php.shtml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;What HipHop means&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;힙합이 (당신에게) 의미하는 것&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you use some open-source PHP applications on your hosted website, the answer is &lt;/font&gt;&lt;b&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;nothing&lt;/font&gt;&lt;/b&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;. You don’t have the ability to compile HipHop, you don’t have access to server restricted ports, etc.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;공유 호스팅(대부분의 웹호스팅에 해당)에서 오픈소스 PHP 프로그램(드루팔, 워드프레스, 텍스트큐브 등)을 쓰고 있다면 &lt;b&gt;의미없다&lt;/b&gt;. HipHop으로 컴파일 할 수도 없고 서버의 제한된 포트도 쓸 수 없고 등등.&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you are developing a PHP application that currently can be run on two servers or less (or virtual servers in the cloud) the answer is &lt;/font&gt;&lt;b&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;nothing&lt;/font&gt;&lt;/b&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;. You don’t have the scale for this to be worth your time.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;두어개 정도의 서버(혹은 가상서버)에서 실행되는 PHP프로그램을 개발하고 있다면 역시 &lt;b&gt;의미없다&lt;/b&gt;. 시간을 들일만한 규모가 아니다. (작은 규모에서는 별로 얻는게 없다는 뜻)&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you do not have a separate development and deployment environment, don’t have a developer who knows C/C++, or use any PHP libraries where the source is not available (thankfully the encoded scripting market is small to non-existent in the PHP world), then the answer is nothing. You don’t have the development model that can support HipHop. Also note, HipHop has bugs, and—given the state of APC development as a model—will never have true compatibility with PHP. You’ll need some resources to either recode around those bugs or fix HipHop.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;만약 개발과 배포 환경이 분리되어있지 않거나, C/C++를 아는 개발자가 없거나, 소스코드가 제공되지 않는 PHP 라이브러리를 쓴다면 (다행히 PHP 세계에는 인코딩된 스크립트 시장이 거의 없다) 대답은 '&lt;b&gt;의미없음&lt;/b&gt;'이다. HipHop을 쓸 수 있는 개발 모델이 아니다. 추가로 HipHop에는 버그가 있다. 그리고 APC가 그러하듯 HipHop은 PHP와 진정한 호환성을 가질 수 없다. 버그를 고치거나 HipHop을 수정할 필요가 있을거다.&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you are a developer of an open-source PHP application, then the answer is not much. Most PHP applications will be deployed in a shared-hosted environment. They won’t be using HipHop.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;오픈소스 PHP 소프트웨어를 개발하고 있다면 그다지 &lt;b&gt;큰 의미 없다&lt;/b&gt;. 대부분의 PHP 소프트웨어는 공유호스팅에서 배포되기 때문이다. 그들은 HipHop을 지원하지 않을거다.&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you are a shared hosting company, the answer is not much. This is because the HipHop parser needs access to all the PHP in an application in order for it to create a working project. The exception is if you provide software as a service that you maintain (say a static build of WordPress, or a custom site tool written in PHP). You can have HipHop optimize this and get the performance increase.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;공유 호스팅 회사에게도 &lt;b&gt;큰 의미는 없다&lt;/b&gt;. 왜냐하면 HipHop이 실제로 작동하려면 그 PHP 애플리케이션 전체에 접근할 수 있어야 한다. (즉 모든 소스코드에 접근해야 한다는) 예외적으로 static build한 워드프레스나 직접 개발한 사이트 관리툴을 제공하고 있다면, 그것들의 HipHop 버전을 제공함으로서 성능 향상을 꾀할 수는 있을거다.&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If PHP is not the operational bottleneck of your web application (your app spends a lot of time waiting on the database, disk, a 3rd party Web API call, etc.), the answer is not yet. At this time, there’s no point in getting a performance gain in PHP. If you don’t know what I’m talking about, your bottleneck is the database.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;만약 PHP가 운영상의 병목지점이 아니라면(즉 DB나 Disk, 써드파티 API call등에서 시간을 많이 소비한다면), 대답은 '&lt;b&gt;아직&lt;/b&gt;'이다. 지금 PHP에서 (HipHop을 도입해서) 얻을 수 있는 성능상 잇점이 없다. 무슨 얘긴지 모르겠다면 지금 당신의 병목지점은 DB다. (ㅋㅋ)&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you have an application already scaled across many machines, a significant number of them running PHP in processor-intensive tasks, have separate development/deployment, have your entire PHP source code, have modest C/C++ resources, then the answer is possibly. It wouldn’t hurt for a developer there to try a hand at cross-compiling the PHP into HipHop and seeing if it runs. An operational deployment will return about 50% of those machines to a pool for other uses or future growth—or, put differently HipHop will basically double that processing on the same hardware/power.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;많은 서버에 걸쳐 동작하는 애플리케이션을 갖고있고, 그 중 많은 서버가 프로세서를 잡아먹는 작업을 하는 PHP를 운영중이라면, 그리고 분리된 개발/배포 체계를 갖고 있고 모든 PHP 소스코드도 가지고 있고 C/C++ 자원도 있다면, 답은 '&lt;b&gt;어쩌면&lt;/b&gt;'이다. HipHop으로 크로스컴파일하고 돌아가는지 한 번 시도해보는 것도 나쁘진 않을거다. (성공한다면) 50% 정도의 머신은 다른 용도로 쓰거나 앞으로의 성장을 대비할 수 있을거다. 다시말하자면 기본적으로 HipHop은 같은 하드웨어/성능으로 (PHP에 비해)두 배의 프로세스를 처리한다.&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you make a turnkey application based on PHP, the answer is somewhat. These are rare, but now you can shrink-wrap PHP into a binary. This isn’t the intended use of HipHop, so some development might have to be done to get this fully supported. Also this is a true binary, not an op-code compile—it cannot run across platforms.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;만약 PHP 기반의 턴-키 애플리케이션을 만들고 있다면 HipHop은 &lt;b&gt;어느정도 의미가 있다&lt;/b&gt;. 드물긴 하지만 PHP를 바이너리로 포장할 수 있다. HipHop의 원래 용도가 아니기 때문에 ..(뭐라는지 모르겠음) 그리고 이건 OP-code가 아니라 진짜 바이너리다 - 다른 플랫폼에서는 동작하지 않는다.&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you are developing a PHP framework, the answer is some. If your framework can compile and run successfully in HipHop, then it should be a good selling point to enterprises in case their application becomes bottlenecked on performance.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;만약 PHP 프레임웍을 개발하고 있다면 대답은 '&lt;b&gt;약간&lt;/b&gt;'이다. 만약 제작한 프레임웍이 HipHop으로 잘 컴파일되고 실행된다면, 기업에 그 프레임웍을 판매할 때 좋은 요소가 된다. 특히 그 애플리케이션이 성능상의 병목이 된다면.&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you have highly-cohesive parts of your architecture that fall into above requirements and those parts are weakly-coupled (via API?) to the rest of the system, then the answer is a lot. Those parts can probably benefit from HipHop, and it should be relatively easy to try it.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;만약 전체 아키텍쳐에서 위에 언급한 요구조건에 해당하면서 highly-cohesive()한 부분이 있다면, 그리고 그 부분이 시스템의 다른 부분과 느슨하게 연결되어 있다면 (API등을 통해서) &lt;b&gt;큰 의미가 있다&lt;/b&gt;. 그 부분들은 HipHop으로 큰 이득을 볼 수 있고, 상대적으로 시도해보기 쉬울거다.&lt;/p&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you are making a decision on which web language to build your site in, the answer is a heck of a lot. Arguing against PHP for performance reasons no longer holds water. PHP under HipHop will probably now out-benchmark Perl, Python, Ruby and possibly even Java and C#. In practice, you can get the advantages of having a scripting language without operational costs. Moreover, because the target is C++ which is more easy to integrate as a library, if you have a multi-language support, you can now provide C++, Python, and other languages with access to components that have before only been written in PHP (without resorting to a web API).&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;웹사이트를 어떤 언어로 개발할지 결정하는 중이라면 의미는 굉장히 크다. PHP의 성능에 관한 논쟁은 끝이다. HipHop/PHP 벤치마크는 아마도 Perl, Python, Ruby를 넘어서고 어쩌면 Java나 C#마저도 제낄지 모른다.실제로 운영비용 없이 스크립트 언어의 장점을 가질 수 있다. 게다가 C++는 다른 언어와 라이브러리 형태로 통합하기 쉽다. 만약&amp;nbsp;이전에는 PHP로만 제공되었던 컴포넌트를&amp;nbsp;여러 언어에 지원해야 한다면 이제 C++나 파이썬 그리고 다른 언어들을 제공할 수 있다. (즉 PHP로 작성한 콤포넌트를 다른 언어에 바인딩하기 쉬워졌다는 말인 듯)&lt;/p&gt;
&lt;meta charset="utf-8"&gt;
&lt;p&gt;&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you are making an argument to recode your entire site from PHP to some other language, the answer is you just lost that argument. (I never bought the argument of recoding an entire site from another language to PHP.)&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;만약 PHP로 개발한 사이트를 통째로 다른 언어로 다시 코딩하는 것에 관해 논쟁하고 있다면, 그 논쟁은 끝이다.&lt;/p&gt;
&lt;p&gt;----&lt;/p&gt;
&lt;p&gt;원문을 읽어보면 힙합에 대한 정보를 더 많이 얻을 수 있기는 한데, 워낙 긴데다 다른 글을 많이 인용해놔서 읽기가 벅차다. 암튼 정리를 해보자면, HipHop for PHP 뿐 아니라 그 어떤 것도 만병통치약이 될 수는 없는거다. 특히 "HipHop is a performance mod, not a scalability one. That’s good because scalability is an architecture problem, not a language one. (HipHop은 성능에 관한 것이지 확장성에 관한게 아니다. 확장성은 구조 문제이지 언어에 관한게 아니다)"라는 말을 새겨보자.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-101-0" class="entry-ccl-by" src="http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-fr/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-fr/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=xH-rrUwC3Qo:gv4LgEvCl6E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=xH-rrUwC3Qo:gv4LgEvCl6E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=xH-rrUwC3Qo:gv4LgEvCl6E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/xH-rrUwC3Qo" height="1" width="1"/&gt;</description>
			<category>신기술,분석</category>
			<category>cross-compiler</category>
			<category>HipHop for PHP</category>
			<category>php</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/101</guid>
			<comments>http://hardworker.tistory.com/101#entry101comment</comments>
			<pubDate>Wed, 10 Feb 2010 15:09:08 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/101</feedburner:origLink></item>
		<item>
			<title>HipHop for PHP, Facebook이 PHP컴파일러를 공개했다.</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/mchgqWTT1UA/99</link>
			<description>&lt;p&gt;페이스북의 순방문자가 야후!를 추월했다는 기사를 본 게 엊그제다. 페이스북 성장세가 대단하기는 한가보다. 근데 얘네는 DBA가 두명이라면서 트래픽은 야후끕이라니, 맨파워 역시 대단한 것 같다. 요즘 뒤적거린 것들에서도 페이스북이 서비스를 지탱하기 위해 개발한 Cassandra라던가 memcached를 많이 활용한다는 걸 소개했었는데, 얘들이 거기에서 그치지 않고 PHP 코드를 최적화한 C++코드로 변환하고, 이걸 컴파일한 다음 전용의 웹서버에 탑재해 돌리는 솔루션을 개발했다. 그리고 소스 공개한단다. 소식은 &lt;a href="http://developers.facebook.com/news.php?blog=1&amp;amp;story=358" target="_blank" title="[http://developers.facebook.com/news.php?blog=1&amp;amp;story=358]로 이동합니다."&gt;여기서.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;서비스를 더 잘 하기위해 새로운 기술을 연구하는 모습이 참 보기좋다. 이게 너무 지나치면 Over Engineering이 될 수도 있고, 게을리하면 기술이 사업 발목잡는 형국이 될 수 있기에 균형을 잘 잡는것도 참 보기좋다.&lt;/p&gt;
&lt;p&gt;그나저나 PHP가 C로 만들어지기는 했지만, C++하고의 차이는 꽤 큰 편인데 이를테면 C++은 Strong type인데 반해 PHP에서는 변수에 아무거나 집어넣을 수 있으니까. 심지어 런타임에 함수도 만들고 eval()같은 것도 있고. 그래서 HipHop 개발팀이 고민을 많이 했나보다. 머 암튼 C++는 내가 잘 모르니 너무 아는척을 했다간 망신을 당할 위험이 있다. 고로 페이스북이 발표한 걸로 정리를 해보면.&lt;/p&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;2년동안 개발했는데, 주력 멤버는 3명 총 7명인가 8명의 팀인 것 같다. (동영상 보고 추측)&lt;/li&gt;
&lt;li&gt;최근 6개월간 페이스북의 실 서비스에 적용하고 있으며 전체 트래픽의 90%가 HipHop을 통해 서비스된다고.&lt;/li&gt;
&lt;li&gt;PHP를 직접 컴파일하는게 아니라, 똑같은 로직을 가진 C++코드로 바꾼 다음 g++로 컴파일한다.&lt;/li&gt;
&lt;li&gt;이 HipHop의 주된 이점은 CPU 점유율을 낮추는거다. (당연한가?)&lt;/li&gt;
&lt;li&gt;웹페이지의 경우 같은 트래픽일 때 CPU 사용이 50%감소했고, API는 2배의 트래픽을 감당하면서도 30% 감소했다.&lt;/li&gt;
&lt;li&gt;PHP의 확장기능(extensions)은 어떻게 되느냐? 페이스북이 쓰는 대부분의 extension을 지원하도록 HipHop팀이 손을 봤고, 몇몇 Thread-safe하지 않은 확장기능은 직접 수정했다고 한다.&lt;/li&gt;
&lt;li&gt;eval()이나 create_function()은 아쉽지만 지원하지 않는다.&lt;/li&gt;
&lt;li&gt;아직 소스가 공개되지는 않은 것 같다. &lt;a href="http://developers.facebook.com/hiphop-php/" target="_blank" title="[http://developers.facebook.com/hiphop-php/]로 이동합니다."&gt;여기&lt;/a&gt;를 통해 확인할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile10.uf.tistory.com/original/1417A10D4B6A3B4C19FCD2" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile10.uf.tistory.com/image/1417A10D4B6A3B4C19FCD2" alt="" filemime="" filename="hp-supported.png" height="368" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile5.uf.tistory.com/original/1815E90D4B6A3B3419A5E9" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile5.uf.tistory.com/image/1815E90D4B6A3B3419A5E9" alt="" filemime="" filename="hp-notsupported.png" height="375" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile10.uf.tistory.com/original/1327450D4B6A3B26026301" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile10.uf.tistory.com/image/1327450D4B6A3B26026301" alt="" filemime="" filename="hp-deploying.png" height="376" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile5.uf.tistory.com/original/1408390D4B6A3B40414234" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile5.uf.tistory.com/image/1408390D4B6A3B40414234" alt="" filemime="" filename="hp-roadmap.png" height="371" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;(2/5 추가) 저녁때 공개한다던 사람들이 아직 감감 무소식이다. 뭔가 사정이 있겠지. 그런데 소스가 공개되더라도 즉시 다른 서비스에 적용하기에는 무리가 있을거다. 6개월 실전에 돌려봤다곤 하지만 페이스북 뿐이고, 여러가지 문제가 생겼었겠지만 힙합 개발팀이 잘 해결해왔겠지. 그래도 궁금하다. 왜 얼른 공개가 안되나?&lt;/p&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-99-0" class="entry-ccl-by" src="http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-fr/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-fr/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  					&lt;embed src="http://api.v.daum.net/static/recombox1.swf" quality="high" flashvars="nid=5705888" allowscriptaccess="always" allowfullscreen="false" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash" wmode="transparent"&gt;&lt;/embed&gt;
						&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=mchgqWTT1UA:xIoSViXE0EA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=mchgqWTT1UA:xIoSViXE0EA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=mchgqWTT1UA:xIoSViXE0EA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/mchgqWTT1UA" height="1" width="1"/&gt;</description>
			<category>신기술,분석</category>
			<category>facebook</category>
			<category>HipHop for PHP</category>
			<category>OpenSource</category>
			<category>php</category>
			<category>scalability</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/99</guid>
			<comments>http://hardworker.tistory.com/99#entry99comment</comments>
			<pubDate>Thu, 04 Feb 2010 12:23:42 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/99</feedburner:origLink></item>
		<item>
			<title>Typekit, 웹페이지에서 트루타입TrueType 폰트를!</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/j0U2D49UIgU/98</link>
			<description>&lt;p&gt;웹 폰트라는게 있다. 싸이월드 이런데 가면 굴림체, 돋움체 이런거 말고 귀여운(척하는) 폰트를 볼 수 있는데, 익스플로러에서만 동작하는 기능을 가지고 수익모델을 만들다니 대한민국도 참 대단하다 싶기는 한데 굴림 궁서 돋움 이런거 지겹기도 하고 뭣보다 안 예쁘니까. 꾸미는 폰트가 아니라, 그냥 기본 폰트니까. 윈도 비스타에서 맑은고딕을 도입해 많은분들이 좋아하기도 하고 ClearType 이런 기술에 관심도 가지기는 했지만, 그래봐야 웹 환경에서 쓸 수 있는 한글폰트가 4개에서 5개로 늘어난 것 뿐이니 IE전용의 기능이라도 어떻게 해보려는 걸 뭐라할 순 없다.&lt;/p&gt;
&lt;p&gt;&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile7.uf.tistory.com/original/167E510B4B6811A53F5869" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile7.uf.tistory.com/image/167E510B4B6811A53F5869" alt="" filemime="" filename="cfile7.uf@167E510B4B6811A53F5869.png" height="275" width="512"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;싸이월드에서 파는 웹폰트(글꼴)&lt;/p&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;이 웹 폰트의&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/@font-face" target="_blank" title="[http://en.wikipedia.org/wiki/@font-face]로 이동합니다."&gt;기술적인 배경은 위키피디아에&lt;/a&gt; 잘 설명되있는데, 요약하자면 웹폰트(Web typography)라는게 css의 @font-face 속성을 이용하는거고, 이게 CSS2.1에서 빠졌다가 CSS3에서 다시 넣는걸로 얘기되고 있다. 그런데 IE는 그 동안에도 &lt;a href="http://ko.wikipedia.org/wiki/WEFT" target="_blank" title="[http://ko.wikipedia.org/wiki/WEFT]로 이동합니다."&gt;EOT라는 파일포멧&lt;/a&gt;만 지원하긴 하지만 이 속성을 꾸준히 지원해왔기 때문에 지금의 "웹폰트"라는게 IE전용인거다.&lt;/p&gt;
&lt;p&gt;여튼 지금의 웹폰트는 단점이 좀 많다. 일단 IE에서만 된다는거. 그리고 유통되는 웹폰트들이 대개 비트맵 폰트라 가독성이 떨어진다. (글씨크기가 딱 한 가지고, 윤곽선이 미려하지 않다.) 이건 아마도 대소문자 합쳐 52자에 특수만자만 좀 넣으면 되는 영문 폰트와 달리, 최소한 수천자를 집어넣어야 하는 한글 폰트의 특수성 때문이기도 하겠지만.&lt;/p&gt;
&lt;p&gt;위에 잠깐 언급을 했는데 CSS3에서 이 @font-face 속성이 다시 추가될 조짐이 있다. 그리고 몇몇 발빠른 웹브라우저들이 벌써 지원하고 있다. 이 &lt;a href="http://typekit.com/" target="_blank" title="[http://typekit.com/]로 이동합니다."&gt;Typekit&lt;/a&gt; 서비스는 이걸 노리고 출시한 서비스다.&lt;/p&gt;
&lt;p&gt;&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile28.uf.tistory.com/original/182C1A034B681DF0178D0F" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile28.uf.tistory.com/image/182C1A034B681DF0178D0F" alt="" filemime="" filename="cfile28.uf@182C1A034B681DF0178D0F.png" height="151" width="448"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;Typekit.com에 있는 배너인데, 이거 이미지 아니고 다 텍스트다.&lt;/p&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;이 타입킷 서비스는, 웹게 말하자면 TTF 폰트를 호스팅해준다. 서비스에 가입하면 이들이 제공하는 다양한 폰트를 둘러볼 수 있다. 무료 계정은 1개의 도메인에서 2가지 폰트를 쓸 수 있다. 사용법 자체는 쉬우니까 소개 생략.&lt;/p&gt;
&lt;p&gt;근데 이게 왜 좋으냐고?&amp;nbsp;물론 이거 아직 한글 폰트도 없고, &amp;nbsp;널리 쓰이는 브라우저 중 &lt;a href="http://www.mikeindustries.com/blog/archive/2009/05/examining-typekit" target="_blank" title="[http://www.mikeindustries.com/blog/archive/2009/05/examining-typekit]로 이동합니다."&gt;대략 80%에서만 동작하는&lt;/a&gt;&amp;nbsp;기능이다. 하지만 관심가질 필요는 충분히 있다고 본다.&lt;/p&gt;
&lt;p&gt;우선, 요 앞에 소개했던 &lt;a href="http://hardworker.tistory.com/96" target="_blank" title="[http://hardworker.tistory.com/96]로 이동합니다."&gt;Readability서비스&lt;/a&gt;가 Typekit을 지원한다. 읽기 편한 폰트로 Readability를 향상한다는 점에서 아주 적절한 조합이다. "이 블로그는 맑은고딕에 최적화되었으니 귀찮으시더라도 다운받아 설치하시라"고 홍보하는 블로그들이 꽤 있는데, 폰트가 어딘가에서 호스팅되고 있다면 방문자가 일부러 폰트를 설치 안해도 된다. 편하겠다.&lt;/p&gt;
&lt;p&gt;또 웹사이트 용량을 줄일 수 있다. 서비스가 커질수록 용량은 곧 돈이다. 지금은 예쁜폰트를 웹사이트에 올리려면 이미지로 만들어 올려야 하는데, 이미지 대신 이걸 텍스트로 만들면 당연히 용량이 줄어든다. 물론 경우에 따라 배가 배꼽보다 클 수도 있다. 폰트 용량이 이미지보다 크면 말짱 황이니까. 특히 한글은 ... 중문보단 훨씬 낫지만 영문 폰트에 비해 용량이 클 수 밖에 없다. 하지만 플래시처럼, 몇몇 글자면 뽑아서 올리는 식으로 용량을 줄이는게 가능하지 않을까?&lt;/p&gt;
&lt;p&gt;그리고, 좀 더 시맨틱한 웹이 된다. 요즘 아이폰때문에도 그렇고 웹표준에 관심들이 많은데, 단지 HTML 문법 잘 지켰다는 수준에서가 아니라 내용까지도 시맨틱해진단 얘기다. 뭔소리냐고? 이를테면, 중요한 내용 강조하려고 굵고 눈에띄는 폰트를 써서 만든 배너 이미지 웹사이트에 올리는 경우가 많은데, 이게 시각적으로는 강조되서 보이지만 네이버고 구글 이런 검색엔진은 내용을 못 알아챈다. 아직 이미지 안에 들어있는 내용까지 검색되게 해주는 기술은 없다. 즉 바꿔말하면 당신의 웹사이트가 더 검색 잘 된다는 뜻. 한국에선 SEO라는 것도 좀 희안하게 키워드광고같은 쪽으로만 발달을 하는 경향이 보이기는 하지만 .... 더 자세한 건 다음 기회에.&lt;/p&gt;
&lt;p&gt;비슷한 맥락에서, 웹 접근성(Web Accessibility)에도 도움이 된다. 웹 접근성이란, 몸이 좀 불편한 사람이나 악조건(햇빛이 엄청 밝은 곳이나 마우스가 없는 상황, 심지어 아이폰같은 제한된 기기를 쓰는 경우도 포함)에 처한 경우라도 정보를 얻는데 어려움이 있는가 없는가 하는 걸 따지는건데, 쉽게 생각하자면 시각장애인용 웹사이트 이런걸 떠올려도 괜찮다. 한국에선 법으로 강제되지는 않고 있다만 몇몇 선진국에서는 공공기관 웹사이트는 누구든 정보접근이 쉽도록 강제하는 법이 있다. 플래시나 이미지를 쓰면 접근성이 떨어지기 땜에 최소한 공공기관에선 쓰지 말라고 하는 것인데, 한국에선 잘 안 지켜진다. 장애가 없는 사람도 쓰기 불편한... 아 이게 주 내용이 아니고. 암튼 웹 표준을 잘 지키면 접근성은 반쯤은 따라온다고 봐도 된다.&lt;/p&gt;
&lt;p&gt;종종 그렇듯이 주 내용보다 잡설이 더 길었다. CSS는 갈수록 빵빵해지고, 이런 기술의 적용은 쉬운게 아니다. 당장 포토샵이 편하고 사다놓은 폰트가 잔뜩인 디자이너가 이 서비스를 쓰고싶을까? 브라우저 호환성도 문제다. IE는 TTF포멧을 지원하지 않아 궁여지책으로 조악한 EOT를 써야한다. 하지만 분명히 웹 문서의 품질이 점점 인쇄물의 그것에 다가가고 있다.&lt;/p&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;&lt;a href="http://typekit.com/" target="_blank" title="[http://typekit.com/]로 이동합니다."&gt;http://typekit.com/&lt;/a&gt;&amp;nbsp;: 서비스 웹사이트&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.typekit.com/2009/05/27/introducing-typekit/" target="_blank" title="[http://blog.typekit.com/2009/05/27/introducing-typekit/]로 이동합니다."&gt;http://blog.typekit.com/2009/05/27/introducing-typekit/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.mikeindustries.com/blog/archive/2009/05/examining-typekit" target="_blank" title="[http://www.mikeindustries.com/blog/archive/2009/05/examining-typekit]로 이동합니다."&gt;http://www.mikeindustries.com/blog/archive/2009/05/examining-typekit&lt;/a&gt; : Typekit에 대해 다양한 관점에서 분석&lt;/li&gt;
&lt;li&gt;&lt;a href="http://typeface.neocracy.org/" target="_blank" title="[http://typeface.neocracy.org/]로 이동합니다."&gt;http://typeface.neocracy.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span id="tx_left_marker"&gt;&lt;/span&gt;&lt;a href="http://www.mikeindustries.com/blog/sifr/" target="_blank" title="[http://www.mikeindustries.com/blog/sifr/]로 이동합니다."&gt;h&lt;/a&gt;&lt;a href="http://www.mikeindustries.com/blog/sifr/" target="_blank" title="[http://www.mikeindustries.com/blog/sifr/]로 이동합니다."&gt;ttp://www.mikeindustries.com/blog/sifr/&lt;/a&gt;&amp;nbsp;비슷한 고민, 좀 다른 해결책.&lt;span id="tx_right_marker"&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-98-0" class="entry-ccl-by" src="http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-fr/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-fr/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  					&lt;embed src="http://api.v.daum.net/static/recombox1.swf" quality="high" flashvars="nid=5684061" allowscriptaccess="always" allowfullscreen="false" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash" wmode="transparent"&gt;&lt;/embed&gt;
						&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=j0U2D49UIgU:WybLjPN6DxQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=j0U2D49UIgU:WybLjPN6DxQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=j0U2D49UIgU:WybLjPN6DxQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/j0U2D49UIgU" height="1" width="1"/&gt;</description>
			<category>학습자료, 추천사이트</category>
			<category>@font-face</category>
			<category>CSS3</category>
			<category>Typekit</category>
			<category>typography</category>
			<category>Webfonts</category>
			<category>웹폰트</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/98</guid>
			<comments>http://hardworker.tistory.com/98#entry98comment</comments>
			<pubDate>Tue, 02 Feb 2010 21:45:56 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/98</feedburner:origLink></item>
		<item>
			<title>Readability? Writability?</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/nKoNpcoEAxw/96</link>
			<description>&lt;p&gt;(좀 시덥잖은 얘기라 꼭 안 읽으셔도 됨)&lt;/p&gt;
&lt;p&gt;Readability라는 서비스가 있다. &amp;nbsp;이게 말하자면 북마크릿(Bookmarklet)인데, 즐겨찾기에 넣은담에 여느 웹페이지에서 얘를 클릭해주면 - 짜잔 하고 &lt;b&gt;읽기좋게&lt;/b&gt; 바꿔준다. 간단한 서비스지만 나는 이런게 정말 필요했기 때문에 엄청 감동받았다.&lt;/p&gt;
&lt;p&gt;직접 해보려면 귀찮을테니까 &lt;a href="javascript:(function(){readStyle='style-newspaper';readSize='size-large';readMargin='margin-medium';_readability_script=document.createElement('SCRIPT');_readability_script.type='text/javascript';_readability_script.src='http://lab.arc90.com/experiments/readability/js/readability.js?x='+(Math.random());document.getElementsByTagName('head')[0].appendChild(_readability_script);_readability_css=document.createElement('LINK');_readability_css.rel='stylesheet';_readability_css.href='http://lab.arc90.com/experiments/readability/css/readability.css';_readability_css.type='text/css';_readability_css.media='all';document.getElementsByTagName('head')[0].appendChild(_readability_css);_readability_print_css=document.createElement('LINK');_readability_print_css.rel='stylesheet';_readability_print_css.href='http://lab.arc90.com/experiments/readability/css/readability-print.css';_readability_print_css.media='print';_readability_print_css.type='text/css';document.getElementsByTagName('head')[0].appendChild(_readability_print_css);})();" target="_blank" title="[javascript:(function(){readStyle='style-newspaper';readSize='size-large';readMargin='margin-medium';_readability_script=document.createElement('SCRIPT');_readability_script.type='text/javascript';_readability_script.src='http://lab.arc90.com/experiments/readability/js/readability.js?x='+(Math.random());document.getElementsByTagName('head')[0].appendChild(_readability_script);_readability_css=document.createElement('LINK');_readability_css.rel='stylesheet';_readability_css.href='http://lab.arc90.com/experiments/readability/css/readability.css';_readability_css.type='text/css';_readability_css.media='all';document.getElementsByTagName('head')[0].appendChild(_readability_css);_readability_print_css=document.createElement('LINK');_readability_print_css.rel='stylesheet';_readability_print_css.href='http://lab.arc90.com/experiments/readability/css/readability-print.css';_readability_print_css.media='print';_readability_print_css.type='text/css';document.getElementsByTagName('head')[0].appendChild(_readability_print_css);})();]로 이동합니다."&gt;이걸 클릭&lt;/a&gt;해보세요. 감이 확 오실듯. 이거 꼭 써보시라고 그런 얘기 하려는 건 아니고.&lt;/p&gt;
&lt;p&gt;그런게 좀 있다. MS워드 켜놓고 블로깅이 잘 안 되고, 블로그에 글 쓰려면 블로그 글쓰기 페이지를 열어놔야 몸도 마음도 블로거가 된다고나 할까. 나는 파워블로거도 아니고 글 쏟아내는 헤비 블로거도 아니지만, 왠만한 블로그 툴은 다 써보긴 했다. (그러느라 블로그를 안 하나 ㅎㅎ) 직업 때문이기도 하고 호기심이 많기도 하고 워낙에 일 할 때 좋은 도구를 쓰는게 중요하다고 생각하는 편이라서.&lt;/p&gt;
&lt;p&gt;그런데 블로깅 한다는게 뭔가. 일단 글을 생산하는 거잖아. 그리고 그게 블로그라는 (상대적으로) 새로운 매체로 유통되고, 댓글이나 트랙백도 오가고. 좋은 블로깅 도구의 미덕이야 여러 가지가 있을 수 있겠다. 이를테면 네이버에 블로그 둥지를 틀면 네이버 검색에 노출이 직빵이다. 내가 사업하는 사람이면 네이버 블로그를 고려할 테다. 티스토리는- 음. 태터툴즈 설치해서 쓰기는 귀찮지만 거의 비슷한 느낌으로 쓰고싶은 나한테 적당한 선택이었다. 워드프레스는 수많은 테마와 플러그인으로 유명하고.&lt;/p&gt;
&lt;p&gt;WriteRoom이란 맥용 소프트웨어가 있다. 이게 일종의 에디터인데, 실행하면 화면이 새카매지면서 한옛날 컴퓨터에서나 볼 수 있던 형광 초록색 커서만 깜빡거린다. 이 에디터의 모토가 "산만하지 않은 글쓰기"쯤 되는데 진짜 단순한 화면이 글쓰기에 집중하게 해주는 면이 있다. 브라우저에서 글 쓰다보면 옆에있는 탭에도 눈이 가고 갑자기 메신저가 뚜둥 하면서 올라오기도 하고 그러니까.&lt;/p&gt;
&lt;p&gt;얘기가 좀 산만해졌는데 내가 하고잡은 얘기는 블로그에 글을 쓸 때, 글 쓰기가 엄청 불편하단거다. 글 쓰는 작업에 더 집중할 수 있는 뭔가가 필요하다. WriteRoom같은 형태를 말하는 건 아니다. 저 에디터 얘기를 꺼낸 건, 저 단순한 에디터가 가지고 있는 고민이나 문제의식 이런게 공감이 가서다. 텅 빈 공간에 써놓은 글만 보여주는 것도 좋은 방법이지만, 모든 종류의 글쓰기에 적용할 수 있는 금과옥조는 아니다.&lt;/p&gt;
&lt;p&gt;티스토리는 꽤 괜찮은 툴이기는 하지만 글쓰기에 그다지 좋게 되어있지는 않다. 일단 써놓은 글을 날려먹는 것보다 기분나쁜게 별로 없는데 이 티스토리의 허술한 "임시저장"시스템은 글을 날려먹을 기회를 아주 자주 제공한다. 이글루스 블로그도 하나 가지고 있는데, 임시저장이나 그런게 아주 불편하게 되어있다. 워드프레스는 그것보단 좀 나은 편인데, draft인지 publish인지 더 확실하게 구분을 하는데다 두 사람이 같은 글을 편집하면 경고를 해준다던가, autosave된 것도 리비전이 있어 위키처럼 바뀐 걸 단계적으로 볼 수 있다던가 하는 기능은 아주 좋다.&lt;/p&gt;
&lt;p&gt;구글닥스나, 하다못해 쥐메일에서 메일 쓰다가 내용 날릴 걱정은 별로 하지 않는다. 자동저장도 잘 되고, 노트북 덮었다 열었다고 해서 세션이 끊기거나 하지는 않으니까. 이런 사실이 사람을 굉장히 편하게 한다. 글쓰기에 집중한다는게 이것 뿐만은 아니지만, 암튼 편하게 해주는 건 아주 중요하다. 더 편하면 사람들은 지갑을 열기도 한다.&lt;/p&gt;
&lt;p&gt;그리고 안심하게 하는 것 말고 내가 좋은 블로그 글쓰기에 꼭 필요하다고 생각하는게, 글 뿐 아니라 자료를 같이 보관할 수 있었으면 하는거다. 본문에 링크건 웹사이트 주소나 뭐 그런것 말고도, 조심스럽게 글을 쓰다보면 같이 보관해야 하는 메모나 그런게 엄청 많은데 그걸 따로 메모장같은데 기록해야 하는거 아주 성가시다. 특히 글을 완성하기 전에는 거의 자료만 따로 저장해두는 경우가 많은데 그런 배려가 좀 없다. 전문적으로 글 쓰시는 분들은 메모장이나 노트가 엄청 중요한 자산인데, 블로그 툴에 그런 기능이 통합되는 건 자연스러운 일일것 같다.&lt;/p&gt;
&lt;p&gt;블로그에 위젯이나 스킨이나 이런것도 중요하기는 한데, 아주 기본중에 기본인 - 글을 쓰고 읽는것을 최대한 편하게 해주는 일은 아직도 개선할 점이 많이 있어보인다. 어떤 블로그는, 내용은 아주 좋은데 행간이 너무 좁거나 글씨가 작아서 도저히 읽을 엄두가 안 나는 경우도 있다. 그거야 도구만의 문제는 아니기는 하지만, 여하튼 읽고 쓰는것에 초점을 맞추는 그런 작업이 필요하다는게 내 생각이다.&lt;/p&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-96-0" class="entry-ccl-by" src="http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-fr/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-fr/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=nKoNpcoEAxw:jw_iU7pR0oQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=nKoNpcoEAxw:jw_iU7pR0oQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=nKoNpcoEAxw:jw_iU7pR0oQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/nKoNpcoEAxw" height="1" width="1"/&gt;</description>
			<category>의견</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/96</guid>
			<comments>http://hardworker.tistory.com/96#entry96comment</comments>
			<pubDate>Mon, 01 Feb 2010 11:22:45 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/96</feedburner:origLink></item>
		<item>
			<title>프레젠테이션 귀염둥이, 프레지~ (Prezi)</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/RUokXPL0RtY/94</link>
			<description>&lt;p&gt;&lt;a href="http://prezi.com/" target="_blank" title="[http://prezi.com/]로 이동합니다."&gt;http://prezi.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;앞선 글에서 플래시의 사용감을 별로 안 좋아한다고 말했었다. 마우스 포인터도 뚝 뚝 뚝 움직이는 것 같고 텍스트 입력 할 때도 어색하고 &amp;nbsp;좀 따로 노는 느낌이 들어서. 한국의 웹사이트들 - 특히 언론사 - 에 가득 찬 플래시 광고 때문에 여름에 노트북 뜨겁게 달궈지는 것도 불쾌하고. 아 그래 뭐 그거야 플래시가 지은 죄는 아닌데, 괜히 같이 미워져.&lt;/p&gt;
&lt;p&gt;와. 그런데 플래시로 만든 웹서비스 중에 제일 마음에 드는 걸 오늘 발견했다. 바로 "프레지"라는 프레젠테이션 툴인데, 아마 프레젠테이션을 귀엽게 프레지라고 줄여 이름지은 것 같다. 아래 슬라이드를 한 번 봅시다. (more메뉴에서 autoplay하면 편합니다.)&lt;/p&gt;
&lt;p&gt;&lt;object id="prezi_xvl9cndahfed" name="prezi_xvl9cndahfed" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="550" height="400"&gt; &lt;param name="movie" value="http://prezi.com/bin/preziloader.swf"/&gt;  &lt;param name="allowfullscreen" value="true"/&gt;  &lt;param name="allowscriptaccess" value="always"/&gt;  &lt;param name="bgcolor" value="#ffffff"/&gt;  &lt;param name="flashvars" value="prezi_id=xvl9cndahfed&amp;amp;lock_to_path=1&amp;amp;color=ffffff&amp;amp;autoplay=no"/&gt;  &lt;embed id="preziEmbed_xvl9cndahfed" name="preziEmbed_xvl9cndahfed" src="http://prezi.com/bin/preziloader.swf" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="550" height="400" bgcolor="#ffffff" flashvars="prezi_id=xvl9cndahfed&amp;amp;lock_to_path=1&amp;amp;color=ffffff&amp;amp;autoplay=no"&gt; &lt;/embed&gt; &lt;/object&gt; &lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;단순한 그림과 텍스트만으로 만든 슬라이드지만 지루하지 않다. 프레지로 이런 슬라이드를 쉽게 만들 수 있다. 만든 걸 웹에서 쉽게 공유할 수도 있고, 맥이나 윈도우용 실행파일로 다운로드 할 수도 있어 활용도가 높다. 가입할 때 보여주는 3분짜리 튜토리얼 비디오만으로 사용법을 익힐수 있다. 편집 화면에서 단축키와 마우스 휠을 이용한 확대/축소를 지원해 무지 편하다.&lt;/p&gt;
&lt;p&gt;아, 뭐랄까. 참 나무랄데 없는 서비스다.&lt;/p&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-94-0" class="entry-ccl-by" src="http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-fr/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-fr/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=RUokXPL0RtY:1lNzoIiTpbo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=RUokXPL0RtY:1lNzoIiTpbo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=RUokXPL0RtY:1lNzoIiTpbo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/RUokXPL0RtY" height="1" width="1"/&gt;</description>
			<category>presentation</category>
			<category>prezi</category>
			<category>slide</category>
			<category>프레지</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/94</guid>
			<comments>http://hardworker.tistory.com/94#entry94comment</comments>
			<pubDate>Sat, 30 Jan 2010 11:46:58 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/94</feedburner:origLink></item>
		<item>
			<title>김우현님이 쓴 "맵리듀스 논쟁과 Schema-Free"</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/AeUsSjDtKb4/95</link>
			<description>&lt;p&gt;기웃거렸던 관심사들에 대해 &lt;a href="http://hardworker.tistory.com/54" target="_blank" title="[http://hardworker.tistory.com/54]로 이동합니다."&gt;요즘 뒤적거린 것들&lt;/a&gt;에 끄적거렸었다. 깊은 내용은 하나도 없고 이런게 다 있구나 하는 얘기들이었는데, 어쨌든 관심이 있다보니 같은 주제의 다른 글들도 눈에 들어오고 그러는데 어제 맵리듀스 뿐 아니라 key-value, document oriented databases류에 대한 최근의 동향을 잘 설명한 글을 읽었기에 소개한다.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.naver.com/wisereign/30079453619" target="_blank" title="[http://blog.naver.com/wisereign/30079453619]로 이동합니다."&gt;http://blog.naver.com/wisereign/30079453619&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;이분&amp;nbsp;&lt;a href="http://dev.naver.com/projects/coord" target="_blank" title="[http://dev.naver.com/projects/coord]로 이동합니다."&gt;http://dev.naver.com/projects/coord&lt;/a&gt;도 개발하시던데.&lt;/p&gt;
&lt;p&gt;사실 내가 하던 일은 이 분야랑 직접 관련되진 않았었다. 굳이 관련이라면 동영상 서비스 때문에 큰 스토리지가 필요하긴 했었는데 SAS 하나로 .. 그러니까 하드웨어로 해결하면 되는 수준이었다. 그런데 몸담았던 회사는 지속적 성장을 위해 플랫폼에 관심을 가져야 한다고 나는 생각했었다. 천만 단위의 레코드가 너무 많다고 걱정해서는 그저그런 수준에 머물 수밖에 없으니까. 그리고 최근의 업계는 단지 레코드 수가 많아서가 아니라, 꽤 많은 데이터를 서로 연관해서 처리하기 때문에 저장된 데이터량이 아니라 처리할 데이터량이 뻥튀기되는 문제에 직면한 것 아닌가.&lt;/p&gt;
&lt;p&gt;암튼 국내에서는, 필요에 의해 네이버, 다음 등이 대용량 플랫폼에 많은 관심을 가지고 있고 BI분야에서도 역시 관심이 있고 그런 모양이다. 지마켓같은덴 어떻게 하고있나 모르겠다. 옥션은 엄청 빵빵한 DB서버 갖고있다고 되게 자랑스러워하던데. 아마존이란 회사가 왜 S3나 EC2같은 플랫폼 서비스를 하는지를 고민해야 한다. 걔들은 개발팀이 시간남아서, 심심해서 만든걸로 사업하나? 그래. 아마존보다 이베이가 돈 많이 벌지. 그런데 이베이는 그냥 이베이잖아. 킨들도 없고. 혁신도 없고.&lt;/p&gt;
&lt;p&gt;지금 하는 사업 하기에도 바쁘겠지. 지금도 개발할 게 산더미고. 성장하고 있고. 그런데 그러다가 iPhone같은, 게임의 룰을 바꾸는 넘이 나타나면 급 당황하는 것 아니겠나. 딱 한 모델밖에 없는 애플에 삼성이 긴장해야 하다니. 위의 맵리듀스 논쟁에서도 비슷한 흐름이 읽힌다.&lt;/p&gt;
&lt;p&gt;음. 감놔라 배놔라 할 때가 아니지. 내 코가 석 자.&lt;/p&gt;&lt;div class="entry-ccl" style="clear: both; text-align: right; margin-bottom: 10px"&gt;
	&lt;img id="ccl-icon-95-0" class="entry-ccl-by" src="http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png" alt="저작자 표시"/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"&gt;
		&lt;Work rdf:about=""&gt;
			&lt;license rdf:resource="http://creativecommons.org/licenses/by-fr/2.0/kr/" /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about="http://creativecommons.org/licenses/by-fr/"&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Reproduction"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/Distribution"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Notice"/&gt;
			&lt;requires rdf:resource="http://web.resource.org/cc/Attribution"/&gt;
			&lt;permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=AeUsSjDtKb4:-ZQdRo5B5WU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=AeUsSjDtKb4:-ZQdRo5B5WU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=AeUsSjDtKb4:-ZQdRo5B5WU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/AeUsSjDtKb4" height="1" width="1"/&gt;</description>
			<category>신기술,분석</category>
			<category>Hadoop</category>
			<category>MapReduce</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/95</guid>
			<comments>http://hardworker.tistory.com/95#entry95comment</comments>
			<pubDate>Sat, 30 Jan 2010 11:30:43 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/95</feedburner:origLink></item>
		<item>
			<title>CSS는 잊자.</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/8x3EBhSuYx8/92</link>
			<description>요즘 별로 CSS 코딩할 일이 없다. 옛날엔 이미지 한 장 받아서 픽셀퍼펙트로 코딩하고 그랬지만 그거 안 한지도 한참 됐고. 하고있는 프로젝트는 (얼굴도 모르지만) HTML/CSS만 해주는 사람이 있어 좀 편하다. 뭐, 그래도 결국 내가 손봐야 할 게 있지만. 암튼, 그러다보니 가물가물한 속성도 많고 그렇다.&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
그런데 꼭 내가 이것저것 까먹어서가 아니라, 이제 정말로 나 CSS 안다고 하면 안되겠더라. 얼마전에 페이지 디자인을 받았는데 글씨가 기울어지에 표현된 부분이 있어서 "어 이건 안될텐데"라고 했었는데, CSS guy가 -webkit-transform:rotate(5deg); 뭐 이렇게 해서 돌려놨더라.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
예전에는 순수한 웹(X/HTML, CSS, Javascript)으로 구현 할 수 있는거랑 아닌거랑 구별이 확실했는데 말이지. 이제는 자바스크립트 프레임웍들도 대중화됐고 (처음 Prototype.js나 Script.aculo.us 나왔을 땐 Fade-out만 봐도 ㅎㄷㄷ했는데) 웹페이지에서 채팅 하는것도 당연하고 (옛날엔 자바 애플릿으로나) 유튜브가 HTML5 video tag로 비디오 튼다 해도 얼~ 하는 정도지 뭐 신기하거나 그런 기분은 안 드니까. 둥근 모서리의 박스나 그림자 같은 효과때문에 삽질했던 프로젝트가 엊그제 같은데 CSS3에서 이런 건 식상한 주제에 속한다. 구글 봐라. 애플이 구글보이스 앱 거절하니 웹으로 해버렸잖아. 아래 예제를 보신 후에 말씀 계속 나누시죠. (구글 크롬이나 사파리로 보세요.)&lt;/div&gt;
&lt;div&gt;
&lt;div class="imageblock dual" style="text-align: center;"&gt;&lt;table cellspacing="5" cellpadding="0" border="0" style="margin: 0 auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://cfile22.uf.tistory.com/original/173DD3024B6135493A15BC" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile22.uf.tistory.com/image/173DD3024B6135493A15BC" alt="" height="186" width="290"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;LP가 굴러나온다.&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;a href="http://cfile25.uf.tistory.com/original/204B98024B613550171308" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile25.uf.tistory.com/image/204B98024B613550171308" alt="" height="177" width="290"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;폴라로이드 스타일의 사진이 확대된다.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;&lt;a href="http://www.zurb.com/playground/css3-polaroids" target="_blank" title="[http://www.zurb.com/playground/css3-polaroids]로 이동합니다."&gt;http://www.zurb.com/playground/css3-polaroids&lt;/a&gt;&amp;nbsp;: 기울어진 사진들 그리고 hover시 스르륵 확대되는게 포인트.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zurb.com/playground/sliding-vinyl" target="_blank" title="[http://www.zurb.com/playground/sliding-vinyl]로 이동합니다."&gt;http://www.zurb.com/playground/sliding-vinyl&lt;/a&gt;&amp;nbsp;: 앨범에 hover하면 굴러나오는 LP판이 포인트.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;a href="http://www.smashingmagazine.com/2010/01/25/the-new-hotness-using-css3-visual-effects/" target="_blank" title="[http://www.smashingmagazine.com/2010/01/25/the-new-hotness-using-css3-visual-effects/]로 이동합니다."&gt;http://www.smashingmagazine.com/2010/01/25/the-new-hotness-using-css3-visual-effects/&lt;/a&gt;에서 뭘 어떻게 한건지 배울 수 있다. 그래, 나도 알고 있어요. 모든 브라우저에서 되는 건 아니라는 것. 솔직히 나도 어느 속성이 CSS3에 속하는지 아닌지 다 모르겠다. 하지만 분명한 CSS가 엄청 강력하고 또 복잡해지고 있다는거다. 이제야 테이블 기반의 레이아웃 졸업했다고 내심 자랑스러워하는 당신, 보시다시피 배움은 끝이 없다오. "웹표준으로 둥근 모서리 만들기" 이딴거 이제 잊어야 한다.&amp;nbsp;CSS는 잊어야 한다. CSS3가 코 앞에 있으니.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
----&lt;/div&gt;
&lt;div&gt;추가. 요즘 HOT! 한 CSS 활용예들 몇 개 더.&lt;/div&gt;
&lt;div&gt;&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;&lt;a href="http://www.romancortes.com/blog/pure-css-coke-can/" target="_blank" title="[http://www.romancortes.com/blog/pure-css-coke-can/]로 이동합니다."&gt;http://www.romancortes.com/blog/pure-css-coke-can/&lt;/a&gt; 가로 스크롤&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.apple.com/kr/ipad/gallery/" target="_blank" title="[http://www.apple.com/kr/ipad/gallery/]로 이동합니다."&gt;http://www.apple.com/kr/ipad/gallery/&lt;/a&gt; 아래 목록에서 360도 클릭하고 iPad 드래그.&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;
한국의 웹사이트는 플래시 아니면 움직이는 GIF 이상의 상상력을 발휘하지 못하고 있는 것 같다. CSS로도 할 수 있으니까 구현한다 이런 개념이 아니라 보는 사람도 편하고 만드는 사람도 뭘 보여주고 싶은지를 더 정확하게 보여줄 수 있는 방법으로서 CSS와 표준 웹 기술을 고려해야겠다. 제품의 실물 크기를 보시려면 이것 받아서 까시구요, 열어놨던 브라우저 창 다 닫으시고 처음부터 새로 찾아오세요 - 이런거 너무 촌스럽잖아. 우아하지 않잖아. 그래 예전엔 환경이 안 받쳐줬다. 그런데 이제 무르익고 있으니까.&lt;/div&gt;
&lt;/div&gt;
&lt;meta charset="utf-8"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=8x3EBhSuYx8:tAtVzH5V350:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=8x3EBhSuYx8:tAtVzH5V350:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=8x3EBhSuYx8:tAtVzH5V350:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/8x3EBhSuYx8" height="1" width="1"/&gt;</description>
			<category>신기술,분석</category>
			<category>CSS</category>
			<category>CSS3</category>
			<category>Web Standards</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/92</guid>
			<comments>http://hardworker.tistory.com/92#entry92comment</comments>
			<pubDate>Thu, 28 Jan 2010 13:39:46 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/92</feedburner:origLink></item>
		<item>
			<title>조엘 스폴스키의 "Why testers?"</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/qqk-KfCX_Ic/91</link>
			<description>&lt;div&gt;
조엘 스폴스키가 자기 블로그에 테스터에 관한 글을 올렸는데, 마침 지인 중 테스터 일을 고려하는 이가 있어 옮겨본다. 조엘온소프트웨어 블로그에 번역용 위키도 있는 걸 보니 허락 안 받고 번역해도 될 것 같기는 한데 -_- 아이고 모르겠다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
원문 : &lt;a href="http://www.joelonsoftware.com/items/2010/01/26.html" target="_blank" title="[http://www.joelonsoftware.com/items/2010/01/26.html]로 이동합니다."&gt;http://www.joelonsoftware.com/items/2010/01/26.html&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Why testers? by Joel Spolsky Tuesday, January 26, 2010&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;My sister got her kids a little puppy, and they’ve been trying to train it. To live with a dog in the house, you need to teach it not to jump on people, not to poop in the house, to sit on command, and to never, ever, ever chew on the iPad. Never. Good girl.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
여동생이 아이들에게 작은 멍멍이를 선물했다. 그리고 훈련시키는 중이다. 개를 집 안에서 기르려면 사람한테 뛰어오르지 않도록, 집 안에 똥싸지 않도록, 명령하면 앉도록 그리고 절대 절대 iPad를 물어뜯지 않도록 가르쳐야 한다. 절대. 착하지-&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;With dogs the main trick to training is that feedback has to be immediate. If you come home to discover that, hours before, the dog tipped over the garbage can in the kitchen, it’s too late for training. You can yell at her but she just won’t get what you’re going on about. Dogs are just not that smart.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
개를 잘 가르치려면 피드백을 즉시 줘야한다. 집에 와서 몇 시간 전에 개가 부엌에 뒤집어놓은 &amp;nbsp;쓰레기통을 발견해도 가르치기엔 너무 늦었다. 개를 혼내더라도 뭣때문에 그러는지 모를거다. 개들은 그렇게 똑똑하지 않으니까.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;For programmers, getting better at what you do requires quick feedback, positive and negative, on what you’ve just done. The faster you get the feedback, the faster you’ll learn. With long-cycle shrinkwrap software, it can take a year or more to hear feedback from customers.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
프로그래머가 성장하려면 긍정적이든 부정적이든 빠른 피드백이 필요하다. 피드백이 빠를수록 빨리 배울거다. 싸이클이 긴 패키지 소프트웨어(투명 비닐에 싸인)의 경우 고객으로부터의 피드백을 받는데 일 년이나 더 오래 걸릴 수도 있다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;That’s one of the reasons we have testers. A great tester gives programmers immediate feedback on what they did right and what they did wrong. Believe it or not, one of the most valuable features of a tester is providing positive reinforcement. There is no better way to improve a programmer’s morale, happiness, and subjective sense of well-being than a La &lt;s&gt;Marzocco Linea espresso machine&lt;/s&gt; to have dedicated testers who get frequent releases from the developers, try them out, and give negative and positive feedback. Otherwise it’s depressing to be a programmer. Here I am, typing away, writing all this awesome code, and nobody cares. Boo hoo.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
그게 바로 테스터가 필요한 이유다. 훌륭한 테스터는 프로그래머가 잘했는지 잘못했는지에 대해 즉시 피드백을 준다. 믿거나 말거나, 테스터의 가장 중요한 역할 중 하나는 긍정적인 reinforcement를 제공하는거다. 개발자에게 자주 릴리스받아 테스트하고 긍정/부정적인 반응을 주는 테스터야말로 좋은 에스프레소 머신보다 프로그래머를 자신감있고 행복하게 해준다. 이런게 없이 프로그래머가 된다는 건 우울한 일이다. 열라게 코딩해서 죽여주는 코드를 짰는데 아무도 신경을 안 쓴다면. 지못미 T-T&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;Who should be a tester? That’s tricky! Software testing is one of those careers that isn’t that well known, so a lot of people who would be great at testing and would probably enjoy it a lot never consider applying for jobs as testers.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
누가 테스터가 되어야 하나? 쉽지 않다. 소프트웨어 테스팅은 잘 알려지지 않은 분야 중 하나이고, 그래서 훌륭한 테스터가 되어 일을 즐길 수 있는 많은 사람들이 테스터로서의 경력을 고려해보지조차 않는다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Signs of a good tester:&lt;/div&gt;
&lt;div&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;Scientific&lt;/li&gt;
&lt;li&gt;Loves a good puzzle, even the kind that takes days to solve&lt;/li&gt;
&lt;li&gt;Likes to think about things methodically&lt;/li&gt;
&lt;li&gt;Generally likes working with software and computers&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
좋은 테스터의 징후:&lt;/div&gt;
&lt;div&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;과학적이다.&lt;/li&gt;
&lt;li&gt;퍼즐(문제 해결)를 좋아한다. 그걸 푸는데 몇 일 걸리더라도.&lt;/li&gt;
&lt;li&gt;조직적(구조적)으로 생각하길 좋아한다.&lt;/li&gt;
&lt;li&gt;컴퓨터나 소프트웨어로 일하는 걸 좋아한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;You don’t have to be a programmer to be a tester. A lot of companies want testers to be programmers who write automated test suites. It seems more efficient that way. This reflects a misunderstanding of what testers are supposed to do, which is evaluate new code, find the good things, find the bad things, and give positive and negative reinforcement to the developers. Sure, automated test suites are a time saver, but testing software covers so much more than that. If you put too much emphasis on those scripts, you won’t notice misaligned text, hostile user interfaces, bad color choices, and inconsistency. Worse, you’ll have a culture of testers frantically working to get their own code working, which crowds out what you need them to do: evaluate someone else’s code.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
테스터가 되기 위해 프로그래머가 될 필요는 없다. 많은 회사들이 테스터가 자동화 테스트도구를 작성할 수 있는 프로그래머쯤 되기를 바란다. 더 효율적인 방법일지도 모른다. (하지만) 이건 테스터가 뭘 해야하는지에 대한 오해를 반영한다. 바로 새 코드를 평가하고, 좋은 점을 찾고, 나쁜 점을 찾아 개발자에게 긍정적인 영향을 주는 것 말이다. 그래, 자동화된 테스트는 시간을 절약해주지. 하지만 소프트웨어를 테스트한다는 건 그 이상의 무엇이다. 자동화 테스트에 너무 정력을 쏟으면 어긋난 텍스트나 어색한 UI, 잘못된 색상이나 불안정함 같은 것들을 놓치게 된다. 최악의 경우 테스터들이 그들이 진짜 해야하는 일 - 다른 사람의 코드를 평가하기 - 을 잊은 채 자기 코드가 동작하도록 만드려고 노심초사하는 모습을 보게 될 걸?&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;A particularly terrible idea is to offer testing jobs to the programmers who apply for jobs at your company and aren’t good enough to be programmers. Testers don’t have to be programmers, but if you spend long enough acting like a tester is just an incompetent programmer, eventually you’re building a team of incompetent programmers, not a team of competent testers. Since testing can be taught on the job, but general intelligence can’t, you really need very smart people as testers, even if they don’t have relevant experience. Many of the best testers I’ve worked with didn’t even realize they wanted to be testers until someone offered them the job.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
특히 프로그래머로 지원한 사람들 중에 좀 부족해 보이는 사람에게 테스터 일을 제안하는 건 끔찍한 아이디어다. 테스터가 프로그래머여야 할 필요는 없지만, 만약 테스터들을 계속 실력없는 프로그래머로 취급한다면 결국 좋은 테스터가 아니라 실력없는 프로그래머들을 얻게 될거다. 테스팅은 일하면서 배울 수 있지만 지능(;; general inteligence)은 아니다. 그래서 테스터는, 혹시 관련 경력이 없더라도 굉장히 스마트해야 한다. 내가 같이 일해본 최고의 테스터들 중에는 누군가 그 일을 제안하기 전에는 자신이 테스터가 되고싶어하는지도 자각하지 못했던 이들이 많았다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;If you:&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;Love software and computers&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;Want to work on a software team, and&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;Don’t particularly like programming&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#8E8E8E"&gt;you should consider being a tester. (We’re hiring! What a coincidence!)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
만약 당신이:&lt;/div&gt;
&lt;div&gt;
소프트웨어와 컴퓨터를 좋아하고&lt;/div&gt;
&lt;div&gt;
소프트웨어 팀(회사)에서 일하고 싶고&lt;/div&gt;
&lt;div&gt;
하지만 꼭 프로그래머가 되고싶은 건 아니라면&lt;/div&gt;
&lt;div&gt;
테스터가 되는 걸 고려해보라. (우연히 우리도 테스터를 구하고 있네?!)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
----&lt;/div&gt;
&lt;div&gt;
결론은 나도 테스터 있는데서 일 해보고 싶다.&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=qqk-KfCX_Ic:W39iK1EOIPY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=qqk-KfCX_Ic:W39iK1EOIPY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=qqk-KfCX_Ic:W39iK1EOIPY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/qqk-KfCX_Ic" height="1" width="1"/&gt;</description>
			<category>학습자료, 추천사이트</category>
			<category>Joel Spolsky</category>
			<category>software testing</category>
			<category>tester</category>
			<category>테스터</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/91</guid>
			<comments>http://hardworker.tistory.com/91#entry91comment</comments>
			<pubDate>Thu, 28 Jan 2010 12:37:46 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/91</feedburner:origLink></item>
		<item>
			<title>Mocking-up? Wireframing?</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/9mYF0hhF2yA/90</link>
			<description>Mock-up은 한국에서는 잘 안 쓰는 말인 것 같다. 와이어프레임이란 말은 꽤 많이들 쓰는데, 내가 다니던 회사에선 그냥 '기획안'이나 '화면' 보자고 했다. 김사장님의 훈시에 따라 그 이름도 찬란한 훈민정음(무려 정품 구매)으로 기획안을 그려야 했던 기획자들, 그리고 그걸 보려고 훈민정음 리더를 설치해야 했던 개발자들에게 영광이 있으라!&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
글을 쓸 때 삼천포로 빠지려는 미지의 힘이 항상 작용하기 때문에 문단을 자주 바꿔줘야 한다. 암튼 기획이라는게 엄청 범위가 넓은데다 나는 그쪽에 전문가도 아니니까 너무 많이 아는척을 하면 안되겠지만, 이것만큼은 말할 수 있다. 기획을 얼마나 자세하게 해야 하는지, 어떤 방법이나 도구를 써야 하는지는 상황에 따라 늘 다르다는거. 안다. 너무 뻔한 얘기다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
모킹업(Mocking-up), 와이어프레이밍(Wireframing), 프로토타이핑(Prototyping)같은 말들은 그 용어 자체만으로도 서로 미묘하게 다른 작업을 나타낸다. 게다가 모든 단어라는게, 모두가 각자의 개념을 살짝 다르게 가지고 있다는 걸 감안하면 이 작업이 얼마나 어려울지 상상해볼 수 있다. 쉬운 예로 개발자는 '아니 이만큼은 기획에서 해줘야지'라고 생각을 하고 디자이너는 기획안에 표현되지 않은, 하지만 합의되어야 할 부분을 나름의 상상력으로 채워넣는다. (그게 디자이너의 일이지.) 기획자 역시 '아니, 전화번호 입력폼은 당연이 XXX해야하는거 아냐?'라고 생각하고 거기까지는 내 몫이 아니라 생각할 테다. 이런게 서로 합의되지 않으면 기획안 할애비를 갖다줘도 씨알이 안 맥힐테다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
다시 강조하지만 정해진 방법론이 딱 있는 곳이나 엄청 큰 프로젝트는, 나는 잘 모르겠다. 그런데 내가 그 동안 개발자로 벌어먹으며 느낀건데, 목업이라 부르던 와이어프레임이라 부르던 간에 혹은 이것들을 다 포함하는 좀 더 넓은 의미의 '기획'이건 간에 - 이걸 전문적으로 가르치고 배울 수 있는 곳이 없는 것 같다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
웹이나 애플리케이션 디자인을 가르치는 대학이 있나? 요즘은 있을지도 모르겠다만, 실제 필드에서 디자이너나 개발자, 혹은 디자이너나 개발자 출신의 기획자가 기획업무를 하곤 하는데 내가 다닌 학교에서는 공대나 미대의 어느 과정도 웹페이지나 애플리케이션의 UI에 대해 가르치지 않았더라. 웹으로 범위를 좁혀보면, 컴공에서도 웹을 배우고 산디과 같은데서도 배우지만 기술과 미술을 조화롭게 하는 - 바로 '기획'의 범주에 들어가는 기술은 배우지 않더라는 말이다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
컨버전스니 뭐니 해서 경계도 희미해져가는데다 좁고 깊은 전문성도 필요하지만 널리 통찰하는 안목이 중요한 시기다. 개발자 혼자 기획부터 디자인과 개발, 배포까지 가능한 세상이다. 아이디어가 있으면 (아 돈도 좀) 그걸 실현해줄 사람도 기술도 드물지 않은 세상이다. 모든게 사람의 일이라 좋은 사람, 능력있는 사람이 함께해야 하는 건 만고불변의 진리지만, 기왕 일을 할 때 말이다 - 연장이 좋으면 몸도 마음도 편하다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
여하튼 훈민정음 아니면 안 된다는 김사장부터, 파워포인트에 맑은고딕과 핑크빛 테마를 입히지 않으면 일이 안 된다는 기획자 강씨. 디자이너 Y는 일단 포토샵부터 띄워야 뭐가 된다. 화이트보드에 그리고 디카로 찍어 공유하기를 즐기는 이도 있고. 어떤 책에는 종이로 프로토타이핑 하라 하고(그러니까 &lt;a href="http://www.uistencils.com/collections/frontpage/products/browser-sketch-pad" target="_blank" title="[http://www.uistencils.com/collections/frontpage/products/browser-sketch-pad]로 이동합니다."&gt;이런 노트&lt;/a&gt;도 나오지) .. 취향은 가지 각색이다. 도구야 자기 손에 편한게 좋기는 하지만 이게 그냥 망치로 벽에 못박는 일보다는 좀 더 복잡한 구석이 있어서 (지식노동이잖나) 몇 가지는 생각을 해보는게 좋을 것 같다.&lt;/div&gt;
&lt;div&gt;
&lt;ol style="list-style-type: upper-alpha; "&gt;
&lt;li&gt;디테일이 필요한 만큼은 표현이 되야한다.&lt;br /&gt;
이게 버튼인지 아닌지, 이 영역은 스크롤되는건지 아닌지 이런 건 좀 중요하다. 그래서 기본적인 UI콤포넌트는 표현이 되주는게 좋다.&lt;/li&gt;
&lt;li&gt;언제든지 수정될 수 있다.&lt;br /&gt;
일을 하다보면 기획안이야 자꾸 바뀌는거잖나. 왼쪽메뉴에 뭐 하나 바꿨다고 30페이지에 있는걸 일일이 고칠텐가? 손이 빠르다고 해도 실수까지 피하기는 어렵다.&lt;/li&gt;
&lt;li&gt;그림만으로 표현되지 않는게 있다.&lt;br /&gt;
때론 글로 설명해야 할 때도 있다. 물론 기획단계의 문서가 다른 것들도 있겠지만.&lt;/li&gt;
&lt;li&gt;때로는 "실제로 동작하는 것"이 중요하다.&lt;br /&gt;
애니메이션이 있다던가, 동적으로 페이지 일부가 갱신되는(Ajax) 경우 2D만으로는 부족하다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt;
내 모든 경험을 통해 얻은 진리까지는 아니고... 글 쓰다 생각나는대로 적어봤다. 중요한게 더 있을텐데, 각자 생각나시는 것 댓글로 남겨주세요^^ 댓글 남겨주신 분 중 추첨을 통해 iPhone 3GS 32Gb White를 드리지는 못하지만.
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
글이 좀 장황해졌는데, 이 글의 발아점은 &lt;a href="http://gomockingbird.com/" target="_blank" title="[http://gomockingbird.com/]로 이동합니다."&gt;Mocking Bird&lt;/a&gt;라는 웹기반 와이어프레이밍 툴? 서비스?라고 할 수 있다. 전에도 비슷한 서비스를 몇 개 봤는데 대개는 Flash 기반으로 사용성이 그닥 별로였다. (나는 따로 노는듯한 플래시의 느낌이 별로) 그런데 이 목킹버드는 뭔가 다르다 싶더니 &lt;a href="http://cappuccino.org/" target="_blank" title="[http://cappuccino.org/]로 이동합니다."&gt;Cappuccino&lt;/a&gt;라는 Javascript 기반의 GUI Framework을 썼더라고. 미투데이에도 간단하게 적었었지만 이 카푸치노가 &lt;a href="http://me2day.net/sanghyun/2010/01/25#00:47:09" target="_blank" title="[http://me2day.net/sanghyun/2010/01/25#00:47:09]로 이동합니다."&gt;Mobile Safari&lt;/a&gt;에서도 잘 돌아가더라. 안그래도 구글이 애플에서 거절당한 구글보이스 앱을 웹 버전으로(HTML5) 내놨던데 허허 참. 이제 아이폰 앱 만드려고 맥 안 사도 되겠어요. 그냥 웹-앱으로 만들어버려.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
아 또 좀 샜네요. 암튼 Mocking Bird를 만지작거리다 보니 예전에 윈도용으로 써봤던 &lt;a href="http://www.axure.com/" target="_blank" title="[http://www.axure.com/]로 이동합니다."&gt;Axure&lt;/a&gt;가 떠올랐다. Axure의 모토가 &amp;nbsp;"Wireframes, Prototypes, Specifications"인데, 정말로 와이어프레임부터 동작되는 프로토타입, 그리고 스펙 워드문서까지 뽑아주는 옹골찬 녀석이다. 이번에 맥용으로 &lt;a href="http://axure.com/CS/blogs/axure/archive/2009/12/22/6104.aspx" target="_blank" title="[http://axure.com/CS/blogs/axure/archive/2009/12/22/6104.aspx]로 이동합니다."&gt;MAxure 알파버전&lt;/a&gt;이 나왔다. (&lt;a href="http://www.axureformac.com/" target="_blank" title="[http://www.axureformac.com/]로 이동합니다."&gt;여기&lt;/a&gt;도 참고)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Axure는 내가 아는 범위에선 제일 좋은 툴인데, 뭐랄까. 이것도 부족하면 뭘 더 바라나? 하는 정도랄까. DB연동까지 되면 좋겠다... 고 생각하면 이게 완전 개발툴이 되버리겠지. 각종 UI콤포넌트는 기본이고, 상단메뉴나 Footer부분만 따로 정의해서 각 화면에 붙어넣을 수 있다. 각 입력폼에도 제약사항을 입력해두면 나중에 워드문서같은걸로 일목요연하게 표현해주고. 또 이렇게 만든 화면을 HTML Prototype으로 만들어주니 모아놓고 데모한번 할 때 간지가 작살이다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile9.uf.tistory.com/original/20142E224B5F95BE5F35CD" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile9.uf.tistory.com/image/20142E224B5F95BE5F35CD" alt="" filemime="" filename="cfile9.uf@20142E224B5F95BE5F35CD.png" height="356" width="450"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;iPhone mockup&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
그런데 닭 잡을때 소 잡는 칼 쓸 이유는 없으니까. (물론 쓰고싶으면 써도 된다.) 두어 페이지만 만들면 되거나, 혼자 생각을 정리하고 싶을 수도 있고. &lt;a href="http://speckyboy.com/2010/01/11/10-completely-free-wireframe-and-mockup-applications/" target="_blank" title="[http://speckyboy.com/2010/01/11/10-completely-free-wireframe-and-mockup-applications/]로 이동합니다."&gt;열개의 완전 공짜 목업, 와이어프레이밍 툴&lt;/a&gt;을 살펴보자. 웹 기반이거나 무료이거나 암튼 가볍게 써볼 수 있는 툴들이 소개되어있다. MockFlow같은 건 웹 기반(플래시)이면서 실시간 공유까지 가능한가보다. iPhone mockup도 실시간 공유가 가능하며 아이폰 앱을 위한 와이어프레임을 그려볼 수 있다. 저기에 소개되진 않았지만 내가 소개하고픈 서비스가 있는데 바로 발사믹(Balsamiq)이란거다. 플래시 기반의 웹 버전이나 AIR를 사용한 데스크탑 버전을 고를 수 있다. 제공되는 콤포넌트들이 정겨우면서도 풍부하다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile27.uf.tistory.com/original/157753234B5F98ED5A8110" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile27.uf.tistory.com/image/157753234B5F98ED5A8110" alt="" filemime="" filename="cfile27.uf@157753234B5F98ED5A8110.png" height="361" width="450"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;Balsamiq&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
목수 연장 나무란다는 말이 뜻하는 바도 모르는 것은 아니나 도구와 생산성이 무관하지도 않다. 천재들은 머릿속에서 하나의 세계를 그려내겠지만 나는 이면지에 모나미 볼펜이라도 있어야 정리가 되더라. 위에 링크한 웹페이지에 유용한 다른 정보들도 많으니 참고들 하시고.&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
사족. 본문이랑 별 상관은 없는데 나는 글 쓰다보니 떠오른게 있다. 바로&amp;nbsp;&lt;a href="http://dotty.org/2698959" target="_blank" title="[http://dotty.org/2698959]로 이동합니다."&gt;http://dotty.org/2698959&lt;/a&gt; 이 블로그에서 소개한 '건축학교에서 배운 101가지'라는 책인데, 재밌다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div class="ttbReview"&gt;
&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;a href="http://www.aladdin.co.kr/shop/wproduct.aspx?ISBN=8972975621&amp;amp;ttbkey=ttbbs00481101006&amp;amp;COPYPaper=1"&gt;&lt;img src="http://image.aladdin.co.kr/cover/cover/8972975621_1.jpg" alt="" border="0"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=9mYF0hhF2yA:SvpJUePHCRg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=9mYF0hhF2yA:SvpJUePHCRg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=9mYF0hhF2yA:SvpJUePHCRg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/9mYF0hhF2yA" height="1" width="1"/&gt;</description>
			<category>학습자료, 추천사이트</category>
			<category>Mockup</category>
			<category>Prototyping</category>
			<category>wireframe</category>
			<category>목업</category>
			<category>와이어프레임</category>
			<category>프로토타이핑</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/90</guid>
			<comments>http://hardworker.tistory.com/90#entry90comment</comments>
			<pubDate>Wed, 27 Jan 2010 10:55:52 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/90</feedburner:origLink></item>
		<item>
			<title>HyperGraphDB</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/n_vrkoCuR5g/89</link>
			<description>&lt;font class="Apple-style-span" color="#333333" face="굴림"&gt;&lt;a href="http://www.kobrix.com/hgdb.jsp" target="_blank" title="[http://www.kobrix.com/hgdb.jsp]로 이동합니다."&gt;http://www.kobrix.com/hgdb.jsp&lt;/a&gt;&lt;/font&gt;&lt;div&gt;
&lt;font class="Apple-style-span" color="#333333" face="굴림"&gt;&lt;br /&gt;
&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" color="#333333" face="굴림"&gt;네네. 또 다른 비-관계형 데이터베이스입니다. 자세한 건 저도 잘 모릅니다만 기억을 위해 기록합니다. 정보 출처는 &lt;a href="http://highscalability.com/blog/2010/1/26/product-hypergraphdb-a-graph-database.html?utm_source=feedburner&amp;amp;utm_medium=feed&amp;amp;utm_campaign=Feed:+HighScalability+(High+Scalability)&amp;amp;utm_content=Google+Reader" target="_blank" title="[http://highscalability.com/blog/2010/1/26/product-hypergraphdb-a-graph-database.html?utm_source=feedburner&amp;amp;utm_medium=feed&amp;amp;utm_campaign=Feed:+HighScalability+(High+Scalability)&amp;amp;utm_content=Google+Reader]로 이동합니다."&gt;High Scalability blog&lt;/a&gt;. &amp;nbsp;&lt;a href="http://nosql-database.org/" target="_blank" title="[http://nosql-database.org/]로 이동합니다."&gt;http://nosql-database.org/&lt;/a&gt;에 더 많은 No-SQL databases 정보가 있어요.&lt;/font&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=n_vrkoCuR5g:56HxV6jW7SA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=n_vrkoCuR5g:56HxV6jW7SA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=n_vrkoCuR5g:56HxV6jW7SA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/n_vrkoCuR5g" height="1" width="1"/&gt;</description>
			<category>신기술,분석</category>
			<category>Database</category>
			<category>Hypergraphdb</category>
			<category>NoSQL</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/89</guid>
			<comments>http://hardworker.tistory.com/89#entry89comment</comments>
			<pubDate>Wed, 27 Jan 2010 08:22:39 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/89</feedburner:origLink></item>
		<item>
			<title>PHPer Rails 시승기 #2</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/9WXTkT-iEbY/88</link>
			<description>&lt;div&gt;
1편에 이어.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
앞서 Ruby와 Rails를 설치하고, 이걸 웹 서비스 할 수 있게 Apache 설정까지 마쳤다. 이쯤에서 내가 만드려는 프로그램이 어떤건지 약간 설명하는게 좋겠다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
바로 ... "뿐빠이"를 해주는 프로그램이다. 아무리 밥값 술값 서로 내려고 멱살까지 잡는 한국인이지만, 뿐빠이 하는게 뭔지는 다들 아시겠지요? N분의 1이라고도 하고 더치페이라고도 하고, 각자 낸다고도 하지요.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
근데 하필 왜 뿐빠이냐고? 이게 배경이 좀 있다. 여기에 처음 와서는 통장이 든 돈 까먹으며 지냈는데, 길가다 밥 한 그릇, 물 한 통 사먹을래도 손이 ㄷㄷㄷ거리더라. 그래서 가계부를 쓰기 시작했는데, 처음엔 iWork의 Numbers를 가지고 간단하게 만들어 썼다.&lt;/div&gt;
&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile10.uf.tistory.com/original/204B53194B5E46BF030757" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile10.uf.tistory.com/image/204B53194B5E46BF030757" alt="" filemime="" filename="expenditure.png" height="499" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
쓴 돈과 카테고리를 입력하면 월별 합계나 용도별 합계 정도를 볼 수 있는 간단한 챠트를 보여준다. Numbers가 워낙 끔찍하게 느리긴 한데, 그냥 참으면서 쓸 만큼은 되더라. 그런데 둘이 돈을 나눠내야 하는 경우가 자꾸 생기는거라. 이를테면 같이 차를 빌려서 어딜 갔다왔다던가. 수퍼마켓에서 잔뜩 샀는데 계산을 한꺼번에 했더라던가. 렌트는 내가 했으니 기름값은 니가 내고 밥은 저넘이 산다 이렇게 하는 방법도 있기는 한데, 여기선 다들 빠듯한 처지라 계산은 정확하게 하는게 좋겠더라. 그리고 여러가지를 산 다음에 돈을 나눌때도, 그냥 N빵으로 나누는 경우도 있지만 나만 쓸 물건이 섞여있거나 하면 골치가 아프지.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
암튼 이런 배경이 있기는 한데 처음부터 프로그램을 만든 건 아니고, 쓰던 Numbers sheet를 더 개선해서 한참을 썼더랬다. 그런데 Numbers가 워낙 느려서 하나하나 입력하다보면 뒷골이 땡겨오더라고. 그래서 하루 날을 잡고 PHP로 만들었던 거다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
시나리오는 ...&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;blockquote&gt;&lt;div&gt;
언제 어디서 쇼핑했는지 기록.&lt;/div&gt;
&lt;div&gt;
그 쇼핑에서 무엇무엇을 얼마얼마에 샀으며, 누구껀지 표시할 수도 있다.&lt;/div&gt;
&lt;div&gt;
다 입력했으면 누가 얼마 내야하는지 계산해주는데, 무조건 N빵이 아니라 얼만큼 내야할지 %로 정할 수 있다. 이를테면 나는 많이 먹으니까 60% 내고 너는 쪼금 먹으니까 40%만. 이런 식으로.&lt;/div&gt;
&lt;/blockquote&gt;&lt;div&gt;
일단 여기까지만 구현을 해 볼 참이다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
시 작.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
$ cd ~/Site&lt;/div&gt;
&lt;div&gt;
$ rails devel1 (아 이름 개성없다)&lt;/div&gt;
&lt;div&gt;
(rails 관련 파일이 devel1 디렉토리 안에 자동으로 생김)&lt;/div&gt;
&lt;div&gt;
$ cd devel1&lt;/div&gt;
&lt;div&gt;
(이제부터 여기가 RAILS_ROOT입니다.)&lt;/div&gt;
&lt;div&gt;
(웹브라우저로 http://devel1.local 열어보면 레일스 세팅됐다는 페이지가 뜬다. 이거 지우자.)&lt;/div&gt;
&lt;div&gt;
$ rm -f public/index.html&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
index를 지우고 나면 이 Rails app에는 아무것도 남는게 없다. 보여줄 게 없다. 뭘 좀 보여줘보자. RoR은 MVC 프레임웍이니까 뷰하고 컨트롤러를 하나씩 만들면 뭘 보여줄 수가 있다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
$ script/generate controller home index&lt;/div&gt;
&lt;div&gt;
( app/controllers/home_controller.rb&lt;/div&gt;
&lt;div&gt;
&amp;nbsp;&amp;nbsp;app/views/home/index.html.erb 이런 파일들이 생긴다.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
$ vim app/views/home/index.html.erb&lt;/div&gt;
&lt;div&gt;
[대충 Hello, World! 이런거 집어넣자]&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
http://devel1.local/home/index 페이지를 띄우면 위 내용이 보여야 한다. Rails는 기본적으로http://host/[controller]/[action] 형식으로 path를 사용한다. 이게 config/routes.rb 파일에 정의되어있는데, 같은 파일의 map.root에 원하는 컨트롤러를 지정해주면 그 컨트롤러의 index액션이 첫 페이지가 된다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
$ vim config/routes.rb&lt;/div&gt;
&lt;div&gt;
map.root :controller =&amp;gt; "home"&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
이제 http://devel1.local/ 에 Hello, World!가 보이면 된다.&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile9.uf.tistory.com/original/1224CA284B5E5A761AA3D4" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile9.uf.tistory.com/image/1224CA284B5E5A761AA3D4" alt="" filemime="image/png" filename="Screen shot 2010-01-26 at 1.58.10 PM.png" height="152" width="325"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
내가 생각해도 지금까지 올린 정보는 어디에나 다 나오는거라 재미가 없다. 아무 책이나 문서를 봐도 다 나온다. 자, 또 그럼 다음 시간에 계속.&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=9WXTkT-iEbY:bRwgpiNnaVM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=9WXTkT-iEbY:bRwgpiNnaVM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=9WXTkT-iEbY:bRwgpiNnaVM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/9WXTkT-iEbY" height="1" width="1"/&gt;</description>
			<category>RUBY</category>
			<category>ruby on rails</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/88</guid>
			<comments>http://hardworker.tistory.com/88#entry88comment</comments>
			<pubDate>Tue, 26 Jan 2010 12:00:42 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/88</feedburner:origLink></item>
		<item>
			<title>백악관, 드루팔 그리고 보안</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/5hkUn282was/86</link>
			<description>그렇다. 백악관이 Whitehouse.gov의 플랫폼으로 드루팔을 선택했다. IT업계의 많은 사람들이 오픈소스의 상징적 성공사례라 평가했다. 나도 긍정적이고. 그런데 다른 생각을 가진 사람들도 물론 있다. 하나 소개해본다.&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;a href="http://ha.ckers.org/blog/20091025/whitehouse-drupal-and-the-open-source-security-model/" target="_blank" title="[http://ha.ckers.org/blog/20091025/whitehouse-drupal-and-the-open-source-security-model/]로 이동합니다."&gt;http://ha.ckers.org/blog/20091025/whitehouse-drupal-and-the-open-source-security-model/&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
요점을 정리해보면 이렇다.&lt;/div&gt;
&lt;div&gt;
&lt;blockquote&gt;백악관이 오픈소스로 간다고? OSVDB에 12페이지의 취약점 목록이 있는 그 드루팔이다. 드루팔 창시자인 드라이스가 "정부가 오픈소스 소프트웨어가 독점 소프트웨어에 비해 더 위험하지 않다는 걸 인식했다는 분명한 신호다"라고 말했는데 이건 완전 잘못 생각한거다. 전문가도 아니면서 자기 보안지식이 진실이라 설파하는 건 위험하다. 소스코드 Line당 취약점 따위를 얘기하는거라면 동의할 수도 있다. 그런데 현실이 그런 식으로 돌아가는게 아니다. 오픈소스와 독점 소프트웨어의 큰 차이점이 있다. 나는 단 한개의 패킷도 백악관에 보내지 않으면서 하루종일 드루팔에 Pen-test(Penetration test, 공격을 시뮬레이션 해보는 것)를 할 수 있다. 만약 백악관이 누구나 다운로드할 수 있는 그 드루팔 소스코드를 사용한다면 그건 바보짓이다. 그리고 백악관이 커스터마이즈된 드루팔 변종을 쓰고있다면 그게 독점 소프트웨어와 뭐가 다른가?&lt;/blockquote&gt;&lt;/div&gt;
&lt;div&gt;
오픈소스 커뮤니티에서는 취약점이 노출되고 공개되고 빨리 고쳐지기 때문에 폐쇄 모델보다 더 안전할 수 있다고 말한다. 이는 분명 유효한 모델이기는 하지만 언제나 해피엔딩을 보장해주는 건 아니다. 한편 블로그의 저자는 심지어 "백악관이 채택한 건 드루팔이 아니라 Akamai(CDN서비스)"라고까지 깎아내리기도 하고, 또 어떤 사람은 OSVDB에 등록된 대부분의 취약점은 드루팔 코어가 아닌 모듈들의 것이라고 반박하기도 한다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
내 생각은? 드루팔 커뮤니티는 굉장히 역동적이다. 백악관 뿐 아니라 드루팔을 채택하는 대형 웹사이트가 늘어나고 있는 상황인데, 아무래도 유명해지만 공격도 더 받고 욕도 먹고 그러는거 아니겠나? 리눅스도 한때 치명적 익스플로잇이 공개되고 그랬는데 갈수록 잠잠해졌다. 유명하지 않으면 취약해도 별로 이슈가 안 된다. 유명하면 사소한 취약점도 치명적 사건으로 이어질 수 있다. 즉 유명해져야 더 완벽해질 기회도 가질 수 있다. 내 생각에 드루팔 커뮤니티는 이 기회를 놓치지 않을 저력이 있다.&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=5hkUn282was:PwugpiPxGTE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=5hkUn282was:PwugpiPxGTE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=5hkUn282was:PwugpiPxGTE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/5hkUn282was" height="1" width="1"/&gt;</description>
			<category>Drupal / 드루팔</category>
			<category>drupal</category>
			<category>Security</category>
			<category>WhiteHouse</category>
			<category>드루팔</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/86</guid>
			<comments>http://hardworker.tistory.com/86#entry86comment</comments>
			<pubDate>Sat, 23 Jan 2010 13:00:41 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/86</feedburner:origLink></item>
		<item>
			<title>PHPer Rails 시승기 #1</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/qyKttH2NF6Q/79</link>
			<description>2007년인가 8년인가 Ruby on Rails가 한창 인기몰던 시절, 호기심에 Hello, World 찍어보고 문법책 한 권 훑고는 소스 좀 읽어보고 하기는 했었다. 그런데 먹고사느라 PHP하기도 바쁘고 Ruby가 잡아먹는 허걱스런 CPU 자원에 당장 실전에 어떻게 해보긴 어렵겠다고 결론내렸었다. 당시 팀원들하고 Front-end는 PHP로 가되 (회사에서 인정하는게 PHP라서) 백엔드를 레일즈로 해볼까? 하는 얘기를 해보기도 했었지만 결국 이 프레임웍의 몇 가지 아이디어를 우리가 만들어 쓰던 프레임웍에 차용하는 정도로 만족했다.&lt;div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
암튼 요즘 놀고먹는 (짬짬이 일을 하긴 하지만) 처지라 자그마한 프로그램을 만들어볼 여유가 있었는데, 기왕이면 놀 때 새로운 언어를 익혀볼까 해서 이것저것 기웃거렸지만 손에 익은 PHP로 뚝딱거리게 되더라. 만들고 보니 나쁘진 않았는데 관성에 젖어 배움을 멀리했다는 죄책감에 휩싸이게 되더라(ㅋㅋ). 그래서 기왕 만든 건 Prototype이라 치고 Ruby on Rails로 다시 만들기로 맘먹었다.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
PHP로 뭘 할라치면 라이브러리, 프레임웍 이런거 없이 시작하는게 익숙한데 파이썬이나 루비같은 언어로 하려니 프레임웍 없이는 왠지 죄 짓는 기분이다. 프레임웍 쓰면 &lt;a href="http://rubyonrails.org/screencasts" target="_blank" title="[http://rubyonrails.org/screencasts]로 이동합니다."&gt;15분만에 블로그도 만들 수 있지만&lt;/a&gt;&amp;nbsp;(이 유명한 스크린캐스트는 고맙게도 최신 버전의 레일즈를 사용해 다시 만들어졌다.) 어쨋든 프레임웍을 익혀야 하니까 처음에 얼른 손이 안 가기는 한다. 그렇다고 바닥부터 코딩하면 시작이야 에디터 띄우면 바로 할 수 있지만 인증 넣고 설계도 약간 바꾸고 이러자면 머리가 딱딱 아프니까. 암튼 우리에겐 자유도 소중하지만 무한한 선택의 자유가 정신건강에 좋지 않을 수도 있다는 &lt;a href="http://www.ted.com/talks/barry_schwartz_on_the_paradox_of_choice.html" target="_blank" title="[http://www.ted.com/talks/barry_schwartz_on_the_paradox_of_choice.html]로 이동합니다."&gt;Barry Schwartz 박사님의 말씀&lt;/a&gt;에 따라 &lt;a href="http://en.wikipedia.org/wiki/Ruby_on_Rails#Philosophy_and_design" target="_blank" title="[http://en.wikipedia.org/wiki/Ruby_on_Rails#Philosophy_and_design]로 이동합니다."&gt;Convention over Configuration&lt;/a&gt;(설정보단 관례)을 주창하는 철길에 올라보기로 했다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
잡얘기가 좀 길어졌는데, 암튼 PHP로 만든 걸 다시 Rails로 옮기고, 더 나아가서 국가와 민족문화 창달에 이바지하기 위해 기능을 확장해볼 것이다. 레일즈는 꽤 잘 쓰여진 문서가 많아서 Ruby 문법에 까막눈인데도 해볼만 하다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
1. Snow Leopard에 Ruby on Rails 설정하기&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Leopard/Snow Leopard에는 레일즈가 번들되어있다. 그런데 나는 최신 버전을 쓰고 싶으므로 다음과 같이 했다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;
$ sudo mv /usr/bin/ruby /usr/bin/ruby.orig&lt;/div&gt;
&lt;div&gt;
$ sudo mv /usr/bin/gem /usr/bin/gem.orig&lt;/div&gt;
&lt;div&gt;
$ sudo mv /usr/bin/rails /usr/bin/rails.orig&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
$ sudo port install ruby rb-rubygems&lt;/div&gt;
&lt;div&gt;
$ sudo gem install rails&lt;/div&gt;
&lt;/blockquote&gt;&lt;div&gt;
&lt;/div&gt;
&lt;div&gt;
이제 레일즈 라이브러리가 설치됐다.
&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
&lt;meta charset="utf-8"&gt;&lt;div&gt;
3. Rails 프로젝트 디렉토리 만들기.&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;blockquote&gt;&lt;div&gt;
$ cd ~/Sites&lt;/div&gt;
&lt;div&gt;$ rails devel1&lt;/div&gt;
&lt;/blockquote&gt;&lt;div&gt;
이제 ~/Sites/devel1에 레일즈 웹 애플리케이션의 기본 골격이 만들어졌다.&lt;/div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;2. 웹서버 설정&lt;/div&gt;
&lt;div&gt;이걸 돌려보려면 웹서버가 있어야지. Webrick은 .. 죄송하지만 사양합니다. 한편 OS X Leopard에 딸려오는 XCode에 Rails 지원이 좀 있는데 여기서 Mongrel을 쓸 수도 있다. 그런데 난 Apache를 좋아하니까. mod_ruby에 해당하는 Phusion Passenger를 설치해보자.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
&lt;meta charset="utf-8"&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;blockquote&gt;&lt;div&gt;
&lt;div&gt;&lt;span style="font-family: Terminal; "&gt;&lt;span style="font-family: Terminal; "&gt;$ sudo gem install passenger&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family: Terminal; "&gt;&lt;span style="font-family: Terminal; "&gt;$ sudo passenger-install-apache2-module&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;span style="font-family: Terminal; "&gt;&lt;span style="font-family: Terminal; "&gt;$ sudo vim /etc/apache2/httpd.conf&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;meta charset="utf-8"&gt;&lt;div&gt;
&lt;span style="font-family: Terminal; "&gt;&lt;span style="font-family: Terminal; "&gt;LoadModule passenger_module /opt/local/lib/ruby/gems/1.8/gems/passenger-2.2.7/ext/apache2/mod_passenger.so&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family: Terminal; "&gt;&lt;span style="font-family: Terminal; "&gt;Include /private/etc/apache2/extra/httpd-passenger.conf&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;div&gt;
&lt;span style="font-family: Terminal; "&gt;&lt;span style="font-family: Terminal; "&gt;PassengerRoot /opt/local/lib/ruby/gems/1.8/gems/passenger-2.2.7&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family: Terminal; "&gt;&lt;span style="font-family: Terminal; "&gt;PassengerRuby /opt/local/bin/ruby&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/blockquote&gt;&lt;div&gt;
&lt;div&gt;&lt;div&gt;
이제 가상호스트를 설정할건데 손노가다로 하는 방법이 있고 Passenger Pref Pane이라는 GUI 툴로 하는 방법이 있다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
3-1.우선 손노가다&lt;/div&gt;
&lt;div&gt;&lt;div&gt;
&lt;blockquote&gt;$ sudo echo "127.0.0.1 &amp;nbsp; &amp;nbsp; devel1.local" &amp;gt;&amp;gt; /etc/hosts&lt;/blockquote&gt;&lt;/div&gt;
&lt;div&gt;&lt;div&gt;
그리고 virtualhost 설정에 다음 추가.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;blockquote&gt;&lt;div&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;ServerName devel1.local&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;DocumentRoot "/Users/bs0048/Sites/devel1/public"&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;b&gt;RailsEnv development&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;Directory "/Users/bs0048/Sites/devel1/public"&amp;gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;AllowOverride all&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Options -MultiViews&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;/Directory&amp;gt;&lt;/div&gt;
&lt;div&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/div&gt;
&lt;/blockquote&gt;&lt;div&gt;
그리고 아파치 재시작&lt;/div&gt;
&lt;div&gt;&lt;meta charset="utf-8"&gt;&lt;blockquote&gt;$ sudo apachectl restart&lt;/blockquote&gt;&lt;/div&gt;
&lt;div&gt;끗&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;meta charset="utf-8"&gt;&lt;div&gt;
3.2 Passenger Pref Pane 써보기(좀 편함)&lt;/div&gt;
&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;
$ sudo port install rb-cocoa&lt;/div&gt;
&lt;div&gt;&lt;div&gt;
$ sudo ln -s /opt/local/bin/ruby /usr/bin/ruby&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;
&lt;div&gt;&lt;a href="http://www.fngtps.com/passenger-preference-pane" target="_blank" title="[http://www.fngtps.com/passenger-preference-pane]로 이동합니다."&gt;http://www.fngtps.com/passenger-preference-pane&lt;/a&gt;에서 최신버전 다운로드하고 Passenger.prefPane파일 더블클릭하면 이게 System Preferences에 설치됩니다. 실행해보면 어떻게 하는지 바로 알 수 있는데, + 클릭하고 rails root디렉토리만 지정해주면 된다. 장점은 /etc/hosts를 안 고쳐도 된다. Directory Service를 쓰기 때문이라는데 자세한 건 모르겠지만 일단 편함.&lt;/div&gt;
&lt;div&gt;&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile6.uf.tistory.com/original/136628194B5A676A20326B" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile6.uf.tistory.com/image/136628194B5A676A20326B" alt="" filemime="image/png" filename="passenger pane.png" height="438" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
Restart클릭 - 끗.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
웹브라우저에 http://devel1.local/ 쳐서 레일즈 환영 화면 나오면 성공.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
다음편에서 계속합니다.&lt;/div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;&lt;ol style="list-style-type: decimal; "&gt;
&lt;li&gt;&lt;meta charset="utf-8"&gt;http://developer.apple.com/tools/developonrailsleopard.html&lt;/li&gt;
&lt;li&gt;&lt;meta charset="utf-8"&gt;http://frozenplague.net/2009/08/snow-leopard-rubyrails-developer-setup/&lt;/li&gt;
&lt;li&gt;&lt;meta charset="utf-8"&gt;http://eddorre.com/posts/installing-ruby-on-rails-postgresql-mysql-on-snow-leopard&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=qyKttH2NF6Q:x4kb191FqY0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=qyKttH2NF6Q:x4kb191FqY0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=qyKttH2NF6Q:x4kb191FqY0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/qyKttH2NF6Q" height="1" width="1"/&gt;</description>
			<category>mod_ruby</category>
			<category>passenger</category>
			<category>RUBY</category>
			<category>ruby on rails</category>
			<category>루비</category>
			<category>루비온레일즈</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/79</guid>
			<comments>http://hardworker.tistory.com/79#entry79comment</comments>
			<pubDate>Sat, 23 Jan 2010 12:08:34 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/79</feedburner:origLink></item>
		<item>
			<title>드루팔 레시피 2부 2편 - 깎고 썰고</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/6yhsSvDNcaM/83</link>
			<description>1부에선 간단하게 앞으로 뭘 만들건지와 거기에 필요한 재료들을 소개했다. 실은 그게 지금 한참 하는중인 일인데, 하다보니 좀 바뀐 것들이 있다. 2편에서는 무엇이 바뀌었는지 소상히 밝히고 요리과정을 쓸 수 있는데까지 함 써보도록 하겠다.&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
우선 바뀐 것이 ... 처음엔 Project와 Training을 하나의 Content type으로 놓고 type이라는 field값으로 구분하도록 설계했는데, 몇 가지 문제가 있어서 바꿨다. Project와 Training을 두 개의 컨텐트 타입으로 나눴다. 마찬가지로 Application도 두 개로 나눠야 했다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
우선 각 컨텐트 타입의 내용을 보자.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile8.uf.tistory.com/original/134B5C104B5787BC3B4B02" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile8.uf.tistory.com/image/134B5C104B5787BC3B4B02" alt="Project와 Training을 구성하는 필드들." filemime="" filename="cfile8.uf@134B5C104B5787BC3B4B02.png" height="353" width="584"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;Project와 Training을 구성하는 필드들.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile10.uf.tistory.com/original/20551C124B57881E2468A7" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile10.uf.tistory.com/image/20551C124B57881E2468A7" alt="Project application" filemime="" filename="cfile10.uf@20551C124B57881E2468A7.png" height="120" width="507"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;Project application&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile25.uf.tistory.com/original/15555E124B57887B4BF6E3" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile25.uf.tistory.com/image/15555E124B57887B4BF6E3" alt="Training application" filemime="" filename="cfile25.uf@15555E124B57887B4BF6E3.png" height="114" width="493"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;Training application&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Project와 Training은 이름만 다르고 내용이 완전히 같다. 그런데 Project application하고 Training application은 한 필드가 서로 다르다. 그리고 지난편에 좀 더 자세한 회원정보를 저장하기 위해 Content profile module을 쓴다고 했는데 계획을 바꿔 Profile + Profile role module을 쓰기로 했다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Content profile을 쓰면 모든 필드를 CCK로 정의할 수 있는 점이 좋다. 다양한 필드 타입이 있으니까. 그런데 회원의 Uid하고 CP node의 Nid하고 항상 맞춰줘야 하는 점이 불편하다. 사실 CP를 써서 구현을 거의 끝냈었는데, 내가 딱 원하는 모양새를 가지려면 모듈을 좀 고쳐야 했다. Profile page에 보여지는 모양이 좀 허접한데 이걸 고치려니 공이 엄청 들겠더라고.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Profile은 상대적으로 단순한 입력항목만 제공한다. 이를테면 Radio button을 만들 수가 없고 '전화번호' 형식에 꼭 맞는 그런 필드도 정의 할 수 없다. 하지만 CP와 마찬가지로 Views하고도 완벽하게 통합되어 있고 User profile page하고 더 자연스럽게 어울린다. CCK의 무한 파워따위 필수가 아닌 상황이라 Profile로 전환.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
암튼 그래서 바꿨는데, 만족스럽다. 혹시 Profile을 엄청 정교하게 꾸며야하면 다시 CP로 노력을 해보겠지만 이번 프로젝트는 Profile 모듈만으로 충분하다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
그리고 조금 달라진 요구사항이 있다. Project는 계정이 없는 직원이 개설할 수 있고, Training은 계정이 있는 직원만 개설할 수 있다. 마침 위에서 얘기했듯이 Content type을 둘로 나눠둔 상태라 약간의 작업만으로 요구사항을 간단하게 만족시킬 수 있었다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
자 이제 조금 속도를 내 보아요.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
1. 컨텐트 타입을 만든다. Project, Projecta, Training, Traininga. 신청서는 뒤에 a 붙여서 만들었다. 길면 귀찮고 Content types페이지에 알파벳순 정렬이라.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
2. Profile 항목을 추가하되, 모두 같은 카테고리 이름을 갖도록 한다. 그래야 나중에 한 화면 한 폼에 나온다. Volunteer라는 Role을 하나 추가하고, Profile role모듈을 이용해 좀전에 만든 Profile 항목들을 Volunteer에 할당한다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
3. Workflow 모듈 준비한다. Project용으로 proposed(미승인) &amp;gt; active(승인) &amp;gt; archived(보관) 세 상태를 갖는 워크플로를 하나 만들고, Training용으로 active &amp;gt; archive를 갖는 워크플로를 만든다. 상태 만들때 Weight는 꼭 순서대로 잘 입력해준다. 낮은 숫자가 먼저다. Training은 계정가진 직원이 등록하는거라 승인과정이 없다. 워크플로 만든 다음에 Edit 화면에서 어느 Role이 어느 상태에서 어떻게 변경할 수 있는지 권한설정을 해 준다. 처음에 좀 헷갈리는데 뚫어져라 보다보면 보인다. Actions도 빼먹지 말자. 이를테면 나는 Project가 proposed에서 active로 바뀔 때 해당 노드가 Publish되게 설정했다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
4. 이제 뷰View를 만들 차례다. 뷰가 좀 많다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
4-1. Volunteer list는 User타입의 뷰다. Filter에 Volunteer role 추가하고, 나머지 검색에 유용할만한 이름, 이메일, 주소 이런걸 Exposed 항목으로 추가한다. Exposed에 Optional을 체크해주면 이것들이 검색조건들이 된다. 무지 편하다. Fields에 적당한 항목을 추가해주고 Basic settings에서 Style : HTML, Use pager : yes, Access는 Role 고른담에 관리자 롤을 골라준다. Page타입의 Display를 하나 추가해서 Path나 Menu를 적당히 지정해주면 끝.&lt;/div&gt;
&lt;div&gt;
(그런데 나는 View에서 메뉴지정을 안 한다. Path만 추가한 다음에 Site building &amp;gt; Menus에서 직접 만들어주는 편이다. View에서 했다가 미아되는 메뉴항목들이 있더라.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
4-2. 프로젝트, 트레이닝 관련 화면들. Project, Training 모두 각각의 Pending(대기) 목록, Active(활성) 목록, Archived(종료 후 보관) 목록이 필요하다. 각각을 Page display로 추가하면 된다. 아참 Pending은 프로젝트만 필요하다. 나중에 요구사항이 바뀐거라 헷갈렸다. 특별히 어려울 건 없다. Filter에 Node: Type = Project / Training해주고, Workflow에 적당한 상태 지정해주면 된다. Active는 특별히 Node: Published - yes 필터도 주자. Fields에도 적당한 필드 찾아 넣어주면 되겠고 Basic settings는 이제 슬슬 눈에 익을테니 설명 생략.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
4-3 프로젝트/트레이닝의 신청자 목록을 Applicants라고 하자. Applicants는 Filters에 Node: type - Projecta (끝에 a있다)로 놓고 Fields에 .... 설명이 복잡할 것 같아 아래 스크린샷을 넣는다.&lt;/div&gt;
&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile25.uf.tistory.com/original/1406340B4B59EB68143AB4" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile25.uf.tistory.com/image/1406340B4B59EB68143AB4" alt="" filemime="image/png" filename="Screen shot 2010-01-23 at 5.14.55 AM.png" height="275" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;
보다시피 Fields에 Profile: Name이 있다. 따로 설정을 안해도 해당 노드의 author의 프로필을 말하자면 Join해준다. 편하다. 맨 아래 Attachment settings는 처음 볼텐데, 내가 Views attach module을 설치해서 그렇다. Views attach를 설치하면 Attachment라는 Display type이 생기는데, 이 디스플레이 타입은 Attach to에 지정한 노드에 덧붙여 보여지게 된다. 무슨 말이냐고? 꼭 필요할 때 다시 설명하겠음. 꼭 Attachment로 만들 필요는 없는데, Page로 하려며 쓸데없이 Path를 줘야해서 그냥 이걸로 했다. 같은 방법으로 applicants of a training 디스플레이를 추가해주면 끝.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
4-4&amp;nbsp;Volunteer 입장에서 신청한 프로젝트/트레이닝 목록은 Applications라고 하자. 이제 처음으로 Relationships를 설정할 차례다.&lt;/div&gt;
&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile8.uf.tistory.com/original/155DD8034B5A5B4E99E964" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile8.uf.tistory.com/image/155DD8034B5A5B4E99E964" alt="" filemime="image/png" filename="Screen shot 2010-01-23 at 1.12.56 PM.png" height="393" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;Filters에 Note:Type을 설정한 다음 Relationships에 Content:project (즉 Node reference type의 field_project 필드)를 추가해준다. Require this relationship에 체크한다. 이게 체크되면 INNER JOIN, 언체크면 LEFT JOIN이라고 생각해도 된다. 그리고 Fields에 필요한 항목들을 불러준다. 여기서는 프로젝트 제목을 리스팅하고 싶으니까 Node:Title을 추가하되, Relationship에서 project를 골라줘야 Projecta의 Title이 아니라 참조된 Project node의 Title이 나온다. 끝으로 Basic settings에 있는 Style: Views Calc Table은 맨 아래에 "합계"를 계산해주려고 넣은건데 &lt;a href="http://drupal.org/project/views_calc" target="_blank" title="[http://drupal.org/project/views_calc]로 이동합니다."&gt;Views calc module&lt;/a&gt;을 쓰면 된다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
자 지금까지 재료 썰기정도를 마친 셈 되겠다. 무슨 말이냐면, 감자 깎고 양파 까고 먹기좋은 크기로 썰어놓은 정도 되었다는 말이다. 또 다시 말하면 칼하고 도마만 있으면 어렵잖게 할 수 있다는 얘기다. 좀 더 빨리 썰었거나 예쁘게 썬 차이는 있겠으나 맛에는 별 차이가 없을게다. 스크린샷을 네 개나 넣었으니 이번 편은 여기서 마쳐야겠다. 3부에서 만나요.&lt;/div&gt;
&lt;meta charset="utf-8"&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=6yhsSvDNcaM:ceasFyMzCYs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=6yhsSvDNcaM:ceasFyMzCYs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=6yhsSvDNcaM:ceasFyMzCYs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/6yhsSvDNcaM" height="1" width="1"/&gt;</description>
			<category>Recipes</category>
			<category>drupal</category>
			<category>드루팔</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/83</guid>
			<comments>http://hardworker.tistory.com/83#entry83comment</comments>
			<pubDate>Sat, 23 Jan 2010 11:22:05 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/83</feedburner:origLink></item>
		<item>
			<title>드루팔, 배포(Deployment)가 어렵수나.</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/THIX8rMJF8s/85</link>
			<description>2년차 드루팔러로써 드루팔링에 가장 어려운 점이 무어냐 물으신다면 배포라고 하겠습니다.&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
그 동안 여기에 대해 두어 번 이야기한 적도 있는데, 드루팔 배포가 어려운 건 주로 다음 두 가지 이유에서다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
우선, 드루팔 개발에서는 클릭질이 곧 코딩이다. 업로드된 이미지를 Resize할 때, 보통의 방법은 imagecreatefromxxx() - imagecreatetruecolor() - imagecopyresampled() - imagejpeg() 뭐 이런 함수의 조합으로 처리한다. 그런데 드루팔에서는 - 예전에 소개했지만 - 클릭질 대여섯번 하면 이게 된다. 좋기는 한데 개발환경에서 이걸 하고나서 실서버에 옮기려면 이만저만 귀찮은게 아니다. 물론 Image Cache Preset은 Export/Import 할 수 있어서 좀 낫기는 한데 (설정값을 PHP코드로 뽑아주는데 이걸 Copy해서 실서버쪽 Admin화면에 Paste 한 후 저장!) SVN같은걸로 버전관리되는 소스코드에 비할 바가 아니다. 지난번 작업 후에 바뀐게 뭐뭐더라? 일일이 노트에 적어가며 작업하지 않으면 낭패다.&lt;/div&gt;
&lt;div&gt;
개발이란게 이렇게도 해보고 저렇게도 해보고 해서 방법을 찾는건데, 수십페이지를 돌아다니면서 수백번 클릭한 것 중에 오늘 아침 10시 반 이후에 한 것만 골라내라면 ... 힘들죠. 그나마 혼자 작업한거 찾으라면 좀 나은데 서너명이 나눠 개발하고 있다면? 정말 안될 일이에요.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
둘째로 계속 증가하는 NID(Node ID)문제다. 드루팔에서는 왠만한 건 다 노드로 저장되는데 ... 이런 상황을 생각해보다. 웹사이트에 그냥 Static page가 좀 있다. Page라는 Content type을 써서 페이지를 세 개 만들었고 이것들의 NID가 55, 56, 57이라고 하자. 그런데 그 동안 서비스 서버에 회원들이 글을 막 올려서 55, 56, 57은 벌써 다른 노드가 되버린거다. 그냥 NID만 바뀐거면 괜찮은데 Nodereference같은걸로 다른 노드를 참조하거나 했으면 이게 다 깨져버리는 불쾌한 상황이 되어버린다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
불평은 그만하고. 해법이 좀 있다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
문방구에서 공책하고 볼펜을 하나 사다가 클릭 한 번 할때마다 다 적어놓고, 실서버에 그대로 따라하는거다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
당연히 장난이구요.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
꽤 많은 모듈이 자기 자신의 설정들은 Export해준다. 혹은 Exporter module이 있어서 그걸 깔아주면 Export 할 수가 있다. Views, Rules 그리고 Content type은 쉽게 Export하고 Import 할 수가 있다. 특히 이 녀석들은 Nid같은 순차적이면서 각 시스템에 종속되는 Identifier가 아니라, 만들 때 개발자가 정하는 Machine name을 갖고있어서 조금만 주의하면 겹치는 걸 막을 수 있다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Node도 방법이 아주 없는 건 아니다. Node export 모듈을 쓰면 원하는 노드, 원하는 컨텐트 타입만 골라서 PHP 코드로 뽑아내고, 이걸 다른 서버에 Import할 수 있다. 그럼 뭐가 문제냐고? 아주 단순한 컨텐트 타입만 있다면 이게 좋은 방법인데, &lt;a href="http://drupal.org/project/node_export" target="_blank" title="[http://drupal.org/project/node_export]로 이동합니다."&gt;이 모듈의 페이지&lt;/a&gt;에도 나와있지만 참조, 관계, 구조 그리고 첨부파일 같은 건 안된다. Oh My God!&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Node export보다 좀 나은 해법이 &lt;a href="http://drupal.org/project/deploy" target="_blank" title="[http://drupal.org/project/deploy]로 이동합니다."&gt;Deployment module&lt;/a&gt;이다. 이건 내가 직접 써보진 않았지만 여러 문서를 뒤져보니 일부 참조 필드도 유지를 해 준다. 디플로이 모듈이 노드 익스포트 모듈보다 더 나은 이유는, 디플로이 모듈이 내부적으로 UUID 테이블을 가지고 있어서 NID가 달라지더라도 원래의 노드를 찾을 수 있기 때문이다. 그리고 노드 익스포트 모듈은 추출된 노드를 Textarea에 Copy &amp;amp; Paste하거나, 파일로 다운로드 한 다음에 업로드하는 수고를 거쳐야 하는데 디플로이 모듈은 배포할 대상 서버의 계정을 이용해서 온라인으로 디플로잉한다.&lt;/div&gt;
&lt;div&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;http://drupal.org/project/deploy&lt;/li&gt;
&lt;li&gt;http://www.palantir.net/blog/bringing-deployment-capability-drupal&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
좀 다른 차원의 접근이 있다. 바로 Backup &amp;amp; Migration module인데, 이 모듈은 DB를 덤프해버리는거다. mysqldump같은걸로 백업하는거랑 기술적으로는 큰 차이가 없지만 아무래도 좀 편하다. 원래 배포가 주 목적이 아니라 백업이 주목적인 모듈이니까 위의 모듈들하고 직접 비교하는 건 곤란하지만, 서버측이 아직 운영중이 아니라 초기 개발단계라면 꽤 유용하게 쓸 수 있다. 백업 스케쥴링도 가능하니 참고하시라.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
마지막으로 Features module을 소개할건데, 이게 참 ㅎㅎ Development Seed라는 회사의 개발자들이 만든건데 역시 DevSeed에서 내놓은 Spaces, Context 모듈과 함께 꽤나 눈에 띄는 모듈이 아닐 수 없겠다. 이 세 모듈의 특징을 내 나름대로 정의해보건대, 다른 모듈들이 대개 구체적 기능 구현에 중점을 뒀다면 이들은 좀 더 상위의 개념(Concept)을 잡아내고 이걸 구현하고 있다. 모듈의 이름부터가 기능, 공간, 맥락 뭐 이런거잖아? Context는 나도 지금 하고있는 프로젝트에 써먹었는데 상당히 유용하다. 자세한 건 다음기회로 미루고 Features를 조금 설명하자면.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Features는 "기능"이라고 부를 수 있는 것이 뭘까? 에 대한 답을 준다. 내가 드루팔 레시피 2부에 쓰고있는 기능을 생각해보시라. 프로젝트랑 강좌를 등록할 수 있고, 특정 Role을 가진 회원이 프로젝트나 강좌에 지원할 수 있다. 각 프로젝트나 강좌는 여러개의 CCK필드를 가진 노드들이고, 이것들이 잘 작동하려면 필요한 Rule이나 View들이 있다. 꼭 있어야 하는 이런저런 모듈들도 있을거고, 적절한 권한(Permission) 역시 기능의 일부라고 할 수 있다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Features모듈은 이 모든 것들을 묶어서 하나의 드루팔 모듈로 만들어준다. 진짜다. 실제로 자주 사용될만한 기능들을 Features 모듈로 패키징해 배포하는 Features server같은 것도 생기는 중이고 그렇다. 이 모듈이 계속 발전한다면 꽤 재밌는 일들이 벌어질 것 같다. 이를테면, 드루팔 블로그 모듈을 바닥부터 모듈로 개발하려면 진짜 쌔가 빠진다. 모듈 전문가만 할 수 있다. 그런데 적당히 이런저런 모듈을 조합해서 기능을 '클릭질'로 구현한 다음에 Features로 패키징하면 이게 모듈이 되는거다. 와우. 그런데 '계속 발전한다면'이라는 단서를 달았지요. 아직 완벽하지는 않아요. 어떻게 이번에 써먹어볼 수 없을까 해서 이리저리 만지작거려 봤는데 아직 원스톱에 배포할 수 있을 정도로 완벽하진 않습니다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
이상 드루팔 배포에 대해 간단하게나마 전반적 문제와 해법을 적어봤다. 이렇게 글로 써서 남기는 이유는 .. 당장 내가 이 뻘짓 노가다를 해야하는 상황에 처리있기 때문이다. 미치겠다. 팀이라서 누가 배포만 전담해주면 얼마나 좋을꼬?&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=THIX8rMJF8s:6vrAdYfwZOc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=THIX8rMJF8s:6vrAdYfwZOc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=THIX8rMJF8s:6vrAdYfwZOc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/THIX8rMJF8s" height="1" width="1"/&gt;</description>
			<category>Drupal / 드루팔</category>
			<category>backup</category>
			<category>deployment</category>
			<category>drupal</category>
			<category>features</category>
			<category>드루팔</category>
			<category>배포</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/85</guid>
			<comments>http://hardworker.tistory.com/85#entry85comment</comments>
			<pubDate>Fri, 22 Jan 2010 20:31:25 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/85</feedburner:origLink></item>
		<item>
			<title>그래미가 드루팔을 선택하다.</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/9TtPi034So0/84</link>
			<description>&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile21.uf.tistory.com/original/195562044B58E95E5F1ADF" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile21.uf.tistory.com/image/195562044B58E95E5F1ADF" alt="" filemime="image/jpeg" filename="Screen shot 2010-01-22 at 10.53.54 AM.png" height="400" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/div&gt;
그래미 어워드의 공식 웹사이트(&lt;a href="http://www.grammy.com/" target="_blank" title="[http://www.grammy.com/]로 이동합니다."&gt;http://www.grammy.com/&lt;/a&gt;)가 새 플롯폼으로 드루팔을 선택했다. 이번 작업은 드루팔 전문 회사인 룰라봇(http://www.lullabot.com/)에서 담당했으며 Pressflow Drupal 배포판을 기반으로 한 모양이다. 그래미상 웹사이트쯤 되면 단순한 홈페이지가 아니라 다양한 컨텐츠가 수시로 업데이트는 곳이고, 시상식 당일로 향해갈수록 엄청난 트래픽 증가를 경험하게 되는 곳이다. 많은 웹사이트가 드루팔을 채택하고 있지만 지난번 백악관 소식에 이어 한국에도 익숙한 곳에서 드루팔을 선택했다기에 소식을 옮겨본다.&lt;div&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;룰라봇의 발표자료 :&amp;nbsp;&lt;a href="http://www.lullabot.com/blog/drupal-wins-grammy-awards" target="_blank" title="[http://www.lullabot.com/blog/drupal-wins-grammy-awards]로 이동합니다."&gt;http://www.lullabot.com/blog/drupal-wins-grammy-awards&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
룰라봇의 발표자료에 언급한 모듈들을 보면&amp;nbsp;CCK, Views, ImageCache, ImageField 등은 이미 연재 1부에서 간단하게나마 소개를 했던 것들이다. Views Slideshow, Fivestar, ImageField Extended, Views Cloud 등은 다른 모듈의 기능을 확장해주는 보조 모듈들이다. Custom Page는 아직 잘 모른다. 써먹는 방법을 알게되면 포스팅 하도록 하겠음.&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" face="verdana, arial, helvetica, clean, sans-serif" size="3"&gt;&lt;span class="Apple-style-span" style="font-size: 13px; line-height: 16px; "&gt;&lt;font class="Apple-style-span" face="돋움" size="3"&gt;&lt;span class="Apple-style-span" style="font-size: 12px; line-height: 18px;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
또 이들의 발표자료에 따르면 대량의 트래픽을 감당하기 위해 여러가지 노력을 기울였다는데, 2대의 MySQL 서버와 8대의 Load-balanced Apache 서버(각 서버는 MySQL slave로 작동하는 memcached를 가짐) 그리고 Varnish proxy를 사용했다고 한다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Varnish는 나도 몰랐던 것이라 얼른 찾아보니&amp;nbsp;&lt;a href="http://varnish.projects.linpro.no/" target="_blank" title="[http://varnish.projects.linpro.no/]로 이동합니다."&gt;http://varnish.projects.linpro.no/&lt;/a&gt;라는 웹사이트가 튀어나온다. 일종의 캐시 서버군요.&lt;/div&gt;
&lt;div&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;&lt;a href="http://mix1009.net/entry/Varnish-20-웹캐시-리버스프록시" target="_blank" title="[http://mix1009.net/entry/Varnish-20-웹캐시-리버스프록시]로 이동합니다."&gt;h&lt;/a&gt;&lt;a href="http://mix1009.net/entry/Varnish-20-웹캐시-리버스프록시" target="_blank" title="[http://mix1009.net/entry/Varnish-20-웹캐시-리버스프록시]로 이동합니다."&gt;ttp://mix1009.net/entry/Varnish-20-웹캐시-리버스프록시&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
그리고 이번 프로젝트에 사용된 Pressflow Drupal이 뭔가 궁금하지 않을 수 없는데, 이 문서에 간단히 소개가 되어있다. 살짝 옮겨보면, Pressflow는 큰 규모와 고성능을 위해 설계된 드루팔이다. 오래된 PHP에 대한 지원을 버렸고 MySQL 5.x를 써야한다. 그리고 APC라던가 memcached같은 캐싱 시스템을 요하기 때문에 일반적인 공유 호스팅에서는 사용할 수 없을 수도 있다.&amp;nbsp;&lt;a href="http://fourkitchens.com/pressflow-makes-drupal-scale" target="_blank" title="[http://fourkitchens.com/pressflow-makes-drupal-scale]로 이동합니다."&gt;http://fourkitchens.com/pressflow-makes-drupal-scale&lt;/a&gt;에도 약간의 정보가 더 있기는 한데, 자세한 문서는 어디에도 보이질 않아서 리플리케이션이나 Varnish 지원을 어떻게 한다는건지는 아직 모르겠다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
Lullabot은 Acquia, Development Seed와 함께 굉장히 활발한 드루팔 회사 중 하나다. 모듈에 공헌도 많이 하고 있고. 그럼 이만 줄입니다.&lt;/div&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=9TtPi034So0:aM0wuJ_IHck:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=9TtPi034So0:aM0wuJ_IHck:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=9TtPi034So0:aM0wuJ_IHck:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/9TtPi034So0" height="1" width="1"/&gt;</description>
			<category>Drupal / 드루팔</category>
			<category>drupal</category>
			<category>Grammy Awards</category>
			<category>Lullabot</category>
			<category>Pressflow</category>
			<category>varnish</category>
			<category>그래미 시상식</category>
			<category>드루팔</category>
			<category>룰라봇</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/84</guid>
			<comments>http://hardworker.tistory.com/84#entry84comment</comments>
			<pubDate>Fri, 22 Jan 2010 09:20:04 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/84</feedburner:origLink></item>
		<item>
			<title>드루팔 기타(Guitar) 모듈</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/bHUxpPWu3pw/82</link>
			<description>코드 프리즈되고 정식 출시로 달려가고 있는 드루팔 버전7이 어떤지는 모르겠지만, 2년간(ㅋㅋ) D6을 가지고 놀다보니 이건 일반인이 쓸 물건은 좀 아니구나 싶다. 굳이 하시겠다는 분 말리지는 못하지만 개발경험 없는 분이 도와달라 하셔도 저는 자신이 없습니다. 절레절레.&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
개발자 중에도 말끔하게 정리된 문서 없이는 어려우신 분도 적합치 않다. 드루팔의 세계, 좀 거칠다. 두 손과 얼굴에 검댕이 뭍혀가며 해야하는게 드루팔 일이구나. 그래서 말인데 Drupaling하는데 있어 가장 큰 장벽은 영어라는 생각이다. 검색만 잘 하면 어지간한 건 해결이 되더라고. 저도 떠듬떠듬거리는 영어실력입니다만 쪽 팔고 부끄럽고 그런거 생각않고, 완벽하지 않더라도 뭐든 해보자 이런 마음가짐으로다 한글로 된 드루팔 자료를 단 1바이트라도 더 많이 남겨보자 이런 차원에서 모듈 소개를 시작해봅니다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
항상 서론이 길죠.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
꼭 맞는 모듈 찾으려고 구글링을 수백번 하다가, Full-scan에 장사없다는 각오로 드루팔 모듈 페이지를 처음부터 훑었지요. 그러다 내게 꼭 맞는 모듈을 발견했!!지만 그건 드루팔 레시피 2부 2편에서 소개하겠고 이번에 소개할 것은 좀 특이한 모듈입니다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
초반에 올렸던 강좌에서 CCK 모듈을 소개했었죠. 요약하자만 - 드루팔은 원래 제목하고 본문으로 구성된 '노드 Node'가 모든 자료의 단위인데 CCK는 이 노드에 아주 다양한 필드를 추가하도록 해준다. 텍스트, 체크박스, 셀렉트 리스트같은 기본 위젯부터 Node reference, User reference같은 참조 필드같은 것들은 기본적인 것들이다. 이 외에도 구글맵 표현하는 필드나 이미지, 동영상, 날짜, 바코드 등등등 아주 왠만한 데이터 타입들은 다 필드 모듈로 개발되있다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
오늘 소개할 모듈은 특이해서 그냥 소개해보는건데, 기타(Guitar) 악보를 표현하는 CCK Field를 만들어주는 Guitar module이다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style="list-style-type: square; "&gt;
&lt;li&gt;&lt;a href="http://drupal.org/project/guitar" target="_blank" title="[http://drupal.org/project/guitar]로 이동합니다."&gt;http://drupal.org/project/guitar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
내가 C코드만 잡아보다 기타를 방치해둔 사람이라 잘 모릅니다만- 모듈을 설치하고 노드에 Guitar 필드를 하나 추가하면 아래같은 화면을 만날 수 있다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile2.uf.tistory.com/original/144E17024B51D7BE973494" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile2.uf.tistory.com/image/144E17024B51D7BE973494" alt="" filemime="image/jpeg" filename="Screen shot 2010-01-17 at 2.11.16 AM.png" height="167" width="393"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
위 화면처럼 입력하면 아래같은 화면을 만들어준다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile2.uf.tistory.com/original/154E17024B51D7BE986D84" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile2.uf.tistory.com/image/154E17024B51D7BE986D84" alt="" filemime="image/jpeg" filename="Screen shot 2010-01-17 at 2.10.13 AM.png" height="106" width="150"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
콤마로 구분된 숫자 혹은 x문자는 왼쪽부터 차례대로 1, 2, 3, 4, 5, 6번 줄을 뜻한다. x는 개방현을 뜻하고 각 숫자는 미루어 짐작할 수 있듯이 몇 번째 플랫을 누를건가를 뜻한다. 이 모듈 좀 더 개선하면 재밌어질 것 같기도 하군요.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
별로 알맹이는 없는 첫 편입니다만 일단 첫 테이프 끊는데에 의미를 두겠습니다. 참고로 '팔팔한 드루팔(&lt;a href="http://palpal.org/" target="_blank" title="[http://palpal.org/]로 이동합니다."&gt;http://palpal.org/&lt;/a&gt;)' 사이트 주인장께서도 좋은 모듈을 꾸준히 소개해주십니다.&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=bHUxpPWu3pw:DmK4remrVkU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=bHUxpPWu3pw:DmK4remrVkU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=bHUxpPWu3pw:DmK4remrVkU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/bHUxpPWu3pw" height="1" width="1"/&gt;</description>
			<category>Module</category>
			<category>drupal</category>
			<category>drupal module</category>
			<category>드루팔</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/82</guid>
			<comments>http://hardworker.tistory.com/82#entry82comment</comments>
			<pubDate>Sun, 17 Jan 2010 00:18:50 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/82</feedburner:origLink></item>
		<item>
			<title>[2부] 드루팔 레시피 1편 - 소개와 재료</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/ndNvxW-S-P0/81</link>
			<description>그 동안 휴가도 다녀오고 이런저런 일 때문에 이사도 했다. 연말 보내느라 또 몇 일 들떠있었고 그 후엔 밀린 일 서두르느라 시간이 안 나더라. 연재 시작 할 때에 비하면 드루팔도 많이 익숙해졌다. 스스로 감개무량ㅎㅎ 기분도 바꿀 겸 제목을 '드루팔 레시피 Drupal recipe'로 정해봤다. (실용주의 시리즈의 &lt;a href="http://www.pragprog.com/titles/fr_rr/rails-recipes" target="_blank" title="[http://www.pragprog.com/titles/fr_rr/rails-recipes]로 이동합니다."&gt;Rails recipes&lt;/a&gt;에서 빌려옴)&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
2부에선 좀 더 어려운 걸 해보겠다. 자원봉사가 필요한 프로젝트나 교육과정을 웹사이트에 게시하고 수강생 및 자원봉사자를 모집한다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
좀 더 자세히,&lt;/div&gt;
&lt;div&gt;
&lt;ol style="list-style-type: upper-alpha; "&gt;
&lt;li&gt;불특정 다수, 웹사이트에 계정이 없는 직원들이 프로젝트 혹은 교육과정을 등록 할 수 있다.&lt;/li&gt;
&lt;li&gt;등록된 프로젝트는 관리자의 승인 후 게시된다.&lt;/li&gt;
&lt;li&gt;계정 없이도 게시한 이가 프로젝트를 관리 할 수 있도록 등록과정에 관리용 비밀번호를 입력받는다.&lt;/li&gt;
&lt;li&gt;비밀번호로 인증한 뒤 내용을 고치거나 신청자 목록 조회, 참석여부 및 참여시간 기록 등 할 수 있다.&lt;/li&gt;
&lt;li&gt;자원봉사자/수강생은 한 학교의 학생들인데, 교육을 받거나 자원봉사를 하려면 웹사이트에 계정을 틀어야 한다.&lt;/li&gt;
&lt;li&gt;그리고 그 계정에 로그인하면 프로젝트 참여/교육 이수 내역 등을 조회할 수 있다.&lt;/li&gt;
&lt;li&gt;그리고 관리자는 위의 이력을 PDF형태의 인증서(Certificate)로 발급해줄 수 있다.&lt;/li&gt;
&lt;li&gt;관리자는 모든 프로젝트와 학생이력 등을 관리할 수 있고 수기로 프로젝트/교육 내역을 추가해줄 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt;
평범한가요? 그렇습니다. 그런데 드루팔이란 플랫폼 위에 모듈을 조립해 얹어야 하니 머리가 좀 아파요. 제 생각에 이 정도면 드루팔 개발 난이도가 1부터 10이라고 할 때 3.5~4 정도인 것 같아요. 지난 강좌는 2 정도.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
2년간의 드루팔 경력(후후)에 비춰보았을 때 이번 일에서 가장 어려운 부분은 두 가지인데, 프로젝트나 강좌의 신청이력을 관리하는 부분이 첫 번째이고 다음은 프로젝트를 비밀번호로 관리하는거다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
일단 재료 소개 나갑니다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
주재료 :&lt;/div&gt;
&lt;div&gt;
Drupal 6.x 한큰술(.. 은 아니고)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
기본양념 :&lt;/div&gt;
&lt;div&gt;
Views, CCK, Rules 등은 갖은 양념.. 아니 모듈은 가지고들 계시죠?&lt;/div&gt;
&lt;meta charset="utf-8"&gt;&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
핵심 재료들 :&lt;/div&gt;
&lt;div&gt;
&lt;u&gt;CCK nodereference&lt;/u&gt; : 다른 노드를 참조하는 CCK 필드. RDBMS의 Foreign key로 생각하면 됩니다.&lt;/div&gt;
&lt;div&gt;
&lt;u&gt;Node Relationship&lt;/u&gt;s : CCK nodereference를 보조해줌. ERD 보여주고&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;u&gt;CCK Viewfield&lt;/u&gt; : View를 필드로. 비슷한 모듈이 여러개 있는데 이게 좀 쓸만하다.&lt;/div&gt;
&lt;div&gt;
&lt;u&gt;Protected Node&lt;/u&gt; : 노드에 비밀번호 걸어주는 모듈.&lt;/div&gt;
&lt;div&gt;
&lt;u&gt;Workflow&lt;/u&gt; : 노드가 원래 Published냐 아니냐 두 가지 상태 뿐인데 이걸 쓰면 다양한 상태를 지정할 수 있다.&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;u&gt;
Content Profile&lt;/u&gt; : 드루팔 기본 User profile은 항목이 별로 없다. Profile 모듈을 쓰면 항목을 추가 할 수 있기는 한데 Content Profile은 아얘 하나의 Content type을 User profile용으로 쓰게 해준다.&lt;/div&gt;
&lt;div&gt;
&lt;u&gt;Content Profile Role&lt;/u&gt; : 어느 Content type이 어느 Role에 할당될지.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;u&gt;
Automatic Nodetitles &lt;/u&gt;: 노드 제목(Title)을 자동으로. 특히 제목이 필요없는 컨텐트 타입에 유용하다. 필수는 아님.&lt;/div&gt;
&lt;div&gt;
&lt;u&gt;Auto-fill from URL(urlfill)&lt;/u&gt; : GET variable로 넘겨진 값을 노드 등록폼에 미리 채워준다. CCK 일부 필드 지원.&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;u&gt;
Node Reference Url &lt;/u&gt;: urlfill하고 비슷하긴 한데 nodereference field를 지원한다. 우린 기본버전이 아니라 약간 수정된 걸 쓸거다.&lt;/div&gt;
&lt;div&gt;
&lt;u&gt;Custom Links&lt;/u&gt; : token을 써서 링크(a 태그)를 만들어주는 모듈. 어디에 쓸 건지는 곧 공개.&lt;/div&gt;
&lt;div&gt;
&lt;u&gt;Token &lt;/u&gt;: 드루팔 개발에서 의외로 아주 중요한 모듈이다. 개념만 알면 쉽다. 우리는 이걸 약간 확장해야 한다.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;u&gt;
Auto Assign Role&lt;/u&gt; : 회원 등록 할 때 어느 Role을 가지도록 할지에 관한 모듈.&lt;/div&gt;
&lt;div&gt;
&lt;u&gt;Logintoboggan &lt;/u&gt;: 유틸리티 모듈. 드루팔의 회원가입 및 로그인 기능을 조금 개선해준다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
이번 일에서 모두&amp;nbsp;세 개의 컨텐트 타입을 만들거다. Project, Volunteer, Application.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Project는 요구사항의 프로젝트/교육과정을 뜻한다. 이름만 다르지 하는 일이 똑같기 때문에 Type field의 값에 따라 project이거나 training을 나타내도록 만들거다.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Volunteer는 웹사이트에 가입하는 학생들의 프로파일로 사용할 노드다. Content Profile 위에 잠깐 설명했지? CP모듈 대신 Profile + Profile role 모듈을 쓰거나 할 수도 있는데 몇 가지 실험해보다가 CP를 골랐다. 그런데 이유가 정확하게 생각이 안 나서 혹시 Profile 모듈을 다시 테스트해볼 짬이 나면 해봐야겠다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&amp;nbsp;Application은 이름 그대로 "신청"에 해당한다. Project와 Volunteer의 M:N관계를 만들어주고 참가여부, 참가시간 등을 추가로 가진다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
여기까지 소개를 마치고 나니 ......... 힘이 빠져서 다음 편에 계속하겠습니다.&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=ndNvxW-S-P0:9M8xHrb86iI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=ndNvxW-S-P0:9M8xHrb86iI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=ndNvxW-S-P0:9M8xHrb86iI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/ndNvxW-S-P0" height="1" width="1"/&gt;</description>
			<category>Recipes</category>
			<category>drupal</category>
			<category>드루팔</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/81</guid>
			<comments>http://hardworker.tistory.com/81#entry81comment</comments>
			<pubDate>Mon, 11 Jan 2010 13:59:24 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/81</feedburner:origLink></item>
		<item>
			<title>'드루팔'하기 / Drupal-ing</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/8UJ_yjJNerk/80</link>
			<description>이제 드루팔 개발 2년차 ㅋㅋ 작년부터 했으니까 오늘부로 2년차라고 하면 안될까? 암튼 8월부터 했으니 대충 반 년 했군요. 아직도 헤메이고 있기는 합니다만 슬슬 오르려는 산이 얼마나 높은지 대충 보입니다. 아, 나는 이제 국립공원 매표소 앞에 있는 건가.&lt;div&gt;
&lt;br /&gt;
&lt;div&gt;
모든 일이 그렇듯, 드루팔로 개발을 한다고 해도 모두가 같은 일은 하는 건 아니다. 누구나 스케이트를 김연아만큼 타야하는 것도 아니니 롯데월드 아이스링크에서 놀 사람은 팔다리 허우적대도 즐거우면 그만이고 태릉 선수촌 가실 분들은 또 나름대로 노력하시면 되겠고. 드루팔의 세계 역시 단순 사용자부터 이걸로 사업 벌이는 사람까지 각양각색이다. 사업도 웹사이트 구축하는 이들부터 Acquia나 &amp;nbsp;Lullabot처럼 드루팔에 올인한 회사, Top notch처럼 Theming(스킨제작)만 취급하는 곳 등등등 다양하다. 사실 드루팔이 일반인(즉 non-개발자)한테 친절한 편은 아닌데, 차기버전인 7 기반으로 드루팔 가든(&lt;a href="http://drupalgardens.com/" target="_blank" title="[http://drupalgardens.com/]로 이동합니다."&gt;http://drupalgardens.com/&lt;/a&gt;)이라는, End-user를 많이 배려한 사이트 빌더도 준비되고 있다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
그런데 2년동안 드루팔을 하면서(ㅋㅋ) 느낀게, 허우적대면서라도 타는 사람이건 트리플악셀 뛰는 사람이건 아니면 하다못해 스케이트 날 가는 사람이건 간에 드루팔 사용자가 국내엔 거의 없단거다.&amp;nbsp;어떤 사람은 다 영어로 되어있어 어렵기 때문이라 하고 또 다른 사람은 프로그램 자체가 (특히 UI) 한국에 안 맞다고 하기도 하고. 국내에서 대표적으로 드루팔을 쓰는 KLDP에서도, 이곳이 국내에서 가장 큰 "오픈소스" 커뮤니티임에도 불구하고, 언어장벽이나 몇몇 문제로 국산 솔루션으로 바꾸려 한 적이 있을 정도.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
제로보드. 참 많이들 썼다. 나도 제로보드로 알바해서 용돈 좀 벌었고. 아직도 4.x버전의 제로보드에 의지해 돌아가는 웹사이트들이 꽤 된다. 초보자가 개인 홈페이지 만들고자 할 때도 커뮤니티의 도움을 받으면 어쨌든 가능하기는 했고, 기술자 없이도 디자인 + HTML코딩(또는 드림위버)에다 제로보드만 끼워넣으면 구색갖춘 "홈페이지"제작이 가능했으니 썩 괜찮은데다 실용적이기까지 했다는 건 분명하다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
다만&amp;nbsp;기이할 정도였던 제로보드의 인기 덕분인지 한국에서는 무슨무슨 보드라는 것이 "홈페이지" 만들 때 쓰는 대표적인 툴이 됐고, 좀 더 완전히 통합된 웹사이트를 만들 수 있는 형태로 발전되지 못한데에 영향을 주기는 줬다는게 내 생각이다. 심지어 제로보드 5버전도 이전 버전만큼 유명해지진 못했고, XE에 이르러 '보드'라는 이름을 폐기하며 드루팔에 비견되는, 모듈화된 CMS형태로의 발전을 꾀하고 있다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
좀 심각해졌는데, 제로보드로 홈페이지 만드는게 유행이던 시절부터 국내에선 땡땡보드니 무슨빌더니 하는걸로 웹사이트 구축을 하면 별로 전문가답지 않게 여겨지는 것 같은데, 그 맥략을 좀 짚어볼까 싶어서. 사실&amp;nbsp;나도 드루팔을 제대로 파보기 전에는 FTP로 소스 올려서 클릭 좀 하는 일이라고 치부했고, XE를 눈 비비고 살펴보기 전에는 아직도 제로보드가 나와? 했으니까.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
한편 두 해에 걸쳐(ㅎㅎ) 드루팔을 만지작거리며 접한 여러 사례들을 보면, 백악관 홈페이지 말고도 드루팔을 기반으로 만든 진지한 -&amp;nbsp;정부기관이나 돈 많은 회사들의&amp;nbsp;웹사이트들이 굉장히 많다. 물론 국내에도 여러 버전의 제로보드로 만든 웹사이트들이 많기는 한데 드루팔에 비할 바는 아니다. Drupal.org에서 지난 2009년을 정리해 올린 글만 보더라도 지난해 세계 정부기관 중 미국(백악관), 프랑스(정부 포털), 호주(수상 웹사이트), 영국(directgov) 등에서 드루팔을 사용한 웹사이트를 런칭했다. 그래미상, 에미상 웹사이트도 드루팔을 썼고 마이클 잭슨이나 에릭 클랩튼 공식 웹사이트도 드루팔이다. 노키아, 구글, AT&amp;amp;T, 소니에릭슨 등도 핵심 부문은 아니지만 연구소 웹사이트를 운영하는데 드루팔을 선택했다. (그 외에도 많은데&amp;nbsp;&lt;a href="http://drupal.org/node/671566" target="_blank" title="[http://drupal.org/node/671566]로 이동합니다."&gt;http://drupal.org/node/671566&lt;/a&gt;를 참고.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
많이들 쓰니까 무조건 좋다는 건 아닌데, 많이들 쓰는 이유를 생각하다 보면 볼 필요는 있다. 드루팔이 완벽하고 이상적인 건 분명히 아닌데 점점 대세가 되가는 이유가 뭘까?&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
사실 잘나가고 있는 걸 왜 잘나가는지 설명하는 거 재미가없다. 남들이 많이 하는데다 결과에 걸맞는 이유를 찾기만 하면 되니까. 그러니까 간단히 한두 가지만.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Drupal API, 단순하다. Hook같은게 엄청 많기는 한데 구조는 단순하다. 드루팔같은 모델이 성공하려면 플러그인/모듈이 많아야되는데 만들기가 쉬워야 많이들 만들 것 아닌가. 마침 비교해볼 겸 XE의 플러그인 개발 문서(&lt;a href="http://xe.xpressengine.net/wiki/18227616" target="_blank" title="[http://xe.xpressengine.net/wiki/18227616]로 이동합니다."&gt;http://xe.xpressengine.net/wiki/18227616&lt;/a&gt;)를 잠깐 봤는데 이게 일단 XML 설정파일 + OOP스타일의 코딩을 요구한다. HTML에도 따로 쓰는 템플릿이 있는 것 같고. 여기서 일단 포기하는 개발자가 생긴다. 객체지향이 좋은거고 그렇긴 한데, 하나의 장벽이 되는 것도 사실이다. 드루팔 모듈은 파일 두 개만 있으면 일단 작동한다. ini 스타일 파일하고 훅 구현한 함수 파일 하나. 올드패션이긴 한데 일단 시작할 맘 먹기가 쉽다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
드루팔 방식은 옳고 XE방식은 그르다 뭐 그런 얘긴 아니다. 드루팔 방식도 아주 쉽지는 않다. 디버깅하기도 불편하고 어디에 무슨 훅이 있고 데이터 형식이 어떤지 이런게 별로 잘 정리되있지 않아서 대개는 소스 열어보고 파악을 해야한다. 근데 &amp;nbsp;좀 지저분해 보여도 여러사람이 갖고 노는데엔 더 발전된 방식보단 쉬운쪽이 낫다는게 내 생각이다. 엄청난 갯수의 스킨이 개발됐던 제로보드4를 돌아보자. 좀 지저분해도 사람들은 저런 걸 좋아해.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
그리고 흔히들 드루팔 커뮤니티가 엄청나단 점을 이야기한다. 애초에 왜 이게 엄청 활발해졌는지가 중요하긴 하지만 나처럼 중간에 올라탄 사람은 역사적 맥락을 잘 모르기도 하거니와 이 막강한 커뮤니티가 생산해내고 구글이 검색하게 도와주는 방대한 양의 자료가 감사할 따름. 그런데 이게 전부 영어로 쓰여있고, 잘 차려진 메뉴얼보다는 토론, 질문과 답변, 드루팔 구루들이 쓴 블로그 같은거다. 영어도 좀 해야되고 검색도 좀 해야되고 처음엔 시간도 좀 들여야 "감"을 잡는다. 때때로 검색을 하다보면 내가 찾는 해법이 아직 없다는 걸 알게되기도 하지만, 그 순간에 이 커뮤니티가 살아 움직이고 있구나 하는 느낌도 함께 받는다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
사실 이 글을 쓰려고 맘먹었을 땐 단점 위주로 쓰려고 했었는데 하하. 이제&amp;nbsp;드루팔하기의 단점 좀 써볼까 싶다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
내가 제일 불편한 건, 왠만한 작업이 다 DB에 저장되는거라 버전관리가 안 된다는 거다. 물론 Theme 작업이나 모듈 관련된 건 소스코드에 남지만 나머진 그렇지가 않다. 좀전에 한 작업이 뭔가를 망가뜨렸다면? 되돌리기가 아주 빡세다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
개발한 걸 실서버에 업데이트하기도 빡세다. 페이지를 하나 추가해도 이게 노드Node로 저장되는데, 드루팔의 모든게 노드인데다 노드의 Nid값이 차례대로 증가하기 때문에 특히 어렵다. 이를테면 Production 서버에서 백업한 걸 개발서버에 넣고 (앞 문단에 얘기한, 버전관리가 어렵기 때문에 개발-실서버 환경을 맞추려면 이렇게 해야된다.) 뭔가 작업을 좀 해. 그런 다음에 이걸 그대로 프로덕션 서버에 넣기가 어렵다. 왜냐하면 프로덕션 서버는 계속 서비스를 하고 있었을 테니까 Nid가 계속 증가했겠지. 이게 엄청 거슬린다. 맘놓고 뭘 할 수가 없으니까.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
위 두 가지랑 무관하지 않게, 여럿이 같이 개발하기도 어렵다. &amp;nbsp;관련해서 Features라던가 여러 시도가 있는걸로 알고 있는데 드루팔이 생겨먹은데서 오는 문제라 쉽게 해결될 것 같지는 않다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
특별히 주제도, 유용한 정보도 없는 글이 되버린 것 같은데 짬짬이 나흘에 걸쳐 쓰다보니 어수선해진 것 같다. 한 달 넘게 쉬다보니 감을 잃었나... 드루팔 강좌를 기다리는 분이 존재하기는 할지 모르겠으나 그것도 곧 계속 쓸 예정.&lt;/div&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=8UJ_yjJNerk:SSC1Gdz0EkY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=8UJ_yjJNerk:SSC1Gdz0EkY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=8UJ_yjJNerk:SSC1Gdz0EkY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/8UJ_yjJNerk" height="1" width="1"/&gt;</description>
			<category>Drupal / 드루팔</category>
			<category>CMS</category>
			<category>drupal</category>
			<category>XE</category>
			<category>드루팔</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/80</guid>
			<comments>http://hardworker.tistory.com/80#entry80comment</comments>
			<pubDate>Wed, 06 Jan 2010 17:18:46 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/80</feedburner:origLink></item>
		<item>
			<title>독트린 Doctrine and other PHP ORMs</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/wxLNm37Zf28/77</link>
			<description>&lt;div&gt;
Drupal은 지금 6.x가 주류이고 다음 버전인 7이 한창 개발중이다. D7에 여러가지 변화&lt;sup class="footnote"&gt;&lt;a id="footnote_link_77_1" href="#footnote_77_1" onmouseover="tistoryFootnote.show(this, 77, 1)" onmouseout="tistoryFootnote.hide(77, 1)" style="color: #f9650d; font-family: Verdana, Sans-serif"&gt;&lt;span style="display: none"&gt;[각주:&lt;/span&gt;1&lt;span style="display: none"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/sup&gt;가 있는 것 같은데 그 중 &amp;nbsp;DB API도 완전히 새로워진단다. 드루팔을 쓴지 불과 두어달이라 API는 잘 모르지만, D6과 D7의 DB API는 한 눈에 띌 정도르 다르다. 아래는 같은 API의 D6과 7 버전&lt;sup class="footnote"&gt;&lt;a id="footnote_link_77_2" href="#footnote_77_2" onmouseover="tistoryFootnote.show(this, 77, 2)" onmouseout="tistoryFootnote.hide(77, 2)" style="color: #f9650d; font-family: Verdana, Sans-serif"&gt;&lt;span style="display: none"&gt;[각주:&lt;/span&gt;2&lt;span style="display: none"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/sup&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
D6에서는 db_query()에 SQL을 직접 넘긴다. 테이블 이름 정도만 table_prefix를 감안해 {}로 감싸 구분짓는 정도다.&lt;/div&gt;
&lt;div&gt;
&lt;div class="txc-textbox" style="border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(238, 238, 238); border-right-color: rgb(238, 238, 238); border-bottom-color: rgb(238, 238, 238); border-left-color: rgb(238, 238, 238); background-color: rgb(238, 238, 238); padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; "&gt;
&lt;span style="font-family: 'Courier New'; "&gt;$parents = db_fetch_array(db_query("SELECT p1, p2, p3, p4, p5, p6, p7, p8 FROM {menu_links} WHERE menu_name = '%s' AND link_path IN (". $placeholders .")", $args));&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
D7은 PDO를 기반으로&lt;sup class="footnote"&gt;&lt;a id="footnote_link_77_3" href="#footnote_77_3" onmouseover="tistoryFootnote.show(this, 77, 3)" onmouseout="tistoryFootnote.hide(77, 3)" style="color: #f9650d; font-family: Verdana, Sans-serif"&gt;&lt;span style="display: none"&gt;[각주:&lt;/span&gt;3&lt;span style="display: none"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/sup&gt;&amp;nbsp;OOP방식의 완전히 새로운 DB Abstract layer를 가졌다. 물론 D6 스타일대로 할 수도 있기는 한데 아무튼 새로 도입된 방법은 이렇다.&lt;/div&gt;
&lt;div&gt;
&lt;div class="txc-textbox" style="border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(238, 238, 238); border-right-color: rgb(238, 238, 238); border-bottom-color: rgb(238, 238, 238); border-left-color: rgb(238, 238, 238); background-color: rgb(238, 238, 238); padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; "&gt;
&lt;div class="txc-textbox" style="border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(238, 238, 238); border-right-color: rgb(238, 238, 238); border-bottom-color: rgb(238, 238, 238); border-left-color: rgb(238, 238, 238); background-color: rgb(238, 238, 238); padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; "&gt;
&lt;span style="font-family: 'Courier New'; "&gt;$parents =&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: 'Courier New'; "&gt;db_select('menu_links')&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-&amp;gt;fields('menu_links', array(&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'p1',&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'p2',&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'p3',&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'p4',&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'p5',&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'p6',&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'p7',&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'p8',&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;))&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-&amp;gt;condition('menu_name', $menu_name)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-&amp;gt;condition('link_path', $args, 'IN')&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-&amp;gt;execute()-&amp;gt;fetchAssoc();&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
딴 얘기가 길어졌는데, D7의 DB APIs를 보니 PHP의 DB Abstract layey나 ORM들에 관심이 가서 몇 가지 찾아본 걸 끄적여볼까 한다. PHP용 ORM에 대한 내 경험은, PEAR::DB/DB_DataObject/DB_DataObject_Form_Builder를 좀 빡세게 써본 적이 있고 Propel이라는, Apache Troque의 PHP포트라 설명할 수 있는 ORM을 써본 적이 있다. 그리고 예전 회사에서 두어개 프로젝트에 사용했던 자작 MVC 프레임웍에 Row-data gateway&lt;sup class="footnote"&gt;&lt;a id="footnote_link_77_4" href="#footnote_77_4" onmouseover="tistoryFootnote.show(this, 77, 4)" onmouseout="tistoryFootnote.hide(77, 4)" style="color: #f9650d; font-family: Verdana, Sans-serif"&gt;&lt;span style="display: none"&gt;[각주:&lt;/span&gt;4&lt;span style="display: none"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/sup&gt;와 Data Mapper&lt;sup class="footnote"&gt;&lt;a id="footnote_link_77_5" href="#footnote_77_5" onmouseover="tistoryFootnote.show(this, 77, 5)" onmouseout="tistoryFootnote.hide(77, 5)" style="color: #f9650d; font-family: Verdana, Sans-serif"&gt;&lt;span style="display: none"&gt;[각주:&lt;/span&gt;5&lt;span style="display: none"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/sup&gt;&amp;nbsp;그리고 Active Record&lt;sup class="footnote"&gt;&lt;a id="footnote_link_77_6" href="#footnote_77_6" onmouseover="tistoryFootnote.show(this, 77, 6)" onmouseout="tistoryFootnote.hide(77, 6)" style="color: #f9650d; font-family: Verdana, Sans-serif"&gt;&lt;span style="display: none"&gt;[각주:&lt;/span&gt;6&lt;span style="display: none"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/sup&gt;의 짬뽕쯤 되는 DB layer를 얹어 쓴 적이 있고. 대단한 것처럼 썼지만 PEAR::DBDO 그리고 RoR의 ActiveRecord, Propel에서 얻은 아이디어를 짬뽕한거죠.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
ORM을 쓰다보면 코딩 자체는 편하긴 한데 SQL을 직접 쓸 때 느끼는 자유로움? 이런게 좀 아쉽다. 특히 복잡한 Join이나 Group by/having이 필요한데 ORM께서 멍청한 SQL을 뿜어내는 걸 보고 있자면 열화통이... Propel은 Criteria라는 객체를 가지고 좀 복잡한 WHERE절을 만들어 낼 수 있기는 한데 이걸로 코딩하는게 생각보다 성가시다. 풍월로만 들어 본 DBA따로 계시고 SQL 몰라도 개발하는 그런 곳이나 여러 DBMS를 지원해야 하는 배포용 프로그램을 개발한다면 Portability라도 건지겠지만 가끔 "이런게 오버엔지니어링Over-engineering인가!"하는 기분도 들고 그렇더라.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
특히 Propel을 쓸 때였는데, 아 이래서 자바 마을에선 Configuration monster라는 말도 생기는건가. Propel 쓰려면 Creole도 써줘야 하고, Phing이라는, 자바의 빌드시스템 Ant의 포트, 녀석하고도 좀 친해져야 되고 .. 무슨 xml이 이렇게 많은지, 이거 파싱하는데 드는 품도 만만치 않겠구나. Propel이 나쁘다는 건 아니고, 가볍고 간편하고 실용적인 걸 좋아하는 내 취향에 꼭 맞지는 않더라.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
얘기가 또 길어졌다. 암튼 요번에 Doctrine이라는 PHP ORM을 알게되서 문서를 좀 읽어봤는데 이게 꽤 괜찮아 보인다. Model(즉 DB의 Table) 구조는 YAML로 된 파일에 저장할 수도 있고 (XML이 아니라서 맘에 든다. PEAR::DBDO는 ini 포멧을 쓴다.) Class에 직접 정의할 수도 있다. Join이나 Where 조건을 만드는 문법도 깔끔하다. 이게 생각보다 중요한데 코딩할 때 자연스럽게 써져야 흐름이 안 끊기니까. 그런데 SQL이란 물건이 꽤 복잡해서 이걸 OOP스타일의 코드로 다 표현하는게 쉬운 일이 아니다. 그래서 ORM 툴들도 SQL을 직접 넣게 해주거나 하는 뒷구멍을 가지고 있는데, 이 독트린은 DQL이라는 방법으로 이걸 해결하고 있다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="txc-textbox" style="border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(238, 238, 238); border-right-color: rgb(238, 238, 238); border-bottom-color: rgb(238, 238, 238); border-left-color: rgb(238, 238, 238); background-color: rgb(238, 238, 238); padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; "&gt;
&lt;div class="txc-textbox" style="border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(238, 238, 238); border-right-color: rgb(238, 238, 238); border-bottom-color: rgb(238, 238, 238); border-left-color: rgb(238, 238, 238); background-color: rgb(238, 238, 238); padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; "&gt;
&lt;span style="font-family: 'Courier New'; "&gt;$q = Doctrine_Query::create()&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;-&amp;gt;select('u.id')&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;-&amp;gt;from('User u')&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;-&amp;gt;leftJoin('u.Groups g')&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;-&amp;gt;innerJoin('u.Phonenumbers p WITH u.id &amp;gt; 3')&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;-&amp;gt;leftJoin('u.Email e');&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;echo $q-&amp;gt;getSql();&lt;/span&gt;&lt;br /&gt;
&lt;div class="txc-textbox" style="border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(238, 238, 238); border-right-color: rgb(238, 238, 238); border-bottom-color: rgb(238, 238, 238); border-left-color: rgb(238, 238, 238); background-color: rgb(238, 238, 238); padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; "&gt;
&lt;span style="font-family: 'Courier New'; "&gt;SELECT&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;u.id AS u__id&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;FROM user u&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;LEFT JOIN user_group u2 ON u.id = u2.user_id&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;LEFT JOIN groups g ON g.id = u2.group_id&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;INNER JOIN phonenumber p ON u.id = p.user_id&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;AND u.id &amp;gt; 3&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;LEFT JOIN email e ON u.id = e.user_id&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
문서에 나와있는 예제를 베껴온건데, 이만하면 상당히 훌륭하지 않습니까? User와 Groups가 M:N관계인 것을 모델이 잘이해하고 있다. 그리고 약간의 작업만&lt;sup class="footnote"&gt;&lt;a id="footnote_link_77_7" href="#footnote_77_7" onmouseover="tistoryFootnote.show(this, 77, 7)" onmouseout="tistoryFootnote.hide(77, 7)" style="color: #f9650d; font-family: Verdana, Sans-serif"&gt;&lt;span style="display: none"&gt;[각주:&lt;/span&gt;7&lt;span style="display: none"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/sup&gt;으로 Read/Write Master - Read-only slaves 지원이 되는 구조도 상당히 깔끔하다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
아직 써본 건 아니고 문서만 읽은거라 더 칭찬을 하거나 하면 거짓말이 될 것 같다. 그런데 암튼 간만에 깔끔하고도 여러 기능이 잘 지원되는 라이브러리를 본 것 같아 기분이 약간 들뜬다. Zend Framework와 Symfony 프레임웍에도 통합이 잘 되어있다고 하니 더욱 믿어볼만하지 않은가 싶다. 문서화도 잘 되어있는 점도 +.&amp;nbsp;&lt;a href="http://www.doctrine-project.org/documentation/cookbook/1_1/en/master-and-slave-connections" target="_blank" title="[http://www.doctrine-project.org/documentation/cookbook/1_1/en/master-and-slave-connections]로 이동합니다."&gt;FAQ&lt;/a&gt;도 참고하시라.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
사족. 드루팔의 API들- 촌스럽다. 그런데 그 촌스러운 단순함이 성공의 요인 중 하나인 듯 하다. OOP도 좋고 패턴도 좋지만 그런것도 잘 하면서 실세계의 문제(우리가 프로그래밍으로 해결하려는 진짜 세상의 문제) 해결에도 능한 사람은 그렇게 많지 않아 보인다. 어느쪽이 옳고 그르고 뭐 그런 문제는 당연히 아닌데, 내 옆에서 같이 일하는 사람하고 같이 쓸 수 있는지도 잘 따져봐야겠다. 그런데 난 백수라서.&lt;/div&gt;&lt;div class="footnotes"&gt;
	&lt;ol class="footnotes"&gt;
		&lt;li id="footnote_77_1"&gt;http://www.cmswire.com/cms/web-cms/the-lowdown-drupal-7-means-big-changes-005986.php &lt;a href="#footnote_link_77_1"&gt;[본문으로]&lt;/a&gt;&lt;/li&gt;
		&lt;li id="footnote_77_2"&gt;http://api.drupal.org/api/function/menu_tree_page_data/6 (버전7도 참고) &lt;a href="#footnote_link_77_2"&gt;[본문으로]&lt;/a&gt;&lt;/li&gt;
		&lt;li id="footnote_77_3"&gt;드루팔 프로젝트는  창시자 Dries를 중심으로 PHP4에서 5로의 이행이 더뎌지면 PHP자체의 발전에 좋지 않다고 생각해서 PHP5 사용을 독려하는 Go! PHP5운동에 동참하고 있기도 하다. http://drupal.org/gophp5 &lt;a href="#footnote_link_77_3"&gt;[본문으로]&lt;/a&gt;&lt;/li&gt;
		&lt;li id="footnote_77_4"&gt;http://martinfowler.com/eaaCatalog/rowDataGateway.html &lt;a href="#footnote_link_77_4"&gt;[본문으로]&lt;/a&gt;&lt;/li&gt;
		&lt;li id="footnote_77_5"&gt;http://martinfowler.com/eaaCatalog/dataMapper.html &lt;a href="#footnote_link_77_5"&gt;[본문으로]&lt;/a&gt;&lt;/li&gt;
		&lt;li id="footnote_77_6"&gt;http://martinfowler.com/eaaCatalog/activeRecord.html &lt;a href="#footnote_link_77_6"&gt;[본문으로]&lt;/a&gt;&lt;/li&gt;
		&lt;li id="footnote_77_7"&gt;http://www.doctrine-project.org/documentation/cookbook/1_1/en/master-and-slave-connections &lt;a href="#footnote_link_77_7"&gt;[본문으로]&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  					&lt;embed src="http://api.v.daum.net/static/recombox1.swf" quality="high" flashvars="nid=4854755" allowscriptaccess="always" allowfullscreen="false" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash" wmode="transparent"&gt;&lt;/embed&gt;
						&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=wxLNm37Zf28:VLz_6ayFjt4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=wxLNm37Zf28:VLz_6ayFjt4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=wxLNm37Zf28:VLz_6ayFjt4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/wxLNm37Zf28" height="1" width="1"/&gt;</description>
			<category>신기술,분석</category>
			<category>Abstract layer</category>
			<category>Database</category>
			<category>DBAL</category>
			<category>Doctrine</category>
			<category>drupal</category>
			<category>Library</category>
			<category>ORM</category>
			<category>pdo</category>
			<category>Pear</category>
			<category>php</category>
			<category>Propel</category>
			<category>Symfony</category>
			<category>zend framework</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/77</guid>
			<comments>http://hardworker.tistory.com/77#entry77comment</comments>
			<pubDate>Sat, 21 Nov 2009 22:02:09 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/77</feedburner:origLink></item>
		<item>
			<title>Drush, the Drupal shell 소개</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/g-aqYpYuyHg/78</link>
			<description>드루팔로 개발을 하다보면 뭐랄까. 내가 개발자 맞나 이런 기분이 들 때가 있다. 나야 원래 별다른 IDE도 쓰지 않고 터미널에 vim이면 족한 사람이라 클릭클릭의 연속인 드루팔 생활이 좀 밋밋하기는 하다. 물론 수많은 모듈에다 여러가지 특성을 파악하려면 어지간한 api문서 보는 것 보다 훨씬 머리가 아프긴 하지만.&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;Drush는 DRUpal SHell이다. 이름에서 알 수 있듯, Command-line으로 드루팔 관리를 커맨드라인에서 할 수 있게 해 준다. 모듈을 설치하고 Enable/Disable 하는 건 Drush로 하면 진짜 편하다. 기능들이 꽤 많기는 한데 나도 아직 다 파악을 못해서 간단한 소개 겸 기본 기능만 적어 보겠다.&lt;/div&gt;
&lt;div&gt;&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;&lt;a href="http://drupal.org/project/drush" target="_blank" title="[http://drupal.org/project/drush]로 이동합니다."&gt;&lt;meta charset="utf-8"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51); "&gt;&lt;a href="http://drupal.org/project/drush" target="_blank" title="[http://drupal.org/project/drush]로 이동합니다." style="color: rgb(90, 81, 148) !important; text-decoration: none !important; "&gt;http://drupal.org/project/drush&lt;/a&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;div&gt;우선 Drush를 다운로드해 적당한 곳에 압축을 풀어둔다. 나는 OS X를 쓰는데 /opt/local/bin/drush에 뒀다. 디렉토리 안에 drush라는 이름의 셸스크립트에 alias를 걸거나 PATH를 걸어두면 끝. 참고로 내 Snow Leopard에는 두 버전의 php가 있어서 나는 .profile에&amp;nbsp;alias drush="/opt/local/bin/php /opt/local/bin/drush/drush.php" 요렇게 추가를 해뒀다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
이제 드루팔이 설치된 디렉토리에서 drush를 실행하면 된다. 아 쉽다!&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
사실 조금 더 설명할 필요가 있다 ㅎㅎ. 드루팔이 설치된 디렉토리 아무데서나 실행을 해도 되는 명령이 있고, Multi-site 환경일 때는 몇몇 명령을 sites/[사이트디렉토리] 에서 실행을 해야한다. 물론 사이트 디렉토리에 들어가지 않고도 -l http://example.com 이렇게 옵션을 줘서 할 수도 있기는 한데, 언제 저걸 다 치나. 그냥 cd하고 말지.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div class="txc-textbox" style="border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(238, 238, 238); border-right-color: rgb(238, 238, 238); border-bottom-color: rgb(238, 238, 238); border-left-color: rgb(238, 238, 238); background-color: rgb(238, 238, 238); padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; "&gt;
&lt;div&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ cd drupal-6.x&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ drush dl cck&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ cd sites/example.com&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ drush enable cck &amp;nbsp;// cck 모듈 설치&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ drush updatedb &amp;nbsp; &amp;nbsp;// update.php 실행&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ drush clear cache // admin &amp;gt; config &amp;gt; perfomance &amp;gt; clear cache&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ drush disable field_permissions&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ drush update &amp;nbsp; &amp;nbsp; &amp;nbsp;// 최신 모듈로 업데이트&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;위 명령들만 써도 본전은 뽑는다는 생각이다. 더 많은 명령들은 drush help 명령으로 확인하거나&amp;nbsp;&lt;a href="http://groups.drupal.org/node/28088" target="_blank" title="[http://groups.drupal.org/node/28088]로 이동합니다."&gt;http://groups.drupal.org/node/28088&lt;/a&gt; 를 참고한다. 꽤 많은 모듈들이 drush를 통한 인터페이스를 제공하는데&amp;nbsp;&lt;a href="http://drupal.org/taxonomy/term/4654" target="_blank" title="[http://drupal.org/taxonomy/term/4654]로 이동합니다."&gt;http://drupal.org/taxonomy/term/4654&lt;/a&gt;에서 확인할 수 있다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;http://groups.drupal.org/node/28088&lt;/div&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  					&lt;embed src="http://api.v.daum.net/static/recombox1.swf" quality="high" flashvars="nid=4853986" allowscriptaccess="always" allowfullscreen="false" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash" wmode="transparent"&gt;&lt;/embed&gt;
						&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=g-aqYpYuyHg:QkvKSKyedO8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=g-aqYpYuyHg:QkvKSKyedO8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=g-aqYpYuyHg:QkvKSKyedO8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/g-aqYpYuyHg" height="1" width="1"/&gt;</description>
			<category>Module</category>
			<category>drupal</category>
			<category>drush</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/78</guid>
			<comments>http://hardworker.tistory.com/78#entry78comment</comments>
			<pubDate>Sat, 21 Nov 2009 20:22:01 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/78</feedburner:origLink></item>
		<item>
			<title>빠뜨린 파일 모두 svn 저장소에 추가하기</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/Qf1p-cIjk3Y/76</link>
			<description>svn을 쓰다보면 하위 디렉토리의 파일들 중에 저장소에 들어있지 않은 것만 골라서 svn add를 하고싶을 때가 있다. 새로 만든 파일이 엄청 많거나, 새로운 버전을 다운로드해서 덮어썼더니 새로 생긴 파일들이 많아서 그럴 때도 있고. 이 파일들은 svn st/svn status 명령으로 쉽게 확인을 할 수 있지만 일일이 svn add를 하려면 여간 성가신게 아니다. 그럴때.&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="txc-textbox" style="border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(219, 232, 251); border-right-color: rgb(219, 232, 251); border-bottom-color: rgb(219, 232, 251); border-left-color: rgb(219, 232, 251); background-color: rgb(219, 232, 251); padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; "&gt;
&lt;span style="font-family: Terminal; "&gt;&lt;span style="font-family: 'Courier New'; "&gt;&lt;span style="font-family: 'Courier New'; "&gt;$&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: terminal; "&gt;&lt;span style="font-family: Terminal; "&gt;&lt;span style="font-family: 'Courier New'; "&gt;&lt;span style="font-family: 'Courier New'; "&gt;svn st | grep '^?' | sed 's/^? *//' | xargs svn add&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div style="font-family:terminal"&gt;
&lt;span style="font-family: Dotum; "&gt;대단한 건 아닌데, 유닉스셸에 익숙치 않은 분들을 위해 약간 설명을 보태자면&lt;/span&gt;&lt;/div&gt;
&lt;div style="font-family:terminal"&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div style="font-family:terminal"&gt;
&lt;span style="font-family: Dotum; "&gt;
svn st를 하면 저장소에 안 들어있는(버전관리 대상이 아닌) 파일은 물음표(?)로 표시된다. grep으로 첫 글자가 ?로 시작하는 라인만 걸러낸다. 그 다음에 sed로 ?와 그 뒤에 따라오는 공백문자만 없애버린다. 여기까지 하면 svn add를 해야 할 파일명만 걸러낼 수 있다. 이 다음에는 여러가지 방법을 쓸 수 있는데 xargs가 제일 간단한듯하다.&lt;/span&gt;&lt;/div&gt;
&lt;div style="font-family:terminal"&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div style="font-family:terminal"&gt;
&lt;span style="font-family: Dotum; "&gt;
xargs는 앞에서 넘어온 내용을 뒤에 따라오는 명령의 arguments로 바꿔 준다. awk를 쓴 예제도 아래에 넣어봤다.&lt;/span&gt;&lt;/div&gt;
&lt;div style="font-family:terminal"&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div style="font-family:terminal"&gt;
&lt;div class="txc-textbox" style="border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(219, 232, 251); border-right-color: rgb(219, 232, 251); border-bottom-color: rgb(219, 232, 251); border-left-color: rgb(219, 232, 251); background-color: rgb(219, 232, 251); padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; "&gt;
&lt;span style="font-family: 'Courier New'; "&gt;&lt;b&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ svn st&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp;file&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp;file2&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
M &amp;nbsp; &amp;nbsp; &amp;nbsp;file3&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp;path1/path2/path3/file&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
M &amp;nbsp; &amp;nbsp; &amp;nbsp;blah/blah/foo/bar/filex&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ svn st | grep '^?'&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp;file&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp;file2&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp;path1/path2/path3/file&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ svn st | grep '^?' | sed 's/^? *//'&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
file&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
file2&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
path1/path2/path3/file&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ svn st | grep '^?' | awk '{print $2}' &amp;nbsp;// 위의 sed와 같다&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-weight: normal; "&gt;&lt;span style="font-family: 'Courier New'; "&gt;file&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
file2&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New'; "&gt;
path1/path2/path3/file&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-weight: normal; "&gt;&lt;b&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ svn st | grep '^?' | sed 's/^? *//' | xargs svn add &amp;nbsp; &amp;nbsp;;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span style="font-family: 'Courier New'; "&gt;방법1 : sed + xargs&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-weight: normal; "&gt;&lt;span style="font-family: 'Courier New'; "&gt;( = svn add file file2 path1/path2/pathe/file )&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style="font-family: 'Courier New'; "&gt;$ svn st | grep '^A' | awk '{print "svn add", $2}' | sh &amp;nbsp;;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: 'Courier New'; "&gt;방법2 : awk + sh&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style="font-family:terminal"&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div style="font-family:terminal"&gt;
&lt;span style="font-family: Dotum; "&gt;응용하면 sed + sh로 갈 수도 있고 awk + xargs로 갈 수도 있고.&lt;/span&gt;&lt;/div&gt;
&lt;div style="font-family:terminal"&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;font class="Apple-style-span" face="terminal"&gt;&lt;span style="font-family: Dotum; "&gt;보너스. sed 갤러리(?)&amp;nbsp;&lt;/span&gt;&lt;a href="http://www.shell-fu.org/lister.php?tag=sed" target="_blank" title="[http://www.shell-fu.org/lister.php?tag=sed]로 이동합니다."&gt;&lt;span style="font-family: Dotum; "&gt;http://www.shell-fu.org/lister.php?tag=sed&lt;/span&gt;&lt;/a&gt;&lt;/font&gt;&lt;/div&gt;&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  					&lt;embed src="http://api.v.daum.net/static/recombox1.swf" quality="high" flashvars="nid=4844420" allowscriptaccess="always" allowfullscreen="false" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash" wmode="transparent"&gt;&lt;/embed&gt;
						&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=Qf1p-cIjk3Y:LV0wNCWM2og:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=Qf1p-cIjk3Y:LV0wNCWM2og:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=Qf1p-cIjk3Y:LV0wNCWM2og:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/Qf1p-cIjk3Y" height="1" width="1"/&gt;</description>
			<category>메모</category>
			<category>awk</category>
			<category>sed</category>
			<category>shell</category>
			<category>Subversion</category>
			<category>svn</category>
			<category>unix</category>
			<category>xargs</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/76</guid>
			<comments>http://hardworker.tistory.com/76#entry76comment</comments>
			<pubDate>Fri, 20 Nov 2009 17:27:15 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/76</feedburner:origLink></item>
		<item>
			<title>드루팔 개발, 예쁘고 편하게! (주의사항 추가)</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/YrTp6ebsX1E/72</link>
			<description>&lt;div&gt;
&lt;div class="txc-textbox" style="border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(254, 254, 184); border-right-color: rgb(254, 254, 184); border-bottom-color: rgb(254, 254, 184); border-left-color: rgb(254, 254, 184); background-color: rgb(254, 254, 184); padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; "&gt;
&lt;font class="Apple-style-span" color="#E31600"&gt;&lt;u&gt;2009/11/12 주의사항 추가&lt;/u&gt;&lt;/font&gt; : Admin 모듈과 Rules Administration UI 모듈이 잘 안 맞는 것 같습니다. 아직 확신하기는 이르지만 &lt;s&gt;Admin을 켠 상태에서 Trigger rule에 Action으로 Rule set을 추가할 때 문제가 생깁니다. Admin module을 끄고 Admin theme을 기본으로 바꾸면 문제가 사라집니다.&lt;/s&gt;&amp;nbsp;&lt;s&gt;Theme의 문제인지 모듈의 문제인지 확실하지는 않습니다만 주의해야겠습니다.&lt;/s&gt;&amp;nbsp;Admin module과 함께 사용하는 Slate theme가 문제를 일으키는 것 같습니다. Admin theme만 기본으로 바꿔도 문제를 피해갈 수 있네요.&amp;nbsp;&lt;/div&gt;
&lt;meta charset="utf-8"&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
요즘 깨어있는 시간의 절반 정도를 드루팔과 함께하고 있다. 하루하루 드루팔의 놀라움을 발견하기도 하지만 슬슬 단점과 한계를 느끼기 시작했다. 드루팔로 웹사이트를 만들다 보면 성가신 점이 하나 있는데, Admin 화면에서 클릭할 일이 엄청 많다는거다. 그리고 모듈을 설치할때마다 메뉴도 한두개씩 늘어나고, 어떤 모듈은 설치한 다음에 메뉴가 어디 생긴건지 한참을 찾아야 한다. (아, 물론 Admin &amp;gt; Site Configuration &amp;gt; by module에서 보면 된다.)&lt;div&gt;
&lt;br /&gt;
&lt;div class="imageblock right" style="float: right; margin-left: 10px;"&gt;&lt;a href="http://cfile10.uf.tistory.com/original/18071D214AF4DFA6BB4FC1" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile10.uf.tistory.com/image/18071D214AF4DFA6BB4FC1" alt="" filemime="image/jpeg" filename="drupal-admin-alotofcheckboxestobechecked.png" height="144" width="240"/&gt;&lt;/a&gt;&lt;/div&gt;오른쪽에 화면은 Permissions 설정 페이지인데, 줄잡아 100개쯤 되는 체크박스가 보이고, 스크롤바를 보시면 알겠지만 ... 1860개의 체크박스가 더 있다. 일일이 코딩하며 개발하는 것 보다 좋은 점도 있지다. 그런데 설정할 것이 엄청나게 많고 버그를 포함해 제각각 어떤 영향을 끼치는지 제대로 이해하는 것... 도 쉽지 않지만 저 체크박스를 하나하나 클릭하는게 참 중노동이다. 터치패드로 하나하나 클릭하는 나를 보고 옆에있던 일반인(즉 비개발자)께서 "좀 해줄까?"라고 하더라. 측은해 보인게지. 오른쪽 검지 첫째마디에 류마티스가 올 것 같다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="imageblock left" style="float: left; margin-right: 10px;"&gt;&lt;a href="http://cfile9.uf.tistory.com/original/15230B204AF4E35D78F527" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile9.uf.tistory.com/image/15230B204AF4E35D78F527" alt="" filemime="image/jpeg" filename="drupal-admin-administration-menu-sample.png" height="210" width="240"/&gt;&lt;/a&gt;&lt;/div&gt;모듈을 하나 Enable 할 때마다 늘어나는 체크박스와 메뉴들, 스타일이나 위치에 일관성 없는 경우가 많아 일을 좀 더 어렵게 한다. 게다가 드루팔의 기본 Admin메뉴도 자주쓰는 Modules라던가 Content-type 메뉴를 안쪽에 숨겨놔 시간을 잡아먹게 한다. 몇몇 메뉴를 펼쳐놓도록(expand) 설정을 할 수도 있지만 스크롤다운해서 클릭해야 하니 여전히 불편하다. 이럴 때 Administration menu라는 모듈을 쓰면 화면 위쪽에 드롭다운 메뉴를 만들어줘서 훨씬 낫다.&lt;/div&gt;
&lt;div&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;&lt;a href="http://drupal.org/project/admin_menu" target="_blank" title="[http://drupal.org/project/admin_menu]로 이동합니다."&gt;http://drupal.org/project/admin_menu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
그런데 사실, 진짜 문제는 드루팔이 촌스럽게 생겼다는거다. 드루팔의 창시자인 Dries&lt;sup class="footnote"&gt;&lt;a id="footnote_link_72_1" href="#footnote_72_1" onmouseover="tistoryFootnote.show(this, 72, 1)" onmouseout="tistoryFootnote.hide(72, 1)" style="color: #f9650d; font-family: Verdana, Sans-serif"&gt;&lt;span style="display: none"&gt;[각주:&lt;/span&gt;1&lt;span style="display: none"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/sup&gt;씨께서 "웹에서의 리눅스"&lt;sup class="footnote"&gt;&lt;a id="footnote_link_72_2" href="#footnote_72_2" onmouseover="tistoryFootnote.show(this, 72, 2)" onmouseout="tistoryFootnote.hide(72, 2)" style="color: #f9650d; font-family: Verdana, Sans-serif"&gt;&lt;span style="display: none"&gt;[각주:&lt;/span&gt;2&lt;span style="display: none"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/sup&gt;가 되고자 한다 하셨는데, 모양새의 세련됨이 부족하다는 점에서는 확실히 리눅스랑 닮은 점이 있다. 아- 지나쳤나요? 드루팔이나 리눅스 까는 건 아니에요. 우분투가 좋기는 한데 OSX나 윈도우7보다 예쁘진 않잖아요. 네네. 겉모양만 중요한 건 아니죠. 우리에겐 GPL이 있잖아요.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
아무튼 "좋은 것도 더 좋아질 수 있다"는 차원에서, 하루에 절반을 끼고 사는 드루팔이 좀 더 예쁘면 일할 맛도 더 나지 않을까. 여기에 드루팔의 룩앤휠을 획기적으로 개선해주는 모듈이 있다. &lt;a href="http://drupal.org/project/admin" target="_blank" title="[http://drupal.org/project/admin]로 이동합니다."&gt;Admin module&lt;/a&gt;이 바로 그것인데, 드루팔7에서 채택할 UI를 미리 모듈로 제공하고 피드백을 얻으려는 목적에서 만들었다고 한다. 목적이야 어떻든 간에 일단 설치해보니 모양이 획기적으로 예뻐진다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
이 모듈은 성형수술보다 도덕적으로 우위를 점한다. 뜬금없이 무슨 소리냐고? 그게 왜냐하면 그냥 모양만 바꿔주는 '스킨'이 아니라 메뉴의 구성과 위치를 쓰임새있게 바꿔주는, 속까지 '착해'지도록 하는 모듈이라 그렇다. 이를테면 드루팔에는 두 가지 테마가 있는데 웹사이트 방문자가 보는 테마 그리고 관리자용 테마(Admin theme) 이렇게 두 가지다. 그런데 드루팔의 기본 관리페이지에서는 방문자테마는 Admin &amp;gt; Site Building &amp;gt; Themes에서 고르고, Admin theme는 Admin &amp;gt; Site Configuration &amp;gt; Administration theme에서 설정해야된다. 헷갈린다. 그런데 이 Admin module을 설치하면 이걸 Appearance라는 한 메뉴 안에 통합해버린다! 자주 쓰는&amp;nbsp;Modules메뉴도 최상위에 배치되서 아주 편하다.&amp;nbsp;예쁜 아이콘도 나오고 Save, Cancel같은 버튼도 예쁘고도 큼직하게 바뀌어 예전처럼 정밀조준클릭 하지 않아도 되니 일 할 맛이 조금 더 난다.&amp;nbsp;(모듈을 Enable한 다음에 Appearance &amp;gt; Administration theme에서 Slate라는 테마를 선택해줘야 제대로 보인다.) &amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile8.uf.tistory.com/original/1125D10B4AF4EE0250DA77" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile8.uf.tistory.com/image/1125D10B4AF4EE0250DA77" alt="" filemime="" filename="cfile8.uf@1125D10B4AF4EE0250DA77.png" height="310" width="480"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;Admin module 적용 후의 첫 화면&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile25.uf.tistory.com/original/1225D10B4AF4EE0251FD30" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile25.uf.tistory.com/image/1225D10B4AF4EE0251FD30" alt="" filemime="" filename="cfile25.uf@1225D10B4AF4EE0251FD30.png" height="256" width="480"/&gt;&lt;/a&gt;&lt;p class="cap1"&gt;Admin module 적용한 Permissions 화면. 그래도 예쁘니까 클릭하기 수월하다. (에..?)&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
덧붙여서 Drupal의 모듈 설치나 업데이트, 각종 관리를 셸 명령으로 편하게 할 수 있는 Drush - DRUpal SHell을 소개하고 싶기는 한데, 아직 제대로 써보질 못한 관계로 어느정도 익숙해지면 본격 소개하겠습니다. 쉽게 말하자면 터미널에서 $ drush dl views 이렇게 하면 views 모듈을 설치해준다는 - 드루팔이 데비안/우분투 리눅스라면 drush는 apt-get쯤 되겠네요. 성격 급하신 분들은&amp;nbsp;&lt;a href="http://drupal.org/project/drush" target="_blank" title="[http://drupal.org/project/drush]로 이동합니다."&gt;http://drupal.org/project/drush&lt;/a&gt;에서 확인하시면 되겠습니다.&lt;/div&gt;&lt;div class="footnotes"&gt;
	&lt;ol class="footnotes"&gt;
		&lt;li id="footnote_72_1"&gt;http://drupal.org/user/1 &lt;a href="#footnote_link_72_1"&gt;[본문으로]&lt;/a&gt;&lt;/li&gt;
		&lt;li id="footnote_72_2"&gt;"We want to make Drupal the best web content management platform; “the Linux of the web”." http://buytaert.net/acquia-my-drupal-startup &lt;a href="#footnote_link_72_2"&gt;[본문으로]&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="blogger-news-widget" style="width: 100%; text-align: center"&gt;
		  					&lt;embed src="http://api.v.daum.net/static/recombox1.swf" quality="high" flashvars="nid=4699411" allowscriptaccess="always" allowfullscreen="false" bgcolor="#ffffff" width="400" height="80" type="application/x-shockwave-flash" wmode="transparent"&gt;&lt;/embed&gt;
						&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=YrTp6ebsX1E:W1SVz6NKLDU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=YrTp6ebsX1E:W1SVz6NKLDU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=YrTp6ebsX1E:W1SVz6NKLDU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/YrTp6ebsX1E" height="1" width="1"/&gt;</description>
			<category>Recipes</category>
			<category>admin module</category>
			<category>administration menu</category>
			<category>CMS</category>
			<category>drupal</category>
			<category>drush</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/72</guid>
			<comments>http://hardworker.tistory.com/72#entry72comment</comments>
			<pubDate>Thu, 12 Nov 2009 13:08:43 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/72</feedburner:origLink></item>
		<item>
			<title>전에 뒤적거린 것들에 보태 - mongoDB, Beanstalkd</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/CyZqkBoCPvw/73</link>
			<description>요전에 좀 끄적거렸던&amp;nbsp;&lt;a href="http://hardworker.tistory.com/54" target="_blank" title="[http://hardworker.tistory.com/54]로 이동합니다."&gt;요즘 뒤적거린 것들&lt;/a&gt;에 업데이트 할만한 걸 알게되서 좀 적어볼까 한다.&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
mongoDB는, 역시 얼마 전 &lt;a href="http://hardworker.tistory.com/68" target="_blank" title="[http://hardworker.tistory.com/68]로 이동합니다."&gt;소개했던&lt;/a&gt; Angular와 마찬가지로 Document-oriented DBMS다. 홈페이지에는 "The best features of document databases, key/values stores, and RDBMSes in one."라고 아주 굵은 글씨로 써놨는데, 좋은 건 다 자기들이 한다는 건지 ㅎㅎ 아무튼 Commercial support로 제대로 된 지원 서비스같은 것도 하는데다 주요 프로그래밍 언어의 바인딩을 다 구비하고 있는걸 보니 관심을 좀 가져봐도 될 것 같다.&lt;/div&gt;
&lt;div&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;&lt;a href="http://www.mongodb.org/" target="_blank" title="[http://www.mongodb.org/]로 이동합니다."&gt;http://www.mongodb.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
Beanstalkd는 '요즘 뒤적거린 것들'에 짧게 언급한 Gearman과 같이 놓고 비교할만한 물건이다. 실제로 RabbitMQ, StompServer (처음 들어보는 것들;;) 다른 Message Queue들과 &lt;a href="http://www.darkcoding.net/software/choosing-a-message-queue-for-python-on-ubuntu-on-a-vps/" target="_blank" title="[http://www.darkcoding.net/software/choosing-a-message-queue-for-python-on-ubuntu-on-a-vps/]로 이동합니다."&gt;비교한 글&lt;/a&gt;도 있으니 참고해보자. Beanstalkd는 Facebook에서 썼다고 하고 Gearman은 Yahoo!등에서 적용중이라 하니 역시 참고하시고.&lt;/div&gt;
&lt;div&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;&lt;a href="http://kr.github.com/beanstalkd/" target="_blank" title="[http://kr.github.com/beanstalkd/]로 이동합니다."&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 51); "&gt;&lt;/span&gt;&lt;/a&gt;&lt;a href="http://kr.github.com/beanstalkd/" target="_blank" title="[http://kr.github.com/beanstalkd/]로 이동합니다."&gt;http://kr.github.com/beanstalkd/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gearman.org/" target="_blank" title="[http://gearman.org/]로 이동합니다."&gt;http://gearman.org/&lt;/a&gt;&lt;a href="http://kr.github.com/beanstalkd/" target="_blank" title="[http://kr.github.com/beanstalkd/]로 이동합니다."&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
Message Queuing System은 언제 쓸까? 나도 일을 하면서 이런게 꼭 필요했던 적이 두어번 있었다. 내가 했던 일이 주로 중소규모의 쇼핑몰의 데이터를 모아서 큰 쇼핑몰과 주고받거나 하는 일이었는데 흔히 이미지 리사이징이 이슈가 됐다. 쇼핑몰에서 사진이란게 굉장히 중요하기 때문에 꼭 맞는 사이즈로 바꿔주는게 중요한데, 요즘은 어떤지 모르겠지만 옥션에 상품을 올리면 사진이 바로 안 뜨고 좀 기다려야 나오는데 이것도 같은 이치다. 또 다른 경우는 역시 SOAP API로 상대방에 상품을 대량 등록하는 경우였는데, 뭐 매일 한번씩 전체를 전송한다 이런 개념이 아니라 화면에서 체크박스 선택해서 몇십개씩 등록을 하면 바로바로 전송을 해야했다. 몇십개가 등록되는 걸 화면에 보여주면서 몇 분에서 몇십 분씩 기다리게 할 수는 없으니까 "대기"상태로 보여주고 백그라운드에서 큐잉 시스템이 열심히 전송 ...&amp;nbsp;이런 걸 크론Cron으로 돌리는 경우도 있는데 나는 크론보다는 큐에 넣는게 좋다고 생각한다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
그런데, 나는 아직도 머리가 나빠서 잘 이해가 안 되는 MapReduce가 조명을 받는 상황이랑 이런 메세지 큐들이 많이 나오는거랑 무관해 보이지가 않는다. 모든 기술이 그렇지만, 단순화해서 놓고 보면 신기술이라는 것들도 옛날에 있던거랑 비슷한 경우가 많다. 15년 전에 종로 중앙정보처리학원 EDPS(라 쓰고 음담패설이라고 읽기도 하는) 배울 때도 Real Time Process하고 Batch Process하고 두 가지 있다고 배웠으니까. 맵리듀스던 메시지큐건 '당장 안 해도 되는건 따로 돌리자'는 아름다운 '미루기' 문화를 반영하는 것 아닐까.&lt;/div&gt;
&lt;div&gt;
&lt;ul style="list-style-type: disc; "&gt;
&lt;li&gt;&lt;a href="http://www.scribd.com/doc/14690639/MapReduce-and-Queues-for-MySQL-Using-Gearman" target="_blank" title="[http://www.scribd.com/doc/14690639/MapReduce-and-Queues-for-MySQL-Using-Gearman]로 이동합니다."&gt;http://www.scribd.com/doc/14690639/MapReduce-and-Queues-for-MySQL-Using-Gearman&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
그런가 하면, 최신 기술들 중에는 '이걸 써서 [초유명웹사이트]가 부하를 절반으로 줄였다'이런식의 홍보를 좀 하는 경우도 있는데 (물론 오픈소스계에서는 너무 심한 뻥은 안 치지만) 은빛 탄환은 없다고 하였지 않은가. 이를테면 Gearman은 데몬이 죽으면 큐도 같이 사라지는 단점이 있다고 한다.&lt;sup class="footnote"&gt;&lt;a id="footnote_link_73_1" href="#footnote_73_1" onmouseover="tistoryFootnote.show(this, 73, 1)" onmouseout="tistoryFootnote.hide(73, 1)" style="color: #f9650d; font-family: Verdana, Sans-serif"&gt;&lt;span style="display: none"&gt;[각주:&lt;/span&gt;1&lt;span style="display: none"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/sup&gt;&amp;nbsp;장단점은 항상 잘 따져볼 일이다.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
뱀다리로.. Beanstalkd를 처음 봤을 때 Subversion hosting중 하나인&amp;nbsp;&lt;a href="http://beanstalkapp.com/" target="_blank" title="[http://beanstalkapp.com/]로 이동합니다."&gt;http://beanstalkapp.com/&lt;/a&gt;가 떠올랐었다는...&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
추가 : Rails and Beanstalkd :&amp;nbsp;&lt;a href="http://nubyonrails.com/articles/about-this-blog-beanstalk-messaging-queue" target="_blank" title="[http://nubyonrails.com/articles/about-this-blog-beanstalk-messaging-queue]로 이동합니다."&gt;http://nubyonrails.com/articles/about-this-blog-beanstalk-messaging-queue&lt;/a&gt;&lt;/div&gt;&lt;div class="footnotes"&gt;
	&lt;ol class="footnotes"&gt;
		&lt;li id="footnote_73_1"&gt;http://highscalability.com/product-gearman-open-source-message-queuing-system &lt;a href="#footnote_link_73_1"&gt;[본문으로]&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=CyZqkBoCPvw:Qy9ACMWVZfs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=CyZqkBoCPvw:Qy9ACMWVZfs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=CyZqkBoCPvw:Qy9ACMWVZfs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/CyZqkBoCPvw" height="1" width="1"/&gt;</description>
			<category>신기술,분석</category>
			<category>beanstalk</category>
			<category>gearman</category>
			<category>message queue</category>
			<category>MongoDB</category>
			<category>메세지큐</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/73</guid>
			<comments>http://hardworker.tistory.com/73#entry73comment</comments>
			<pubDate>Tue, 10 Nov 2009 23:56:11 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/73</feedburner:origLink></item>
		<item>
			<title>드루팔로 웹사이트 만들기 네 번째 / Building website with Drupal part 4</title>
			<link>http://feedproxy.google.com/~r/Hardworker/~3/KFSU9sXmGOA/71</link>
			<description>원래는 다 해서 4~5편 정도로 그것도 그닥 친절하지 않게 쓸 기분이었는데 하다보니 스크린샷까지 하게되고 벌써 4편인데 아직 반에 반 밖에 진도가 안 나갔다. 이러다가 너무 길어져서 -&amp;gt; 계속 미루게 되서 끝끝내 끝이 안 나는 상황이 될까 벌써부터 걱정이 됩니다.&lt;div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
이번 편에는 예고한 대로 썸네일을 만드는 Image Cache 모듈을 설명하겠습니다. Image Cache 모듈은 이미지를 다루거나(manipulating) 캐시하는 능력을 가진 모듈이고, Image 모듈이랑은 별 관계가 없다. 이미지를 다룰 백엔드로 PHP의 GD2를 쓸 수도 있고, ImageMagick을 쓸 수도 있다. 물론 이미지매직을 쓰려면 convert 파일의 경로를 설정해줘야 한다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
ImageAPI, ImageCache, ImageCache UI 그리고 ImageAPI GD 혹은 ImageAPI ImageMagick 중 하나를 골라 enable한다. 나는 속편하게 ImageAPI GD를 골랐다. Admin에 아래 두 가지 메뉴가 새로 생긴다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
Admin &amp;gt; Site Configuration &amp;gt; Image API : 간단해서 보면 알 수 있음.&lt;/div&gt;
&lt;div&gt;Admin &amp;gt; Site Building &amp;gt; ImageCache : 여기가 진짜로 썸네일을 만들거나 하는 Preset 설정하는 곳이다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile3.uf.tistory.com/original/142B001B4AF0F5E63673BA" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile3.uf.tistory.com/image/142B001B4AF0F5E63673BA" alt="" filemime="image/png" filename="drupal-admin-add-new-imagecache.png" height="188" width="419"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
지금까지와 마찬가지로 알파벳과 숫자 그리고 언_더_스_코_어만으로 이름을 지어야 한다. 개발자에겐 어려운 일도 아니다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile23.uf.tistory.com/original/123CC51B4AF0F5F0156ED5" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile23.uf.tistory.com/image/123CC51B4AF0F5F0156ED5" alt="" filemime="image/png" filename="drupal-admin-list-of-imagecache-actions.png" height="413" width="443"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
이제 이 Preset에서 뭘 할 수 있는지를 알 수 있다. 위 화면에서 보면 알 수 있듯이, Crop이나 Resize, Scale 같은 작업을 원하는 만큼 추가해 놓으면 원본 이미지가 이것들을 차례대로 거쳐 최종 결과물이 나오게 된다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
내 경우엔 Add Scale And Crop 하나로만 작업했다. 180 x 120 정도의 사이즈를 지정해주면 쓸만한 모양이 된다. 이 화면 아래에는 드루팔의 마스코트 이미지를 활용해 Preview가 제공되니 결과물을 미리 예측하는데 큰 도움이 된다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
이렇게 만든 Image Cache Preset을 적용해보자. 그렇다. 이 Preset을 만든 것 만으로는 아무 일도 일어나지 않는다. 아래 화면을 보자.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
&lt;div class="imageblock center" style="text-align: center; clear: both;"&gt;&lt;a href="http://cfile29.uf.tistory.com/original/1519F61C4AF0F82D494C11" rel="lightbox" target="_blank"&gt;&lt;img src="http://cfile29.uf.tistory.com/image/1519F61C4AF0F82D494C11" alt="" filemime="image/png" filename="drupal-admin-content-type-apply-imagecache-preset-to-the-fi.png" height="255" width="590"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
다시 Content type에서 이전에 만들었던 Photo Album으로 옮겨가자. 그리고 이전에 다루지 않았던 Display fields 섹션으로 이동하면 위와 같은 화면을 볼 수 있다. 이곳에서 CCK필드가 화면에 보여지는 방식을 정할 수 있는데 조금전에 만든 ImageCache Preset 역시 "보여지는 방식" 중의 하나로서 선택할 수가 있다. 굉장히 간단하면서 유연한 방식이라 하지 않을 수 없다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
View를 설명할 때 Teaser와 Full node에 대해서 이전에도 간단히 얘기했었는데, 이 화면에서 각 CCK 필드에 대해 Teaser와 Full Node가 어떻게 다르게 보여질지, 그리고 제외(exclude)할지를 설정할 수 있어 굉장히 편하다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
그리고 캡쳐한 위의 화면에서 보듯이 Image Cache Preset도 이미지만 보여줄 것인지, 이미지가 노드로 링크되게 할 것인지 아니면 이미지를 보여주지 말고 file path 혹은 URL이 보이도록 할 것인지 세세하게 설정할 수 있다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
자, 이제 갤러리 화면에 가서 완성된 화면을 보자. 여전히 화면이 어수선하지만 개발자로서는 이 쯤에서 "개발을 다 했다"고 생각을 할 수 있다. 이제 그만 미투데이나 구글리더를 보다가 칼퇴근을...&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
모두 4편에 걸쳐 Content type과 Views 모듈 그리고 ImageCache 모듈을 활용해 전형적이지는 않지만 간단한 갤러리를 만드는 과정을 함께했다. 앞으로 갤러리, 자원봉사자 등록, 중고품거래 등의 기능 중에서 지금까지 소개하지 않은 드루팔의 기능을 살펴보기 좋은 것을 골라 연재를 계속 할 것이다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;
1편에서 지금까지 "80%를 완료"했다고 했는데, 개발과정이 늘 그렇듯이 착각이었다. 개발자는 요구사항이 간단하다고 생각했고, 고객사마께서는 요구사항을 변경하셨다. 그리고 본인도 아직 드루팔을 익혀나가는 중이기 때문에 - 공부에는 끝이 없다 - 더 좋은 방법을 찾으면 새로 구현을 하기도 했다. 그럼 다음편에 뵈어요.&lt;/div&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=KFSU9sXmGOA:OJViD5vQATs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Hardworker?a=KFSU9sXmGOA:OJViD5vQATs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hardworker?i=KFSU9sXmGOA:OJViD5vQATs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Hardworker/~4/KFSU9sXmGOA" height="1" width="1"/&gt;</description>
			<category>Recipes</category>
			<category>CMS</category>
			<category>drupal</category>
			<category>ImageCache</category>
			<category>드루팔</category>
			<author>sh.</author>
			<guid isPermaLink="false">http://hardworker.tistory.com/71</guid>
			<comments>http://hardworker.tistory.com/71#entry71comment</comments>
			<pubDate>Wed, 04 Nov 2009 12:56:33 +0900</pubDate>
		<feedburner:origLink>http://hardworker.tistory.com/71</feedburner:origLink></item>
	</channel>
</rss>

