실용 가이드

GitHub 별 추이 코드가 깨졌다면, 사용자 목록 대신 집계 API로 바꿔라

|작성자: QUASA 편집팀|5 분 소요| 2
GitHub 별 추이 코드가 깨졌다면, 사용자 목록 대신 집계 API로 바꿔라

사용자별 stargazer와 starred_at을 수집하던 GitHub 별 추이 코드가 접근 제한이나 페이지 한계로 깨졌다면, GET /repos/{owner}/{repo}/stargazers/history로 교체하면 된다. 이 엔드포인트의 week·total·days를 오래된 날짜부터 펼쳐 누적하면 사용자 신원 없이 별이 추가된 추이를 다시 구성할 수 있다.

단, total은 저장소의 현재 별 개수가 아니라 해당 주에 생성된 별의 수다. 따라서 모든 페이지를 받은 뒤 주간 객체를 오름차순으로 정렬하고, days의 일별 값을 running_total에 더해 차트용 시계열을 만든다. 별 취소는 이 합계에서 빠지지 않으므로 결과를 현재 별 개수와 같은 지표로 취급해서는 안 된다.

사용자 목록 모델을 집계 모델로 교체한다

기존 목록 엔드포인트는 application/vnd.github.star+json 미디어 유형을 사용하면 각 stargazer의 사용자 객체와 starred_at을 반환한다. 하지만 저장소의 성장 곡선만 그리는 기능에는 사용자 이름, 아바타, 프로필 주소가 필요하지 않다. 입력과 저장 단위를 user·starred_at에서 repository·date·daily_delta·cumulative_created로 바꾸면 기능에 필요한 범위만 다룰 수 있다.

GitHub의 공식 출시 안내 는 새 REST 엔드포인트가 개별 stargazer 데이터를 노출하지 않고 타임스탬프가 포함된 과거 별 집계를 제공한다고 설명한다. 앞서 목록 엔드포인트가 관리자와 협업자로 제한되면서 작동하지 않게 된 성장 추적 도구를 갱신하는 것이 이 API의 명시된 용도다.

대형 저장소에서 목록을 끝까지 읽지 못했던 문제도 이전 이유가 된다. Star History의 이전 기록 에 따르면 이 서비스가 사용한 목록 방식은 페이지당 최대 100명, 400페이지에서 멈춰 4만 개 이후의 구간을 직접 가져오지 못했다. 이는 모든 클라이언트의 보편적인 동작을 뜻하는 수치가 아니라 해당 서비스가 기존 API를 운용하며 겪은 한계다.

history 엔드포인트를 호출하고 페이지를 끝까지 받는다

GitHub 저장소 history 엔드포인트에서 week, total, 7개 days 값을 받는 호출 과정

첫 호출은 curl -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer <YOUR-TOKEN>" -H "X-GitHub-Api-Version: 2026-03-10" "https://api.github.com/repos/OWNER/REPO/stargazers/history?per_page=30&page=1"처럼 구성한다. OWNER와 REPO를 대상 저장소에 맞게 바꾸며, 공개 저장소는 인증 없이도 요청할 수 있다. 비공개 저장소에 fine-grained 토큰을 사용한다면 Metadata 읽기 권한이 필요하다.

GitHub REST API 레퍼런스 에 따르면 응답은 최신 주부터 시작하며 페이지를 늘릴수록 저장소 생성 시점 쪽으로 이동한다. history 엔드포인트는 페이지당 최대 30주, page는 최대 100까지 받고, 별이 추가되지 않은 주도 0으로 포함한다. 같은 문서는 별도 count 엔드포인트가 과거에 별을 취소한 사용자를 제외한 현재 개수를 반환한다고 명시하므로 history 누적값과 count는 의미가 다르다.

각 주간 객체에는 주 시작을 나타내는 Unix 타임스탬프 week, 그 주에 생성된 별의 수 total, 일요일부터 시작하는 일곱 개의 일별 생성 수 days가 들어 있다. 다음 페이지가 없을 때까지 응답을 합친 뒤 한 번만 week 오름차순으로 정렬한다. 첫 페이지만 사용하면 최근 30주 이내의 데이터만 남을 수 있다.

week·total·days를 일별 시계열로 펼친다

최신순 주별 응답을 일요일부터 펼쳐 일별 누적 시계열로 변환하는 과정

변환기는 기존 사용자 정렬 함수와 분리하는 편이 안전하다. total을 누적값으로 오해하거나, 최신순 응답을 그대로 차트에 전달하는 오류를 입력 단계에서 차단할 수 있기 때문이다.

  1. 모든 페이지의 주간 객체를 하나의 목록으로 합친다.
  2. week를 기준으로 오래된 주부터 정렬한다.
  3. running_total을 0으로 초기화한다.
  4. 각 주의 days를 인덱스 0부터 6까지 순서대로 읽는다.
  5. day_count를 running_total에 더하고 date, daily_delta, cumulative_created를 출력한다.
  6. 차트에는 date를 x축, cumulative_created를 y축으로 전달한다.

코드 없는 의사코드로 줄이면 “weeks 오름차순 정렬 → 각 week의 days 순회 → running_total에 day_count 추가 → 날짜와 누적값 저장”이다. 주간 신규 별 막대그래프에는 total을 바로 쓸 수 있지만, 누적 곡선에는 days를 펼친 결과가 필요하다.

