Friday, February 10, 2012

jQuery 에서 동적 이벤트 등록시 이벤트 중복 문제

Javascript 에서 addEventListener 그리고 jQuery에서 .bind , .click 등 으로 다양하게 이벤트를 등록할 수 있다. 하지만, 어떤 DOM에 이벤트가 등록되는지에 따라 이벤트는 원하는 대로 동작하지 않는 경우가 발생할 수 있다. 몇가지 상황을 들어 본다.

1. 동적으로 생성되는 DOM에 대한 이벤트 등록
동적으로 새롭게 생성되는 이벤트에 대한 등록은 상대적으로 안전하다고 본다. 생성되는 이벤트에 대해 이벤트가 1:1로 등록이 되게 코딩을 한다는 가정 하에서. 하지만, DOM이 여러번 생성되고 동적 생성시 동적 삭제가 제대로 동반되지 않을 때 문제가 발생할 수 있다.

$('#create').click( function(){
     $('<div id=button >Button</div>').appendTo('body');
     $('#button').click( function(){
          alert('good');
     });
  });

위의 코드는 어떻게 동작할까? create 을 누르면 id=button인 버튼이 생성이 되고, 버튼을 누르면 'good' 이란 문구를 띄우는 창이 발생하는 이벤트가 등록된다. create를 두번 누르면 어떻게 될까?

버튼이 하나더 생긴다! 하지만, 새로 만들어진 버튼에는 이벤트가 등록되지 않는다. 동시에 처음에 만들어졌던 버튼을 누르면 alert 창이 두번 뜬다. id=button를 가진 첫번째 엘리먼트에 이벤트가 등록되므로 이후로 만들어지는 버튼에는 이벤트가 등록되지 않는다.

id 가 같은 엘리먼트가 여러개 만들어지는 건 피해야하지만, 그럼에도 불구하고 굳이 이 상황을 해결하고 싶다면, 즉 만들어지는 버튼 각각에 대해 이벤트를 등록하고 싶다면? 아래와 같이 각 엘리먼트 발생시 직접 이벤트를 연결해주면 된다.

$('#create').click( function(){
     $('<div id=button>Button</div>').appendTo('body').click( function(){
          alert('good');
     });
  });

2. 존재하는 DOM에 대한 이벤트 등록
보통 문제는 존재하는 DOM에 대한 이벤트 등록이다.
$('#button').click( function(){
       $('#start').click( function(){
               alert('What?');
       });
  });

위의 코드는 버튼( id=button인 엘리먼트)을 클릭하면, id=start 인 엘리먼트에 alert 를 띄우는 이벤트를 등록한다. 버튼을 한번 누르고 나면 이후에 start 를 눌렀을 때, 한번 alert 창을 띄운다, 이것이 이 코드를 작성한 사람의 의도일 것이다.

그런데 버튼을 두번 누르면 어떻게 될까?

start 엘리먼트에 이벤트가 두번 등록된다. 그래서 start 를 누르면 두번 alert 창이 뜬다. 한번 더 버튼을 누르면? 당연히 세번 alert 창이 뜬다.
이 문제를 해결하는 가장 간단한 방법은 버튼을 누를 때 마다 아래와 같이 기존에 등록된 'click' 이벤트를 제거하는 것이다.

$('#button').click( function(){
       $('#start').unbind('click');
       $('#start').click( function(){
               alert('What?');
       });
  });

기본적으로 동적 생성되는 DOM 이 아닌 경우라면 이벤트 등록을 중복하지 않는 것이 후폭풍을 막는 지름길이 아닐까 생각하고, 써야하는 상황이라면 항상 이벤트 중복이 되지 않게 주의를 기울여야 함을 기억해 놓자!!

Wednesday, December 21, 2011

Google PageRank 로 뽑아보는 인기 Blog 글

 한해를 정리하며 자신이 일년간 쓴 블로그 글들이 얼마나 impact가 있었는지 체크해보는 것도 의미 있으리라... Google analytics 등 분석 툴을 이용해 각 글들의 클릭수, 읽은 시간 등을 체크해 볼 수도 있지만, 여기서는 각 블로그 글의 Google PageRank 를 이용해 인기순위를 체크해 보는 간단한 Perl script 를 만들어 본다.

준비
WWW::Google::PageRank
Web::Query
두개의 Perl 모듈

