GitHub 전투력 측정하기 - Devrank 점수산정 알고리즘

Yaminyam·2022년 12월 13일
0
post-thumbnail

Devrank는 게임과 유사한 등급 시스템과 랭킹을 제공하여, Github 활동시 사용자에게 성취감을 주고 오픈소스 활동을 장려하는 서비스 입니다.

서론

배포주소

내가 오픈소스 활동을 꾸준히 이어올 수 있었던 이유가 뭐냐고 묻는다면 성취감 때문인 것 같다.
Dependancy Security 이슈에 대해서 고민할때는 해당 이슈에 MS, AWS 등 엄청난 회사들에서도 해당 문제를 언급하고 고민하고 있는것을 봤을때 나도 이런 사람들과 함께 일을 하고 있구나 라고 느낄 수 있었고, 처음 CPython에 기여하게 되었을때는 내가 짠 코드가 CPython을 사용하는 모든 사용자의 컴퓨터에서 돌아갈 것이라 생각하니 굉장히 뿌듯 했던 것 같다.

최근 깃허브에 새롭게 도전과제 기능이 업데이트 되었다.

별거 아니지만 이 기능또한 나에게 오픈소스 활동을 하는데 동기부여가 되었던것 같다.

나는 평소 게임을 할 때도 자유로운 오픈월드 게임보다는 나의 캐릭터가 착실히 성장하고 그 성장이 수치화되어 보여지는 RPG류의 게임을 좋아했고 어떤일을 하든 수치화된 나의 성장치를 보는것이 가장 큰 의욕을 만들어 주었다.

모든 오픈소스가 깃허브에서 운영되는 것은 아니지만 그래도 대부분의 오픈소스는 깃허브에서 관리된다고 생각해 오픈소스 활동을 하면서 나의 점수를 산정하여 수치화 할 수 있는 서비스를 통해 많은 사람들에게 오픈소스 활동에 동기부여를 해줄 수 있는 서비스를 만들고 싶었다.

프로젝트 시작하기

OPGC, CODUCK과 같은 유사한 서비스가 있지만 유지보수 되지 않고있고 점수 로직이 빈약하다고 생각되어 점수 산정 로직에 신경을 많이 쓴 형태의 서비스를 만들고 싶었다.

OP.GG와 Solved.ac 와 같은 서비스들 처럼 많은 사람들에게 유의미한 점수가 될 수 있도록 하고 싶었다.

깃허브 도전과제도 출시되고 나서 우려적인 시선이 꽤 있었던 것으로 알고있다.
오픈소스는 게임이 아니며 이런 도전과제 시스템은 어뷰징 유저를 생산할 가능성이 생길 수 있기 때문이었다.
물론 시스템적으로도 이를 방지해야 겠지만 모두 걸러낼 수 있는것은 아니며, 나는 Github의 생태계는 그래도 클린하게 조성되어있다고 생각했기에 이런 서비스를 시작하게 되었다.

점수산정 알고리즘

레포 가중치 = Star
(레포의 language sum / diskUsage < 1) 인 경우 레포 점수 0점
*주의 language sum은 default 브랜치의 전체 코드 크기(마크다운이나 코드가 아닌 파일은 제외)
*주의 코드가 아닌 문서레포의 기여의 비정상적인 가중치를 제외하기 위함
*주의 diskUage가 git obj의 사이즈이므로 branch가 많아질경우 값이 커질 수 있음

시간 가중치 = (1 / 1.0019) ^ 지난 일 수
레포점수 = 최대 100개까지의 commit별 (레포 가중치) * (시간 가중치) 합 / 100
커밋점수 = 개인레포 25개, 외부레포 25개의 레포점수 합
이슈점수 = 최대 100개까지의 (레포 가중치) * (시간 가중치) 합 / 1000
*주의 collaborator로 등록되지않은 조직 레포는 집계되지 않음
*주의 외부레포는 star 순으로 정렬이 되지 않음
활동점수 = 모든 커밋수 + 모든 이슈수 + 모든 PR수 + 모든 리뷰수 + 모든 레포생성수

