GitHub 이슈에 이미 PR이 있는지 확인하는 도구를 만든 방법 — 그리고 왜 이것이 아무도 만들지 않은 기능인지

발행: (2026년 5월 5일 PM 12:30 GMT+9)
6 분 소요
원문: Dev.to

Source: Dev.to

위에 제공된 링크에 있는 전체 텍스트를 알려주시면, 해당 내용을 한국어로 번역해 드리겠습니다. (코드 블록, URL 및 마크다운 형식은 그대로 유지됩니다.)

문제

초보자에게 친화적인 이슈를 찾고, 레포를 포크하고, 개발 환경을 설정하고, 코드베이스를 읽는 것은 기분이 좋을 수 있습니다—하지만 다시 이슈를 확인했을 때 다음과 같은 최근 댓글을 보면요:

“Hey I’m working on this, should have a PR up soon.”

두 시간 낭비. 이런 상황이 반복되는 이유는 대부분의 이슈 탐색 도구(예: goodfirstissue.dev, up‑for‑grabs.net, codetriage)가 정적 리스트나 주기적인 스크래핑에 의존하기 때문입니다. 이 도구들은 이슈를 보여주지만, 누군가 이미 조용히 해당 이슈를 작업 중인지 여부는 알려주지 않습니다.

GitTrek 소개

GitTrek은 그 격차를 메웁니다. 개발자가 이슈 작업을 시작할 때 남기는 “디지털 흔적”을 찾습니다:

흔적 유형표시 방식
PR 멘션이슈 번호가 PR 설명이나 커밋 메시지에 언급됩니다 (예: Fixes #847).
연결된 브랜치GitHub UI를 통해 이슈에서 브랜치를 생성하고, 그 브랜치에서 PR을 엽니다.

두 흔적 모두 GitHub의 GraphQL API를 통해 노출되며, 특히 이슈의 timelineItems 필드를 통해 확인할 수 있습니다.

관련 GraphQL 이벤트

  • CROSS_REFERENCED_EVENT – PR이나 커밋이 이슈 번호를 언급할 때 발생합니다. PR은 이벤트의 source(소스)입니다.
  • CONNECTED_EVENT – 이슈와 연결된 브랜치가 풀 리퀘스트가 될 때 발생합니다. PR은 이벤트의 subject(주제)입니다.

팁: sourcesubject를 혼동하면 오류 없이 null 결과가 반환됩니다.

샘플 쿼리

issue(number: $issueNumber) {
  timelineItems(
    first: 25,
    itemTypes: [CROSS_REFERENCED_EVENT, CONNECTED_EVENT]
  ) {
    nodes {
      ... on CrossReferencedEvent {
        source {
          ... on PullRequest {
            number
            state      # OPEN | CLOSED | MERGED
            isDraft
          }
        }
      }
      ... on ConnectedEvent {
        subject {
          ... on PullRequest {
            number
            state
            isDraft
          }
        }
      }
    }
  }
  linkedBranches(first: 3) {
    totalCount
  }
}

GitTrek이 경쟁을 시각화하는 방법

GitTrek은 위 데이터에 따라 각 이슈에 색상을 입힌다:

배지의미
Active PR열려 있는 비‑초안 PR 존재 — 경쟁이 높음
Someone started초안 PR 연결됨 — 신중히 진행
Branch existslinkedBranches > 0 이지만 아직 PR 없음 — 초기 신호
Safe to claim연결된 PR이나 브랜치가 없음

20개의 이슈를 확인하려면 21개의 API 호출이 필요한다 (검색 1회 + 상태 확인 20회). UI를 빠르게 유지하기 위해 GitTrek은 이슈 목록을 즉시 표시하고 배지를 병렬로 “채워넣는다”.

백그라운드에서 배지 채우기

// Fetch fresh data from APIs in the background
// This ensures one badge failure doesn't block the entire dashboard
const settlements = await Promise.allSettled([
  fetch(`/api/github/badges/pull-shark?username=${user}`).then(r => r.json()),
  fetch(`/api/github/badges/starstruck?username=${user}`).then(r => r.json()),
  // ... more badge checks
]);

// Safely extract results even if some failed
const [pullShark, starstruck, ...] = settlements.map(s =>
  s.status === "fulfilled" ? s.value : null
);

// Apply fallback values for failed items
const psData = pullShark || { count: 0 };

Promise.allSettledPromise.all 대신 사용되어, 단일 체크 실패(예: 권한 문제나 속도 제한) 때문에 전체 대시보드가 중단되지 않도록 한다.

“ghost PR” 감지를 넘어

GitTrek은 오픈‑소스 성장의 동반자이기도 합니다:

  • Repository Quality Gates – 별(stars), 포크(forks), 그리고 CONTRIBUTING.md 파일 존재 여부로 필터링합니다.
  • Live Achievement Tracking – 실시간 GraphQL 계산을 사용해 Pull Shark, Galaxy Brain, YOLO와 같은 배지를 향한 진행 상황을 모니터링합니다.
  • Focus Mission – 배지를 몇 개의 PR만 더 하면 될 경우, GitTrek은 정확히 필요한 이슈를 찾아내는 맞춤 검색 쿼리를 생성합니다.

시작하기

  • 실제 앱:
  • 소스 코드:

GitTrek은 무료이며 오픈 소스이고, 탐색을 위해 별도의 설정이 필요하지 않습니다. 개인화된 배지 추적을 원할 경우에만 GitHub 계정을 연결하세요.

당신의 경험

이미 작업 중인 이슈에 시간을 낭비한 적이 있나요? 댓글에 이야기를 공유해주세요—실제로 얼마나 흔한지 궁금합니다.

0 조회
Back to Blog

관련 글

더 보기 »