GitHUB API Rate limiting

WooJin Shin·2021년 5월 29일

GitHUB

목록 보기
1/2

GitHUB은 API 요청에 대해 요청 제한, 속도 제한 등 API를 요청하는 제한을 두고 있다.

제한을 하는 이유??

  • 이러한 제한을 하는 이유는 간단하다. 네트워크 트래픽을 제한해서 서버의 부담을 줄이는 것이다.
  • API 요청이 과도하게 들어오면 서버가 수용하지 못할 수 있다
  • DDos, 웹 스크래퍼 등 보안 문제에 대비
    • 속도 제한이 보안 문제에 대한 근본적인 해결책은 아니다. 예방 효과가 있는 것.

속도 제한 방법?

  • 일반적으로 속도 제한은 요청이 들어오는 IP 주소를 추적하고, 각 요청 사이에 경과 된 시간을 추적하는 것을 기반으로 한다.
  • 각 IP 주소의 각 요청 사이의 시간을 측정하고 지정된 기간 내 요청 수를 측정하는 것
  • 단일 IP에서 너무 많은 요청이있는 경우, 일정 시간 동안 IP 주소의 요청이 제한되는 방식
  • 속도 제한을 구현하는 전략은 여러가지가 있다. (필요하다면 찾아보자)

속도 제한 예시

ex) 로그인 속도 제한
  • 사용자가 짧은 시간은 너무 많은 로그인을 시도하면 계정을 잠기게한다.
  • 사용자가 아닌 악성 봇이 계정을 해킹하려고, 무차별 대입 공격을 예방하기 위한 방법
  • 사용자의 IP 주소, 사용자 이름 등. 구현한 방법에 따라 다를 수 있다.
    • 사용자 IP 주소만을 사용하기에는 주소를 우회할 수 있기 때문에 IP주소, 이름 다 사용하는 것이 이상적이다.

GitHUB API에서 속도 제한

개발자를 위한 API에서도 속도 제한이 있는 이유는 API를 제공하는 서버에서 API 요청에 대한 응답을 구성하는데 비용이 존재하기 때문이다. API를 제공하는 모든 애플리케이션 또는 서비스는 각 사용자가 시간 또는 일당 API 호출을 수행 할 수있는 횟수에 제한을 둔다.

속도 제한 분류

  • GitHUB에서는 API를 활용하는데 속도 제한 방식이 다르다.
    • core : REST API 요청 속도 제한
    • search : 검색 API 요청 속도 제한 (엔터프라이즈 기준, 최대 1,000 개)
    • graphql : graphQL API 요청 속도 제한
    • 그 외 분류 존재

속도 제한 확인 endpoint 제공

  • GET /rate_limit
{
  "resources": {
    "core": {
      "limit": 5000,  //시간당 요청 수
      "remaining": 4999,  //남은 요청 수
      "reset": 1372700873 //limit가 초기화되는 시간
    },
    "search": {
      "limit": 30,
      "remaining": 18,
      "reset": 1372697452
    },
    "graphql": {
      "limit": 5000,
      "remaining": 4993,
      "reset": 1372700389
    },
    ...
  },
  "rate": {
    "limit": 5000,
    "remaining": 4999,
    "reset": 1372700873
  }
}

REST API 속도 제한

  • 인증되지 않은 사용자의 경우 시간당 최대 60개의 요청을 허용한다.
  • 인증된 사용자의 경우 시간당 최대 5000개의 요청을 허용한다.
  • 엔터프라이즈 사용자는 Repository당, 시간당 최대 15000개의 요청을 허용한다.

인증된 사용자란?

  • 기본인증 : 사용자 이름과 암호로 인증
  • AccessToken 인증 : OAuth 인증 또는 개인 AccessToken을 발급받아 인증
  • GitHub에서는 API 요청시 Authorization 헤더를 사용하여 토큰을 보낼 것을 권장
  • OAuth 인증 절차를 API로 직접 요청해서 토큰을 발급 받을 수 있었지만 보안문제로 지원 중단.

