me2Virus 시각화

June 10th, 2009

어제 소개드린 me2Virus HyperTree를 더욱 확장해 임의의 숙주에 대해서도 시각화 가능하게끔 만들었습니다. URL에는 변화 없습니다.

me2Virus HyperTree
cock 님의 태연바이러스 전염지도

숙주주소를 입력하면 해당 숙주의 전염/확산 경로를 JSON 데이터로 만들어 캐시하고 그 다음부터는 캐시된 데이터를 이용합니다. 따라서 첫 실행 시 시간이 더 걸립니다. 만약 해당 숙주에 새로운 하위숙주가 생긴다면 다음번 요청 때 다시 캐시합니다.

JITHyperTree를 이용해 시각화했지만 더 재밌는 시각화 결과들이 나타났으면 좋겠습니다. 따라서 아무나 다룰 수 있도록 JSON 데이터를 공개합니다. 누군가 나서서 만들어주시면 감사하겠습니다. 특정 숙주의 JSON 데이터는 다음 URL로부터 얻을 수 있습니다.

http://heungsub.net/apps/me2virus/json.php?post=<post_url>

데이터 구조는 다음과 같습니다.

{
  url: "http:\/\/me2day.net\/sub\/2009\/06\/06#09:11:45",
  name: "sub",
  posted: "2009-06-06 09:11:45",
  scale: 26,
  route: [
    "http:\/\/me2day.net\/sub\/2009\/06\/04#02:55:04",
    "http:\/\/me2day.net\/dark\/2009\/06\/04#04:06:48",
    "http:\/\/me2day.net\/jy2077\/2009\/06\/04#09:00:13",
    "http:\/\/me2day.net\/eek\/2009\/06\/04#09:50:44",
    "http:\/\/me2day.net\/sunghoonbae\/2009\/06\/04#09:51:30",
    "http:\/\/me2day.net\/gedoc\/2009\/06\/04#09:56:28",
    "http:\/\/me2day.net\/kangyena\/2009\/06\/04#09:57:36",
    "http:\/\/me2day.net\/sumanpark\/2009\/06\/04#10:18:25",
    "http:\/\/me2day.net\/bandi\/2009\/06\/04#10:33:58",
    "http:\/\/me2day.net\/ickjong\/2009\/06\/04#15:52:30",
    "http:\/\/me2day.net\/anotheround\/2009\/06\/05#16:28:32",
    "http:\/\/me2day.net\/gakoihalu\/2009\/06\/05#19:37:39",
    "http:\/\/me2day.net\/distanthowl\/2009\/06\/05#10:11:01"
  ],
  infectees: [
    {
      url: "http:\/\/me2day.net\/distanthowl\/2009\/06\/05#20:27:21",
      name: "distanthowl",
      posted: "2009-06-05 20:27:21",
      scale: 14,
      route: [
        "http:\/\/me2day.net\/sub\/2009\/06\/04#02:55:04",
        ...,
        "http:\/\/me2day.net\/sub\/2009\/06\/06#09:11:45"
      ],
      infectees: [...]
    },
    {...},
    {...},
    ...
  ]
}

me2Virus 첫 시각화

June 9th, 2009

이 포스팅은 낡았습니다. “me2Virus 시각화“를 봐주세요.

자바스크립트 시각화 라이브러리인 JITHyperTree를 이용해 me2Virus 전염경로를 표현해봤습니다.

JIT의 Hypertree로 시각화한 최초의 숙주 전염지도

우선 전염 규모가 비교적 큰 숙주 네 개만 시각화시켰습니다. 오늘 0시 근처 기준으로 캐시한 데이터를 사용하기 때문에 전염 현황이 실시간으로 반영되지는 않습니다.

JIT 굉장히 맘에 드네요.

Markdown 코드 구문강조

June 8th, 2009

블로그에 올린 코드블록에 구문강조가 안되니 보기 흉하더랍니다. 그래서 간단히 Syntax Highlighting in JavaScript(이하 SHJS)를 붙여보았습니다. 포스팅 작성 시 다음과 같이 입력하면 pre/@class에 따라 SHJS가 해당 언어의 구문강조 규칙을 적용해줍니다.

<pre class="sh_javascript_dom"><code>
alert('Heung, world!');
</code></pre>

그런데 HTML 코드를 삽입하려니 굉장히 불편합니다.

<pre class="sh_html"><code>
&lt;p&gt;Heung, world!&lt;/p&gt;
</code></pre>