1. Blogger 에서 BlogID 얻어내기
Google 에서 제공하는  Blogger API 를 보면, 각 Blogger 블로그에 대한 feed를 얻기 위해, blogID를 알아야 한다. 이를 확인 하는 방법은 아래 두가지를 꼽아 볼 수 있다.

 a) 디폴트 feed 페이지( http://blog-name.blogspot.com/feeds/posts/default )에서 id 태그에 blog-'blogID' 형태로 삽입된 blogID 를 얻어내는 방법

b) feedburner 등으로 디폴트 feed 페이지를 변경하여 a) 방법이 불가능한  경우, 블로그 대문 html 파일 하에 item-action 클래스로 묶인 태그 하의 링크 주소에 blogID='blogID' 형태로 삽입된 blogID를 읽어오는 방법

위 두가지 방법으로 이 블로그의 blogID 를 얻어내는 코드는 아래와 같다.

# Blogger계정의 블로그 feed 주소 ( goldbio 부분에 자신의 블로그 주소 앞부분을 넣으면 된다 )
my $blog_add=qq|http://goldbio.blogspot.com/feeds/posts/default|;
# a 방법 wq($blog_add)->find('id')->text=~/blog-(\d+)/; my $id=$1; # b 방법  wq($blog_add)->find('.item-action')->find('a')->attr('href')=~/blogID=(\d+)/; my $id=$1;




위의 코드에는 Web::Query 를 이용해 html 페이지를 파싱했는데, 이 모듈은 jQuery와 같은 방식으로 태그 이름, 클래스 이름 등을 사용해 간편하게 html 페이지 요소에 접근할 수 있도록 하는데, 같은 기능을 하는 모듈로 pQuery 라는 모듈도 있다.  ( 이 모듈은 올해 진행되는 서울 펄 크리스마스 트리에 언급되어 알게 되었는데, jQuery 를 최근에 많이 쓰다보니 다른 모듈들 보다 훨씬 편한 느낌^^)




2. 각 블로그 글의 PageRank 얻어내기
  
blogID 를 얻어낸 후엔 이를 이용해 해당 블로그의 feed를 아래 주소를 통해 접근할 수 있다.
http://www.blogger.com/feeds/blogID/posts/default ( blogID 부분에 해당 블로그 id를 넣으면 된다 )
이 주소로는 대문 페이지에 보이는 글들만 얻어올 수 있기에, 한해 동안의 블로그 글을 얻어내려면 옵션을 추가해야 한다. 


&published-min=2011-01-01-T00:00:00 을 위의 feed 주소 뒤에 붙이면 2011년 1월 1일 0시 부터 쓴  모든 글들에 접근할 수 있다. 2011년에 쓴 글들이 꾀나 많다면 &max-results=100000 과 같이 적당한 최대 검색값을 덧붙인다.  


www.blogger.com/feeds/$id/posts/default?published-min=2011-01-01T00:00:00&max-results=100000000


위의 주소로 접근하면 이 블로그에 2011년 한 해 동안 업데이트된 글들이 모두 포함된 feed 를 확인할 수 있다.  이제 각 글들의 Pagerank 를 확인하면 된다. 먼저  각 글들의 URL 을 얻어내고, 얻어진 URL 을 WWW::Google::PageRank 를 이용해 확인하면 된다.


글의 URL 은 아래와 같은 형태로 각 블로그 글 마다 삽입되어 있는데, 
<link rel='alternate' type='text/html' href='http://goldbio.blogspot.com/2011/09/jquery.html' title='jQuery::이미지 크기 동적으로 변경'/>

여기서 href 아래 주소만 Web::Query 를 이용해 얻어내는 코드는 
$feed->find('link')->attr('href') 와 같이 쓸 수 있다.  $feed에는 이와 같은 link 가 블로그 글 숫자 만큼 들어 있고, 이를 모두 얻어내야 하므로 코드는

$feed->find('link')->each ( sub {
   my $i=shift;
   my $post_link=$_->attr('href');
});
와 같이 쓸 수 있다. 

WWW::Google::PageRank 사용법은 간단하다.

주어진 URL 에 대해 아래와 같은 코드로 pagerank를 확인할 수 있다.

my $pagerank=WWW::Google::PageRank->new;
my $pagerank= scalar( $pagerank->get( URL ) ) ; 

