반응형
1. 비교표
| 방식 | 범위 | 만료 | 사용자 의존 | 설정 난이도 | 주 용도 |
| Classic PAT | 사용자 전체 리포 | 설정 가능 (최대 무제한) | 강함 | 1분 | 레거시, 빠른 스크립팅 |
| Fine-grained PAT | 선택한 리포만 | 최대 1년 | 강함 | 5분 | 개인 스크립트, 단기 자동화 |
| Deploy Key | 리포 1개 | 영구 | 없음 | 10분 | 단일 서버 ↔ 단일 리포 (read/write) |
| SSH Key (personal) | 사용자 전체 리포 | 영구 | 강함 | 5분 | 개발자 개인 작업 |
| GitHub App | 설치한 리포 (다수 가능) | Installation token 1시간 | 없음 | 1시간+ | 조직 차원 자동화 플랫폼 |
| Actions OIDC | 외부 클라우드 인증 (AWS/GCP 등) | 단일 workflow 수행시간 | 없음 | 30분 | GitHub Actions → 외부 클라우드 |
| GITHUB_TOKEN | workflow가 실행되는 리포 | 단일 workflow 수행시간 | 없음 | 0분 (자동) | Actions workflow 내부 작업 |
| Machine User + PAT | 리포 collaborator 권한 범위 | PAT 만료일 | Machine user 계정 | 30분 | 공유 봇 계정 |
2. 각 방식 상세
2.1 Personal Access Token (Classic)
개요
가장 오래된 방식. 사용자 계정 전체의 범용 토큰. scope로 권한 범위 조정.
동작 원리
- GitHub 계정 Settings → Developer settings → Personal access tokens (classic) 에서 발급
- HTTP Basic Auth 또는 Authorization: token <PAT> 헤더로 인증
- scope 예: repo, admin:org, write:packages, workflow 등 카테고리 단위
설정
# git credential 저장 예시
git config --global credential.helper store
# 첫 clone 시 username + PAT 입력하면 ~/.git-credentials 에 저장
장점
- 발급 즉시 사용 가능 (복잡한 설정 불필요)
- 모든 GitHub API 동작 지원 (scope만 맞으면)
- 보편적 지원 (대부분의 도구/SDK가 지원)
단점
- 계정 전체 리포에 영향 — 침해 시 파급 범위 매우 넓음
- 사용자 의존: 계정 정지/퇴사 시 작동 중단
- scope가 카테고리 단위라 세밀한 제어 어려움 (예: 특정 리포만 읽기 불가)
- GitHub 자체도 "Deprecated in future" 로 분류 — 신규 기능 안 받음
보안 위험
- 한 번 유출되면 사용자 모든 리포 + 조직 멤버십 전체 접근 가능
- scope 과다 부여 관행 (귀찮아서 repo 풀권한 주는 경우 많음)
- 만료 없이 설정 가능 → 유출 인지 못 한 채 장기 방치 리스크
언제 사용
- 개인 스크립트에서 여러 리포 접근할 때 (편의성 우선)
- 새 방식이 지원 안 되는 레거시 도구 호환용
피해야 할 경우
- 프로덕션 CI/CD (계정 의존성)
- 여러 명이 공유해야 하는 자동화 (공유 = 사실상 서비스 계정인데 개인 PAT)
- 장기 운영 자동화 (만료 관리 번거로움)
2.2 Fine-grained PAT
개요
Classic PAT의 후속. 리포·권한을 세밀하게 지정 가능. 2022년 후반 GA.
동작 원리
- Settings → Developer settings → Personal access tokens → Fine-grained tokens
- 선택 항목: 특정 리포 또는 조직 / 각 리소스(Contents, Metadata, Pull requests, Actions 등) read/write 독립
- 최대 만료 1년 (무제한 설정 불가)
- 조직 리포 대상 시 조직 owner 승인 필요 가능 (조직 정책 설정에 따라)
장점
- 최소 권한 원칙 적용 용이 — 리포 1개 + contents read-only 같은 세팅 가능
- scope가 명확 (Classic의 repo 처럼 모호하지 않음)
- 조직 차원 감사 가능 (owner 승인 프로세스)
- Classic 대비 유출 시 피해 범위 한정
단점
- 여전히 사용자 계정 종속
- 만료 강제 (최대 1년) → 주기적 갱신 작업 필요
- 일부 레거시 API/도구가 지원 안 함 (점차 개선 중)
- 조직 리포 대상이면 owner 승인 필요해 약간 번거로움
언제 사용
- 개인 CI/CD 스크립트에서 특정 리포만 건드릴 때
- Classic PAT을 쓰고 있던 곳의 보안 강화 마이그레이션
피해야 할 경우
- 서버 고정 자동화 (→ Deploy Key 가 더 나음)
- 조직 차원 플랫폼 (→ GitHub App 가 더 나음)
2.3 Deploy Key
개요
리포 단위 SSH 키. 특정 리포 하나에만 접근 가능. 사용자 계정과 무관.
동작 원리
- 클라이언트에서 SSH 키페어 생성 (ssh-keygen -t ed25519)
- 리포 Settings → Deploy keys → Add deploy key 에 공개키 등록
- read-only 또는 read-write 선택
- SSH URL (git@github.com:org/repo.git) 사용 시 이 키로 인증
설정
# 1. 서버에서 키 생성
ssh-keygen -t ed25519 -f ~/.ssh/my-repo-deploy -C "deploy-key" -N ""
# 2. 공개키 내용을 GitHub UI에 붙여넣기
cat ~/.ssh/my-repo-deploy.pub
# 3. ~/.ssh/config 설정
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/my-repo-deploy
IdentitiesOnly yes
# 4. git remote를 SSH URL로
git remote set-url origin git@github.com:org/repo.git
장점
- 사용자 계정 완전 독립 — 개인 퇴사/PAT 만료 영향 0
- 범위가 1개 리포로 한정 — 유출 시 피해 제한적
- 만료 없음 — 교체/재발급 안 해도 영구 동작
- 설정 간단, 동작 단순
단점
- 리포 1개 = 키 1개 → 여러 리포 쓰려면 키 여러 개 관리
- read-only / read-write 이분법만 존재 (더 세밀한 권한 불가)
- 조직 차원 정책: org 설정에서 Deploy Key 허용해야 사용 가능 (owner가 enable 필요)
- Push 가능한 키는 GitHub API 호출 불가 (git 프로토콜만)
보안 고려
- 키 파일 보호 (chmod 600)
- 서버 장애 시 키 분실 대비 (복구 시 재등록 필요)
- 서버 탈취 시 해당 리포만 영향 받음 (제한적 피해)
언제 사용
- 단일 서버에서 단일 리포 clone/pull/push 자동화 ← 교과서 케이스
- Kubernetes secret 형태로 pod에서 리포 접근
- Ansible/Terraform 등 단일 인프라 도구에서 리포 접근
피해야 할 경우
- 여러 리포 접근 필요 (키 관리 복잡)
- GitHub API 호출 필요 (Deploy Key는 git only)
- 조직 차원 공유 자동화 (GitHub App 적합)
2.4 SSH Key (personal)
개요
사용자 계정에 연결된 SSH 키. Deploy Key와 혼동 주의.
차이점 (Deploy Key vs Personal SSH Key)
| 항목 | Deploy Key | Personal SSH Key |
| 등록 위치 | 리포 Settings | 계정 Settings |
| 접근 범위 | 해당 리포 1개 | 사용자 전체 리포 |
| 계정 의존 | 없음 | 강함 |
| 용도 | 서버/자동화 | 개발자 개인 작업 |
장점
- 개발자가 본인 머신에서 git clone 편리하게
- 비밀번호/PAT 입력 없이 SSH 키 인증
단점
- 자동화에 부적합 — 퇴사·계정 이동 시 모든 자동화 깨짐
- 키 관리가 사용자 책임
언제 사용
- 개발자 개인 워크스테이션에서 GitHub 사용
- 자동화/CI 용도에는 사용 금지
2.5 GitHub App
개요
GitHub이 제공하는 정식 자동화 프레임워크. 앱을 생성하고 조직/리포에 설치하면 installation token을 발급받아 API/git 접근.
동작 원리
1. App 생성 (개발자 설정 화면에서)
- webhook URL, permissions, events 정의
- Private key (.pem) 발급
2. 조직/리포에 설치 (install)
- "어느 리포에 접근 허용할지" 선택
3. 클라이언트에서 토큰 발급 flow:
Private key → JWT 생성 (10분 유효)
→ /app/installations/{id}/access_tokens 호출
→ Installation token 받음 (1시간 유효)
→ API / git 호출에 사용
4. 1시간마다 갱신 반복
설정 복잡도
- App 생성 + 권한 정의
- 각 리포/조직에 설치
- 클라이언트 코드: JWT 생성 → token 발급 로직 필요
- Private key 안전한 저장 (Secrets Manager 등)
장점
- 정교한 권한 제어 — 리소스별 read/write 세분화 (Actions, Issues, Contents, etc.)
- 사용자 독립: 계정 변화에 영향 없음
- 여러 리포 한꺼번에 관리 — 1개 App을 20개 리포에 설치 가능
- 감사 로그: 조직 차원 audit에서 App 행위 전부 추적
- rate limit 독립: App installation 마다 시간당 5000 req
- Webhook 수신 가능: push, PR 등 이벤트에 반응 가능
- 발급 토큰이 단기(1시간) — 유출 시 피해 제한
단점
- 설정 복잡 — 익숙해지기까지 학습 비용
- 토큰 갱신 로직 구현 필요 (직접 또는 라이브러리 사용)
- 작은 규모에선 오버킬
- Private key 관리가 또 다른 비밀(secret) 관리 이슈
구현 예시 (Node.js)
import { createAppAuth } from '@octokit/auth-app';
const auth = createAppAuth({
appId: process.env.APP_ID,
privateKey: process.env.PRIVATE_KEY,
installationId: process.env.INSTALLATION_ID,
});
const { token } = await auth({ type: 'installation' });
// token 은 1시간 유효, 이후 자동 재발급
언제 사용
- 조직 차원 CI/CD 플랫폼 (scaffold-ops, ArgoCD, Atlantis 등)
- 봇 (PR 리뷰, 이슈 triage, 릴리즈 자동화)
- 여러 리포 동시 관리 필요
- 감사 요구사항 강함
- webhook 이벤트 처리 필요
피해야 할 경우
- 단일 서버 단일 리포 pull (Deploy Key가 훨씬 단순)
- 1회성 스크립트 (PAT으로 충분)
- GitHub App 운영 전문성 없는 조직 (설정 잘못하면 더 위험)
실제 사용 예
- scaffold-ops / gh-app-dispatcher (회사 기존 구조)
- Renovate, Dependabot
- GitHub 자체 봇들
2.6 GitHub Actions OIDC
개요
GitHub Actions workflow가 외부 클라우드 제공자(AWS, GCP, Azure 등)에 인증할 때 사용. GitHub 자체 리소스 접근용은 아님.
동작 원리
1. 외부 클라우드에 GitHub OIDC provider 등록
(AWS: OIDC identity provider, IAM role trust policy)
2. workflow 실행 시:
GitHub이 OIDC JWT 발급 (repo, branch, actor 등 claim 포함)
→ workflow가 이 JWT로 AWS STS AssumeRoleWithWebIdentity 호출
→ 임시 AWS credential 획득 (수십 분 유효)
→ AWS API 호출
3. workflow 종료 시 자동 만료
장점
- 장기 credential 불필요 — AWS access key / secret을 GitHub Secrets에 저장할 필요 없음
- Secret 유출 리스크 제거 — 토큰이 workflow 내에서만 존재
- fine-grained trust: IAM trust policy로 "특정 리포의 main 브랜치만" 같은 조건부 접근 가능
- 감사 용이 — CloudTrail에 어느 workflow가 호출했는지 기록
단점
- GitHub → 외부 클라우드 방향만 — GitHub 리소스 자체 접근엔 못 씀
- 외부 클라우드 측 설정 필요 (IAM role, trust policy)
- 초기 학습 비용
설정 예시 (AWS)
# .github/workflows/deploy.yml
permissions:
id-token: write # OIDC 토큰 발급 허용
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-oidc-...
aws-region: ap-northeast-2
# 이후 AWS CLI 사용 시 임시 credential 자동 사용
언제 사용
- GitHub Actions에서 AWS/GCP/Azure 리소스 제어
- ECR push, S3 업로드, EKS 배포 등
2.7 GITHUB_TOKEN
개요
Actions workflow 시작 시 자동으로 생성되는 임시 토큰. 별도 설정 없이 ${{ secrets.GITHUB_TOKEN }} 으로 사용.
특징
- workflow 실행 중에만 유효 (최대 6시간)
- 해당 리포의 일부 권한만 자동 부여
- permissions: 블록으로 권한 조정 가능 (기본은 read-only로 제한하는 게 권장)
기본 권한 (조직 설정에 따라 다름)
기본 contents: read 만 허용하도록 설정하고 필요 시 workflow별 추가 부여하는 것이 베스트 프랙티스.
설정 예시
permissions:
contents: write # 리포에 commit/push
pull-requests: write # PR 생성/댓글
packages: write # GHCR 이미지 push
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
# ... 자동으로 인증된 상태로 git 작업
장점
- 별도 설정 0분 — workflow 시작과 함께 준비됨
- 만료가 workflow 수행시간뿐이라 유출 리스크 매우 낮음
- GitHub 내부 제공이라 안정적
단점
- 같은 리포 내에서만 유효 — 다른 리포 접근 불가 (cross-repo 작업엔 별도 토큰 필요)
- 같은 workflow 재트리거 못 함 — GITHUB_TOKEN으로 push한 커밋은 기본적으로 새 workflow 발동 안 됨 (무한루프 방지)
언제 사용
- Actions workflow 내에서 해당 리포 조작 (commit, PR 생성, 릴리즈)
- GHCR에 이미지 push (권한 부여 시)
피해야 할 경우
- cross-repo 작업 (다른 리포 trigger 필요하면 App token 또는 PAT)
2.8 Machine User (Bot Account)
개요
자동화 전용으로 생성한 일반 GitHub 사용자 계정. 개인 계정 대신 팀이 공유. 해당 계정으로 PAT / SSH key 발급해 사용.
설정
- 별도 이메일로 GitHub 계정 생성 (예: barunn-bot@barunn.net)
- 조직에 Collaborator / 팀 멤버로 추가
- 해당 계정에서 PAT / SSH key 발급
- 자동화에서 사용
장점
- 개인 퇴사 영향 없음 (팀 공유 계정이므로)
- 기존 GitHub 사용자 방식 그대로 가져갈 수 있어 마이그레이션 쉬움
- 감사 로그에 "bot 계정 행위" 로 구분됨
단점
- GitHub 약관상 회색지대 — GitHub은 free 플랜에서 "1인 1계정" 원칙, 유료 플랜에서 Machine user 허용 (GitHub Enterprise에선 명시적 지원)
- 이메일·비밀번호·2FA 관리 부담 — 누가 소유자인가 명확히 해야 함
- 계정 기반 인증의 본질적 한계 그대로 (PAT 만료 등)
언제 사용
- GitHub App 도입은 부담스럽지만 개인 계정 의존은 피하고 싶을 때
- 레거시 도구가 "사용자 계정" 만 지원할 때
피해야 할 경우
- 무료 플랜 조직에서 권장 안 함 (약관 이슈)
- GitHub App으로 대체 가능한 케이스 (대부분 그러함)
3. 결정 가이드
3.1 의사결정 트리
Q1. GitHub Actions workflow 내부 작업인가?
YES → Q1a. 같은 리포만 건드리나?
YES → GITHUB_TOKEN
NO → Q1b. 외부 클라우드 (AWS/GCP/Azure)?
YES → Actions OIDC
NO → GitHub App or cross-repo PAT
NO → Q2. 서버/자동화 시스템에서 git 접근?
YES → Q2a. 리포 몇 개?
1개 → Deploy Key ✓
여러개 → Q2b. 조직 차원 플랫폼?
YES → GitHub App
NO → Fine-grained PAT (여러 리포 모두 선택)
NO → Q3. 개발자 개인 머신?
YES → Personal SSH Key or Fine-grained PAT
NO → (용도 재검토)
3.2 시나리오별 추천
| 시나리오 | 추천 | 비고 |
| 단일 서버가 단일 리포 pull (오늘 demo-server 케이스) | Deploy Key (read-only) | 교과서 케이스 |
| Actions가 ECR push / EKS 배포 | OIDC + IAM role | 이미 회사 구축됨 |
| Actions가 같은 리포 commit/PR 생성 | GITHUB_TOKEN | 기본 제공 |
| 봇 계정이 여러 리포 자동화 (PR 생성, 이슈 triage) | GitHub App | 조직 차원 |
| 개발자 로컬 clone | Personal SSH Key | |
| 1회성 스크립트로 특정 리포 API 호출 | Fine-grained PAT | 만료 짧게 |
| 여러 서버가 같은 리포 pull (scale-out) | GitHub App or Deploy Key × N | 규모에 따라 |
| cross-repo Actions 트리거 | GitHub App installation token or PAT | GITHUB_TOKEN 불가 |
3.3 조직 규모별 추천
소규모 (1~3명, 리포 ~10개)
- 개인 개발: Personal SSH Key
- 서버 자동화: Deploy Key
- Actions: GITHUB_TOKEN + OIDC
- 특수 케이스: Fine-grained PAT
중규모 (10+명, 리포 30+개)
- 개인 개발: Personal SSH Key
- 서버 자동화: Deploy Key (당분간) → GitHub App (성숙 시)
- 플랫폼 자동화: GitHub App
- Actions: GITHUB_TOKEN + OIDC
- 특수 케이스: Fine-grained PAT
대규모 (50+명, 리포 100+개, 감사 요구사항)
- 대부분 GitHub App 기반
- SSH Key는 개인 개발만
4. 우리 조직 적용 현황
현재 사용 중
| 용도 | 방식 | 위치 |
| GitHub Actions → AWS (ECR, EKS 등) | OIDC + IAM role | github-oidc-.... |
| scaffold-ops 웹훅 처리 | GitHub App | gh-app-dispatcher Lambda |
| demo-server → docker-manager 리포 pull | Deploy Key (오늘 설정) | 서버 ~/.ssh/docker-manager-deploy |
| 개발자 개인 작업 | Personal SSH Key / HTTPS + PAT | 개발자별 자유 |
5. 보안 체크리스트
모든 자동화 토큰 공통
- [ ] 최소 권한 원칙 (read-only 가능한 곳은 read-only)
- [ ] 만료일 설정 (가능한 모든 토큰)
- [ ] Secret 저장소 사용 (AWS Secrets Manager, GitHub Secrets, 환경변수) — 코드/레포에 커밋 금지
- [ ] 주기적 rotation 스케줄 (PAT, App private key)
- [ ] 유출 의심 시 즉시 revoke 절차 문서화
PAT 특화
- [ ] Classic PAT 대신 Fine-grained PAT 우선
- [ ] [ ] ~/.git-credentials 파일 권한 600
- [ ] 사용 안 하는 PAT 삭제
- [ ] GitHub Settings → Security log 에서 PAT 사용 이력 주기 확인
Deploy Key 특화
- [ ] read-only로 충분하면 read-only 설정
- [ ] 키 파일 chmod 600
- [ ] 서버 폐기 시 GitHub에서 키 삭제
- [ ] 복수 서버가 같은 키 공유 금지 (서버별 발급)
GitHub App 특화
- [ ] Private key를 secret store에 저장 (평문 파일 금지)
- [ ] Installation 단위로 권한 최소화
- [ ] Webhook secret 설정 + 검증
- [ ] 주기적 private key rotation
OIDC 특화
- [ ] IAM trust policy의 StringEquals / StringLike 조건 구체적으로 (리포·브랜치 제한)
- "StringLike": { "token.actions.githubusercontent.com:sub": "repo:org/repo:ref:refs/heads/main" }
- [ ] 와일드카드() 사용 최소화
- [ ] AssumeRole session duration 짧게 (1시간 기본)
6. 흔한 실수와 피해야 할 패턴
| 실수 | 영향 | 개선 |
| Classic PAT을 모든 scope(repo) 체크해서 사용 | 유출 시 계정 전체 영향 | Fine-grained PAT 으로 리포·권한 한정 |
| 서버에 사용자 개인 PAT 저장 | 퇴사/만료 시 배포 멈춤 | Deploy Key 또는 GitHub App |
| 1개 Deploy Key를 여러 서버/용도에 재사용 | 유출 시 피해 확산 | 서버·용도별 발급 |
| GitHub App의 Private Key를 Git 리포에 커밋 | 즉시 전체 노출 | Secrets Manager / Vault |
| AWS Access Key를 GitHub Secrets에 저장 | Secret 유출 위험 + rotation 필요 | OIDC로 전환 |
| permissions: 지정 안 한 workflow | GITHUB_TOKEN이 기본값으로 과도한 권한 | 명시적 minimal permissions 선언 |
| OIDC trust policy에 "sub": "repo:*:*" 같은 와일드카드 | 우리 조직 모든 리포가 해당 role 사용 가능 | 리포·브랜치 한정 |
반응형
'GIT > Github' 카테고리의 다른 글
| GitHub Actions Private Repo에서 ARM64 빌드와 비용 최적화 (0) | 2025.12.04 |
|---|---|
| GitHub Actions에서 actions/checkout@v4 (1) | 2025.09.11 |
| git branch tracking 하기 (0) | 2023.05.16 |
| git branch 분기 (1) | 2022.11.29 |
| github actions 란 (0) | 2022.11.12 |
댓글