HTML 엔터티를 손으로 써야하니 편집 시 가독성도 나빠지고 실수도 자주 할 것 같습니다. 그래서 제 블로그에서 사용하고 있는 Markdown for WordPress and bbPress를 확장하기로 했습니다. 다음과 같이 코드 블록 첫째 줄에 #!lang이라고 적으면 해당 언어의 구문강조 규칙이 적용되도록 말이죠.

    #!html
    <p>Heung, world!</p>

확장을 위해 ~/wp-content/plugins/markdown/markdown.php에 있는 Markdown_Parser 클래스의 doCodeBlock 메소드와 _doCodeBlocks_callback 메소드를 다음과 같이 수정했습니다.

function doCodeBlocks($text) {
#
#   Process Markdown `<pre><code>` blocks.
#
    $text = preg_replace_callback('{
            (?:\n\n|\A\n?)
            [ ]{'.$this->tab_width.'}(?:\#!([^\s]+))?\n
            (
              (?>
                [ ]{'.$this->tab_width.'}
                .*\n+
              )+
            )
            ((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)
        }xm',
        array(&$this, '_doCodeBlocks_callback'), $text);

    return $text;
}
function _doCodeBlocks_callback($matches) {
    $langs = array(
        'c++' => 'cpp',
        'cxx' => 'cpp',
        'c#' => 'csharp',
        'js' => 'javascript_dom',
        'javascript' => 'javascript_dom',
        'bash' => 'sh',
        'shell' => 'sh'
    );
    $lang = strtolower($matches[1]);
    $codeblock = $matches[2];

    $codeblock = $this->outdent($codeblock);
    $codeblock = htmlspecialchars(
        $codeblock,
        ENT_NOQUOTES
    );

    # trim leading newlines and trailing newlines
    $codeblock = preg_replace(
        '/\A\n+|\n+\z/',
        '',
        $codeblock
    );

    $markup = "<pre";
    if ($lang) {
        if (array_key_exists($lang, $langs))
            $lang = $langs[$lang];
        $markup .= " class=\"sh_{$lang}\"";
    }
    $markup .= "><code>$codeblock\n</code></pre>";
    return "\n\n".$this->hashBlock($markup)."\n\n";
}

잘 되는군요. :)

me2Virus 제작기

June 8th, 2009

me2PHeungP

최근에 me2PHP를 포크한 me2PHeungP[미투피흥피] 프로젝트를 개설했습니다. me2PHP가 최신 me2API 스펙을 반영하지 않은 것이 포크 사유였기에 요 며칠간 me2PHeungP에 이런저런 최신 스펙들을 추가하고 있었습니다. 그 중 하나가 콜백기능입니다. 이것을 사용할 경우 포스팅 작성 시 포스팅아이콘을 원하는 이미지로 바꾸고 아이콘을 클릭하면 삽입될 웹 문서나 이미지, 동영상, 음원의 URL을 지정할 수 있습니다.

me2Nick 콜백문서

콜백기능을 지원하자마자 우선 일전에 만들었던 me2Nick에 적용해보았습니다. 잘 작동하는걸 보고 흡족해하다가 문득 궁금증이 생겼습니다. 이 안에 스크립트를 넣으면 실행될까? 간단히 다음 코드를 추가해봤습니다.

<script type="text/javascript">
//<![CDATA[
    alert('Heung, world!');
//]]>
</script>

콜백 문서에서 스크립트 실행

실행 되는군요. 이때부터 장난기가 발동해 me2Nick 콜백문서를 보게되면 2초간 그 페이지의 모든 아이콘과 프로필사진이 제 프로필사진으로 바뀌도록 만들었습니다. 그리고 나선 사진을 제 맘대로 바꾼 것에 대한 사과 메시지를 미투데이 알림창으로 뿌려주고자 JavaScript 콘솔을 이용해 미투데이 페이지에 현재 살아있는 객체들을 살펴보았습니다.

아이콘 바꿈

살펴보면서 더 대단한 것도 할 수 있겠단 것을 깨달았습니다. 남의 미투데이에 포스팅을 올리거나 특정한 me2App에 막대한 량의 토큰을 후원시키거나, 심지어 일시정지나 탈퇴도 마음대로 제어할 수 있을 것 같았습니다. 그때 떠오른 것이 예전에 본 FaceBook 바이러스였습니다. FaceBook 프로필페이지에 삽입된 JavaScript 코드가 이 페이지를 열람한 다른 회원의 프로필페이지에 자동으로 복제되는–그렇다고 유해하지는 않은–바이러스였죠. 그것에 모티브를 얻어 me2Virus를 만들기에 이르렀습니다.