최종적으로 Feed 페이지를 Web::Query 모듈을 이용해 파싱하여 각 블로그 글들의 URL 을 얻고, 해당 URL 을 이용 Pagerank 를 얻어내는 코드를 종합해 보면 아래와 같이 쓸 수 있다. 




## 2011년 블로그 Feed 주소
my $blogger_API=qq|http://www.blogger.com/feeds/$id/posts/default?published-min=2011-01-01T00:00:00&max-results=100000000|;



## 각 블로그 글에 해당하는 Google Pagerank 출력
my $q=Web::Query->new( $blogger_API );
$q->find('link')->each( sub{
    my $i=shift;
    next if $_->attr('rel')!~/alternate/;
    my $post_link=$_->attr('href');
    my $post_title=$_->attr('title');
    my $post_pagerank=scalar( $pr->get($post_link) );
    print "$post_title\t$post_link\t$post_pagerank\n" ;
});




3. 종합

인기 블로거가 아닌 이상, 각 블로그 글들은 아마 대부분의  글의 Pagerank 가 0 일 것이다. (참고로 이 블로그의 모든 글 108개 중 pagerank 가 1 이상인 글은 2개 뿐이다 -pagerank 는 10점이 최고 점수) 그러니 결론적으로 블로그 글 인기순위 메기기에 pagerank 는 부적합해 보인다. 따라서 다른 용도로 pagerank 수치를 적절하게 결합해서 사용하는 것을 추천!

Monday, November 21, 2011

뭔가 배우고 싶다면 6개월 지속하자!!


3-4년 전 쯤 읽었던 책 'The brain that changes itself' 는 뇌과학의 흥미로운 연구결과들을
대중의 입맛에 맞게 맛나게 풀어써 놓은 책인데, 오늘 책장을 뒤적거리다 이 책을 뽑아들고
휙휙 넘겨보다 기억해 둘 만한 내용이 있어 나눠 본다. 

1. 만시간 법칙

학습 이론에 관해선 수많은 연구결과들이 발표되어 왔는데, 그 중 유명한 것이
에릭슨의 '만시간 법칙' 으로, 현재 전세계에서 가장 잘 팔리는 논픽션 작가
말콤 글래드웰의 책 '아웃라이어' 에 소개되어 널리 알려졌다. 

만시간 법칙은 어떤 분야의 전문가가 되기 위해선 만시간, 10년 정도의 시간을
꾸준히 노력해야 한다는 내용이다. 에릭슨의 이 연구 결과는 다양한 분야의
전문가들을 꼼꼼히 연구한 결과 밝혀진 내용으로 상당히 신뢰할 만 하다. 
단, 여기에 조건이 있는데, '10년 동안 그냥 했던거 반복' 만 하면 안 되고, 
자신의 실력을 향상 시키기 위한 '잘 조직된 연습' ( Deliberated effort ) 로서의
만시간이 필요하다는 것이다. 

2. 'Monday-Friday' 법칙
The brain that changes itself 에 담긴 연구 결과는 의사이자 생리학 박사인 Alvaro Pascual-Leone 이란
사람이 하버드 의대에서 수행한 것으로, '읽기 능력' 의 수행 능력 향상과 학습의 지속 시간 그리고
뇌의 변화를 관찰한 결과로 얻어진 것이다. 

간단하게 결과를 요약하면, 주중에 월요일 부터 금요일 까지 열심히 익히고 배우면 금요일까지
수행 능력이 매일 향상이 된다. 하지만 토요일, 일요일을 쉬고 월요일에 수행 능력은 다시 연습을
시작하지 전과 같은 레벨로 떨어진다. 

하지만, 장기간 이런 수행능력 향상 연습을 반복하면 평균 6개월이 지나면 '월요일 효과' 가 사라진다.
즉, 몇일 쉬어도 수행 능력은 꾸준히 유지가 된다. 이 상태에서 2달 정도가 지나도 수행 능력은 
약간의 '회복 시간' 이 지나고나면 다시 원상태로 회복된다.