요청 제한 해결은 어떻게??

  • API를 요청하는 경우, 필요에 따라 요청제한을 넘겨서 많은 데이터가 필요할 수 있다.
  • GitHUB에서는 조건부 GET 요청을 활용하라고 가이드
  • 조건부 GET 요청을 위한 Etag, Last-Modified 헤더가 응답에 포함된다.
  • 요청 제한 발생한 경우, 이 헤더를 활용하여 조건부 GET 요청을 날릴 수 있는데 이 요청은 요청 제한에 카운팅 되지 않는다.
  $ curl -I http(s)://[hostname]/api/v3/user
  > HTTP/2 200
  > Cache-Control: private, max-age=60
  > ETag: "644b5b0155e6404a9cc4bd9d8b1ae730"
  > Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT
  > Vary: Accept, Authorization, Cookie
  > X-RateLimit-Limit: 5000
  > X-RateLimit-Remaining: 4996
  > X-RateLimit-Reset: 1372700873

  $ curl -I http(s)://[hostname]/api/v3/user -H 'If-None-Match: "644b5b0155e6404a9cc4bd9d8b1ae730"'
  > HTTP/2 304
  > Cache-Control: private, max-age=60
  > ETag: "644b5b0155e6404a9cc4bd9d8b1ae730"
  > Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT
  > Vary: Accept, Authorization, Cookie
  > X-RateLimit-Limit: 5000
  > X-RateLimit-Remaining: 4996
  > X-RateLimit-Reset: 1372700873

  $ curl -I http(s)://[hostname]/api/v3/user -H "If-Modified-Since: Thu, 05 Jul 2012 15:31:30 GMT"
  > HTTP/2 304
  > Cache-Control: private, max-age=60
  > Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT
  > Vary: Accept, Authorization, Cookie
  > X-RateLimit-Limit: 5000
  > X-RateLimit-Remaining: 4996
  > X-RateLimit-Reset: 1372700873

GraphQL API 속도 제한

REST API의 한계?

  • REST API는 자원을 요청하는데 여러번 요청을 해야한다.
  • 목록을 요청해야하는 경우, PR이나 issue등 한번에 받아올 수 있는 응답량에도 제한이 존재한다. (최대 100개)
    • ex) 어떤 저장소의 PR의 리뷰정보들을 모두 모아보고 싶다면? (PR은 2000개가 존재한다고 가정)
      • 2000개의 정보를 모두 요청하려면 100개씩 20번 요청해야한다...
      • PR당 리뷰에 대한 API 요청도 100개씩 요청해야한다는 것 (100개나 있는 경우는 드물지만)
  • 시간당 요청 횟수에 대한 제한도 있지만, 요청 간격간에 너무 빠르게 요청하면 제한도 존재한다.

GraphQL을 이용한다면??

  • GraphQL을 이용하면 REST API로 여러번 요청해야하는 횟수를 줄일 수 있지 않을까?
  • GraphQL을 사용하면 한번에 많은 데이터를 가져올 수 있지만 다른 요청 제한 룰을 적용한다. API 응답을 구성하는데 서버가 얼마나 컴퓨팅을 하는지 계산해서 적용을 한다.

노드 제한

  • 쿼리를 날릴 때, 각 노드들을 연결하는데 first, last 인수를 사용해야한다.
    • 쿼리의 depth가 깊어지고, 그 목록이 여러 존재할 때
    • first와 last는 1~100사이다. (제한이 존재한다.)
  • 총 500,000개 이상의 노드를 요청할 수 없다.
  • 요청 제한 계산 예시
  query {
    viewer {
      repositories(first: 50) { //50개의 Repository
        edges {
          repository:node {
            name

            issues(first: 10) { // 500개의 Issue
              totalCount
              edges {
                node {
                  title
                  bodyHTML
                }
              }
            }
          }
        }
      }
    }
  }
 // 총 550개 노드 요청

속도 제한

  • REST API와 달리 GraphQL의 응답을 구성하는데 서버 비용을 계산
    • MySQL, ElasticSearch, Git 등 서버의 잠재적 부하를 계산
  • 포인트를 기반으로 호출 속도 제한 점수를 계산, 시간당 5000점
    • REST API의 시간당 호출 5000 제한과는 다르다.
    • API 호출에서 각 노드를 연결하는데 필요한 요청 수를 더한다.
    • 총 요청 수에서 100으로 나누고 반올림하여 총 비용을 계산한다.
  • 속도 제한 계산 예시
  query {
    viewer {
      login
      repositories(first: 100) { //100개의 Repo이지만 viewer에 1번만 접근 = 1
        edges {
          node {
            id

            issues(first: 50) { //50개 issue, Repo 100번 접근 = 100
              edges {
                node {
                  id

                  labels(first: 60) { //60개 label, Repo(100) * issue(50) 접근 = 5000
                    edges {
                      node {
                        id
                        name
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  
  // 총 5101번 접근 = round(5101 / 100) = 51점

참고 : 속도 제한 방식은 개발자가 GraphQL API를 사용하는 방식을 관찰하면서 바뀔 수 있다고 한다.

속도 제한 확인

  • REST API와 마찬가지로 GraphQL도 요청 제한 상태 확인 쿼리가 존재
query {
  viewer {
    login
  }
  rateLimit {
    limit  //시간당 최대 점수
    cost   // 현재 사용한 점수
    remaining //남아있는 점수
    resetAt //속도 제한 reset되는 시간. 
  }
}

참고 : REST와는 달리 속도 제한을 확인하는데 속도 제한 점수가 깎인다...

참고문서

GitHUB docs - Rate limiting
GitHUB docs - Rate limit
GitHUB docs - GraphQL API Resource limitations
Everything You Need To Know About API Rate Limiting

profile
꿈꾸는 개발자

0개의 댓글