me2Virus

복제될 포스팅은 콜백문서를 지녀야하므로 me2PHeungP를 사용해야했습니다. 그러기 위해 타겟이 될 미친의 사용자키와, 그 미친의 미투데이에 포스팅할 PHP 문서가 필요했습니다. 내부 도메인 XHR을 이용해 사용자키를 획득하는건 무척 쉬웠으며 외부 도메인으로 XHR을 날리는 것도 간단했습니다. 미투데이 페이지들에 이미 붙어있는 Prototype 프레임워크 덕분이었죠. 이로써 포스팅을 복제하는데 성공한 것입니다.

var me2day = {
    notify: notification_message.show_message
            .bind(notification_message),
    request: function(url, options) {
        url += '?' + $H(options.parameters).toQueryString();
        options.parameters = {url: url};
        options.method = 'get';
        return new Ajax.Request(
            'http://me2day.net/get_html', options
        );
    }
};

하지만 너무 위험해보였습니다. 포스팅아이콘을 누르자마자 가차없이 포스팅이 복제돼버리다보니 테스트 하다 올라간 복제포스팅만 8개였습니다. 최대한 매너 있는 바이러스가 되게끔 차후 감염을 막을 수 있는–면역력 체크박스도 추가하고, 스스로로부터는 감염되지 않게 하며, 확산 경로를 분석해 나중에 공개하기 위해 모든 복제 상황을 기록토록 했습니다.

최초의 숙주

그러고 나서 최초의 숙주를 공개한 게 6월 4일 새벽 2시 55분이었습니다. 다음날 일어나 출근하기 전에 확인한 직접 감염자 수는 서른 명이 넘어있었고 전체 감염자 수는 140명 대에 이르렀습니다. 생각보다 빠른 확산 속도에 조금 놀랐습니다. 그러나 출근하고 나니 감염 되지 않는다는 사람들이 속출했습니다. 분명히 출근 전까지만 해도 잘 됐었는데 말이죠.

알고보니 me2Virus가 사용하는 Basic 등급 애플리케이션키는 24시간동안 150개로 포스팅 작성이 제한되어 있기 때문이었습니다. 따라서 만박 님과 꽃띠앙 님께 Premium Partner를 요청하는 동시에 우선 (버려진)me2Time 애플리케이션키를 사용하도록 바꿔놓았습니다. 그리고 누구나 스스로의 애플리케이션키를 등록해 자신만의 새로운 최초의 숙주를 만들 수 있게끔, 그 숙주로부터 전염되는 모든 me2Virus가 선조의 애플리케이션키를 사용하게끔 개선했습니다. 전염이 다시 시작되었죠.

그때 꽃띠앙 님께서 연락하여 기존에는 콜백문서에서의 스크립트 실행을 전혀 막지 않았으나, 이제부터는 화이트리스트에 등록된 콜백문서 이외에는 스크립트가 실행되지 않을 것이라고 알려주셨습니다. 다행히 me2Virus에 악의는 없었기 때문에 화이트리스트에 등록해주셨으며, 애플리케이션키도 Premium Partner 등급으로 올려주셨습니다. 안심하면서도 약간은 아쉬웠습니다. 알림창 띄우는 스크립트 같은 경우 안전하면서도 굉장히 유용히 쓰일 수 있는데 앞으로 다른 콜백 애플리케이션에서는 볼 수 없을 것이기 때문입니다.

미투데이 알림창

꽃띠앙 님 덕분에 이제 me2Virus는 합법적으로 제한 없이 확산되기 시작했습니다. 각각 me2Virus의 감염 경로와 전염 규모도 볼 수 있도록 개선했으며, 이 확산 경로를 어떻게 하면 멋지게 시각화할 수 있을지도 계속 고민 중입니다.

me2Virus 콜백화면 설명서

현재 최초의 숙주가 감염시킨 하위숙주(하위숙주의 하위숙주들도 포함한)는 700개를 넘어섰으며, 전체 숙주는 1,800개에 도달했습니다. 감염경로는 스무 단계까지 깊어졌고, 한 사람이 가장 많게는 27번 감염되었습니다. 이제 열기도 식고 면역력을 지닌 사용자도 330명을 넘어서 더이상 첫날만큼 빠른 확산은 기대할 수 없게 되었습니다. 그럼에도 불구하고 느리지만 꾸준히 확산되는 모습에 전 만족스럽답니다.

