GitHub의 모든 객체에는 두 개의 ID가 있다

3 weeks ago 8

  • GitHub API를 사용하던 중 PR 코멘트 링크 생성 기능에서 ID 불일치로 링크가 작동하지 않는 문제가 발생
  • 조사 결과 GitHub은 GraphQL의 node IDREST API의 database ID라는 두 가지 ID 체계를 병행 사용
  • node ID를 base64 디코딩한 결과, 하위 32비트에 database ID가 포함되어 있음이 확인되어 간단한 비트마스크 연산으로 변환 가능
  • 추가 분석을 통해 GitHub이 MessagePack 기반의 새로운 ID 포맷문자열 기반의 레거시 포맷을 혼용하고 있음이 드러남
  • 이러한 구조는 GitHub 내부 객체 식별 체계의 이중성을 보여주며, 개발자에게 API 통합 시 주의가 필요함

GitHub의 이중 ID 체계 발견

  • Greptile의 AI 코드 리뷰 도구 기능 개발 중, GitHub PR 코멘트 링크가 작동하지 않는 문제 발생
    • 저장된 코멘트 ID를 URL에 연결했으나, 클릭 시 GitHub 페이지로 이동되지 않음
  • GitHub 문서 확인 결과, GraphQL API의 node IDREST API의 database ID가 서로 다른 체계로 존재
    • node ID 예시: PRRC_kwDOL4aMSs6Tkzl8
    • database ID 예시: 2475899260
  • node ID는 GitHub 전체에서 객체를 전역적으로 식별하기 위한 base64 인코딩 문자열, database ID는 정수형 URL 식별자로 사용

node ID와 database ID의 관계 분석

  • 여러 PR 코멘트의 node ID와 database ID를 비교한 결과, 두 값이 일정한 간격으로 증가함을 확인
  • node ID의 base64 부분을 디코딩하자 96비트 정수가 생성되었으며, 이 값의 하위 32비트가 database ID와 일치
    • 예시: PRRC_kwDOL4aMSs6Tkzl8 → 하위 32비트 = 2475899260
  • 간단한 비트마스크 연산으로 database ID를 추출 가능
    • decoded & ((1 << 32) - 1) 형태의 연산으로 변환 수행

GitHub의 레거시 ID 포맷

  • 오래된 저장소(torvalds/linux)의 node ID를 디코딩하자 다른 형식의 문자열이 나타남
    • 예시: MDEwOlJlcG9zaXRvcnkyMzI1Mjk4 → 010:Repository2325298
  • 이 포맷은 [객체 타입 번호]:[객체 이름][Database ID] 구조로, 명시적 문자열 기반 식별자
  • 트리 객체의 경우 04:Tree2325298:7201bfb9... 형태로, 리포지토리 ID와 SHA 값을 함께 포함
  • GitHub은 레거시 포맷과 새로운 포맷을 병행 사용하며, 객체 유형과 생성 시점에 따라 포맷이 달라짐

새로운 node ID 포맷의 구조

  • GitHub의 GraphQL 마이그레이션 가이드는 node ID를 불투명 문자열로 취급하라고 명시하지만, 내부 구조는 존재
  • base64 디코딩 후 MessagePack으로 언팩하면 배열 형태의 데이터가 나타남
    • 예시: [0, 47954445, 2475899260]
  • 배열의 구성
    • 첫 번째 요소(0): 버전 식별자로 추정
    • 두 번째 요소(47954445): 리포지토리의 database ID
    • 세 번째 요소(2475899260): 객체의 database ID
  • 객체 유형에 따라 배열 길이가 다르며, 커밋은 SHA를 포함, 리포지토리는 두 요소만 포함

실용적 활용과 결론

  • 새로운 node ID에서 database ID를 추출하는 Python 코드 예시 import base64, msgpack def node_id_to_database_id(node_id): prefix, encoded = node_id.split('_') packed = base64.b64decode(encoded) array = msgpack.unpackb(packed) return array[-1]
  • 이 방식으로 PR 코멘트의 database ID를 직접 추출하여 URL 링크 문제 해결 가능
  • GitHub은 현재 MessagePack 기반의 새로운 ID 체계와 문자열 기반의 레거시 체계를 동시에 유지
  • 이러한 구조는 GitHub 내부의 전환 과정과 호환성 유지 노력을 보여주며, API를 사용하는 개발자는 ID 포맷 차이에 주의해야 함

Read Entire Article