방어적 검증으로 days가 일곱 항목인지, 값이 음수가 아닌지, 합계가 total과 같은지 확인한다. 불일치한 객체를 임의로 보정하지 말고 해당 페이지를 실패 처리해 다시 가져오는 편이 낫다. week와 day의 경계는 UTC와 일치한다고 보장되지 않으므로 Unix 타임스탬프를 무조건 UTC 자정으로 잘라 날짜를 재구성해서도 안 된다.

표시 시간대는 하나로 고정하고 전환 전후의 주 경계 라벨을 비교한다. 특히 한국 표준시로 날짜를 보여 주던 차트라면 일요일 배열의 첫 값이 토요일이나 월요일로 이동하지 않는지 확인해야 한다. 원본 week, day_index와 표시용 date를 함께 두면 시간대 규칙을 바꾸더라도 집계 입력을 다시 받을 필요가 없다.

0인 주와 페이지 경계를 보존한다

history 응답에 포함된 0인 주를 삭제하면 연속 시계열의 날짜 간격이 벌어진다. 차트 라이브러리가 떨어진 두 점을 직선으로 잇는 경우 실제로 변화가 없던 기간이 다른 모양으로 보일 수 있으므로, 제공된 0 값은 그대로 유지한다. 반대로 API 수집 범위 밖의 날짜까지 추측해 0으로 채우지는 않는다.

페이지를 합칠 때는 week를 키로 중복을 검사한다. 같은 week가 두 번 나타났다면 즉시 한쪽을 덮어쓰기보다 요청 시각과 응답 내용을 남기고 전체 수집을 재시도한다. 캐시를 갱신할 때도 페이지별 결과를 현재 데이터에 차례로 섞지 말고, 전체 페이지의 변환과 검증이 끝난 새 스냅샷을 한 번에 읽기 경로로 교체한다.

이 시계열이 나타내는 값의 이름도 분명히 해야 한다. days를 더한 결과는 기간별 별 생성 건수의 누적값이며, 별 취소를 반영한 당시의 순별 개수나 현재 stargazers_count가 아니다. 기존 화면이 “현재 별 수의 역사”라고 표시했다면 레이블과 설명을 함께 수정해야 지표가 과장되지 않는다.

기존 사용자 데이터는 전환 검증 뒤 정리한다

사용자별 stargazer 저장을 중단하고 검증된 날짜별 집계 데이터로 읽기 경로를 전환하는 과정

호출만 바꾸고 기존 stargazer 테이블에 계속 쓰면 사용자 데이터의 수집 범위는 줄지 않는다. 먼저 목록 수집기의 신규 쓰기를 중단하고 새 집계 파이프라인을 별도 스냅샷에 연결한다. 두 결과를 비교할 때는 사용자 목록의 행 수와 history 합계가 반드시 같다고 가정하지 말고, 공통 기간의 날짜 경계와 별 생성 이벤트 분포가 일관적인지 본다.

별 추이 차트에만 쓰던 login, avatar URL, profile URL과 원본 starred_at은 새 집계 구조에 필요하지 않다. 검증 및 정해진 롤백 기간이 끝나면 운영 테이블뿐 아니라 파생 캐시, 내보내기 파일, 로그와 백업의 보존 정책까지 확인해 삭제 범위를 정한다. 다른 기능이 실제로 개별 계정 정보를 사용한다면 history API는 그 기능의 대체재가 아니므로 별도의 목적과 보존 근거를 검토해야 한다.

  • 수집 중단: 기존 stargazers 목록 작업과 사용자 객체 신규 저장을 멈춘다.
  • 새 구조 검증: repository, date, daily_delta, cumulative_created와 마지막 동기화 정보만으로 차트가 재현되는지 확인한다.
  • 읽기 전환: 모든 페이지와 날짜 경계를 통과한 집계 스냅샷으로 애플리케이션을 전환한다.
  • 원본 정리: 차트만을 위해 저장한 사용자별 행과 복제본을 정해진 보존 절차에 따라 제거한다.

배포 전 검증표

  • history 응답의 첫 객체가 최신 주이며 다음 페이지로 갈수록 과거로 이동하는가
  • 모든 페이지를 합친 뒤 week가 오름차순이고 중복되지 않는가
  • 각 days 배열이 일곱 항목이며 합계가 total과 일치하는가
  • 0인 주와 날짜가 연속 시계열에 남아 있는가
  • 주 시작과 일요일 인덱스가 선택한 표시 시간대에서 하루 밀리지 않는가
  • 누적 필드와 화면 문구가 현재 별 개수가 아니라 생성 건수임을 드러내는가
  • 새 응답, 로그와 캐시에 사용자 신원 필드가 기록되지 않는가

검증을 통과하면 새 스냅샷으로 읽기 경로를 바꾸고 기존 사용자 데이터의 정리 절차를 실행한다. 이 전환의 핵심은 단순히 URL을 교체하는 데 있지 않다. 사용자별 사건 모델을 주간·일간 집계 모델로 바꾸고, 차트가 보여 주는 지표까지 새 응답의 의미에 맞추는 작업이다.

함께 읽기:

공유:

뉴스레터 구독

최신 Web3, AI, 암호화폐 뉴스를 이메일로 받아보세요.

0