<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>루미넌스 - TechNote</title>
    <link>https://lumitech.tistory.com/</link>
    <description>루미넌스의 테크노트입니다.
프로그래머로서 살면서 얻은 쓸만한 지식들을 나누고자 만든 공간입니다^^</description>
    <language>ko</language>
    <pubDate>Wed, 10 Jun 2026 16:54:39 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>루미넌스</managingEditor>
    <item>
      <title>Python String/Unicode translate() 함수</title>
      <link>https://lumitech.tistory.com/entry/Python-String-Unicode-translate-function</link>
      <description>&lt;p&gt;문자(열) 교체 함수 str.translate(), unicode.translate() 사용법&lt;/p&gt;
&lt;p&gt;우선 일반 문자열(unicode object 아닌 문자열)부터.&lt;/p&gt;
&lt;p&gt;str.translate(tbl,del)두개의 인자를 받는다. tbl은 0~255의 ASCII문자를 각각 대체할 문자로 만든 매핑테이블이다. 말이 테이블이지 길이 256짜리 문자열이다. 즉, ASCII코드 32인 문자(스페이스)는 매핑테이블의 32번째 글자로 바꿔주는 것이다. 따라서 tbl은 꼭 길이 256인 문자열(str object)여야 한다.&lt;/p&gt;
&lt;p&gt;string.translate(s, tbl, del) == s.translate(tbl, del) 이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;바로 예제 ㄱㄱㅅ&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol class=&quot;code&quot; style=&quot;margin-left: 2em;&quot;&gt;
&lt;li&gt;&lt;div style=&quot;border: 1px solid rgb(121, 165, 228); padding: 10px; background-color: rgb(219, 232, 251);&quot; class=&quot;txc-textbox&quot;&gt;
#원본 문자열. \n는 개행, \t는 탭문자, \b는 앞글자를 지운다.&lt;br /&gt;
tstr = &quot;&quot;&quot;가나다\n\t\b123 4\b5\b6\babcd efgh (789) -_-+ 라마바 사2사2 文字&quot;&quot;&quot;&lt;br /&gt;
&lt;br /&gt;
# 원본 문자열을 프린트&lt;br /&gt;
print &quot;original:&quot;, tstr&lt;br /&gt;
&lt;br /&gt;
# 간단한 translate. 각 바이트의 첫 비트로 translate&lt;br /&gt;
tbl = &quot;&quot;&lt;br /&gt;
for cc in range(256):&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;if cc &amp;lt; 128: tbl += &quot;0&quot;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;else: tbl += &quot;1&quot;&lt;br /&gt;
print &quot;tbl =&quot;, tbl&lt;br /&gt;
print &quot;initial bit:&quot;, tstr.translate(tbl)&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;컨트롤 캐릭터를 지우는데 활용해 보기.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol class=&quot;code&quot;&gt;
&lt;li&gt;&lt;div style=&quot;border: 1px solid rgb(121, 165, 228); padding: 10px; background-color: rgb(219, 232, 251);&quot; class=&quot;txc-textbox&quot;&gt;
# ascii code값이 32미만(컨트롤캐릭터)이면 32(space)로 바꾸는 매핑테이블. \n \r \t \b 이런거 다 공백으로 바뀐다.&lt;br /&gt;
TRMAP_ASCII_CTRL2SPACE = &quot;&quot;.join([chr(max(32,cc)) for cc in range(256)])&lt;br /&gt;
print &quot;ctrl to space:&quot;, tstr.translate(TRMAP_ASCII_CTRL2SPACE)&lt;br /&gt;
&lt;br /&gt;
# 컨트롤 캐릭터를 공백으로 바꾸고 홀수는 지우는 변환.&lt;br /&gt;
print &quot;ctrl to space deleting '13579':&quot;, tstr.translate(TRMAP_ASCII_CTRL2SPACE, &quot;13579&quot;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;컨트롤 캐릭터를 공백으로 바꾸지 않고 del인자를 써서 삭제할 수도 있다.&lt;/p&gt;
&lt;ol class=&quot;code&quot;&gt;
&lt;li&gt;&lt;div style=&quot;border: 1px solid rgb(121, 165, 228); padding: 10px; background-color: rgb(219, 232, 251);&quot; class=&quot;txc-textbox&quot;&gt;
# 아무것도 바꾸지 않는 매핑 테이블&lt;br /&gt;
TRMAP_NOCHANGE = &quot;&quot;.join([chr(cc) for cc in range(256)])&lt;br /&gt;
&lt;br /&gt;
# 컨트롤 캐릭터만 삭제&lt;br /&gt;
ASCII_CTRLCHARS = &quot;&quot;.join([chr(cc) for cc in range(32)])&lt;br /&gt;
print &quot;delete ctrl chars:&quot;, tstr.translate(TRMAP_NOCHANGE, ASCII_CTRLCHARS)&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;character code가 127이하인 문자를 삭제하는 del인자를 써서 한글, 한자, 일어 등 멀티바이트문자만 남길 수도 있다. 간단하므로 예제 코드 생략.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다음은 unicode.translate()&lt;/p&gt;
&lt;p&gt;이건 사용법은 비슷하지만 두가지 차이점이 있다. 첫째, 매핑 테이블은 진짜-_-테이블이라는것. 둘째, del 인자를 주지 않는다는 것.&lt;/p&gt;
&lt;p&gt;매핑테이블은 dict로 정의한다. 그래서 메모리를 크게 잡아먹을 수도 있다. 그래도 함수 수행자체는 뎁따 빠르므로 활용가치가 높다.&lt;/p&gt;
&lt;p&gt;매핑 테이블을 만드는 유용한 함수를 하나 같이 소개한다.&lt;/p&gt;
&lt;p&gt;__builtins__.zip(seq1, seq2, ... ) 함수는 리스트를 반환하는데, seq1, seq2, ... 에서 순서대로 하나씩 꺼내서 tuple로 묶은 리스트를 반환한다.&lt;/p&gt;
&lt;p&gt;즉, zip([1,2,3], ('a', 'b', 'c')) 는 [(1,'a'), (2,'b'), (3,'c')] 를 리턴한다.&lt;/p&gt;
&lt;p&gt;dict object는 zip의 결과를 초기화 인수로 받을 수 있도록 만들어져 있으므로, 이걸 활용하면 unicode translate 맵핑테이블을 쉽게 작성할 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;한글이 나타나는 unicode range가 정해져 있으므로, 한글을 공백으로 바꿔버리는 예제를 만들어 보자.&lt;/p&gt;
&lt;ol class=&quot;code&quot;&gt;
&lt;li&gt;&lt;div style=&quot;border: 1px solid rgb(121, 165, 228); padding: 10px; background-color: rgb(219, 232, 251);&quot; class=&quot;txc-textbox&quot;&gt;
# 위에서 사용한 테스트 문자열을 unicode로 바꾼다.&lt;br /&gt;
utstr = unicode(tstr, &quot;utf8&quot;)&lt;br /&gt;
&lt;br /&gt;
# unicode에서 한글이 나타나는 영역이다.&lt;br /&gt;
__unicode_range_hangul = range(0xac00, 0xd7a4)&lt;br /&gt;
__unicode_range_hangul_jamo1 = range(0x1100, 0x11fa)&lt;br /&gt;
__unicode_range_hangul_jamo2 = range(0x3131, 0x318f)&lt;br /&gt;
__unicode_range_korean = __unicode_range_hangul + __unicode_range_hangul_jamo1 + __unicode_range_hangul_jamo2&lt;br /&gt;
&lt;br /&gt;
__build_mapping_range2char = lambda r,uc: zip(r, uc * len(r))
&lt;br /&gt;
&lt;br /&gt;
# 한글을 모두 공백으로 바꿔버리는 매핑테이블&lt;br /&gt;
trmap_korean = dict(__build_mapping_range2char(__unicode_range_korean, u&quot; &quot;))&lt;br /&gt;
&lt;br /&gt;
print &quot;utstr:&quot;, utstr&lt;br /&gt;
print &quot;utstr without Korean chars:&quot;, utstr.translate(trmap_korean)&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;삭제를 하려면 매핑 테이블에서 빈 문자열( u&quot;&quot; )을 주면 된다. __build_mapping_range2char() 람다함수를 조금 고치면 된다. 예제 생략.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: right;&quot;&gt;이 글은 &lt;a href=&quot;http://basher.springnote.com/&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: right;&quot;&gt;근데 코드 영역이 이상하게 붙여져서 티스토리 편집기로 다시 수정했습니다ㅡ_ㅡ 젝일;;&lt;br /&gt;
&lt;/p&gt;</description>
      <category>Python</category>
      <category>Python</category>
      <category>string</category>
      <category>TIP</category>
      <category>Unicode</category>
      <author>루미넌스</author>
      <guid isPermaLink="true">https://lumitech.tistory.com/17</guid>
      <comments>https://lumitech.tistory.com/entry/Python-String-Unicode-translate-function#entry17comment</comments>
      <pubDate>Mon, 29 Sep 2008 15:53:58 +0900</pubDate>
    </item>
    <item>
      <title>python 디버그: line 번호 찍기</title>
      <link>https://lumitech.tistory.com/entry/python-%EB%94%94%EB%B2%84%EA%B7%B8-line-%EB%B2%88%ED%98%B8-%EC%B0%8D%EA%B8%B0</link>
      <description>디버그할때 가장 만만한게 표준출력(stdout)으로 몇가지 메세지를 찍어보며 버그 위치와 내용을 진단하는 것이다. 어떤 언어를 사용하든 가장 손쉽게 적은양만 고치고도, 의외로 높은 성과를 내는 방법이다.&lt;br /&gt;&lt;br /&gt;파이썬에서 이런 방법을 쓸때 프린트하는 라인번호를 함께 찍는 간단한 방법을 메모해 둔다.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;border: 1px solid rgb(204, 204, 204); padding: 10px; background-color: rgb(231, 231, 231);&quot;&gt;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;import inspect&lt;/span&gt;&lt;br style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;&lt;br style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;def lineno():&lt;/span&gt;&lt;br style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;&quot;&quot;&lt;/span&gt;&lt;br style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; 이 함수를 호출한 곳의 라인번호를 리턴한다.&lt;/span&gt;&lt;br style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;&quot;&quot;&lt;/span&gt;&lt;br style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; return inspect.getlineno(inspect.getouterframes(inspect.currentframe())[-1][0])&lt;br /&gt;&lt;br /&gt;print lineno(), &quot;message&quot;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;</description>
      <category>Python</category>
      <category>CODE</category>
      <category>Debug</category>
      <category>Python</category>
      <category>Tips</category>
      <author>루미넌스</author>
      <guid isPermaLink="true">https://lumitech.tistory.com/16</guid>
      <comments>https://lumitech.tistory.com/entry/python-%EB%94%94%EB%B2%84%EA%B7%B8-line-%EB%B2%88%ED%98%B8-%EC%B0%8D%EA%B8%B0#entry16comment</comments>
      <pubDate>Fri, 1 Aug 2008 01:01:37 +0900</pubDate>
    </item>
    <item>
      <title>python 키 입력 받는 함수; input, raw_input, getpass</title>
      <link>https://lumitech.tistory.com/entry/python-%ED%82%A4-%EC%9E%85%EB%A0%A5-%EB%B0%9B%EB%8A%94-%ED%95%A8%EC%88%98-input-rawinput-getpass</link>
      <description>python builtin에는 두가지 키입력 처리 함수가 있다. input()과 raw_input()&lt;br /&gt;둘다 공통적으로 한개의 문자열 인자를 사용할 수 있고, 이 인자가 키입력 프롬프트로 사용된다.&lt;br /&gt;&lt;br /&gt;두 함수는 미묘한 차이점이 있으므로 용도에 따라 주의깊게 선택하여 사용해야 한다.&lt;br /&gt;차이점은, raw_input()은 엔터키를 입력할때까지 입력된 &quot;문자열&quot;을 리턴하며, input()은 raw_input()이 받은 결과를 eval()한 결과와 같이 리턴한다는 점이다. 즉, input() == eval(raw_input())이 된다.&lt;br /&gt;&lt;br /&gt;
&lt;DIV style=&quot;BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #e7e7e7&quot;&gt;&lt;FONT face=&quot;'courier new',courier,monospace&quot;&gt;&amp;gt;&amp;gt;&amp;gt; ibuff=input('input?')&lt;br /&gt;input?&lt;FONT color=#993366&gt;&lt;STRONG&gt;123&lt;/STRONG&gt;&lt;/FONT&gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; ibuff&lt;br /&gt;123&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; ibuff=input('input?')&lt;br /&gt;input?&lt;FONT color=#993366&gt;&lt;STRONG&gt;asdf&lt;/STRONG&gt;&lt;/FONT&gt;&lt;br /&gt;&lt;br /&gt;&lt;FONT color=#d41a01&gt;Traceback (most recent call last):&lt;br /&gt;&amp;nbsp; File &quot;&amp;lt;pyshell#7&amp;gt;&quot;, line 1, in &amp;lt;module&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; ibuff=input('input?')&lt;br /&gt;&amp;nbsp; File &quot;&amp;lt;string&amp;gt;&quot;, line 1, in &amp;lt;module&amp;gt;&lt;br /&gt;NameError: name 'asdf' is not defined&lt;/FONT&gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; ibuff=input('input?')&lt;br /&gt;input?&lt;STRONG&gt;&lt;FONT color=#993366&gt;'asdf'&lt;/FONT&gt;&lt;/STRONG&gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; ibuff&lt;br /&gt;'asdf'&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; rbuff=raw_input('raw_input?')&lt;br /&gt;raw_input?&lt;FONT color=#993366&gt;&lt;STRONG&gt;1234&lt;/STRONG&gt;&lt;/FONT&gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; rbuff&lt;br /&gt;'1234'&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; rbuff=raw_input('raw_input?')&lt;br /&gt;raw_input?&lt;FONT color=#993366&gt;&lt;STRONG&gt;qwer&lt;/STRONG&gt;&lt;/FONT&gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; &lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; rbuff&lt;br /&gt;'qwer'&lt;/FONT&gt;&lt;/DIV&gt;&lt;br /&gt;두 함수 모두 인자를 주지 않으면 아무 프롬프트(prompt)없이 입력을 무한정 기다린다.&lt;br /&gt;그리고 아무 입력 없이 엔터키를 누르면 input()함수는 evaluation할 내용이 없는 것이 되므로 SyntaxError를 일으키지만 raw_input()은 그냥 엔터키를 누르면 빈 문자열을 리턴한다.&lt;br /&gt;&lt;br /&gt;키보드로부터 입력받는 내용은 화면에 보이지 말아야 할 때가 있다.(echo off) 위의 두 함수는 이런 경우에 사용하기 까다롭다. 이럴땐 getpass module을 import해서 사용한다. getpass.getpass() 함수는 default prompt로 'Password: ' 가 설정되어 있다.&lt;br /&gt;&lt;br /&gt;
&lt;DIV style=&quot;BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #e7e7e7&quot;&gt;&lt;FONT face=&quot;'courier new',courier,monospace&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import getpass&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; pswd=getpass.getpass()&lt;br /&gt;Password: &lt;EM&gt;&lt;FONT color=#d41a01&gt;&lt;STRONG&gt;(여기서 qwerasdf를 입력하지만 화면에는 보이지 않는다.)&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; pswd&lt;br /&gt;'qwerasdf'&lt;br /&gt;&lt;/FONT&gt;&lt;/DIV&gt;&lt;br /&gt;getpass는 Windows에서는 잘 작동하지 않을 수도 있다.&lt;br /&gt;</description>
      <category>Python</category>
      <category>Python</category>
      <category>Tips</category>
      <category>프로그래밍</category>
      <author>루미넌스</author>
      <guid isPermaLink="true">https://lumitech.tistory.com/15</guid>
      <comments>https://lumitech.tistory.com/entry/python-%ED%82%A4-%EC%9E%85%EB%A0%A5-%EB%B0%9B%EB%8A%94-%ED%95%A8%EC%88%98-input-rawinput-getpass#entry15comment</comments>
      <pubDate>Sun, 13 Jul 2008 00:36:39 +0900</pubDate>
    </item>
    <item>
      <title>python object의 멤버 attribute를 런타임에 생성하기</title>
      <link>https://lumitech.tistory.com/entry/python-object-attribute-runtime-creation</link>
      <description>python을 사용하여 프로그램을 작성하다보면 class를 정의하여 사용하게 되는 경우가 많이 있습니다.&lt;br /&gt;class의 인스턴스로서 만들어진 object는 class에서 정의하고 있는 attribute를 가지고 있습니다. 그런데, 스크립트 실행 도중에 class에 정의되어 있지 않은 attribute를 정의하고 싶을 때가 있습니다.&lt;br /&gt;&lt;br /&gt;이 기능을 구현해둔 예가 optparse.Values 라는 class입니다.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;border: 1px solid rgb(204, 204, 204); padding: 10px; background-color: rgb(231, 231, 231);&quot;&gt;import optparse&lt;br /&gt;v = optparse.Values()&lt;br /&gt;v.a=1&lt;br /&gt;print v.a&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;이 코드가 문제없이 실행되고 1을 찍습니다.&lt;br /&gt;&lt;br /&gt;파이썬에는 역시 dict라고 하는 dictionary 또는 map이라고 불리는 기본 데이터타입이 있습니다.&lt;br /&gt;key-value의 쌍을 모아둔 데이터입니다.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;border: 1px solid rgb(204, 204, 204); padding: 10px; background-color: rgb(231, 231, 231);&quot;&gt;d = {'a' : 1, 'b' : 2}&lt;br /&gt;print d['a'], d['b']&lt;/div&gt;&lt;br /&gt;위와같이 정의하고 사용합니다.&lt;br /&gt;또는,&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;border: 1px solid rgb(204, 204, 204); padding: 10px; background-color: rgb(231, 231, 231);&quot;&gt;d={}&lt;br /&gt;d['a'] = 1&lt;br /&gt;d['b'] = 2&lt;br /&gt;print d['a'], d['b']&lt;/div&gt;&lt;br /&gt;이렇게 정의해도 결과는 같습니다.&lt;br /&gt;&lt;br /&gt;별것 아닌거 같아 보이는 이런 사용 방법이 매우 편리할 때가 있습니다.&lt;br /&gt;어떤 값들이 저장될지가 코딩타임에 결정하기 어려운 경우죠..&lt;br /&gt;위의 두 가지 경우가 별로 유용한 예로서 대표적인게 윈도우에서 흔히보는 &lt;a href=&quot;http://www.faqs.org/rfcs/rfc822.html&quot; target=&quot;_blank&quot;&gt;RFC822&lt;/a&gt;스타일의 *.ini 설정파일입니다.&lt;br /&gt;&lt;div style=&quot;border: 1px solid rgb(204, 204, 204); padding: 10px; background-color: rgb(231, 231, 231);&quot;&gt;# comment&lt;br /&gt;[section]&lt;br /&gt;key = value&lt;br /&gt;key: value&lt;/div&gt;&lt;br /&gt;위와같은 형식으로 작성되는데, 이 설정파일을 객체화하여 사용하기 위해서는 위의 기능이 참으로 아쉬워집니다.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;border: 1px solid rgb(204, 204, 204); padding: 10px; background-color: rgb(231, 231, 231);&quot;&gt;[mysqld]&lt;br /&gt;log-bin = /var/log/mysql/binlog&lt;/div&gt;&lt;br /&gt;위는 mysql설정파일인 my.cnf의 일부분입니다. mysql의 설정에 따라 적절히 행동하는 프로그램을 만들고자 할 때에, 이 설정파일을 읽어서 객체화하여,&lt;br /&gt;&lt;div style=&quot;border: 1px solid rgb(204, 204, 204); padding: 10px; background-color: rgb(231, 231, 231);&quot;&gt;if conf_mysql.mysqld.log_bin.startswith(&quot;/var/log&quot;):&lt;br /&gt;&amp;nbsp; &amp;nbsp; os._exit(1)&lt;/div&gt;&lt;br /&gt;이런걸 만든다고 하면 정말이지 아쉬운 기능입니다.&lt;br /&gt;이밖에도 예는 많이 있을 겁니다.(생각은 딱히 안납니다만..ㅎㅎ;;;)&lt;br /&gt;&lt;br /&gt;저의 경우에 이런 용도로 사용되는 클래스를 많이 설계하게되다보니, 위 두가지가 모두 가능한 클래스를 만들어 씁니다. BaseObject라는 class에 위 기능을 구현해 두고 필요할때 상속해서 사용하면 됩니다.&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/tistoryfile/fs6/18_1_25_25_blog96420_attach_0_0.JPG?original&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Ftistoryfile%2Ffs6%2F18_1_25_25_blog96420_attach_0_0.JPG%3Foriginal&quot; alt=&quot;사용예&quot;/&gt;
  &lt;p class=&quot;cap1&quot;&gt;사용예. 변수나 함수 모두 이미 만들어진 객체에 추가해 줄 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/tistoryfile/fs5/18_1_25_25_blog96420_attach_0_3.jpg?original&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Ftistoryfile%2Ffs5%2F18_1_25_25_blog96420_attach_0_3.jpg%3Foriginal&quot; alt=&quot;pydoc결과&quot;/&gt;
  &lt;p class=&quot;cap1&quot;&gt;pydoc결과 예시&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/tistoryfile/fs5/18_1_25_25_blog96420_attach_0_1.JPG?original&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Ftistoryfile%2Ffs5%2F18_1_25_25_blog96420_attach_0_1.JPG%3Foriginal&quot; width=&quot;526&quot; height=&quot;944&quot; alt=&quot;BaseObject의 doctest 결과&quot;/&gt;
  &lt;p class=&quot;cap1&quot;&gt;BaseObject의 doctest 결과&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/tistoryfile/fs5/18_1_25_25_blog96420_attach_0_2.JPG?original&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Ftistoryfile%2Ffs5%2F18_1_25_25_blog96420_attach_0_2.JPG%3Foriginal&quot; width=&quot;525&quot; height=&quot;984&quot; alt=&quot;MyObject의 doctest 결과&quot;/&gt;
  &lt;p class=&quot;cap1&quot;&gt;MyObject의 doctest 결과&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;위 예제에 보여진 두개의 간단한 코드를 첨부합니다.&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;https://t1.daumcdn.net/tistoryfile/fs5/18_1_25_25_blog96420_attach_0_4.zip?original&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://i1.daumcdn.net/cfs.tistory/v/0/blog/image/extension/zip.gif&quot; style=&quot;vertical-align: middle;&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;invalid-file&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;</description>
      <category>Python</category>
      <category>builtin 응용</category>
      <category>CODE</category>
      <category>flexible object</category>
      <category>object</category>
      <category>Python</category>
      <category>runtime</category>
      <author>루미넌스</author>
      <guid isPermaLink="true">https://lumitech.tistory.com/13</guid>
      <comments>https://lumitech.tistory.com/entry/python-object-attribute-runtime-creation#entry13comment</comments>
      <pubDate>Thu, 20 Mar 2008 00:15:25 +0900</pubDate>
    </item>
    <item>
      <title>my.cnf에 wait_timeout설정하는 문제</title>
      <link>https://lumitech.tistory.com/entry/mycnf-wait-timeout-problem</link>
      <description>&lt;ul&gt;&lt;li&gt;구글링을 해보면 이 문제로 많은 사람들이 삽질을 이미 했다. 그리고 대다수가 버그라고 생각하고 있었다.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;버그가 아니다. 당연한 삽질이었다.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;my.cnf&lt;/span&gt;의 &lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;[mysqld]&lt;/span&gt; section에 &lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;wait_timeout=300&lt;/span&gt; 으로 설정 추가하고 다시 띄운다.(기본값은 28800)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;mysql&lt;/span&gt;로 접속하여 &lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;show variables like 'wait_timeout'&lt;/span&gt; 을 해본다.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;어라? 28800이다. 왜 적용이 안되는 걸까..&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;show variables like '%timeout%'&lt;/span&gt;을 해보면, &lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;interactive_timeout&lt;/span&gt;이라는게 있는데, 이게 바로 커맨드라인 클라이언트인 mysql (보통 &lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;/usr/local/mysql/bin/mysql&lt;/span&gt; 또는 &lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;/usr/local/bin/mysql&lt;/span&gt; 등등)을 말하는 거다. 당연히 mysql 기본 클라이언트로 interactive mode접속하면 &lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;wait_timeout&lt;/span&gt;을 &lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;interactive_timeout&lt;/span&gt;값으로 바꿔주는거다.&lt;/li&gt;&lt;li&gt;왜냐구?&amp;nbsp; interactive mode로 접속했으니까 그렇지 ㅡ_ㅡ&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;show global variables like '%timeout%'&lt;/span&gt;을 해본다.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;wait_timeout=300&lt;/span&gt;으로 설정이 잘 되어있다. 즉, interactive mode가 아닌 접속 쓰레드에 대해서 wait_timeout이 새로 설정한 값이 된다는거다. 당연히 &lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;mysql&lt;/span&gt;로 접속해서는 확인을 못한다.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;본인이 작성하는 프로그램의 라이브러리를 이용하여 테스트 커넥션을 만들고 300초간 아무것도 하지 않은 후에 쿼리를 하나 날려보자 &quot;&lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;SELECT 1&lt;/span&gt;&quot; 같은..&lt;br /&gt;&lt;/li&gt;&lt;li&gt;에러가 난다. &lt;span style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;2006, Mysql server has gone away&lt;/span&gt;. 설정한 wait_timeout이 먹었다.&lt;/li&gt;&lt;li&gt;뭐.. 그런거다.. 설정 잘 돼있는거 가지구 착각하고, 삽질하지 말자.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;</description>
      <category>Tips</category>
      <category>my.cnf</category>
      <category>MySQL</category>
      <category>삽질</category>
      <category>설정</category>
      <author>루미넌스</author>
      <guid isPermaLink="true">https://lumitech.tistory.com/11</guid>
      <comments>https://lumitech.tistory.com/entry/mycnf-wait-timeout-problem#entry11comment</comments>
      <pubDate>Thu, 31 Jan 2008 17:21:12 +0900</pubDate>
    </item>
    <item>
      <title>Google pagerank를 알아내는 python코드</title>
      <link>https://lumitech.tistory.com/entry/Google-pagerank-checker-in-python</link>
      <description>테크노트 블로그 정말 간만에 씁니다.&lt;br /&gt;&lt;br /&gt;서핑중에 &lt;a href=&quot;http://snippets.dzone.com/posts/show/3284&quot; target=&quot;_blank&quot;&gt;Ruby로 된 Google PageRank Checker&lt;/a&gt; 라는 프로그램이 있어서 Python버전으로 단순 번역한 것입니다. 제가 루비를 안써봐서 익숙한 언어인 python으로 변경했습니다.ㅡㅡㅋ&lt;br /&gt;&lt;br /&gt;자세한 코드 설명은 생략합니다.&lt;br /&gt;구글툴바가 웹서핑시에 방문한 URL과 그 URL을 변환한 정수키값을 이용하여 툴바가 페이지랭크를 조회하는 유효한 URL을 생성하고, HTTP Request 결과로 받은 텍스트를 쪼개서 페이지랭크를 얻어오는 것이 로직의 전부입니다.&lt;br /&gt;대부분의 코드는 URL을 정당한 키값으로 변환하는데 사용되었습니다.&lt;br /&gt;&lt;br /&gt;MS-Windows 기반의 시스템에서 작동하기 위해서는 첫줄을 지우던가 적절히 고쳐야 될겁니다.&lt;br /&gt;&lt;br /&gt;--------&lt;span style=&quot;font-family: monospace;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;pre&gt;&lt;blockquote style=&quot;font-family: 'courier new',courier,monospace;&quot;&gt;#!/usr/bin/env python&lt;br /&gt;# -*- coding: utf-8 -*-&lt;br /&gt;&quot;&quot;&quot;&lt;br /&gt;Original version(ruby): http://snippets.dzone.com/posts/show/3284&lt;br /&gt;&quot;&quot;&quot;&lt;br /&gt;M = 0x100000000 # modulo for unsigned int 32bit(4byte)&lt;br /&gt;&lt;br /&gt;class GooglePageRank:&lt;br /&gt;	def __init__(self, uri):&lt;br /&gt;		self.uri = uri&lt;br /&gt;		self.iurl = &quot;info:%s&quot; % uri&lt;br /&gt;&lt;br /&gt;	def m1(self, a, b, c, d):&lt;br /&gt;		return (((a + (M - b) + (M - c)) % M) ^ (d % M)) % M # mix/power mod&lt;br /&gt;&lt;br /&gt;	def i2c(self, i):&lt;br /&gt;		return [i &amp;amp; 0xff, i&amp;gt;&amp;gt;8 &amp;amp; 0xff, i&amp;gt;&amp;gt;16 &amp;amp; 0xff, i&amp;gt;&amp;gt;24 &amp;amp; 0xff]&lt;br /&gt;&lt;br /&gt;	def c2i(self, s, k=0):&lt;br /&gt;		try:&lt;br /&gt;			try: c0 = ord(s[k])&lt;br /&gt;			except: c0 = 0&lt;br /&gt;			try: c1 = ord(s[k+1])&lt;br /&gt;			except: c1 = 0&lt;br /&gt;			try: c2 = ord(s[k+2])&lt;br /&gt;			except: c2 = 0&lt;br /&gt;			try: c3 = ord(s[k+3])&lt;br /&gt;			except: c3 = 0&lt;br /&gt;			c2i = ((c3*0x100+c2)*0x100+c1)*0x100+c0&lt;br /&gt;		except:&lt;br /&gt;			c2i = 0&lt;br /&gt;		return c2i&lt;br /&gt;&lt;br /&gt;	def mix(self, a, b, c):&lt;br /&gt;		a %= M; b %= M; c %= M&lt;br /&gt;		a = self.m1(a, b, c, c&amp;gt;&amp;gt;13); b = self.m1(b, c, a, a&amp;lt;&amp;lt; 8); c = self.m1(c, a, b, b&amp;gt;&amp;gt;13)&lt;br /&gt;		a = self.m1(a, b, c, c&amp;gt;&amp;gt;12); b = self.m1(b, c, a, a&amp;lt;&amp;lt;16); c = self.m1(c, a, b, b&amp;gt;&amp;gt; 5)&lt;br /&gt;		a = self.m1(a, b, c, c&amp;gt;&amp;gt; 3); b = self.m1(b, c, a, a&amp;lt;&amp;lt;10); c = self.m1(c, a, b, b&amp;gt;&amp;gt;15)&lt;br /&gt;		return [a, b, c]&lt;br /&gt;&lt;br /&gt;	def old_cn(self, iurl = None):&lt;br /&gt;		if not iurl:&lt;br /&gt;			iurl = self.iurl&lt;br /&gt;		a = 0x9E3779B9; b = 0x9E3779B9; c = 0xE6359A60&lt;br /&gt;		size = len(iurl)&lt;br /&gt;		k = 0&lt;br /&gt;		while size &amp;gt;= k+12:&lt;br /&gt;			a += self.c2i(iurl, k); b += self.c2i(iurl, k+4); c += self.c2i(iurl, k+8)&lt;br /&gt;			a, b, c = self.mix(a, b, c)&lt;br /&gt;			k += 12&lt;br /&gt;		a += self.c2i(iurl, k)&lt;br /&gt;		b += self.c2i(iurl, k+4)&lt;br /&gt;		c += (self.c2i(iurl, k+8) &amp;lt;&amp;lt; 8) + size&lt;br /&gt;		a, b, c = self.mix(a, b, c)&lt;br /&gt;		return c&lt;br /&gt;&lt;br /&gt;	def cn(self):&lt;br /&gt;		ch = self.old_cn()&lt;br /&gt;		ch = ((ch / 7) &amp;lt;&amp;lt; 2) | ((ch - (ch / 13) * 13) &amp;amp; 7)&lt;br /&gt;		new_url = &quot;&quot;&lt;br /&gt;		for ii in range(20):&lt;br /&gt;			for i in self.i2c(ch):&lt;br /&gt;				new_url += chr(i)&lt;br /&gt;			ch -=9&lt;br /&gt;		return int(&quot;6%s&quot; % self.old_cn(new_url))&lt;br /&gt;	&lt;br /&gt;	def request_uri(self):&lt;br /&gt;		from urllib import quote&lt;br /&gt;		uri = &quot;http://toolbarqueries.google.com/search?client=navclient-auto&amp;amp;hl=en&amp;amp;ch=%s&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8&amp;amp;features=Rank&amp;amp;q=info:%s&quot;&lt;br /&gt;		cn = self.cn()&lt;br /&gt;		quoted_uri = quote(self.uri, safe=&quot;&quot;)&lt;br /&gt;		return uri % (cn, quoted_uri)&lt;br /&gt;&lt;br /&gt;	def page_rank(self, uri=None):&lt;br /&gt;		if not uri:&lt;br /&gt;			uri = self.uri&lt;br /&gt;		else:&lt;br /&gt;			self.uri = uri&lt;br /&gt;		uri = self.request_uri()&lt;br /&gt;		from urllib2 import urlopen&lt;br /&gt;		doc = urlopen(uri)&lt;br /&gt;		return int(doc.read().split(&quot;:&quot;)[2])&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;def Main(cmdoptions, cmdargs):&lt;br /&gt;	for cmdarg in cmdargs:&lt;br /&gt;		pr = GooglePageRank(cmdarg).page_rank()&lt;br /&gt;		print &quot;%4s/10 (%s)&quot; % (pr, cmdarg)&lt;br /&gt;&lt;br /&gt;	return 0&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if __name__ == &quot;__main__&quot;:&lt;br /&gt;	import os, optparse&lt;br /&gt;	cmdparser = optparse.OptionParser(usage=&quot;%prog &amp;lt;uri&amp;gt; [&amp;lt;uri&amp;gt; ...]&quot;)&lt;br /&gt;	(cmdoptions, cmdargs) = cmdparser.parse_args()&lt;br /&gt;	&lt;br /&gt;	os._exit(Main(cmdoptions, cmdargs))&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;--------&lt;br /&gt;&lt;pre&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;https://t1.daumcdn.net/tistoryfile/fs6/7_1_25_25_blog96420_attach_0_0.py?original&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://i1.daumcdn.net/cfs.tistory/v/0/blog/image/extension/unknown.gif&quot; style=&quot;vertical-align: middle;&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;invalid-file&lt;/a&gt;
  &lt;p class=&quot;cap1&quot;&gt;이 파일을 다운로드 받으셔도 됩니다.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/tistoryfile/fs6/7_1_25_25_blog96420_attach_0_1.jpg?original&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Ftistoryfile%2Ffs6%2F7_1_25_25_blog96420_attach_0_1.jpg%3Foriginal&quot; width=&quot;640&quot; height=&quot;55&quot; alt=&quot;실행 예제&quot;/&gt;
  &lt;p class=&quot;cap1&quot;&gt;실행 예제(클릭해서보세요); 꼭 URL은 &amp;quot;&amp;quot;로 묶어서 사용해야 Querystring의 &amp;amp;가 shell에 의해 잘못 해석되지 않습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;/pre&gt;</description>
      <category>Python</category>
      <category>Google</category>
      <category>pagerank</category>
      <category>Python</category>
      <author>루미넌스</author>
      <guid isPermaLink="true">https://lumitech.tistory.com/10</guid>
      <comments>https://lumitech.tistory.com/entry/Google-pagerank-checker-in-python#entry10comment</comments>
      <pubDate>Sat, 26 Jan 2008 00:09:48 +0900</pubDate>
    </item>
    <item>
      <title>Python Built-in 가지고 놀기</title>
      <link>https://lumitech.tistory.com/entry/PythonBuiltinBasic</link>
      <description>&lt;h1&gt;기본컨셉: __builtin__&lt;/h1&gt;
&lt;p&gt;&amp;nbsp;Python에서는 모든것이 object이다. 그리고 모두 &lt;strong&gt;object&lt;/strong&gt; class를 상속받아 정의되어 있다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;object&lt;/strong&gt; class의 instance인 object는 모두 __ (underscore 2개) 로 둘러쌓인 __bultins__ 를 물려받게 된다. __builtins__ 와 object는 모두 &lt;strong&gt;__builtin__&lt;/strong&gt;에 정의되어 있다. 이 모듈은 파이썬이 시작되면서 항상 로드되는 파이썬의 가장 밑바닥의 초석이다. 파이썬이 실행되면 마치 from __builtin__ import *; import __builtin__ as __builtins__ 를 수행한것과 같은 상태라고 생각하면 쉽다.(꼭 같지는 않다. python 기본 실행 상태에서 __main__이라는 이름을 가지는 메인스레드에서 __builtin__의 모든 name을 디렉토리에 갖고 있지는 않다. dir()로 확인해보시길..)&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;&lt;img title=&quot;python_builtin.png&quot; class=&quot;attachment&quot; src=&quot;http://basher.springnote.com/pages/429778/attachments/187333&quot; alt=&quot;python_builtin.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;위 화면을 보면, python을 실행만 하고 아무것도 안한 상태에서 기본으로 로드된 hash()와 repr()의 id는 강제로 __builtins__를 import 한 후에도 바뀌지 않는 것을 볼 수 있는데, Python은 import명령을 사용해도 이미 적재된 동일한 개체를 다시 적재하지 않기 때문이다. (강제로 다시 적재하고 싶을 때에는 reload()를 써야 한다.)&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Python에는 C++과 같은 Operator overloading이 없다. 혹자들이 말하는 &quot;코드를 어지럽게 만들 뿐인&quot; 군더더기 문법은 존재하지 않는 것이고 이런 필요성을 모두 객체(object)에 흡수하였다. class를 정의할 때 instance의 __함수를 재정의(override)해 줌으로써, operator overloading을 구현할 수 있다.&lt;/p&gt;
&lt;p&gt;__함수가 Python __builtin__의 모든것은 아니다. C/C++과 같은 전통적인(?) 언어에서 built-in data types라고 말하는 int, float, 등등이 Python에서는 모두 object로 다루어지기 때문에 이런 유용한 기본 데이터타입 역시 __builtin__에서 정의하고 있다.&lt;/p&gt;
&lt;br /&gt;
&lt;h1&gt;Built-in Data Types&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;이 문서에는 전통적으로 built-in type으로 알려져있는 각종 상수들과 몇몇 자주 쓰이는 기본적인 데이터 타입만 다루고 있다. 자세한 내용은 &lt;strong&gt;pydoc __builtins__&lt;/strong&gt;에서 확인할 수 있다.&lt;/li&gt;
&lt;li&gt;Number&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;int(), long(): int()는 정수객체를 리턴하는 built-in 함수처럼 사용할 수 있지만, 사실은 int 라는 클래스의 생성자(__init__()함수) 를 호출하여 객체를 만드는 클래스의 이름이다.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;널리 쓰이는 32비트 프로세서에서 2**32-1이 int object가 가질 수 있는 최대값이다. 이 값보다 크면 int는 long object를 생성하여 리턴한다. long은 크기 제한이 없다.&lt;/li&gt;
&lt;li&gt;int, long 모두 한개 또는 두 개의 인자를 받아 object를 생성한다. 필수 인자인 첫번째 인자는 10진수 정수값 또는 정수값이 될수 있는 문자열이며, 선택사항인 두번째 인자는 기수법이다. 단 두번째 인자를 가질 때에는 첫번째 인자는 정수가 될 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;float(): 소수점 이하의 값이 있는 실수형의 데이터&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;정수의 경우와 마찬가지로 float class의 instance가 생성된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;complex(): 실수부와 허수부를 갖는 복소수 데이터&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;String&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;__builtin__.object.basestring.str과 __builtin__.object.basestring.unicode 의 두가지 문자열이 있다.&lt;/li&gt;
&lt;li&gt;str는 확장ASCII문자열까지 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;unicode는 생성자 두번째 인자로 넘겨주는 인코딩의 unicode문자열을 사용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Collection&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;순서가 있는 sequence과 순서가 없는 set이 있다. object생성후 값의 일부를 수정할 수 없는 immutable과 수정할수 있는 mutable이 있다.&lt;/li&gt;
&lt;li&gt;Python의 Collection 타입들은 한가지 데이터타입의 원소만을 모을 필요가 없다. 정수, 실수, class instance등을 한곳에 묶어둘 수 있다. 이를테면, [1, 2.5, &quot;asdf&quot;] 는 정상적인 list object이다.&lt;/li&gt;
&lt;li&gt;tuple(): immutable sequence. t = (1, 2, 3) 과 같이 괄호()로 묶은 n차원의 순서쌍. t[1] == 2이지만, t[1] = 3은 불가능하다.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;참고: str, unicode 도 tuple과 같이 일부를 수정할수 없는 immutable이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;list(): mutable sequence. l = [1, 2, 3] 과 같이 괄호[]로 묶은 n개의 배열. C/C++/JAVA의 array와 같은 표기방식. l[1] = 5와 같이 일부를 수정할 수 있다.&lt;/li&gt;
&lt;li&gt;set(): mutable set. s = set([1, 2, 3, 3, 4]) 와 같이 Iterable object를 unique원소의 집합으로 만든다. 이 경우 s는 1, 2, 3, 4의 4개의 원소를 갖는다. ss = set([5, 4, 3, 2, 1])라고 ss를 만들어도 ss는 1, 2, 3, 4, 5 5개의 순서를 유지하지 않는다.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;여러개의 set object에 대해 교집합(intersection), 합집합(union), 차집합(difference)의 연산을 할 수 있도록 set class에 정의되어 있다. 이 연산들은 class method이기 때문에, set.union(s, ss) 또는 s.union(ss) 의 두가지 사용법이 모두 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;dict(): mutable set. d = {&quot;a&quot;:1, &quot;b&quot;:2, &quot;c&quot;:3}와 같이 괄호{}로 묶은 n개의 Key:Value 쌍. d[key] = value와 같이 []연산자안에 key를 주어 값에 접근 또는 수정, 추가를 할 수 있다. 즉, d[&quot;a&quot;] == 1이고, d[&quot;b&quot;] = 20으로 수정 가능하고, d[&quot;d&quot;] = 4와 같이 추가 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;알아두면 유용한 _ _ 함수&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;이곳에 나열한 것이 builtin의 전부는 아니다.&lt;/li&gt;
&lt;li&gt;__repr__()이 정의되어 있는 class의 instance는 repr() 함수의 인자로 줄수 있다. 마찬가지로, __add__()가 정의되어 있는 class의 instance는 + 연산자의 좌측(L-value)로 사용할 수 있다.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;repr()과 __repr__()은 다른 함수이다. 이문서에서의 repr(x) == x.__repr__()와 같은 표기는 이 절의 나머지 함수들에도 똑같이 적용되며 굳이 매번 설명을 달지는 않았다. 일반적으로 같은 결과가 리턴되는것 뿐이다. repr()함수는 __builtin__에 정의된 함수이며 object class의 함수이다. 이 함수는 내부적으로 인자로 받은 object의 __repr__()를 호출하여 받은 결과를 그대로 리턴한다. 이 역시 나머지 함수들의 설명에도 똑같이 적용되는 원리이다. 이를테면 int(x) == x.__int__()인 것은 int(x)가 x.__int__()를 호출한 결과를 리턴한다는 표현을 한 것이다. 하지만 int(x)는 바로 x.__int__()를 호출하여 이를 리턴하기만 하는 것은 아니므로 각 builtin에 대해서는 별도의 문서를 참고해야 한다. shell에서 pydoc __builtins__ 또는 python interactive mode에서 help(__builtins__)를 보면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;h2&gt;표현, 타입캐스팅, 변환&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;__init__(): class의 constructor(생성자)&lt;/li&gt;
&lt;li&gt;__repr__(): representation 함수&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;repr(x) == x.__repr__()&lt;/li&gt;
&lt;li&gt;Python interactive mode의 프롬프트에서 아무 object나 하나 입력해 보자. 이때 엔터키 누른 직후에 나오는 것이 바로 그 object의 __repr__()값이다.&lt;/li&gt;
&lt;li&gt;많은 builtin data type은 그 내용이 분명하고 간단하기 때문에 __str__()과 같은 결과를 리턴한다. 즉, &lt;strong&gt;문자열화&lt;/strong&gt;한다. 이 경우에 __str__()과의 차이점은 object를 문자열로 표현하긴 하되, quoatation하지 않는다는 것이다. __repr__()을 명시적으로 부르면 quoatation한다.&lt;/li&gt;
&lt;li&gt;보다 복잡한 object (어떤 class로부터 생성한 instance)의 경우에는 &lt;strong&gt;&amp;lt;type과 object의 address&amp;gt;&lt;/strong&gt;의 형태로 보여준다. 이는 __repr__()이 정의 되지 않았을 경우에 파이썬의 기본행동이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img title=&quot;python_builtin_repr_.png&quot; class=&quot;attachment&quot; src=&quot;http://basher.springnote.com/pages/429778/attachments/181670&quot; alt=&quot;python_builtin_repr_.png&quot;&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;__str__(): 문자열 변환 함수&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;str(x) == x.__str__()&lt;/li&gt;
&lt;li&gt;str변환이 일어나는 가장 대표적인 경우는 &quot;%s&quot; 로 문자열을 만들 때이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;__int__():&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;int(x) == x.__int__()&lt;/li&gt;
&lt;li&gt;정수형으로 캐스팅을 시도한다.&lt;/li&gt;
&lt;li&gt;모든 class에 이 함수가 정의되어 있지는 않다. 상식적으로 정수로 캐스팅 될것 같지 않은 경우에는 (int로의 캐스팅이라는 기본행동이 정의되지 않는 클래스들) __int__()가 없기 때문에 int(x)를 시도하면 AttributeError라 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;__long__():&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;long(x) == x.__long__()&lt;/li&gt;
&lt;li&gt;__int__()와 매우 유사.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;__float__():&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;float(x) == x.__float__()&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;__hash__():&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;hash(x) == x.__hash__()&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;__getitem__(i):&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;list, tuple, basestring과 같은 순서가 있는 컬렉션 객체에 대해 특정 원소를 접근하는 방법을 제공한다.&lt;/li&gt;
&lt;li&gt;[]연산자 오버로딩에 해당한다. 즉, x[3] == x.__getitem__(3) 이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;__getslice__(i, j):&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;__getitem__()과 같이 순서가 있는 컬렉션 객체에 대해 특정 구간의 원소를 접근하는 방법을 제공한다.&lt;/li&gt;
&lt;li&gt;특정구간의 원소집합을 slice라 한다.&lt;/li&gt;
&lt;li&gt;x[3:5] == x.__getslice__(3,5) 는 3 &amp;lt;= index &amp;lt; 5를 만족하는 원소구간을 리턴한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;산술연산자&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;특정한 목적에 의해 설계된 class instance끼리의 사칙연산을 정의할 수 있다.&lt;/li&gt;
&lt;li&gt;연산자 오버로딩으로 생각하면 된다.&lt;/li&gt;
&lt;li&gt;binary operators; __add__(), __sub__(), __mul__(), __div__(), __divmod__():&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;x + y == x.__add__(y)&lt;/li&gt;
&lt;li&gt;x - y == x.__sub__(y)&lt;/li&gt;
&lt;li&gt;x * y == x.__mul__(y)&lt;/li&gt;
&lt;li&gt;x / y == x.__div__(y)&lt;/li&gt;
&lt;li&gt;x % y == x.__divmod__(y)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;unary operators; __neg__(), __pos__():&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;-x == x.__neg__()&lt;/li&gt;
&lt;li&gt;+x == x.__pos__()&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img title=&quot;python_builtin_ex.png&quot; class=&quot;attachment&quot; src=&quot;http://basher.springnote.com/pages/429778/attachments/187556&quot; alt=&quot;python_builtin_ex.png&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;이상의 내용을 사용하여 간단히 복소수 클래스를 정의한 경우&lt;/p&gt;

&lt;h2&gt;비교연산자&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;산술 연산자보다 때로는 더욱 유용하고 막강한 기능이 비교연산자 함수를 오버로딩 하는 것이다. 이것들을 잘 정의해 두면, 비교구문을 단순화하여 보다 직관적이고 간단명료한 코드를 작성할 수 있다.&lt;/li&gt;
&lt;li&gt;비교연산구문과 마찬가지로 모두 bool값(True, False)를 리턴한다.&lt;/li&gt;
&lt;li&gt;==, &amp;gt;, &amp;gt;=, &amp;lt;, &amp;lt;=가 각각 __eq__(), __gt__(), __ge__(), __lt__(), __le__()이다.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;x == y : x.__eq__(y) ; x is &lt;strong&gt;EQ&lt;/strong&gt;ual to y&lt;/li&gt;
&lt;li&gt;x &amp;gt; y : x.__gt__(y) ; x is &lt;strong&gt;G&lt;/strong&gt;rater &lt;strong&gt;T&lt;/strong&gt;han y&lt;/li&gt;
&lt;li&gt;x &amp;gt;= y : x.__ge__(y) ; x is &lt;strong&gt;G&lt;/strong&gt;rater than or &lt;strong&gt;E&lt;/strong&gt;qual to y&lt;/li&gt;
&lt;li&gt;x &amp;lt; y : x.__lt__(y) ; x is &lt;strong&gt;L&lt;/strong&gt;ess &lt;strong&gt;T&lt;/strong&gt;han y&lt;/li&gt;
&lt;li&gt;x &amp;lt;= y : x.__le__(y) ; x is &lt;strong&gt;L&lt;/strong&gt;ess than or &lt;strong&gt;E&lt;/strong&gt;qual to y&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Reference&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Python Documentation in python interactive mode&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;p align=&quot;right&quot;&gt;이 글은 &lt;a href=&quot;http://basher.springnote.com/pages/429778&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;</description>
      <category>Python</category>
      <category>BASIC</category>
      <category>builtin</category>
      <category>Language</category>
      <category>Python</category>
      <author>루미넌스</author>
      <guid isPermaLink="true">https://lumitech.tistory.com/9</guid>
      <comments>https://lumitech.tistory.com/entry/PythonBuiltinBasic#entry9comment</comments>
      <pubDate>Thu, 30 Aug 2007 17:05:04 +0900</pubDate>
    </item>
    <item>
      <title>루미넌스의 TechNote를 시작합니다.</title>
      <link>https://lumitech.tistory.com/entry/Opening</link>
      <description>프로그래머로 살아오면서 참 많은것을 생각하고 느끼고 배웠습니다.&lt;br /&gt;머릿속에서 복잡하게 서로 아무의미도 연관도 없는 듯이 퍼져있는 이 지식들, 노하우들..&lt;br /&gt;&lt;br /&gt;많지는 않을지라도 정리를 해봐야겠다는 생각이 들었습니다.정리하면서 새로운 관계를 발견하고 발전적인 아이디어도 떠오를수 있고..깨닫지 못했던 무언가를 발견할지도 모르겠다는 생각이 듭니다. 그리고, 그렇게 되길 간절히 바라기도 하구요..&lt;br /&gt;이 공간은 그런 목적으로 만들게 되었습니다.&lt;br /&gt;&lt;br /&gt;이미 &lt;a href=&quot;http://luminance.kr/&quot; target=&quot;_blank&quot;&gt;루미넌스의 miscellaneous&lt;/a&gt;라는 이름의 블로그를 쓰고 있었고 그곳에 가끔 뭔가 적어놓기도 했었지만.. 그곳에 적었던 포스팅중 TechNote에 더 어울릴 내용은 가끔 생각나면 옮겨다 놓을겁니다. 여기는 주로 새로 작성하는 내용이 될겁니다.&lt;br /&gt;&lt;br /&gt;제가 근무하는 회사에는 TechNote라는 제도가 있습니다. 기술직군의 직원들이 노하우나 신기술을 공유하면서 다함께 성장하기 위한 제도입니다. 이름을 뺏겨 버렸는데..&lt;br /&gt;이름이 문제가 된다면.. 조용히 연락 주시면 적절한 향응을 제공하... ㅡ_ㅡ;;;;&lt;br /&gt;&lt;br /&gt;저에게.. 그리고 누군가에게 도움이 되는 블로그가 되길 바랍니다.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;font face=&quot;times new roman,times,serif&quot; size=&quot;4&quot;&gt;There are only &lt;em&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;/em&gt; types of people,&lt;br /&gt;
 &amp;nbsp;&amp;nbsp; those who understand binary and those who do not.&lt;/font&gt;&lt;/p&gt;</description>
      <category>오프닝</category>
      <author>루미넌스</author>
      <guid isPermaLink="true">https://lumitech.tistory.com/8</guid>
      <comments>https://lumitech.tistory.com/entry/Opening#entry8comment</comments>
      <pubDate>Sat, 25 Aug 2007 21:18:08 +0900</pubDate>
    </item>
    <item>
      <title>sudo를 씁시다.</title>
      <link>https://lumitech.tistory.com/entry/sudoAndSudoer</link>
      <description>인터넷을 통한 서비스를 위하여 설치된 서버에는 반드시 OS설치시부터 관리자 계정(root 또는 administrator)이 만들어져 있다. 이 계정의 권한은 직원이라 하더라도 함부로 알려줘서는 안되며, 관리자 권한이 필요한 업무를 보는 사람에게, 제한적으로 권한을 수행할 수 있도록 허용하는 보안정책이 필요하다. 작업용 공용계정을 사용하는 경우도 마찬가지이다.(하지만 작업용 공용계정을 없애는것이 보안의 첫걸음이다.)&lt;br /&gt;이 기능을 훌륭히 수행해주는 sudo의 사용법에 대하여 요약해 보았다.&lt;br /&gt;&lt;br /&gt;
&lt;H2 style=&quot;COLOR: rgb(0,51,102)&quot;&gt;sudo&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;개발, 운영 등의 작업을 수행함에 있어, 로그인계정 외의 다른 계정의 권한이 요구될 때, 그 계정을 직접 사용하지 않고(혹은, 패스워드를 알아내지 않고), 본인의 로그인계정의 인증을 통해 해당 계정의 권한으로 작업을 수행할 수 있다. 
&lt;LI&gt;용법&lt;/LI&gt;&lt;/UL&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/tistoryfile/fs2/13_17_9_17_blog96420_attach_0_0.png?original&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Ftistoryfile%2Ffs2%2F13_17_9_17_blog96420_attach_0_0.png%3Foriginal&quot; width=&quot;411&quot; height=&quot;68&quot; alt=&quot;사용자 삽입 이미지&quot;/&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;UL&gt;
&lt;LI&gt;가장 간단한 방법은 &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;sudo &amp;lt;command&amp;gt;&lt;/SPAN&gt;이다. 이렇게 하면 &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;&amp;lt;command&amp;gt;&lt;/SPAN&gt;에 적은 쉘커맨드가 &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;root&lt;/SPAN&gt;권한으로 수행된다. 
&lt;LI&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;root&lt;/SPAN&gt; 계정이 아닌 다른 계정의 권한이 필요한 경우엔, &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;sudo -u username &amp;lt;command&amp;gt;&lt;/SPAN&gt; 로 수행하면 &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;username&lt;/SPAN&gt; 계정의 권한으로 &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;&amp;lt;command&amp;gt;&lt;/SPAN&gt;를 수행한다. 
&lt;UL&gt;
&lt;LI&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;sudo -u #uid &amp;lt;command&amp;gt;&lt;/SPAN&gt; 와 같이 uid값을 사용할 수도 있다.&lt;/LI&gt;&lt;/UL&gt;
&lt;UL&gt;
&lt;LI&gt;이 유저를 Runas user라고 한다.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;sudo로 su - (root계정의 로그인쉘 얻기)를 수행한 예&lt;/LI&gt;&lt;/UL&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/tistoryfile/fs2/13_17_9_17_blog96420_attach_0_1.png?original&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Ftistoryfile%2Ffs2%2F13_17_9_17_blog96420_attach_0_1.png%3Foriginal&quot; width=&quot;500&quot; height=&quot;239&quot; alt=&quot;사용자 삽입 이미지&quot;/&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;H2 style=&quot;COLOR: rgb(0,51,102)&quot;&gt;sudoers&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;sudo를 사용하여 권한을 부여할 구체적인 설정을 하는 파일이 ''sudoers'' 파일이다. 시스템에 따라 약간씩 위치는 다르나, 이 파일을 편집할 권한을 얻으면&amp;nbsp; 시스템의 모든 권한을 얻을 수도 있기 때문에 매우 높은 보안 레벨로 보호되어야 한다. 
&lt;LI&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;sudo su -&lt;/SPAN&gt; 또는 &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;sudo visudo&lt;/SPAN&gt;등의 커맨드를 허용하는 것은 매우 신중해야 한다. 
&lt;LI&gt;이 파일의 편집은 &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;visudo&lt;/SPAN&gt; 명령을 실행하여 편집한다. &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;visudo&lt;/SPAN&gt;의 기본 편집기(보통은 vi 또는 nano)가 sudoers파일을 열은채로 실행된다. 
&lt;LI&gt;visudo가 사용할 기본 편집기 역시 sudoers파일에 설정할 수 있다. 
&lt;LI&gt;각 Alias 설정은 문자열 단위로 매치시키기 때문에 주의깊게 작성해야 한다. 
&lt;LI&gt;sudo /usr/bin/su 는 가능하나, cd /usr/bin; sudo ./su는 불가능할 수 있다.&lt;br /&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;H2 style=&quot;COLOR: rgb(0,51,102)&quot;&gt;How to Write sudoers&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;Alias 정의 섹션, Default 정의 섹션, Privilege정의 섹션으로 나누어 볼 수 있다. 
&lt;LI&gt;라인당 하나의 정의 
&lt;LI&gt;Aliases 
&lt;UL&gt;
&lt;LI&gt;Alias에는 &lt;SPAN style=&quot;FONT-WEIGHT: bold&quot;&gt;User_Alias, Runas_Alias, Host_Alias, Cmnd_Alias&lt;/SPAN&gt;의 4가지 Alias_Type이 있다. 
&lt;LI&gt;모든 Alias에 대해 ALL은 항상 매치되는 와일드카드로 미리 정의되어 있다(아래 예제 참조) 
&lt;LI&gt;각 Alias는 NAME = LIST의 형태로 만든다. 
&lt;UL&gt;
&lt;LI&gt;NAME은 알파벳 대문자로 시작하여야 하고, 두번째 글자부터는 알파벳 대소문자와 숫자, 언더스코어문자('_')를 쓸 수 있다. 
&lt;LI&gt;LIST는 콤마(,)로 구분되고 공백은 무시된다. 
&lt;LI&gt;LIST의 item앞에 '!'(negate operator)를 쓰면 리스트에서 해당 아이템만을 배제시킨다.&lt;br /&gt;예:[CODE]ALL, !/bin/su &amp;nbsp;&amp;nbsp; # &quot;/bin/su를 제외한 모두&quot;라는 의미&lt;br /&gt;ALL, !!/bin/su &amp;nbsp;&amp;nbsp; # &quot;모두&quot;의 의미, 짝수번 negate 의미 없다.[/CODE] 
&lt;LI&gt;같은 종류의 Alias는 콜론(:)으로 묶을 수 있다. 다른 라인에 새로운 정의로 포함시킬수도 있다.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Alias는 다음과 같은 형태가 된다. 
&lt;UL&gt;
&lt;LI&gt;Alias_Type NAME = item1, item2, item3, item4&lt;/LI&gt;&lt;/UL&gt;
&lt;UL&gt;
&lt;LI&gt;Alias_Type NAME = item1, item2, item3 : Name = item4, item5&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold&quot;&gt;User_Alias&lt;/SPAN&gt; 
&lt;UL&gt;
&lt;LI&gt;sudo 권한을 적용할 유저의 집합을 정의한다. 
&lt;LI&gt;(sudoer 그룹명) = (List of login names) 
&lt;LI&gt;유저명 대신 &lt;SPAN style=&quot;FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;%&amp;lt;group&amp;gt;&lt;/SPAN&gt; 을 사용할 수도 있다. 
&lt;UL&gt;
&lt;LI&gt;예: %admin # admin 그룹에 속하는 모든 유저&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold&quot;&gt;Runas_Alias&lt;/SPAN&gt; 
&lt;UL&gt;
&lt;LI&gt;어떤 유저 또는 그룹의 권한으로 명령을 수행할지를 지정할 수 있다. 
&lt;LI&gt;정의 방법은 User_Alias와 동일하나, &lt;SPAN style=&quot;FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;#&amp;lt;uid&amp;gt;&lt;/SPAN&gt; 의 형태도 사용할 수 있다. 
&lt;LI&gt;주의: &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;root&lt;/SPAN&gt;와 &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;#0&lt;/SPAN&gt;은 동일한 유저이지만, 문자열 매치를 하기 때문에 다른 것으로 간주된다. &lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;root, %0&lt;/SPAN&gt;도 마찬가지.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold&quot;&gt;Host_Alias&lt;/SPAN&gt; 
&lt;UL&gt;
&lt;LI&gt;hostname, IP address, Network address, 다른 Host_Alias를 묶어 호스트 집합을 만들 수 있다.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold&quot;&gt;Cmnd_Alias&lt;/SPAN&gt; 
&lt;UL&gt;
&lt;LI&gt;권한을 허용할 커맨드를 나열하여 집합으로 만든다. 
&lt;LI&gt;커맨드는 full path로 적는다. 디렉토리명을 커맨드로 지정할 수 있다. 디렉토리를 지정하면 그 디렉토리이하의 모든 커맨드에 대해 허용된다.&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold&quot;&gt;Defaults&lt;/SPAN&gt; : 권한 부여의 기본 옵션을 지정한다. 
&lt;UL&gt;
&lt;LI&gt;라인당 하나의 Default_Entry를 정의 한다. 
&lt;LI&gt;Default_Entry는 Default_Type Parameter_List로 정의한다. 
&lt;LI&gt;Default_Type는 다음의 4가지 정의 방법이 있다. 
&lt;UL style=&quot;FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;
&lt;LI&gt;Defaults 
&lt;LI&gt;Defaults@Host_Alias 
&lt;LI&gt;Defaults:User_Alias 
&lt;LI&gt;Defaults&amp;gt;runas_username&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Parameter_List는 Parameter의 리스트를 적는다. Parameter는 다음과 같은 형태가 있다. 
&lt;UL&gt;
&lt;LI style=&quot;FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;flag 
&lt;LI style=&quot;FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;!flag 
&lt;LI style=&quot;FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;flag=value 
&lt;LI style=&quot;FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;flag+=value 
&lt;LI style=&quot;FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;flag-=value 
&lt;LI&gt;&lt;SPAN style=&quot;FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;other Parameter_Lists&lt;/SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;여기서는 유용한 몇개 flag만 소개한다. 자세한 flags는 SUDOERS(5)를 참조한다 (이말을 쓰기 싫어서 작성한 문서에 쓸수 밖에 없다니;;;) 
&lt;UL&gt;
&lt;LI&gt;lecture: 앞절의 예제 이미지와 같이 타인의 권한으로 수행할때 기억해야 할 것에 대한 짧은 경고문.&lt;br /&gt;lecture=(never, once, always 중 하나) 
&lt;LI&gt;lecture_file: lecture를 보여줄 때, 이 파일을 보여준다.&lt;br /&gt;lecture_file=(full path of lecture_file) 
&lt;LI&gt;timestamp_timeout: sudo를 수행한 후 다시 수행할 때, 패스워드를 다시 물어볼지를 결정하는 타임아웃값. 0이면 항상 물어본다.&lt;br /&gt;timestamp_timeour=(분 단위 정수) 
&lt;LI&gt;editor: visudo에서 사용할 기본 에디터&lt;br /&gt;editor=(/usr/bin/vim 등의 에디터 full path) 
&lt;LI&gt;passwd_tries: 비밀번호를 틀렸을 경우 다시 물어보는 횟수.&lt;br /&gt;passwd_tries=(정수) 
&lt;LI&gt;passwd_timeout: 비밀번호 입력대기시간 타임아웃값. 0이면 무한정 기다린다.&lt;br /&gt;passwd_timeout=(분 단위 정수) 
&lt;LI&gt;fqdn: Host 이름에 Fully Qualified Domain Name을 사용할 것인지의 여부. 이 플래그를 사용하면, sudo수행시에 hostname을 DNS에 쿼리한다.&lt;br /&gt;fqdn (또는 !fqdn) 
&lt;LI&gt;set_logname: runas user(타겟 유저라고도 함)의 LOGNAME과 USER 환경변수값을 가져오지 않고 현재 값을 유지한다.&lt;br /&gt;set_logname (또는 !set_logname)&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI style=&quot;FONT-WEIGHT: bold&quot;&gt;User privilege specification 
&lt;UL&gt;
&lt;LI&gt;앞서 정의한 Alias들의 조합으로 권한을 부여한다. 
&lt;LI&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: 'courier new',courier,monospace&quot;&gt;User_Alias (Host_Alias) = Cmnd_Alias&lt;/SPAN&gt;의 형태로 정의한다. 
&lt;LI&gt;Tag_Spec과 Runas_Spec을 사용하는 방법은 역시&amp;nbsp; SUDOERS(5)를 참조한다. (또.;; 그치만 많이 써본적은 없으므로 필요할때 읽어볼 것.)&lt;br /&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;H3 style=&quot;COLOR: rgb(153,51,102)&quot;&gt;sample&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;가장 소극적인 보안책으로 사용할수 있는 sudoers 예제&lt;br /&gt;[CODE type=config]# 아무런 Alias를 정의하지 않고,&lt;br /&gt;# admin group에 속한 계정 전체에 대해서&lt;br /&gt;# 모든 커맨드를 root권한으로 수행할수 있도록 허용함&lt;br /&gt;# sudo를 사용하기 위해서 항상 패스워드를 물어본다.&lt;br /&gt;&lt;br /&gt;# Host alias specification&lt;br /&gt;&lt;br /&gt;# User alias specification&lt;br /&gt;&lt;br /&gt;#Cmnd alias specification&lt;br /&gt;&lt;br /&gt;# Defaults&lt;br /&gt;Defaults &amp;nbsp; lecture=always,tty_tickets,!fqdn,timestamp_timeout=0,editor=/usr/bin/vi&lt;br /&gt;&lt;br /&gt;# User privilege specification&lt;br /&gt;root &amp;nbsp;&amp;nbsp; ALL=(ALL) ALL&lt;br /&gt;&lt;br /&gt;# Members of the admin group may gain root privileges&lt;br /&gt;%admin ALL=(ALL) ALL&lt;br /&gt;[/CODE] 
&lt;LI&gt;다양한 용법과 문법의 예&lt;br /&gt;[CODE type=config]# User alias specification&lt;br /&gt;# 3가지의 유저셋을 정의한다.&lt;br /&gt;User_Alias &amp;nbsp; &amp;nbsp; FULLTIMERS = millert, mikef, dowdy&lt;br /&gt;User_Alias &amp;nbsp; &amp;nbsp; PARTTIMERS = bostley, jwfox, crawl&lt;br /&gt;User_Alias &amp;nbsp; &amp;nbsp; WEBMASTERS = will, wendy, wim&lt;br /&gt;&lt;br /&gt;# Runas alias specification&lt;br /&gt;# 2가지 Runas 유저셋을 정의한다.&lt;br /&gt;Runas_Alias &amp;nbsp;&amp;nbsp; OP = root, operator&lt;br /&gt;Runas_Alias &amp;nbsp;&amp;nbsp; DB = oracle, sybase&lt;br /&gt;&lt;br /&gt;# Host alias specification&lt;br /&gt;# 4가지 호스트셋을 정의한다.&lt;br /&gt;&lt;br /&gt;# IP/NETMASK 지정방법, 호스트명 지정방법의 예가 모두 나와있다.&lt;br /&gt;Host_Alias &amp;nbsp; &amp;nbsp; CUNETS = 128.138.0.0/255.255.0.0&lt;br /&gt;Host_Alias &amp;nbsp; &amp;nbsp; CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0&lt;br /&gt;Host_Alias &amp;nbsp; &amp;nbsp; SERVERS = master, mail, www, ns&lt;br /&gt;Host_Alias &amp;nbsp; &amp;nbsp; CDROM = orion, perseus, hercules&lt;br /&gt;&lt;br /&gt;# Cmnd alias specification&lt;br /&gt;# 커맨드셋을 정의한다.&lt;br /&gt;Cmnd_Alias &amp;nbsp; &amp;nbsp; DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; /usr/sbin/restore, /usr/sbin/rrestore&lt;br /&gt;Cmnd_Alias &amp;nbsp; &amp;nbsp; KILL = /usr/bin/kill&lt;br /&gt;Cmnd_Alias &amp;nbsp; &amp;nbsp; SHUTDOWN = /usr/sbin/shutdown&lt;br /&gt;Cmnd_Alias &amp;nbsp; &amp;nbsp; HALT = /usr/sbin/halt&lt;br /&gt;Cmnd_Alias &amp;nbsp; &amp;nbsp; REBOOT = /usr/sbin/reboot&lt;br /&gt;Cmnd_Alias &amp;nbsp; &amp;nbsp; SHELLS = /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh, \&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /usr/local/bin/tcsh, /usr/bin/rsh, \&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /usr/local/bin/zsh&lt;br /&gt;Cmnd_Alias &amp;nbsp; &amp;nbsp; SU = /usr/bin/su&lt;br /&gt;&lt;br /&gt;# Override built-in defaults&lt;br /&gt;# 기본 옵션을 지정한다.&lt;br /&gt;# lecture를 항상 보여준다. fqdn 사용하지 않는다. 3분내에 다시 sudo하면 패스워드를 물어보지 않는다. visudo의 편집기로 /usr/bin/vi를 사용한다.&lt;br /&gt;Defaults &amp;nbsp; lecture=always,!fqdn,timestamp_timeout=3,editor=/usr/bin/vi&lt;br /&gt;&lt;br /&gt;# runas user가 root가 될때는 set_logname 하지 않는다.&lt;br /&gt;# 즉, root 의 환경을 가져오지 않는다&lt;br /&gt;Defaults&amp;gt;root &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; !set_logname&lt;br /&gt;&lt;br /&gt;# FULLTIMER에게는 lecture를 보여주지 않는다.&lt;br /&gt;Defaults:FULLTIMERS &amp;nbsp;&amp;nbsp; !lecture&lt;br /&gt;&lt;br /&gt;# SERVERS에서는 패스워드 입력을 1분내로 해야 한다. sudo 로그 파일을 별도로 지정한다.&lt;br /&gt;Defaults@SERVERS &amp;nbsp; &amp;nbsp; &amp;nbsp; passwd_timeout=1, logfile=/var/log/sudo.log&lt;br /&gt;&lt;br /&gt;# User privileges&lt;br /&gt;# root도 sudo를 수행할 수 있다.&lt;br /&gt;root &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ALL = (ALL) ALL&lt;br /&gt;&lt;br /&gt;# wheel그룹에 속한 모든 유저는 sudo를 통해 모든 명령을 수행할 수 있다.&lt;br /&gt;%wheel &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ALL = (ALL) ALL&lt;br /&gt;&lt;br /&gt;# FULLTIMERS에게는 패스워드를 물어보지 않는다.&lt;br /&gt;FULLTIMERS &amp;nbsp; &amp;nbsp; ALL = NOPASSWD: ALL&lt;br /&gt;&lt;br /&gt;# PARTTIMERS에게는 패스워드를 물어본다.&lt;br /&gt;PARTTIMERS &amp;nbsp; &amp;nbsp; ALL = ALL&lt;br /&gt;&lt;br /&gt;# operator에게는 패스워드를 물어보고, 지정된 커맨드셋을 허용한다.&lt;br /&gt;operator &amp;nbsp; &amp;nbsp; &amp;nbsp; ALL = DUMPS, KILL, SHUTDOWN, HALT, REBOOT, PRINTING,\&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; sudoedit /etc/printcap, /usr/oper/bin/&lt;br /&gt;&lt;br /&gt;# joe는 operator가 될수 있다.&lt;br /&gt;joe &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; ALL = /usr/bin/su operator&lt;br /&gt;&lt;br /&gt;# fred는 DB 유저권한이 필요할때에만 패스워드를 물어보지 않고 모든 권한이 허용된다.&lt;br /&gt;fred &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ALL = (DB) NOPASSWD: ALL&lt;br /&gt;&lt;br /&gt;# john은 SERVERS호스트셋에서 옵션없이 su를 수행할 수 있다. su에 옵션을 줄수 없고 root로의 su는 불허한다.&lt;br /&gt;john &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SERVERS = /usr/bin/su [!-]*, !/usr/bin/su *root*&lt;br /&gt;&lt;br /&gt;# jen은 SERVERS호스트셋을 제외한 모든 호스트에서 모든 권한을 패스워드를 물어본후 얻을 수 있다.&lt;br /&gt;jen &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; ALL, !SERVERS = ALL&lt;br /&gt;[/CODE]&lt;/LI&gt;&lt;/UL&gt;&lt;br /&gt;
&lt;H3 style=&quot;COLOR: rgb(153,51,102)&quot;&gt;참고&lt;/H3&gt;man pages; SUDO(8), VISUDO(8), SUDOERS(5)&lt;br /&gt;&lt;br /&gt;</description>
      <category>Unix</category>
      <category>sudo</category>
      <category>visudo</category>
      <category>보안</category>
      <author>루미넌스</author>
      <guid isPermaLink="true">https://lumitech.tistory.com/5</guid>
      <comments>https://lumitech.tistory.com/entry/sudoAndSudoer#entry5comment</comments>
      <pubDate>Thu, 21 Jun 2007 20:05:00 +0900</pubDate>
    </item>
    <item>
      <title>구글 페이지랭크..로직을 교정하는 중일까?</title>
      <link>https://lumitech.tistory.com/entry/GooglePageRankRenewal</link>
      <description>내 블로그 내의 각 URL들의 구글 페이키랭크 값이 최근 바뀌었다.&lt;br /&gt;이미 널리 알려졌다시피, 구글은 검색결과 페이지를 보여줄때 어떤 기준에 의한 정렬(ordering)을 하는 대신, &lt;STRONG&gt;모든 인덱스된 페이지의 랭크값을 미리 계산해 두고 이 값이 높은 수서대로 보여준다&lt;/STRONG&gt;. 그래서 웹페이지가 구글 페이지랭크값으로 얼마를 할당받는가는 검색 결과 노출 순서와 직결되는 마케팅 영역에서 아주 중요하게 여겨진다. 오죽하면 검색엔진 최적화 프로젝트 같은것도 하겠나..&lt;br /&gt;&lt;br /&gt;근데 이런 페이지랭크를 산출하기 위한 정확한 로직은 공개된 바가 없다. 아무리 집요하게 물어봐도 안가르쳐준단다. 구글의 거의 유일하다시피 하는 수익모델인 검색광고의 기반중 하나가 되기 때문일 거다. 어찌됐건 약 500여가지의 변수에 의해 페이지랭크가 결정된다고 알려져 있고, 이중 큰 영향력을 가지는 변수로서 &lt;STRONG&gt;하이퍼텍스트의 링크 구조&lt;/STRONG&gt;가 있다.&lt;br /&gt;도서관 정보학 시절부터 있었던 이론인, &lt;STRONG&gt;중요한 문서일수록 많이 참조된다(가치있는 논문은 타 논문의 reference에 많이 등장한다)&lt;/STRONG&gt;는 이론에 근거하고 있다는 말이다.&lt;br /&gt;&lt;br /&gt;즉, basher.pe.kr/tt/lumi 라는 페이지로 향하는 링크가 많이 발견될 수록, 또 이미 높은 랭크를 가지는 페이지 안에서 발견될 수록 basher.pe.kr/tt/lumi 라는 페이지의 랭크는 올라간다. 여기까지는 검색엔진이나 구글에 관심있는 사람이면 누구나 한번쯤 들었을 만한 이야기 인데..&lt;br /&gt;&lt;br /&gt;밥먹고 살기 위해 하는 일이 웹문서를 수집하고 랭킹매기고 인덱싱하고 찾아내는 일이다 보니 선발주자인 구글의 행동을 많이 분석하게 된다. 근데 최근 내 블로그의 랭크 값이 바뀐 것이다. 랭크값은 &lt;A href=&quot;http://blogutil.net/pagerank.php&quot; target=_blank&gt;블로그유틸 사이트&lt;/A&gt;에서 알아낼 수도 있고, 구글 툴바를 설치해도 알수 있고, 구글에서 페이지랭크 알아내는 법을 쉽게 검색할 수 있다. 그럼 도대체 구글이 무슨 짓을 하고 있는 걸까?&lt;br /&gt;&lt;br /&gt;또 끝없는 상상의 나래를 펼쳐보자.&lt;br /&gt;&lt;br /&gt;구글의 페이지랭크 모델은 완벽하지 못하다. 아마 영원히 완벽한 랭킹 모델은 만들어지지 않을지 모른다. 링크 구조에 기반한 랭크 모델은, 무의미한 수많은 URL을 랜덤하게 만들어 내고 링크를 메인 페이지로 향하게 하는 작은 낚시질용 CGI를 만들기만 하면 무력화시킬수 있다. 이런 약점을 커버하기 위해서 구글이 500여가지 변수를 사용하는 것이다.&lt;br /&gt;&lt;br /&gt;이하의 내용은 구글의 페이지랭크의 행동을 나름 간략히 분석해 보고 랭킹 로직을 설계하면서 추측했던 내용으로서 실제 구글의 구현과는 무관한 나의 상상이다..ㅡㅡㅋ&lt;br /&gt;&lt;br /&gt;
&lt;UL&gt;
&lt;LI&gt;구글의 페이지 랭크에서 느껴지는 몇가지 변수중 하나는, &quot;도메인명&quot;이다. 그 변수는 .com이 .co.kr 보다 좋은 점수를 가지는 것으로 보인다. (변수 A)&lt;br /&gt;즉, asdf.com이 asdf.co.kr 보다 A값이 크다. 
&lt;LI&gt;path depth가 깊어질수록 점수를 떨어뜨리는 변수를 가지고 있는듯 하다.(변수B)&lt;br /&gt;asdf.com/qwe/rty 보다 asdf.com/qwe 가 B값이 크다. 
&lt;LI&gt;Query string이 있는것보다 없는것이 유리하다.(변수C)&lt;br /&gt;asdf.com/qwert.php가 asdf.com/qwert.php?var1=val1&amp;amp;var2=val2보다 C값이 크다. 
&lt;LI&gt;외부링크(타 도메인에서 들어오는 링크)에 의한 랭크 분배가 내부링크에 의한 랭크 분배보다 크다.&lt;/LI&gt;&lt;/UL&gt;등등 몇가지 정해진 로직에 의한 행동을 보이지만, 최근 구글봇과, 구글 인덱서의 행동은 한글 페이지에 대한 몇가지 정책을 교정중인 것으로 보인다. 그 과정에서 나타나는 문제인지.. 아니면, 내가 미처 간파하지 못한 고도의 기술이 숨어있는 것인지 모를 오류(?)도 느껴진다.&lt;br /&gt;&lt;br /&gt;
&lt;UL&gt;
&lt;LI&gt;basher.pe.kr/tt/lumi 와 basher.pe.kr/tt/lumi/ 의 랭크를 다르게 부여한다.&lt;br /&gt;이건 오류라고 볼수만은 없다. 실제로 웹서버 설정에 따라, basher.pe.kr/tt/lumi와 basher.pe.kr/tt/lumi/ 를 다르게 보이도록 할 수 있긴 하다. 
&lt;LI&gt;basher.pe.kr 은 HTTP 302 Redirection를 하며, basher.pe.kr/tt/lumi 로 보낸다. 이것을 링크로 간주한다. 이건 로직의 결함이라고 봐야 할 것 같다. basher.pe.kr은 아무 내용을 갖지 않기 때문에 basher.pe.kr 로 향하는 모든 링크는 결국 basher.pe.kr/tt/lumi 로 그 랭크 점수를 분배해 주어야 한다. 상식적으로는 그렇다. 
&lt;LI&gt;basher.pe.kr/blog 는 basher.pe.kr/tt/lumi로 HTTP 302 Redirection을 한다. 그런데 외부에서 발견되는 basher.pe.kr 로 향하는 링크중 일부를 basher.pe.kr/blog로 향하는 것으로 간주한다. 바로 위의 내용과 종합하여 볼때, 모종의 HTTP Redirection response에 대한 처리로직이 들어가 있으나, 결함을 가지고 있다.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;구글의 한국어 처리를 위한 Lexical analyzer에도 변화가 있었다. &lt;A href=&quot;https://www.google.com/webmasters/tools/&quot; target=_blank&gt;구글 웹마스터 도구&lt;/A&gt;에 들어가면 &quot;사이트의 컨텐츠&quot;라는 항목으로 Lexical analyze된 내용을 표로 보여주는 곳이 있다. 근데 조사와 어미를 컨텐츠로 많이 잡고 있다. 뭔가 Analyzer에 버그가 생겼거나 아직 테스트 중인 버전을 사용한듯 하다. Lexical analyzer를 수정하고 있다는 것은 &quot;사이트에 대한 외부링크&quot;항목에서도 느껴진다. 앵커 텍스트를 분석한 것이라고 생각되는 이 영역이 이전에는 매우 부실했는데, 앵커 주변의 텍스트를 함께 포함하는 방식으로 바뀐듯 하다.&lt;br /&gt;&lt;br /&gt;쓰다보니 좀 횡설수설 했는데,&lt;br /&gt;어찌됐건 구글의 변화는 검색엔진 개발자들의 주목을 받고 있는 만큼, 뭔가 보여주길 한편 기대하면서, 뭔가 큰 실수를 하나쯤 하지는 않을까 하는 생각도 해 본다.(너무 얄팍한가;;)&lt;br /&gt;&lt;/P&gt;
&lt;HR&gt;

&lt;DIV style=&quot;TEXT-ALIGN: left&quot;&gt;이하는 내 블로그 내의 Top페이지를 보여주는 몇몇 URL들의 랭크 값이다. 이것들이 같게 나오는게 가장 지능적이고 이상적인 랭크 로직이겠으나 아마 아직은 불가능할 거다.&lt;br /&gt;
&lt;BLOCKQUOTE&gt;&lt;IMG src=&quot;http://blogutil.net/lib/gprimg.php?domain=basher.pe.kr&quot; align=middle border=0&gt;&lt;A href=&quot;http://basher.pe.kr/&quot;&gt;http://basher.pe.kr&lt;/A&gt;&lt;br /&gt;&lt;IMG src=&quot;http://blogutil.net/lib/gprimg.php?domain=basher.pe.kr/&quot; align=middle border=0&gt;&lt;A href=&quot;http://basher.pe.kr/&quot;&gt;http://basher.pe.kr/&lt;/A&gt;&lt;br /&gt;&lt;IMG src=&quot;http://blogutil.net/lib/gprimg.php?domain=basher.pe.kr/tt&quot; align=middle border=0&gt;&lt;A href=&quot;http://basher.pe.kr/tt&quot;&gt;http://basher.pe.kr/tt&lt;/A&gt;&lt;br /&gt;&lt;IMG src=&quot;http://blogutil.net/lib/gprimg.php?domain=basher.pe.kr/tt/&quot; align=middle border=0&gt;&lt;A href=&quot;http://basher.pe.kr/tt/&quot;&gt;http://basher.pe.kr/tt/&lt;/A&gt;&lt;br /&gt;&lt;IMG src=&quot;http://blogutil.net/lib/gprimg.php?domain=basher.pe.kr/tt/lumi&quot; align=middle border=0&gt;&lt;A href=&quot;http://basher.pe.kr/tt/lumi&quot;&gt;http://basher.pe.kr/tt/lumi&lt;/A&gt;&lt;br /&gt;&lt;IMG src=&quot;http://blogutil.net/lib/gprimg.php?domain=basher.pe.kr/tt/lumi/&quot; align=middle border=0&gt;&lt;A href=&quot;http://basher.pe.kr/tt/lumi/&quot;&gt;http://basher.pe.kr/tt/lumi/&lt;/A&gt;&lt;br /&gt;&lt;IMG src=&quot;http://blogutil.net/lib/gprimg.php?domain=basher.pe.kr/blog&quot; align=middle border=0&gt;&lt;A href=&quot;http://basher.pe.kr/blog&quot;&gt;http://basher.pe.kr/blog&lt;/A&gt;&lt;br /&gt;&lt;IMG src=&quot;http://blogutil.net/lib/gprimg.php?domain=basher.pe.kr/blog/&quot; align=middle border=0&gt;&lt;A href=&quot;http://basher.pe.kr/blog/&quot;&gt;http://basher.pe.kr/blog/&lt;/A&gt;&lt;br /&gt;&lt;IMG src=&quot;http://blogutil.net/lib/gprimg.php?domain=luminance.kr/&quot; align=middle border=0&gt;&lt;A href=&quot;http://luminance.kr/&quot;&gt;http://luminance.kr/&lt;/A&gt;&lt;br /&gt;&lt;/BLOCKQUOTE&gt;&lt;/DIV&gt;</description>
      <category>검색엔진</category>
      <category>구글</category>
      <category>페이지랭크</category>
      <author>루미넌스</author>
      <guid isPermaLink="true">https://lumitech.tistory.com/4</guid>
      <comments>https://lumitech.tistory.com/entry/GooglePageRankRenewal#entry4comment</comments>
      <pubDate>Sat, 24 Mar 2007 01:13:00 +0900</pubDate>
    </item>
  </channel>
</rss>