보안은 나중에 붙이는 기능이 아니다
GitHub를 오래 쓰다 보면 코드보다 중요한 것이 생깁니다. 누가 수정할 수 있는지, 무엇이 자동으로 검사되는지, 실수했을 때 어떻게 막을지입니다.
초보 팀에서 자주 하는 실수는 기능 개발을 먼저 시작하고, 보안과 운영 규칙은 문제가 생긴 뒤에 정하는 것입니다. 하지만 GitHub에서는 몇 가지 기본 설정만 해도 큰 사고를 줄일 수 있습니다.
이 장의 목표는 복잡한 보안 이론을 외우는 것이 아닙니다. 개인 프로젝트와 팀 프로젝트에서 바로 적용할 수 있는 안전한 습관을 정리하는 것입니다.
핵심은 단순합니다.
비밀값은 코드에 넣지 않고, 중요한 브랜치는 직접 수정하지 않으며, 자동 검사와 리뷰를 거친 코드만 main에 합칩니다.

민감 정보는 절대 커밋하지 않는다
민감 정보란 외부 서비스나 시스템에 접근할 수 있는 값입니다. 예를 들면 다음과 같습니다.
.env파일API 키
데이터베이스 비밀번호
개인 액세스 토큰, PAT
SSH 개인 키
클라우드 접근 키
이 값들이 GitHub에 올라가면, 저장소가 비공개라도 안전하다고 볼 수 없습니다. 팀원이 많아질수록 접근자가 늘어나고, 실수로 공개 저장소로 바뀌거나 로그에 노출될 수도 있습니다. GitHub 문서에서도 비밀값은 하드코딩하지 말고 환경 변수나 저장소 Secrets 같은 안전한 저장 방식을 사용하라고 안내합니다.1
가장 기본적인 방법은 .gitignore에 민감 파일을 등록하는 것입니다.
# 환경 변수 파일
.env
.env.local
.env.production
# 키 파일
*.pem
*.key
# 운영체제/에디터 파일
.DS_Store
.vscode/그리고 실제 값 대신 예시 파일을 공유합니다.
# .env.example
DATABASE_URL=your_database_url
OPENAI_API_KEY=your_api_key
JWT_SECRET=your_jwt_secret팀원은 .env.example을 보고 자신의 PC에 .env 파일을 따로 만듭니다. 저장소에는 .env.example만 올라가고, 실제 비밀값은 올라가지 않습니다.
GitHub Actions에서 배포나 테스트에 비밀값이 필요하다면 코드에 직접 쓰지 말고 GitHub Actions Secrets를 사용합니다.
설정 경로는 다음과 같습니다.
저장소로 이동
SettingsSecrets and variablesActionsNew repository secret
예를 들어 DEPLOY_TOKEN이라는 Secret을 만들었다면 워크플로우에서는 이렇게 사용합니다.
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy
run: npm run deploy
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}주의할 점은 Secret을 로그에 출력하지 않는 것입니다.
# 나쁜 예: 실제 프로젝트에서 금지
- run: echo $DEPLOY_TOKENGitHub가 일부 비밀값을 ***로 가려 주기도 하지만, 모든 상황을 완벽하게 막아 주지는 않습니다. 출력하지 않는 습관이 가장 안전합니다.
이미 비밀값을 올렸다면 즉시 폐기한다
초보자가 많이 오해하는 부분이 있습니다.
"커밋에서 지우고 다시 push하면 괜찮지 않을까?"
괜찮지 않습니다. Git은 과거 기록을 보관합니다. 최신 파일에서 지워도 이전 커밋에 남아 있을 수 있습니다.
실수로 API 키나 비밀번호를 올렸다면 순서는 다음과 같습니다.
해당 키를 즉시 폐기한다.
새 키를 발급한다.
새 키는 GitHub Secrets나 안전한 환경 변수에 저장한다.
저장소에서 민감 정보가 들어간 파일을 제거한다.
필요하면 Git 기록에서 민감 정보를 제거한다.
팀원에게 알리고, 의심스러운 사용 기록을 확인한다.
가장 먼저 해야 할 일은 기록 삭제가 아니라 키 폐기입니다. 이미 누군가 복사했을 가능성이 있기 때문입니다.
기록 삭제는 git filter-repo, BFG Repo-Cleaner 같은 도구를 사용할 수 있습니다. 다만 이 작업은 커밋 히스토리를 다시 쓰기 때문에 팀 프로젝트에서는 신중해야 합니다. 다른 팀원에게 미리 알리고, 작업 후에는 모두가 저장소를 다시 동기화해야 합니다.
계정과 권한부터 안전하게 만든다
저장소 보안의 출발점은 코드가 아니라 계정입니다.
먼저 GitHub 계정에 2단계 인증, 즉 MFA를 켭니다. MFA는 비밀번호 외에 인증 앱, 보안 키, 패스키 같은 추가 확인 수단을 요구하는 방식입니다. 비밀번호가 유출되어도 계정 탈취 가능성을 낮출 수 있습니다.
그다음은 권한입니다. 원칙은 하나입니다.
필요한 사람에게, 필요한 기간 동안, 필요한 권한만 준다.
GitHub 저장소 권한은 보통 다음처럼 나눌 수 있습니다.
| 역할 | 권한 예시 | 적합한 대상 |
|---|---|---|
| Read | 읽기만 가능 | 기획자, 외부 검토자 |
| Triage | 이슈와 PR 관리 | QA, 프로젝트 매니저 |
| Write | 브랜치 push, PR 작성 | 일반 개발자 |
| Maintain | 저장소 운영 일부 관리 | 팀 리드 |
| Admin | 설정 변경, 권한 관리 | 저장소 책임자 |
초보 팀에서는 모든 팀원에게 Admin을 주는 경우가 많습니다. 편하긴 하지만 위험합니다. Admin은 브랜치 보호 설정, Secrets, 저장소 공개 여부 같은 중요한 설정을 바꿀 수 있습니다. Admin은 최소 인원만 가져야 합니다.
PAT를 만들 때도 마찬가지입니다. 모든 권한을 켜지 말고 필요한 범위만 선택합니다. 가능하면 만료일을 짧게 설정하고, 오래된 토큰은 삭제합니다.
GitHub의 자동 보안 기능을 켠다
사람은 실수합니다. 그래서 자동 검사 기능을 켜 두는 것이 중요합니다.
GitHub에서 우선 확인할 기능은 다음 세 가지입니다.
Secret scanning: 저장소에 비밀값이 들어갔는지 탐지
Push protection: 비밀값이 포함된 push를 사전에 차단
Dependabot alerts / security updates: 취약한 패키지를 알려 주고 수정 PR 생성
GitHub의 보안 빠른 시작 문서도 저장소 접근 관리, dependency graph, Dependabot alerts, Dependabot security updates, code scanning, secret scanning 같은 기능을 저장소 보안의 기본 요소로 설명합니다.2
다만 이 기능들은 저장소가 Public인지 Private인지, 개인 계정인지 조직 계정인지, 사용하는 GitHub 요금제와 조직 정책이 무엇인지에 따라 화면 위치나 사용 가능 범위가 달라질 수 있습니다. 메뉴가 보이지 않는다면 계정 권한, 저장소 설정, 조직 정책을 함께 확인하세요.
설정 위치는 보통 다음 흐름입니다.
저장소
Settings로 이동Advanced Security또는Code security and analysis확인Dependency graph활성화Dependabot alerts활성화Dependabot security updates활성화사용 가능한 경우
Secret scanning활성화사용 가능한 경우
Push protection활성화
Dependabot이 PR을 만들면 무조건 바로 병합하지 말고 테스트를 확인합니다.
실전 흐름은 다음과 같습니다.
Dependabot이
lodash취약점 업데이트 PR 생성GitHub Actions가 테스트 실행
테스트 통과 확인
변경 내용 확인
main 브랜치에 병합
이 흐름이 익숙해지면 보안 업데이트가 부담이 아니라 일상적인 유지보수 작업이 됩니다.
main 브랜치는 직접 수정하지 않는다
main 브랜치는 프로젝트의 기준입니다. 배포되는 코드이거나, 최소한 안정적이라고 믿을 수 있는 코드여야 합니다.
따라서 팀 프로젝트에서는 main에 직접 push하지 않는 규칙을 세워야 합니다. 이때 사용하는 기능이 Branch protection 또는 Rulesets입니다. GitHub 화면에서는 저장소 설정과 계정 유형에 따라 기존 Branch protection rules 방식과 Rulesets 방식이 함께 보이거나, Rulesets가 더 중심적으로 보일 수 있습니다.
기본 설정은 다음을 추천합니다.
main 브랜치 직접 push 금지
Pull Request를 통해서만 병합
최소 1명 이상 리뷰 승인 필요
GitHub Actions 테스트 통과 필요
PR 브랜치가 최신 main을 반영해야 병합 가능
force push 금지
브랜치 삭제 금지
관리자도 가능하면 우회하지 못하게 설정
GitHub의 브랜치 보호 규칙은 PR 승인, 상태 검사 통과, 최신 브랜치 요구, 코드 오너 리뷰, 서명 커밋 등 중요한 브랜치에 적용할 여러 조건을 제공합니다.3
초보 팀이라면 처음부터 너무 많은 규칙을 켜지 않아도 됩니다. 아래 조합부터 시작하면 충분합니다.
main 보호 기본값
- Require a pull request before merging
- Require approvals: 1
- Require status checks to pass before merging
- Require branches to be up to date before merging
- Block force pushes
- Restrict deletions이렇게 설정하면 코드가 main에 들어가기 전에 최소한 두 가지 문을 통과합니다.
사람이 보는 리뷰
자동으로 실행되는 테스트
이 두 가지가 있으면 실수로 깨진 코드가 main에 들어갈 가능성이 크게 줄어듭니다.
팀 규칙은 문서로 남긴다
좋은 운영은 기억에 의존하지 않습니다. 문서로 남깁니다.
저장소에 다음 파일을 준비하면 팀원이 바뀌어도 같은 기준으로 일할 수 있습니다.
README.md: 프로젝트 소개, 실행 방법, 주요 명령어CONTRIBUTING.md: 브랜치 이름, 커밋 규칙, PR 규칙SECURITY.md: 보안 취약점 제보 방법.github/pull_request_template.md: PR 작성 양식.github/CODEOWNERS: 파일별 리뷰 담당자
GitHub도 README, 라이선스, 기여 가이드, 보안 정책 같은 문서가 프로젝트의 기대 사항을 전달하고 기여를 관리하는 데 도움을 준다고 설명합니다.4
예를 들어 PR 템플릿은 이렇게 만들 수 있습니다.
## 변경 내용
-
## 확인한 내용
- [ ] 로컬에서 실행해 보았습니다.
- [ ] 테스트를 통과했습니다.
- [ ] 관련 문서를 수정했습니다.
## 관련 이슈
Closes #이 템플릿이 있으면 PR 작성자가 무엇을 설명해야 하는지 덜 고민합니다. 리뷰어도 변경 이유와 테스트 여부를 빠르게 확인할 수 있습니다.
CODEOWNERS는 특정 파일이나 폴더의 리뷰 담당자를 지정하는 파일입니다.
# .github/CODEOWNERS
# 전체 기본 리뷰어
* @my-org/core-team
# 배포 설정은 DevOps 담당자 리뷰 필요
.github/workflows/ @my-org/devops-team
# 인증 코드는 백엔드 담당자 리뷰 필요
src/auth/ @my-org/backend-teamCODEOWNERS를 제대로 활용하려면 브랜치 보호 설정에서 "Require review from Code Owners"를 함께 켜야 합니다. 파일만 만들어 두면 자동 요청은 되더라도, 필수 승인 규칙으로 강제되지 않을 수 있습니다.
워크플로우는 단순하게 시작한다
GitHub 협업 방식에는 여러 흐름이 있습니다.
GitHub Flow는 가장 단순합니다.
짧은 브랜치 생성 → 커밋 → PR → 리뷰/테스트 → main 병합작은 팀, 웹 서비스, 초보 프로젝트에 잘 맞습니다. 오래 유지되는 브랜치가 적어서 충돌이 적고 이해하기 쉽습니다.
Git Flow는 main, develop, feature, release, hotfix처럼 여러 브랜치를 나누는 방식입니다. 릴리스 주기가 명확한 제품에는 유용하지만 초보자에게는 복잡할 수 있습니다.
Trunk-Based Development는 main에 가까운 하나의 중심 브랜치를 기준으로 아주 짧게 작업하고 자주 병합하는 방식입니다. 자동 테스트와 배포 체계가 잘 갖춰진 팀에 적합합니다.
초보자나 작은 팀은 GitHub Flow부터 시작하는 것을 추천합니다.
규칙은 이렇게 정하면 충분합니다.
1. main에서 직접 작업하지 않는다.
2. 기능마다 브랜치를 만든다.
3. 작업이 끝나면 PR을 연다.
4. 최소 1명이 리뷰한다.
5. 테스트가 통과해야 병합한다.
6. 병합 후 작업 브랜치는 삭제한다.이 흐름은 단순하지만 실무에서도 강력합니다.
작은 팀을 위한 실전 운영 예시
3명이 만드는 웹 프로젝트를 예로 들어 보겠습니다.
저장소 운영 규칙은 다음처럼 잡을 수 있습니다.
브랜치
- main: 배포 가능한 코드
- feature/*: 기능 개발
- fix/*: 버그 수정
권한
- 팀장 1명: Admin
- 개발자 2명: Write
보안
- MFA 필수
- .env 커밋 금지
- GitHub Secrets로 배포 키 관리
- Dependabot alerts 활성화
- Secret scanning 활성화 가능 여부 확인
PR 규칙
- main 직접 push 금지
- PR 승인 1명 이상 필요
- test GitHub Actions 통과 필요
- 리뷰 코멘트 해결 후 병합이 정도만 적용해도 "누가 main에 바로 올려서 배포가 깨졌다", "API 키가 저장소에 올라갔다", "취약한 패키지를 몇 달 동안 모르고 썼다" 같은 문제를 상당히 줄일 수 있습니다.
마지막 체크리스트
새 저장소를 만들거나 팀 프로젝트를 시작할 때 아래 항목을 확인하세요.
GitHub 계정에 MFA를 켰다.
팀원 권한을 최소 권한으로 부여했다.
.env와 키 파일을.gitignore에 추가했다.실제 비밀값 대신
.env.example을 제공했다.배포 키와 API 키는 GitHub Secrets에 저장했다.
Secret scanning과 push protection 사용 가능 여부를 확인했다.
Dependabot alerts와 security updates를 켰다.
main 브랜치에 보호 규칙 또는 Rulesets를 적용했다.
PR 리뷰와 테스트 통과를 병합 조건으로 설정했다.
README, CONTRIBUTING, PR 템플릿을 준비했다.
필요하면 CODEOWNERS로 리뷰 담당자를 지정했다.
GitHub를 잘 쓴다는 것은 명령어를 많이 아는 것만이 아닙니다. 실수해도 크게 망가지지 않는 구조를 만드는 것입니다.
안전한 저장소는 특별한 팀만 만드는 것이 아닙니다. 작은 규칙을 일찍 정하고, 반복해서 지키는 팀이 만듭니다.
참고
1Storing your secrets safely - GitHub Docs
2Quickstart for securing your repository - GitHub Docs
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.