6개월 동안의 연습 시간이 지나고 나서, 뇌 fMRI 사진을 찍어보면, 연습한 과업을 수행할 때
뇌가 관여하는 형태가 6개월 전과 확연히 다르다. 즉, 6개월 정도의 '꾸준한 노력' 이 지속되면
뇌 자체가 이 과업을 '빠르고 효과적으로 수행할 수 있을 만큼' 새로운 뇌 세포간 네트워크를
만들어 내게 되고, 한번 이렇게 '뇌 구조가 바뀌고 나면' 이 과업은 이제 쉽게 잊지 못하는
언제든지 익숙하게 수행할 수 있는 일이 된다는 것이다. 


3. 6개월 지속 법칙

이 연구 결과를 따르자면 '평범한 보통사람' 으로서 어떤 일을 제대로 익히기 위해서는 6개월
정도를 꾸준히 지속하는 노력이 필요하다. 생각해 보면, 대게 우리는 몇주 열심히 혹은
한두달 열심히 하고 나서 조금 시간이 지나서 그 동안 열심히 한걸 새까맣게 까먹고
자신의 우둔함을 한탄하는 경우가 아주 빈번하지 않나? 

하지만, 그게 당연한 것이니 그럴 필요가 없다. 뭐든 6개월 정도를 꾸준히 지속하면
그 일 자체가 우리 뇌속에 각인이 되고, 우리 몸의 일부분이 된다. 
'빡세게 짧은 기간 열심히' 보다는 '꾸준한' 노력이 필요하다. 


4. 전문가의 뇌

예전에도 전문가가 일을 처리할 때의 뇌에 관한 글을 많이 썼었는데, 
다시 한번 더 언급해 본다. 전문가는 흔히 생각하듯 '창의적' 인 사람과는
거리가 멀다. 반대로 전문가는 어떤 특정한 일을 수행하는데 보통 사람이
믿지 못할 만큼 빠르고 효율적으로 일을 처리할 수 있다. 

이것이 가능한 것은 앞서 언급했던것 처럼 뇌 자체가 그 일을 빠르고
효율적으로 처리할 수 있는 새로운 뇌구조를 만들어 두었기 때문이다.

대게 여기는 '장기기억' 에 관련한 뇌가 관련한다. 전문가들은 엄청나게
많은 경우의 수, 그리고 필요한 정보를 장기기억에 저장해 놓고 언제든지
빠르게 꺼내 쓰고, 또 효율적으로 조합할 수 있다. 반면에 비전문가들은
어떤 정보가 필요한지 모르는 경우가 많고, 또 안다 하더라도 이런 정보들을
확인해서 확보하고, 또 이들을 어떻게 적절히 조합해서 문제를 해결해야하는지
에 대해 엄청나게 머리를 쓰면서 에너지를 소비해야 한다. 

그래서 실제로 비전문가들이 전문가들에 비해 머리를 훨씬더 많이 쓴다. 
뭔가를 잘 못하는 사람한테 '머리 좀 써라' 라고 전문가가 핀잔을 주는 건
사실 잘못된 말이다. 전문가는 비전문가에 비해 같은 일을 수행할 때
20% 정도 밖에 뇌를 쓰지 않는다. 


5. 마무리
나이탓, 머리탓 하는 사람들 무지 많다. 
뭐든 6개월은 지속해서 노력하고 나서 그런 소리 하자. 


실제로 자기가 '나이가 들어서 이런저런 일들을 할 수 없다' 라고 
생각하면 실제로 그렇게 된다는 최근 연구 결과가 있다. 그런 사람들이
평균적으로 훨씬 건강 상태도 안 좋고, 평균 수명도 짧았다고 한다.  

그딴 핑계는 대지 말고 젊게, 항상 배우고 살자. 

Thursday, September 1, 2011

jQuery::이미지 크기 동적으로 변경

아래와 같이 이미지를 표현하고 난 후,

<img src='yes.jpg'>


상황에 따라 이미지 사이즈를 동적으로 변경해야 하는 경우가 종종 발생한다.
한 예로, 이미지의 가로와 세로의 길이를 비교해서 긴 쪽 이미지를 100px 로 바꾸는 경우를 jQuery 를 이용하면 어떻게 될까.


var img=$('img');
if( img.width()  > img.height() ) {
   img.width('100px');
}else{
  img.height('100px');
}


작동해야 할 것 같은 이 코드는 원하는 대로 작동하지 않는다.
원인은 이미지가 완전히 로딩되지 않은 상태에서 이미지의 가로, 세로 길이를 비교했기 때문이다. alert 를 이용해 img.width() 와 img.height() 를 찍어보면 값은 0으로 나온다.

