GitHub REST API 개요
PyGitHub 라이브러리, 개인 액세스 토큰, API 요청 제한을 알아봅니다.
GitHub REST API 개요은(는) CoddyKit의 무료 AI Agents 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Agents 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
PyGitHub — Python용 GitHub 클라이언트
PyGitHub는 GitHub REST API에 가장 널리 사용되는 Python 라이브러리입니다. 원시 HTTP API를 저장소, 이슈, PR, 커밋, 사용자를 나타내는 Python 객체로 감쌉니다. 거의 모든 GitHub 자동화 작업은 Github(token=)과 g.get_repo()에서 시작합니다.
# Install: pip install PyGitHub
from github import Github
import os
# Authenticate with a personal access token
g = Github(token=os.environ['GITHUB_TOKEN'])
# Get the authenticated user
user = g.get_user()
print(f'Logged in as: {user.login}')
print(f'Name: {user.name}')
print(f'Public repos: {user.public_repos}')
# Get a specific repository
repo = g.get_repo('octocat/Hello-World')
print(f'Repo: {repo.full_name}')
print(f'Stars: {repo.stargazers_count}')인증: 개인 액세스 토큰
가장 간단한 인증 방법은 개인 액세스 토큰(PAT)입니다. 이는 GitHub 계정에 연결된 장기 토큰입니다. github.com → Settings → Developer settings → Personal access tokens에서 토큰을 생성하십시오. 토큰은 환경 변수에 저장하고, 코드에는 절대 저장하지 마십시오. 보안을 강화하려면 특정 저장소로 범위를 제한할 수 있는 세분화된 PAT를 사용하십시오.
from github import Github, Auth
import os
# Method 1: Classic token (works with PyGitHub)
token = os.environ['GITHUB_TOKEN']
g = Github(token=token)
# Method 2: Auth object (recommended for PyGitHub >= 1.59)
auth = Auth.Token(os.environ['GITHUB_TOKEN'])
g = Github(auth=auth)
# Test authentication
try:
user = g.get_user()
print(f'Authenticated as {user.login}')
except Exception as e:
print(f'Auth failed: {e}')
print('Check: Is GITHUB_TOKEN set? Has it expired?')
g.close() # close the connection when doneGitHub 앱 인증
프로덕션 에이전트에는 PAT보다 GitHub 앱을 사용하는 것이 좋습니다. GitHub 앱은 세분화된 권한을 제공하고 특정 저장소에 설치할 수 있으며, 자동으로 교체되는 단기 설치 토큰을 사용합니다. github.GithubIntegration을 사용하여 설치 토큰을 생성하십시오.
import os
import github
APP_ID = os.environ['GITHUB_APP_ID']
PRIVATE_KEY = os.environ['GITHUB_APP_PRIVATE_KEY'] # PEM content
INSTALLATION_ID = os.environ['GITHUB_INSTALLATION_ID']
# Create GitHub App client
auth = github.Auth.AppAuth(APP_ID, PRIVATE_KEY)
gi = github.GithubIntegration(auth=auth)
# Get installation access token (expires in 1 hour)
installation = gi.get_installation(int(INSTALLATION_ID))
access_token = gi.get_access_token(int(INSTALLATION_ID))
# Use the token with a standard Github client
g = github.Github(token=access_token.token)
print(f'App authenticated, token expires: {access_token.expires_at}')요청 한도: 시간당 5000회 요청
GitHub REST API는 인증된 사용자에게 시간당 5,000회 요청을 허용합니다. 각 API 호출은 페이지로 나뉜 호출이라도 한 번의 요청으로 계산됩니다. 일괄 작업을 실행하기 전에 남은 할당량을 확인하십시오. 할당량을 모두 사용하면 요청 한도가 재설정될 때까지 모든 요청이 403 Forbidden을 반환합니다.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
# Check current rate limit status
rate_limit = g.get_rate_limit()
core = rate_limit.core
print(f'Remaining: {core.remaining}/{core.limit} requests')
print(f'Resets at: {core.reset}')
# Calculate time until reset
import datetime
now = datetime.datetime.utcnow()
reset_in = (core.reset.replace(tzinfo=None) - now).seconds
print(f'Reset in: {reset_in // 60}m {reset_in % 60}s')
# Check before heavy operations
if core.remaining < 100:
print('WARNING: Rate limit nearly exhausted!')저장소 객체 가져오기
repo 객체는 거의 모든 GitHub 작업의 시작점입니다. g.get_repo('owner/name')으로 가져오십시오. 이 객체에는 메타데이터(별표, 포크, 설명, 공개 범위)와 이슈, PR, 커밋, 릴리스 등에 액세스하는 메서드가 포함되어 있습니다.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Repository metadata
print(f'Full name: {repo.full_name}')
print(f'Description: {repo.description}')
print(f'Default branch: {repo.default_branch}')
print(f'Stars: {repo.stargazers_count}')
print(f'Forks: {repo.forks_count}')
print(f'Open issues: {repo.open_issues_count}')
print(f'Private: {repo.private}')
print(f'Language: {repo.language}')
print(f'Created: {repo.created_at}')
print(f'Last push: {repo.pushed_at}')API 페이지 매김 — PaginatedList
많은 항목(이슈, 커밋, PR)을 반환하는 GitHub API 호출은 PaginatedList를 반환합니다. 일반 목록처럼 반복할 수 있으며, 반복하는 동안 PyGitHub가 페이지를 자동으로 가져옵니다. 하지만 len()을 PaginatedList에 호출하면 모든 페이지를 가져오므로 비용이 많이 들 수 있습니다.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# PaginatedList: fetch pages lazily as you iterate
issues = repo.get_issues(state='open') # returns PaginatedList
# Iterate — fetches pages 30 at a time automatically
for issue in issues:
print(f'#{issue.number}: {issue.title}')
# Get first N items without fetching everything
first_10 = list(issues[:10]) # only fetches first page
# Count (WARNING: fetches ALL pages)
total_open = issues.totalCount # uses the count from API metadata, not iteration요청 한도 예외 처리
요청 한도를 초과하면 PyGitHub가 github.GithubException.RateLimitExceededException을 발생시킵니다. 재설정 시간을 확인하고 요청 한도가 재설정될 때까지 대기하여 처리하십시오. 이를 재시도 래퍼에 포함하면 모든 GitHub 호출을 안정적으로 만들 수 있습니다.
from github import Github
from github.GithubException import RateLimitExceededException
import os
import time
import datetime
g = Github(token=os.environ['GITHUB_TOKEN'])
def github_call_with_rate_limit(func, *args, **kwargs):
while True:
try:
return func(*args, **kwargs)
except RateLimitExceededException:
rate_limit = g.get_rate_limit()
reset_time = rate_limit.core.reset.replace(tzinfo=None)
now = datetime.datetime.utcnow()
wait_seconds = (reset_time - now).total_seconds() + 10
print(f'Rate limit exceeded. Sleeping {wait_seconds:.0f}s until reset...')
time.sleep(max(wait_seconds, 1))
# Usage
repo = github_call_with_rate_limit(
g.get_repo, 'myorg/myrepo'
)GitHub 전체 검색
g.search_issues(), g.search_repositories(), g.search_code()를 사용하면 모든 공개 저장소와 내 비공개 저장소에서 GitHub 검색을 실행할 수 있습니다. 이 메서드들은 분당 30회라는 별도의 요청 한도를 사용하는 Search API를 이용합니다.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
# Search issues across all your repos
results = g.search_issues(
query='is:open is:issue label:bug user:myorg',
sort='created',
order='desc'
)
print(f'Found {results.totalCount} open bugs')
for issue in results[:10]:
print(f'{issue.repository.full_name}#{issue.number}: {issue.title}')
# Search for repos using a specific package
repos = g.search_repositories(
query='topic:machine-learning language:python stars:>100'
)
for repo in repos[:5]:
print(f'{repo.full_name}: {repo.stargazers_count} stars')여러 저장소 작업하기
에이전트는 조직 내 여러 저장소에서 작업해야 하는 경우가 많습니다. g.get_organization()을 사용하여 조직의 모든 저장소를 나열한 다음 반복문으로 처리하십시오. 비활성 저장소를 처리하지 않도록 언어, 보관 상태 또는 활동 날짜로 필터링하십시오.
from github import Github
import os
import datetime
g = Github(token=os.environ['GITHUB_TOKEN'])
org = g.get_organization('myorg')
# Get all active Python repos
cutoff = datetime.datetime.now() - datetime.timedelta(days=180)
active_repos = [
repo
for repo in org.get_repos(type='all')
if (
not repo.archived
and repo.language == 'Python'
and repo.pushed_at
and repo.pushed_at.replace(tzinfo=None) > cutoff
)
]
print(f'Active Python repos: {len(active_repos)}')
for repo in active_repos[:5]:
print(f' {repo.name}: last push {repo.pushed_at.date()}')저장소에서 파일 내용 읽기
repo.get_contents(path)를 사용하여 저장소의 모든 파일을 읽을 수 있습니다. 내용은 base64로 인코딩되어 있지만 PyGitHub가 .decoded_content 속성을 통해 자동으로 디코딩합니다. ref 매개 변수로 브랜치 또는 커밋 SHA를 지정하십시오.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Read a file from the default branch
contents = repo.get_contents('README.md')
readme_text = contents.decoded_content.decode('utf-8')
print(f'README ({len(readme_text)} chars):')
print(readme_text[:200])
# Read from a specific branch
requirements = repo.get_contents(
'requirements.txt',
ref='feature/new-deps'
)
deps = requirements.decoded_content.decode('utf-8')
print('Dependencies:', deps[:300])일반적인 GitHub 예외 처리
PyGitHub는 모든 API 오류에 대해 GithubException을 발생시킵니다. 일반적인 하위 클래스는 다음과 같습니다. UnknownObjectException(404 — 저장소 또는 이슈를 찾을 수 없음), BadCredentialsException(401 — 잘못된 토큰), RateLimitExceededException(403 — 요청 한도 초과)입니다. 항상 이러한 예외를 구체적으로 포착하십시오.
from github import Github
from github.GithubException import (
GithubException, UnknownObjectException,
BadCredentialsException, RateLimitExceededException
)
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
def get_repo_safely(repo_full_name):
try:
return g.get_repo(repo_full_name)
except BadCredentialsException:
print('ERROR: GitHub token is invalid or expired')
return None
except UnknownObjectException:
print(f'ERROR: Repo not found: {repo_full_name}')
print('Check: typo in name? Private repo you can\'t access?')
return None
except RateLimitExceededException:
print('ERROR: GitHub rate limit exceeded, retry later')
return None
except GithubException as e:
print(f'GitHub API error {e.status}: {e.data}')
return None빠른 확인: 요청 한도
GitHub API 요청 한도에 대한 이해도를 확인해 보십시오.
GitHub REST API 복습
이제 PyGitHub로 GitHub에 연결할 수 있습니다.
- PAT 인증에는 Github(token=) 또는 Github(auth=Auth.Token(...))을 사용합니다.
- 세분화된 권한이 필요한 프로덕션 에이전트에는
GithubIntegration을 사용하는 GitHub 앱을 활용합니다. - 요청 한도: 시간당 5,000회 요청이며,
g.get_rate_limit()으로 확인하고RateLimitExceededException을 처리합니다. - PaginatedList: 지연 방식으로 반복하고, 모든 페이지를 가져오지 않고 개수를 확인하려면
.totalCount를 사용합니다. - g.get_repo('owner/name') — 저장소 수준 작업의 진입점입니다.
UnknownObjectException(404)과BadCredentialsException(401)을 명시적으로 포착합니다.
AI 튜터와 함께 AI Agents을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 60
- 레슨
- 239
자주 묻는 질문
“GitHub REST API 개요” 강의는 무료인가요?
네 — “GitHub REST API 개요” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Agents 강의 전체를 잠금 해제할 수 있습니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
“GitHub REST API 개요”에서 뭘 배우나요?
PyGitHub 라이브러리, 개인 액세스 토큰, API 요청 제한을 알아봅니다. 브라우저에서 직접 실행하는 실습 코드로 AI Agents을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Agents을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Agents은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“GitHub REST API 개요” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Agents 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Agents 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- GitHub REST API 개요
- 이슈 조회 및 관리
- 자동화된 PR 검토 댓글
- 커밋 기록 및 변경 내용 분석