사용자 분들의 동의 없이 멋대로 포스팅 올라가게 만든 점 사과드립니다. 그래도 포스팅 주소와 전염 경로 이외에 그 어떤 정보도 저장하지 않고, 감염 즉시 알려줌으로써 1분 간의 삭제 기회와 감염거부 기능을 제공하니 가벼운 맘으로 지켜봐주시면 감사하겠습니다.

전염에 성공한 최초의 숙주들

참, 이제 최초의 숙주를 만들때 메시지도 마음대로 설정할 수 있습니다. 모쪼록 많이 이용해주시길.

3년만의 픽셀애니메이션

December 19th, 2008

기말고사 마지막 시험을 치르며 이 시간 이후 집에서 보낼 이틀 간 뭘 하면 좋을지 고민해봤습니다. 그 때 생각난 것이 고등학교 1학년때까지 주력하다 포기한 픽셀애니메이션이었습니다.

Project 630: Attack

3년만에 하는 작업은 어떨지 궁금하기도 했고 오래전부터 그려보고 싶던 것도 있고 해서 집에 돌아가는 길에 열심히 구상했죠.

그리고자한 것은 격투게임 캐릭터 같은 대기자세를 취하고 있는 저를 그린 자화상이었습니다.

img_81421

그림이 엉망이네요. 아무튼 이 스케치를 바탕으로 바로 드로잉에 들어갔습니다.

fighter01

이걸 작업할 때만 해도 “뭔가 이상하긴 하지만 이정도면 흡족하군”이라고 생각했습니다. 그래서 제 미투데이에 올려 흡족한 부분은 뽐내고 뭔가 이상한 부분은 지적받기로 했습니다. 여러가지 의견이 달렸고, 다행히 김준민 선배께선 정말로 좋은 지적을 해주셨습니다.

코트 속에 다리 그려봤어? 그려보면 허벅지가 비정상적으로 긴 사람이 될거야… 만약 실제로 그렇다고 해도 키높이 구두를 신겨줘…. 그리고 저번에 재석이 합성이 이상했던건 다리는 긴데 팔이 짧아서야. 다리가 길면 팔도 늘려주세요 ㅎㅎ 그림자는 다리를 좀 굵게 그리면 괜찮지 않을까?

아하! 얘기를 듣고보니 정말 엉망이었네요. 또 이날 잠시 만난 해멍 누나는 그림자가 어디어디에 들어가야할지 지도해주셨습니다. 준민 선배의 지적에 따라, 해멍 누나의 지도에 따라,

img_8136

그리고 오른팔은 실제로 사진을 찍은 후 참고하여 그림을 다음과 같이 수정했습니다.

fighter02

여기에 부족한 하이라이트는 조재희 씨의 도움으로 덧붙일 수 있었습니다.

fighter03

fighter04

첫째날 작업은 여기까지였습니다. 시시때때로 빈둥거리며 작업해서 속도는 굉장히 느렸습니다.

이튿날, 바로 애니메이션 작업에 들어갔습니다. 전 본격적인 애니메이션 작업에 앞서 그림의 부분부분을 떼어내 옮겨서 프로토타입을 구성합니다. 다음은 첫 번째 프로토타입입니다.

fighter05

어딘가 어색하길래 사막여우 누나에게 조언을 구했습니다. 이번엔 몸통이 앞뒤로 움직이는 것이 어색하다는 지적을 받았습니다. 바로 상하운동만 하도록 수정했고 결과는 만족스러웠습니다.

fighter06

프로토타입에 생긴 틈들을 메우고 다듬기만 하면 간단한 애니메이션은 완성됩니다. 거기에 목도리의 파동을 가이드할 선을 추가했습니다.

fighter07

마지막으로 바람에 휘날리는 목도리를 그려넣고, 자잘한 부분을 손 봄으로써 마침내 작품을 완성했습니다.

fighter07

3년동안 손 놓고있던 것에 비하면 꽤 만족스러운 작품이 나왔다고 생각합니다. 만약 저 혼자서 작업했다면 잘못된 형태, 어색한 그림자와 동작을 해결하지 못해 형편없는 작품이 만들어졌을 것입니다. 처음부터 뭔가 어색한 것 같긴 하다고 느꼈으나 이론적인 바탕이 전혀 없다보니 그 이유를 알 수 없음에 굉장히 답답해 했습니다. 다행히 몇몇 분이 그 의문을 해소시켜주었고 나은 방향으로 인도해주었습니다.

완성하는데 도움 주신 분들, 아낌없이 칭찬해주신 분들께 감사하며 역시 혼자만으로의 한계는 다른 사람과의 협동으로 쉽게 극복할 수 있단걸 다시 한 번 느낀 기회였습니다.