따라서 위의 코드를 이미지가 완전히 로딩되고 난 이후에 동작하도록 고쳐야 한다.
load 함수를 이용해 이를 고려한, 완전히 동작하는  코드는 아래와 같다.



var img=$('img');

img.load( function() {
   if( img.width()  > img.height() ) {
     img.width('100px');
   }else{
     img.height('100px');
   }
}



PS::
위의 코드를 이용한 이미지 사이즈 변경은 한가지 문제점을 가지고 있는데,
.load 함수의 실행은 이미지가 완전히 로딩된 후에 일어난다는 사실이다.

즉, 큰 이미지가 로딩되어 화면에 표시된 후( 네트웍 속도가 느릴 수록 이 효과는 극대화),
load 함수에 따라 이미지 리사이징이 일어난다.
문제 해결은간단한데, .load 함수 이전에 이미지 표시를 막으면 된다.

1. css 파일에 이미지 표시를 하지 않는 것으로 default 설정을 한다.

img{
  visibility:hidden;
} 


2. .load 함수에서 이미지 표시 제한을 풀어준다.

img.load( function() {
   if( img.width()  > img.height() ) {
     img.width('100px');
   }else{
     img.height('100px');
   }
   img.css('visibility','visible');

}

Saturday, August 6, 2011

GigaScience :: BGI 가 출간하는 저널

BGI 가 BioMedCentral 과 합작하여 GigaScience라는 새로운 저널을 출간한다는 소식이다.  ( http://www.gigasciencejournal.com/ )

'Big Data' 에 기반한 생의학 연구들의 출판을 목표로 하고 있고, 리뷰 과정에서 기존의 '학문적 의미'에 대한 잣대와 동시에 데이터의 유용성과 재연성을 중요한 잣대로 할 계획이라고 한다.

또하나 흥미로운 점은 '데이터셋' 자체에 DOI 를 부여하여, 데이터가 하나의 연구 논문에서 분석되는데서 벗어나 넓리 퍼져나가 다양한 연구에 이용될 수 있도록하여 데이터의 가치를 극대화하겠다는 점을 공언한 점이다.

"데이터의 '저장'과 함께 데이터의 효과적인  '전파' 도 중요한 문제다  "
- GigaScience 저널의 편집장 Scott Edmunds( BGI 소속)

데이터셋 자체에 DOI 를 부여하는 건 정말 '학계' 에서 보기 드문 획기적인 발상이다.  또한 이는 지난 10년 간의 Genomic data 들의 낮은 재사용성을 NGS data에 대해 답습하지 않을 수 있는 가능성을 어느 정도 열어 준다고 평가한다.

Microarray database인 NCBI 의 GEO에는 현재 24,000여개의 독립된 dataset (GSE 단위) 이 존재하지만, 두번 이상 재분석 된 dataset은 손에 꼽을 정도다. 기본적으로 어떤 논문에 어떤 GSE data가 쓰였는지 논문 본문을 검색하거나, 반대로 geo 데이터를 검색하지 않는 이상 알 수 없고, 해당 논문이 인용이 되어도, 논문에 딸린 dataset에 대한 인용인지를 평가하는 것도 어려운 등의 문제가 존재하여, dataset 자체에 대한 평가가 어려웠다는 문제가 있었기 때문이다.

1. Dataset 자체에 DOI 가 붙으면, 이를 분석한 논문과 별개로 dataset 자체에 대한 citation 이 가능해진다. 따라서 어떤 Dataset 이 퀄리티 높고, 재연성이 높은 dataset 인지를 일목요연하게 search하고 분석하는 것이 가능해 진다.

2. 인용이 가능해짐은 곧, dataset 자체로 높은 citation 을 얻을 수 있다는 얘기. 이는 곧, 높은 품질의 dataset 생산과 '전파' 에 대한 연구자들의 '동기'를 유발하게 하는 효과를 불러 일으킬 수 있다.
이는 다시 재연가능하고 유용한 dataset 숫자의 증가라는 긍정적인 결과로 이어진다.

2010년이 넘어가면서 본격적으로 생물학은 data dependent information science 로 넘어왔다. 바야흐로 bioinformatics 의 전성시대가 열리고 있고, dataset 자체가 논문과 상응하는 DOI 를 가질 수 있는 시대가 열렸다는 것은 이런 '시대의 흐름'을 보여주는 한 단면이 아닐까

Monday, July 25, 2011

GWAS catalog 데이터 등록 날짜 통계


2011년 7월 26일자 GWAS catalog DB 에 수록된 데이터들의 등록일 통계( 총 5846건). 심심해서 한번 그려봤다.

1. 2008년 DB 생성 이래로 연도별로 꾸준히 증가하는 추세. 2011년 7월  까지 데이터가 전년도 데이터 총량의 85.7% 로 추세가 이어지면 2011년 데이터는 2010년에 비해 거의 두배 가까이 될 것으로 예상

2. 월별, 일별 데이터 등록일을 보면 월별로 1월과 11월이, 일별로는 매월 25일에 등록된 데이터가 압도적으로 많다. 12월 연휴를 앞두고 11월에 처리하거나, 12월 연휴를 마치고 복귀해 전년도 데이터를 마무리 정리하기 때문에 1월과 11일이 많지 않나 싶고, 월별로는 매월을 마무리하는 월말에 데이터 등록량이 많지 않나 싶은데, 왜 꼭 굳이 25일이 특이하게 많을까? GWAS catalog 데이터 관리 팀의 매월 데이터 등록 마감일이 25일이 아닐까?

Monday, June 27, 2011

iPAD APP:: Bio-IT World

아이패드는 기존의 컨텐츠를 완전히 다른 레벨의 컨텐츠로 진화를 가능케 해주는 매우 뛰어난, 새로운 영역의 기계다. (적어도 내게는)PC에서의 꾸리한 인터페이스에 거의 사용도 안 하던 youtube가 가장 우수한 동영상 컨텐츠 뷰어가 되고, 웹툰이라는 컨텐츠가 '다음 코믹스' 아이패드 앱을 통해 내게는 완전히 새로운 형태의 만화 컨텐츠로 격상되는 경험을 주었다.

BioITWorld 아이패드 앱도 역시 이처럼 기존의 컨텐츠가 완전히 새로운 경험을 담은 우수한 컨텐츠로 새롭게 다가오게 만든 앱이다. BioITWorld 는 생물학과 컴퓨터 공학의 접점, 즉 Bioinformatics 라 명명하는 영역의 다양한 뉴스와 깊이 있는 분석 보고서를 담아 2달에 한번씩 발간되는 잡지다. 무료로 제공되기 때문에 주로 웹을 통해서 볼 수밖에 없는데, 웹을 통해 발간된 잡지는 오랜 시간 컴퓨터 모니터를 통해 읽기가 힘들어 제대로 컨텐츠 소비를 하기 어려운 단점이 있었다.

그러던 것이 이번 BioITWorld 아이패드 앱을 통해, 종이 잡지 보다도 훨씬 읽기 편한, interactiive 한 컨텐츠를 효과적으로 전달하는 잡지로 거듭났다고 개인적으로 평가해본다.

BioIT World 아이패드 앱, 초기 Archive 화면


앱을 실행시키면 위와 같이 Archive 화면이 뜨고, 원하는 달의 잡지를 볼 수 있다.




기사를 클릭하면 왼쪽과 같이 기사를 보여주는데, 이 상태론 글씨가 너무 작아서 제대로 읽을 수가 없다. 이제껏 웹 버전( 및 이를 출력한 프린트 버전 ) 은 이런 화면에서 잡지를 읽어야 했기 때문에, 제대로 내용을 읽기가 힘들고, 설령 읽는다해도 PC 화면을 붙잡고 오래 읽어내기는 힘들었다. 이제 아이패드용 앱에서 오른쪽과 같이 자유자재로 확대해서 편하게 내용을 읽을 수 있다.

동영상이 삽입된 페이지 ( 붉은색 카메라 아이콘)


위 페이지에서 동영상 아이콘을 누르면 연결되는 페이지


웹버전 잡지 답게,  내용에 맞는 동영상이 링크되어 있고, 이를 누르면 바로 Youtube에 등록된 동영상을 볼 수 있다.

BioIT world 아이패드 앱으로 Bioinformatics 뉴스를 실감나게 즐겨보자!