보안·관리 매뉴얼
시크릿 노출 방지부터 인증·권한·브랜치 보호까지, 저장소를 안전하게 운영하는 GitHub·git 보안 기능 레퍼런스 | 공식 문서: docs.github.com
보안 관리 구조 한눈에
보안·관리 ├── 커밋 전 차단 시크릿이 저장소에 들어오지 못하게 막기 │ └── .gitignore 패턴 .env · node_modules/ · *.log 등을 추적에서 제외 ├── 실수 대응 이미 커밋된 비밀에 대처 │ ├── git rm --cached 로컬은 유지한 채 추적만 해제 │ └── 키 회전(rotate) 노출된 키 즉시 폐기·재발급 (최우선) ├── 자동 방어 사람 손을 거치지 않는 1차 방어선 │ ├── secret scanning 히스토리·이슈·PR에서 비밀 자동 탐지 │ └── push protection 푸시 전 단계에서 비밀 차단 ├── 인증 git/API에 안전하게 접근 │ ├── PAT HTTPS·API 토큰 (fine-grained 권장) │ ├── SSH 키 ssh-keygen 키 쌍 인증 │ └── gh auth login CLI 로그인 + 자격증명 저장 └── 운영 팀·저장소 단위 관리 ├── 권한·협업자 Read/Triage/Write/Maintain/Admin 역할 ├── 브랜치 보호 PR 리뷰·상태 체크·push 제한 └── Actions secrets 암호화 환경변수 ${{ secrets.X }}
1. .gitignore와 추적 제외
.gitignore — 버전관리에서 제외할 파일 지정
저장소 안의 텍스트 파일로, 여기에 적힌 패턴과 일치하는 파일은 Git이 추적하지 않습니다. 빌드 산출물·의존성 폴더·환경설정·OS 부산물처럼 공유할 필요가 없거나 공유하면 안 되는 파일을 걸러냅니다. 협업자와 규칙을 공유하도록 .gitignore 자체는 커밋하는 것이 권장됩니다.
# 흔히 제외하는 항목 node_modules/ .env .DS_Store *.log build/
패턴 문법 — 빈 줄·주석·슬래시 위치의 의미
빈 줄은 아무것도 매칭하지 않아 가독성용으로 쓰고, #으로 시작하는 줄은 주석입니다. 여러 패턴이 한 파일에 맞으면 마지막으로 일치한 패턴이 우선합니다. 슬래시 위치에 따라 의미가 달라집니다.
foo/: 끝 슬래시 → 디렉터리만 매칭(같은 이름의 파일은 제외 안 됨)./hello.txt: 앞 슬래시 → 저장소 루트에만 anchor(하위 폴더의 동명 파일은 제외 안 됨).*.log: 슬래시가 없으면 모든 깊이의 디렉터리에서 매칭.doc/frotz: 중간에 슬래시가 있으면 그 경로 기준으로 anchor.
와일드카드 — *, ?, [a-z], ** 의 매칭 범위
와일드카드로 한 줄에 여러 파일을 매칭합니다. *·?·[a-z]는 슬래시를 넘지 않고, **만 디렉터리 경계를 가로지릅니다.
| 패턴 | 의미 | 예 |
|---|---|---|
* | 슬래시를 제외한 모든 문자 | *.log |
? | 슬래시를 제외한 단일 문자 | file?.txt |
[a-z] | 범위 안의 한 문자 | [0-9].log |
** | 디렉터리를 가로지르는 매칭 | **/foo |
**/foo는 어느 깊이의 foo든, abc/**는 abc 내부 전부, a/**/b는 a/b·a/x/b를 매칭합니다. 반면 foo/*는 foo/test.json은 매칭하지만 foo/bar/hello.c는 매칭하지 않습니다(한 단계만).
**/foo abc/** a/**/b foo/*
! — 부정 패턴으로 재포함
느낌표로 시작하는 패턴은 앞서 제외된 파일을 다시 포함시킵니다. 큰 묶음을 제외하되 특정 파일만 살릴 때 씁니다. 단, 상위 디렉터리 자체가 제외된 경우 그 안의 파일은 !로도 되살릴 수 없는 함정이 있습니다.
*.html !foo.html
git rm --cached — 이미 추적된 파일을 추적 해제
.gitignore는 아직 추적되지 않은 파일에만 효과가 있습니다. 이미 커밋된 파일은 패턴을 추가해도 계속 추적되므로, 먼저 추적에서 빼야 합니다. --cached는 인덱스(추적)에서만 제거하고 로컬 파일은 그대로 남깁니다.
git rm --cached FILENAME git rm -r --cached node_modules/
~/.config/git/ignore — 전역(global) ignore
모든 저장소에 자동 적용되는 사용자 글로벌 규칙 파일입니다. 편집기 백업이나 .DS_Store 같은 OS 부산물처럼, 특정 프로젝트가 아니라 본인 환경에서 늘 생기는 파일을 한 번에 거를 때 적합합니다. 한 저장소에만 적용하되 공유는 하지 않으려면 .git/info/exclude를 씁니다.
# 전역 ignore 파일 위치 ~/.config/git/ignore # 공유하지 않는 저장소 로컬 전용 .git/info/exclude
2. 시크릿 보호 (Scanning · Secrets)
secret scanning — 비밀을 자동 탐지
API 키·비밀번호·토큰을 Git 히스토리·이슈·PR·위키·gist에서 자동으로 탐지합니다. public 저장소는 별도 설정 없이 무료로 동작하고, private/internal 저장소는 GitHub Secret Protection(Team/Enterprise)에서 제공됩니다. 탐지되면 즉시 해당 비밀을 회전(rotate)하는 것이 권고됩니다.
# Settings → Code security → Secret scanning 에서 활성화 # 탐지 결과는 Security 탭의 알림으로 확인
push protection — 푸시 전 비밀 차단
비밀이 커밋·푸시되기 전 단계에서 푸시 자체를 차단합니다. 차단되면 사용자는 코드를 검토해 비밀을 제거한 뒤 다시 푸시합니다. write 권한자는 사유를 지정해 우회할 수도 있으며, 저장소·조직·엔터프라이즈 단위로 활성화합니다.
# 푸시가 차단되면 # 1) 비밀을 코드에서 제거 # 2) git commit --amend 등으로 정리 후 # 3) 다시 push
${{ secrets.NAME }} — Actions secrets
Actions secrets는 암호화되어 저장되는 환경변수로, repository·environment·organization 3단계로 둘 수 있습니다. 워크플로에서는 ${{ secrets.NAME }}으로 참조하며, 평문으로 하드코딩하는 대신 여기에 보관합니다. GITHUB_TOKEN을 제외한 secrets는 fork PR 워크플로에는 전달되지 않습니다.
steps:
- shell: bash
env:
SUPER_SECRET: ${{ secrets.SuperSecret }}
run: example-command "$SUPER_SECRET"
gh secret set — CLI로 secret 등록
GitHub CLI로 secret을 명령줄에서 등록합니다. 저장소·환경·조직 범위를 옵션으로 지정합니다.
gh secret set SECRET_NAME gh secret set --env ENV SECRET_NAME gh secret set --org ORG SECRET_NAME --visibility all
3. 인증 (PAT · SSH · gh)
HTTPS vs SSH — 접속 방식 고르기
GitHub은 비밀번호 대신 토큰이나 키로 인증하며, 접속 방식은 크게 HTTPS와 SSH 두 가지입니다. 어느 방식인지는 clone URL 앞부분만 보면 바로 구분됩니다. https://로 시작하면 HTTPS(PAT로 인증), git@github.com: 형태면 SSH(등록한 공개키로 인증)입니다.
| clone URL 형태 | 방식 | 인증 수단 | 언제 |
|---|---|---|---|
https://github.com/... | HTTPS | Personal Access Token | 설정이 단순해 입문·1회성 접속에 적합 |
git@github.com:... | SSH | 등록한 공개키 | 키를 한 번 등록하면 매번 입력이 없어 상시 작업에 편리 |
HTTPS는 토큰만 있으면 바로 쓸 수 있어 처음 시작하기 쉽고, SSH는 키를 한 번 등록해 두면 push·pull 때마다 인증을 입력하지 않아 자주 쓰는 머신에 유리합니다. 둘 중 무엇을 골라도 보안 수준은 동등하므로, 익숙한 쪽을 쓰면 됩니다.
Personal Access Token — HTTPS·API 인증
HTTPS Git·API에서 비밀번호 대신 사용하는 토큰입니다. fine-grained PAT가 권장되며, 단일 사용자/조직과 특정 저장소·세분 권한으로 한정할 수 있습니다. classic PAT는 넓은 scope를 가져 비권장이며, 만료일 설정이 권장됩니다(classic은 1년 미사용 시 자동 삭제). 토큰은 비밀번호처럼 다뤄야 합니다.
| 종류 | 특징 | 권장 |
|---|---|---|
fine-grained PAT | 단일 사용자/조직 · 저장소 한정 · 세분 권한 | 권장 |
classic PAT | 넓은 scope · 1년 미사용 시 자동 삭제 | 비권장 |
ssh-keygen — SSH 키 쌍 생성·등록
키 쌍으로 인증하며 매번 비밀번호를 입력하지 않습니다. ed25519 키를 만들고 ssh-agent에 추가한 뒤, 공개키(~/.ssh/id_ed25519.pub)를 GitHub 계정의 SSH keys에 등록합니다. macOS는 키체인 연동 옵션을 씁니다(Linux는 --apple-use-keychain 없이).
ssh-keygen -t ed25519 -C "email" eval "$(ssh-agent -s)" # macOS ssh-add --apple-use-keychain ~/.ssh/id_ed25519
macOS에서는 ~/.ssh/config에 다음을 두면 키체인과 연동됩니다.
Host github.com AddKeysToAgent yes UseKeychain yes IdentityFile ~/.ssh/id_ed25519
gh auth login — CLI 로그인·자격증명 저장
GitHub CLI로 로그인합니다. HTTPS를 선택하면 Git 자격증명이 자동으로 저장되어 이후 push/pull에서 별도 인증이 필요 없습니다.
gh auth login
4. 접근 권한 · 브랜치 보호
저장소 역할 — Read/Triage/Write/Maintain/Admin
협업자에게는 다섯 단계 역할 중 하나를 부여합니다. 읽기만 가능한 Read부터 전체 설정을 다루는 Admin까지, 필요한 최소 권한만 주는 것이 안전합니다.
| 역할 | 대략적 권한 |
|---|---|
Read | 코드 읽기·클론 |
Triage | 읽기 + 이슈·PR 분류 관리 |
Write | 코드 push 가능 |
Maintain | 일부 설정 + 저장소 관리 |
Admin | 전체 설정·권한 관리 |
협업자 추가 — Collaborators & teams
협업자는 저장소의 Settings > Collaborators & teams > Add people에서 추가하고 역할을 지정합니다.
# 경로 Settings → Collaborators & teams → Add people
브랜치 보호 규칙 — 직접 push 막고 PR 강제
보호 규칙으로 중요한 브랜치를 지킵니다. PR 리뷰 요구, 상태 체크 통과 요구, 선형 히스토리, push 제한 등을 설정해 검토 없이 코드가 들어오는 것을 막습니다.
- PR 리뷰 요구: 병합 전 지정 인원의 승인을 받도록.
- 상태 체크 요구: CI 등 체크가 통과해야 병합 가능.
- 선형 히스토리: 머지 커밋 없이 깔끔한 히스토리 유지.
- push 제한: 특정 사용자/팀만 직접 push 허용.
Dependabot alerts — 취약 의존성 알림
GitHub Advisory Database를 기반으로, 저장소가 의존하는 패키지에 알려진 취약점이 있으면 알림을 보냅니다. 어떤 의존성을 어떤 버전으로 올려야 하는지 파악하는 출발점이 됩니다.
# Settings → Code security → Dependabot alerts 에서 활성화
git rm --cached나 히스토리 재작성은 시간이 오래 걸릴 뿐 아니라 과거의 노출을 되돌리지 못한다. 핵심은 발급처에서 즉시 키를 폐기하고 새로 발급하는 것이다. 히스토리 정리는 그다음 일이다..gitignore는 이미 추적 중인 파일에는 효과가 없다. 이미 커밋된 .env는 패턴을 추가해도 계속 추적되므로 git rm --cached로 추적을 해제한 뒤 커밋해야 한다. 부정 패턴(!)도 상위 디렉터리 자체가 제외되면 무력하다.GITHUB_TOKEN을 제외한 secrets는 fork 워크플로에 전달되지 않는다. secret을 run:에서 echo하거나 로그로 출력하지 말고 env:로 주입하며 따옴표로 감싼다. AI가 키를 하드코딩하는 실수는 push protection(public 무료)으로 1차 방어하되, 근본 해법은 .env·Actions secrets로 분리하는 것이다.참고 링크
- 📖 git-scm.com — gitignore 패턴 문법
- 📁 docs.github.com — Ignoring files
- 🔑 docs.github.com — Secret scanning
- 🔐 docs.github.com — Authentication (PAT · SSH)
- ⚙️ docs.github.com — Using secrets in GitHub Actions
- 🌿 docs.github.com — Configuring branches and merges
GitHub 보안 기능 · git 2.5x 기준 | 2026년 6월