Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Github Data Challenge용 개인 프로젝트 : Popular Convention

4월 초에 Github에 블로그에 올라온 The GitHub Data Challenge II의 공지를 보았다. 작년에 처음 진행하고 이번에 두번째인데 해카톤같은 행사는 유심히 보는 편이고 특히 Github는 정말 사랑하는 서비스이기 때문에 할만한게 없을까 고민을 몇일했다. 이때 다른 해커톤 행사도 국내에 있었는데 아무래도 Github쪽에 마음이 더 많이 쏠렸고 오픈소스의 표준 저장소가 되어버린 Github에 정말 많은 데이터들이 쌓여있을 것이므로 이것으로 많은걸 할 수 있을것 같았지만 (항상 그렇듯이) 별다른 생각은 떠오르지 않았다.

원래 이 글은 사용자들이 접속했다가 버그로 사이트 죽을까봐 대회가 끝나면 올릴려고 했는데 5월 20일쯤에 나온다던 결과는 6월이 되도 올라오지 않기에 그냥 올린다.

동기

그러다가 작년 말 DailyJS에서 JavaScript 개발자들을 대상으로 진행했던 설문조사가 생각났다. 이 설문조사에 여러가지 설문내용이 포함되었지만 "콤마를 앞에 쓰냐 뒤에 쓰냐?", "메서드 뒤에 공백문자를 넣느냐?"등의 질문들이 있었다. 이 설문조사가 생각난 순간 Github에 거의 모든 오픈소스의 소스코드가 들어 있는데 이걸 굳이 설문조사로 파악할 필요가 있을까 하는 생각이 들었다. 실제로 개발자들이 사용한 상당수의 소스코드가 Github에 올라가 있고 이걸 분석할 수 있다면 개발자들이 어떤 관례를 사용해서 코드를 작성하는 지도 알 수 있을 것이라는 생각이 들었다.

프로토타이핑

먼저 생각한게 실제로 가능할지 궁금했기 때문에 프로토타이핑에 들어갔다. Github 데이터챌린지는 대부분의 행사와 달리 어떤 특별한 제약이 없다. 그냥 Github 데이터가 있으니 표현해봐! 정도말고는 아무런 제약도 없다. 그리고 Github에 올라오는 전체 타임라인을 구글 BigQueryGithub Archive 사이트를 통해서 제공하고 있다. 여기서 전체 타임라인은 로그인했을 때 팔로잉한 사람들이 하는 활동이 나오듯이 Github의 모든 유저가 하는 활동(push, 이슈처리, watch등등)을 매 시간별로 제공하고 있다. 처음에는 Github Archive를 모르고 BigQuery를 사용하려고 했지만 무척이나 어려웠다.(Google은 너무 커서그런지 API 좀 사용하려면 문서 찾아서 테스트해보는게 엄청 힘들다. ㅠㅠ) 한창 고생하다가 Github Archive에서는 그냥 JSON파일을 압축해서 제공하고 있는 것을 알게 되었고 이는 그냥 wget등으로 바로 내려받아 볼 수 있었고 시간별로 누가 어떤 행위를 했는지가 모두 기록되어 있었다.(참고로 Github Archive는 Ilya Grigorik라는 구글 개발자가 만든 사이트이다.)

타임라인을 기반으로 실제 코드를 얻을 수 있는지 API 테스트에 들어갔고 commits API를 통해서 커밋에 대한 패치내용을 함께 받을 수 있는 걸 알게 되었고 이걸 바탕으로 구현할 수 있을것 같았다.

실제 구현

빠르게 작업해야 했기에(실 서비스라기 보다는 깃헙 챌린지에 타게팅한 것이므로) Node.js를 자연스레 사용했고 당시에 Hubot을 만지면서 오랜만에 사용해보는 CoffeeScript에 재미를 다시 느끼고 있었기에 커피스크립트를 사용해서 구현하기로 했다. 보통은 개인 프로젝트에서 연습삼아 테스트코드도 좀 엄격하게 짜는 편이지만 품질과 생산성의 경계에서 좀 고민이 있었기에 이번에는 러프하게 기능만 확인해 볼 수 있는 수준에서만 테스트코드를 작성하면서 구현했다.

일단 데이터 분석은 푸시된 커밋을 기반으로 하기로 했다. 매 시간별로 올라온 푸시의 각 커밋의 패치내용을 가져와서 분석하기로 했다. 원 저장소에 더 많은 소스가 있을 것이지만 이럴 경우 수정된 내용을 파악하기가 어렵고 어느 저장소를 타게팅할지도 애매했기 때문에 패치된 소스를 기반으로 추가된 라인만을 기준으로 분석하기로 했다. 하지만 현재 Github는 인증을 할 경우 한시간에 5,000개의 API 요청제한이 있는데 정확한 하긴을 어려웠지만 매시간마다 갱신되지 않는것 같았고(기준시간을 모르므로 하루에 120,000개(5,000 * 24)가 아닌것 같다는 얘기다.) 한 시간 분량에 올라오는 Push가 5천개까지는 안됐지만 하나의 Push에는 커밋이 한개만 있을 수도 있지만 수십개도 있을 수 있을 수 있으므로 커밋마다 보내야 하는 API수는 매 시간 5,000개가 훨씬 넘어갔다. 결국 저장소를 watch와 fork수로 정렬해서 인기있는 저장소를 기준으로만 분석하고 나머지는 그냥 포기하기로 했다.

