Hacker News 의견들
  • 최신 GitHub 글로벌 노드 ID'X-Github-Next-Global-ID' 헤더를 통해 강제로 사용할 수 있음
    ID는 객체의 타입 접두사와 base64로 인코딩된 msgpack 페이로드로 구성됨
    예를 들어 내 사용자 ID "U_kgDOAAhEkg"[0, 541842]로 디코딩되며, 이는 REST API의 databaseId와 일치함
    하지만 이런 내부 구현에 의존하지 말고, GraphQL API의 databaseId 필드를 직접 조회하는 것이 좋음
    관련 문서: GraphQL 글로벌 노드 ID 마이그레이션 가이드, 내 GitHub 사용자 정보, CyberChef 디코딩 예시, GitHub ETag 구현

  • 이런 식으로 디코딩하는 건 취약하다고 생각함
    GraphQL의 글로벌 노드 ID는 본래 불투명(opaque) 해야 함
    GitHub의 여러 타입(PullRequest 등)은 databaseId 필드를 제공하므로 그걸 쓰는 게 맞음
    대부분의 GraphQL API는 타입명과 DB ID를 base64로 인코딩하지만, 이 규칙이 항상 유지된다고 보장할 수 없음
    참고: PullRequest 객체 문서, GraphQL 글로벌 ID 스펙

    • GitHub의 GraphQL 타입에는 permalink, url 같은 필드와 UniformResourceLocatable 인터페이스가 있어서 직접 URL을 구성할 필요가 없음
    • 이런 내부 구조는 시간이 지나면 깨질 가능성이 높음
      그래서 API가 permalink를 제공하는 이유가 있음. ID나 링크 패턴은 언제든 바뀔 수 있음
    • 식별자에 메타데이터를 넣고 싶다면, 사용자가 내부 구조에 의존하지 않도록 암호화하는 게 좋음
      이런 방식은 pagination 토큰에서도 자주 사용됨
  • 010:Repository2325298 같은 ID는 명확한 구조를 가짐
    010은 타입 enum, Repository는 이름, 2325298은 DB ID임
    즉, 길이 접두사(length prefix) 형태임. Repository는 10자, Tree는 4자임

    • BitTorrent 프로토콜이 떠오름
    • 거의 URN처럼 보임
  • Opus 4.5는 이런 GitHub ID 디코딩 트릭을 알고 있으며, 자동으로 디코딩 코드를 작성함

  • 작성자가 발견한 내용은 기술적으로는 맞지만, 문서화되지 않았고 지원되지 않음
    GitHub는 과거에도 노드 ID 내부 구조를 조용히 바꾼 적이 있음
    MessagePack 배열에 필드를 추가하거나, 인코딩을 바꾸거나, 암호화하거나, UUID 기반으로 바꾸면
    이런 내부 구조에 의존한 시스템은 즉시 깨짐

  • 내가 명시적으로 저장하는 GitHub 식별자는 불변 URL 키(issue/pr 번호나 커밋 해시) 정도임
    댓글 ID는 JSON 블롭 안에 그냥 포함시킴
    모든 걸 정규화하려고 할 필요는 없음. JSON은 충분히 빠름
    코멘트 단위로 교차 쿼리를 하지 않는 이상, 성능 문제로 드러날 일은 거의 없음

    • 하지만 issue/pr URL은 불변이 아님
      저장소가 이름을 바꾸거나 다른 조직으로 옮기면 URL이 바뀔 수 있음
  • 예전 v3 API에는 ID가 없어서, 누군가 사용자명이나 저장소명을 바꾸면 누군지 추적하기 어려웠음
    그래서 나는 팀 단위 소유권 관리 시스템을 직접 구현했음
    Terraform provider가 별로라서, 오프보딩 시 “유일한 관리자였던 사람이 나갔다” 같은 문제가 자주 생겼기 때문임
    모든 저장소는 팀이 소유하고, 접근 권한도 팀 단위로만 부여함

    • “사용자에게 접근 권한을 준다”가 아니라 “팀에 권한을 주고, 사용자는 그 팀의 일원이다”라는 사고방식이 훨씬 효율적임
      이런 팀 기반 접근 제어는 GitHub뿐 아니라 다른 시스템에도 유용함
  • Hyrum’s Law의 전형적인 사례임 — 사람들이 문서화되지 않은 동작에 의존하기 시작하면 결국 깨짐

  • 데이터베이스 설계에서는 보통 외부에는 불투명한 자연 키를 제공하고, 내부에서는 증가형 정수 ID를 사용함

    • 그 이유는 두 가지임
      1. 외부에 객체 개수를 노출하지 않기 위해
      2. ID를 단순히 증가시켜 모든 객체를 순회하지 못하게 하기 위해
        하지만 복합 ID를 쓰면 이런 문제가 줄어듦.
        예를 들어 저장소 ID 안에 객체 ID가 포함되어 있으면, ID를 증가시켜도 같은 저장소 내 객체만 탐색됨
        여기에 엔트로피나 타임스탬프를 섞으면 악용이 거의 불가능함
    • 하지만 자연 키는 변경될 수 있음
      그래서 의미 없는 대체 키(surrogate key) 를 노출하는 게 더 안전함
      예를 들어 YouTube는 내부적으로 인덱스 번호를 쓰더라도, 외부에는 의미 없는 코드 형태의 ID를 제공함
  • GitHub 팀이 최근 몇 년간 Rails에 sharded/multi-database 지원을 대폭 확장한 이유가 이제 이해됨