유저활동점수 = 커밋점수 + 이슈점수 + 활동점수
유저개인점수 = 팔로워수 / 100

유저 점수 = 유저활동점수 + 유저개인점수

primaryLanguages = 점수산정에 포함되는 레포의 primaryLanguage의 점수 합 상위 3개 언어

y = (1 / 1.0019) ^ x 1년이 지났을때 시간가중치가 0.5가 되는 지수함수

해당 산정식이 현재 devrank에서 사용되는 점수산정 알고리즘 이다.
레포지토리의 star수가 절대적인 점수는 아니지만 그래도 star수가 많은 레포에 기여한 것일 수록 더욱 많은 사람들에게 사용될 오픈소스에 기여한다고 생각하여 더욱 많은 가중치를 주고 싶었고 이를 점수에 반영했다.
하지만 star수가 많은 레포에 maintainer 라거나 꾸준히 기여하는 사람들의 점수가 기하급수적으로 늘어날 가능성이 있는것을 방지하기 위해 한 레포당 최대 100개의 커밋까지 점수를 반영하였다.
그 이상의 commit을 하더라도 꾸준히 점수산정에 의미가 있도록 하는 것은 시간 가중치를 통해 해결하게 된다.

시간가중치를 적용하여 이전 과거의 레전드들이 영원히 랭킹에 남는것을 방지하고자 했고 꾸준히 계속 기여를 이어나가는 사람에게 좀 더 점수를 주고 싶었다.
그래서 1년이 지날때마다 점수가 반감되도록 하는 지수함수를 적용했고 이를 통해 100개 이상의 커밋을 한 레포에 기여하더라도 최근의 커밋이 생길수록 시간가중치가 높기 때문에 100개 이상의 커밋을 한 기여내역에 대해서도 점수를 부여 할 수 있었다.

레포 점수를 현재 100으로 나누고 있는데 이는 star수가 만약 10만개라고 한다면 commit을 100개를 하게된다면 한 레포에서 점수를 1000만점을 얻게 된다.
점수별로 가중치를 적절하게 설정하여 숫자를 너무 커지지 않도록 조절하려고 했지만 이럴 경우 초기 유저의 점수가 대부분 0점으로 집계되게 되었다.

이 문제를 해결하기 위해 레포의 가중치를 주는것 뿐만 아니라 Github에서 하는 모든 활동에 대해 점수를 부여하도록 하였다.
Github에서 일어나는 모든 활동에 의미가 있다고 생각했고 commit, issue, pr, review, repository에 각각 1점씩을 부여하도록 했다.

그리고 Github에서는 정보를 얻기위한 흔히 awesome 류의 레포들이 star 갯수를 많이 받는 경향이 있는데 이런 레포의 기여의 점수가 굉장히 높게 책정되고 있어 이를 현재 배제하고 있다.
하지만 문서레포의 기여또한 훌륭한 오픈소스 기여활동 이라고 생각하기에 적절한 가중치 값을 찾아 점수에 추후 반영할 계획이다.

마치며

여러가지 요소들을 많이 신경쓴 점수산정 알고리즘이라고 생각하지만 아직 갈 길이 너무나도 멀다.
Github GraphQL API를 사용하고 있는데 10초이상 request가 걸린다며 요청이 실패하게되어 한번에 너무 많은 데이터에 접근 할 수 없어 현재 점수산정이 실패하는 유저들도 몇몇 존재한다.
그리고 내가 임의로 설정한 가중치들이 대부분이므로 이를 납득 할 수 없는 유저도 많이 존재 할 것이며, 이는 데이터가 많이 쌓이게 됨에 따라 차근차근 튜닝해 나갈 예정이다.
그리고 현재 쓰이는 데이터뿐만 아니라 더욱 많은 요소들을 점수 산정에 포함시켜 더욱 다이나믹한 점수를 만들어내고 싶다.

0개의 댓글