흐름은 복잡하진 않았다. Github Archive에서 json을 받아와서 MongoDB에 해당 시간을 이름으로 컬렉션을 만들어서 import시킨다. 이를 큐로 사용할 컬렉션에 넣어놓고 배치가 돌면서 처리하지 않은 데이터에서 Push 이벤트만 가져와서 순차적으로 Github API에서 커밋데이터를 가져오고 파일명에 기반해서 언어별 파서를 돌려서 분석하고자 했던 각 컨벤션에 대한 점수를 매긴다.(A 컨벤션에 적용되면 +1같은 식으로) 이를 모아서 각 점수를 디비에 다시 넣는다. 생각보다 데이터가 많아서 데이터를 모으는데 시간이 걸리므로 추가적으로 배치를 돌아서 이를 시간대별로 통계를 낸 데이터를 따로 모으다. 이를 화면에 내려주고 화면에서 보여준다.

Popular Convention

이렇게 만든게 Popular Convention on Github이다. 지금은 배치는 멈춰있어서 더이상 수집하지 않는다.

Popular Convention 프로젝트 홈페이지

현재는 자바스크립트, 자바, 파이썬, 스칼라만 분석을 했다.

Popular Convention에서 자바스크립트의 컨벤션 통계 화면

그래프는 d3를 사용했고 디자인은 요즘 유행하는 FlatUI를 사용했다.

아쉬운 점

  • 컨벤션 분석을 전체코드로 수행하지 않고 패치에 수정된 부분만을 기준으로 하다보니 의미적인 분석은 전혀 할 수 없고 그냥 텍스트 분석밖에는 할 수 없다.(실제로는 그냥 정규식으로 비교한거지만 ㅡㅡ;;) 그러다 보니 초기에 구상했던 자바스크립트는 간단한 정도로 분석할 수 있었지만 언어별 특성에 따른 분석을 거의 할 수 없었기에 결과적으로 언어별 관례 분석이라지만 거의 차이가 없어졌다. ㅠㅠ 그리고 자바스크립트에 비해서 다른 언어는 관례가 좀 더 고정되어 있었기에 분석한 내용이 큰 의미를 갖기가 어려워졌다.
  • d3.js를 처음 사용해 보고 예제를 보면서 화려한 비쥬얼라이제이션을 생각했었다. 처음에는 여러가지 그래프형식으로 보여주고 애니메이션으로 변화되면서 화려하게 보여주려고 했지만 처음 사용해보는 d3.js는 생각보다 쉽지 않았고 대충 통밥으로 활용할 수 있는 수준을 넘어섰기에 간단한 도넛그래프외에는 제대로 그려낼 수가 없었다. 결국 시간의 압박으로 포기했지만 d3.js의 강력함은 확실히 느꼈기에 시간내서 배워둘만하다.
  • 앞에서 테스트코드를 엄격히 작성하지 않았다고 했는데 꼭 그 때문만은 아니지만 하나의 함수에 로직을 너무 떼려넣어서 오류가 은근히 많이 발생했고 실제 Github 데이터를 끌어오면서 예상치 못한 데이터나 문자때문에 발생하는 오류 등 때문에 뒤로 갈수록 디버깅이 너무 힘들었다.
  • Node.js의 비동기적인 특성과 callback기반은 편하기도 하지만 예외처리나 흐름제어가 역시 만만치 않다. 결국 이때문에 한 함수에 많은 로직을 넣게 된 것도 있다.
  • MQ를 쓸 수 있을만한 요소가 꽤 있었음에도 그냥 로직내에서만 처리하려다 보니 독립적으로 동작하게 만들 수 있었을 것 같은 부분도 상당한 의존성을 서로 가지게 되었다.
  • 데이터가 많아질 때의 고려가 제대로 되지 않아서 데이터를 수집할 수록 문제가 터져나왔다. MongoDB에 대한 많은 고려를 하지 않고 그냥 눈앞의 편의에 데이터를 임베딩해서 막 떼려넣었더니만 데이터가 증가하면서 문제가 속속들이 터져나오기 시작했고 페이지 로딩시간도 너무 올래걸려서 데이터도 캐싱하는 등의 로직을 계속 넣어줘야 했다.

에필로그

잠시 프로토타이핑하다가 필 받아서 4월내내 다른 일 미뤄두고 이 프로젝트에만 매달렸다. 이래저래 즐거운 시간이었다. 새로운 것들도 많이 써보기도 했고 반은 학습목적인 개인 프로젝트는 제대로 결과물이 나오지 않고 계속 새로운 라이브러리를 시도해보거나 반복적인 리팩토링으로 프로젝트진도가 잘 나가지 않는 특성이 있는 편인데 이번에는 마감기한이 있다가 보니 적절한 선에서 기술적인 부분과 시간적인 부분을 조정해 나가야 했기 때문에 좀 더 흥미로웠는지도 모르겠다.(회사에서는 흔히 겪는 상황이지만 회사에서는 협의라는 별도의 과정이 따로 필요하므로.. ㅋ) 소스는 엉망이지만 어쨌든 Github에 올려져 있다.

2013/06/05 02:34 2013/06/05 02:34