권현우의 프로필 사진

Hyunwoo

GitHub 잔디를 GraphQL로 가져오기

블로그에 GitHub 잔디를 표시하면서 GraphQL 쿼리를 작성하고 fetch로 기여 데이터를 가져온 경험을 기록한다.

2026.09.06

  • graphql
  • github
  • api

GitHub 잔디

블로그에 GitHub 잔디를 표시하면서 GraphQL을 사용해 봤다. GitHub에서 제공하는 공개 API를 이용해 최근 90일의 기여 데이터를 가져오는 기능이다.

처음에는 GraphQL이라는 이름 때문에 별도의 도구가 필요할 것 같았는데, 요청 자체는 익숙한 fetch로 보낼 수 있었다. 이번에 작성한 코드를 보면서 어떻게 데이터를 요청하는지 정리해 보려고 한다.

필요한 데이터를 쿼리로 작성하기

먼저 어떤 데이터를 가져올지 쿼리를 작성했다. 프로젝트의 app/api/github/contributions/route.ts에 있는 코드다.

const query = `
  query($username: String!, $from: DateTime!, $to: DateTime!) {
    user(login: $username) {
      contributionsCollection(from: $from, to: $to) {
        contributionCalendar {
          totalContributions
          weeks {
            contributionDays {
              date
              contributionCount
              color
            }
          }
        }
      }
    }
  }
`

중첩된 구조라 처음에는 복잡해 보이지만, 차례대로 읽으면 된다. 사용자를 찾고, 지정한 기간의 기여 기록에서 달력 데이터를 조회한다. 여기서는 총 기여 수와 날짜별 기여 수, 색상을 요청했다.

그렇다고 필드 이름이나 구조를 마음대로 정할 수 있는 건 아니다. GitHub가 공개한 스키마에 정의된 필드와 구조에 맞춰 작성해야 한다. 백엔드가 조회할 수 있는 데이터와 규칙을 정해 두고, 클라이언트는 그 안에서 필요한 필드를 선택하는 방식이다. 예를 들어 응답에 색상이 필요 없다면 쿼리에서 color를 빼면 된다.

처음에는 DB 쿼리와 비슷한 건가 싶었는데, DB에 직접 보내는 쿼리는 아니다. GitHub API 서버에 어떤 데이터를 받고 싶은지 전달하는 요청문이다. 서버 내부에서 어떤 DB를 사용하고 어떻게 조회하는지는 클라이언트가 몰라도 된다.

변수를 넣고 fetch로 요청하기

쿼리에서 사용하는 실제 값은 variables로 전달했다.

const endDate = new Date()
const startDate = new Date()
startDate.setDate(endDate.getDate() - 89)
 
const variables = {
  username,
  from: startDate.toISOString(),
  to: endDate.toISOString(),
}

쿼리에 선언한 $username, $from, $to에 들어갈 값들이다. 쿼리 문자열을 직접 수정하지 않고도 사용자나 조회 기간을 바꿀 수 있다. String!처럼 타입 뒤에 붙은 !는 해당 값이 null일 수 없다는 의미다.

이제 쿼리 문자열과 변수를 JSON body에 담아 요청하면 된다. 요청 부분만 간추리면 다음과 같다.

const response = await fetch('https://api.github.com/graphql', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${githubToken}`,
  },
  body: JSON.stringify({ query, variables }),
})
 
const result = await response.json()

이 프로젝트에서는 Next.js의 서버 라우트에서 환경 변수 GITHUB_TOKEN을 읽어 요청에 사용한다. 브라우저는 블로그의 /api/github/contributions를 호출하고, 이 서버 라우트가 GitHub에 요청을 보내는 구조다.

정상 응답의 기여 달력 데이터는 다음 경로에서 꺼낼 수 있다.

const calendar = result.data.user.contributionsCollection.contributionCalendar

요청했던 필드의 중첩 구조가 응답에도 이어지는 것을 볼 수 있다. 실제 코드에서는 HTTP 응답 상태와 GraphQL 응답의 errors, 사용자 데이터 유무를 확인한 뒤 데이터를 사용한다. 받아온 날짜별 기여 기록은 화면에 잔디를 그리는 데 사용했다.

써보고 느낀 점

이번처럼 간단히 데이터를 조회하는 데는 별도의 GraphQL 클라이언트 라이브러리가 필요하지 않았다. 서버가 제공하는 스키마를 보고 쿼리를 작성한 뒤, 변수를 넣고 fetch로 요청하는 것부터 시작할 수 있었다.

fetchPOST를 사용한다고 모두 REST API인 것은 아니라는 점도 알게 됐다. 지금 코드도 HTTP로 통신하지만, 데이터를 요청하는 방식은 GraphQL이다.

아직 간단한 조회만 해봤지만, 필요한 데이터를 골라 요청한다는 말이 실제 코드로 보니 조금 더 와닿았다. 이름만 들었을 때보다는 덜 낯설게 느껴진다.