도입: GitHub Actions 배포 환경을 staging과 production으로 분리하는 한 줄 답
같은 배포 job에 조건문만 붙이는 대신 GitHub Environments를 staging과 production으로 나누고, 각 job이 사용할 환경을 명시한다. 환경별 Secrets와 Variables, 배포 branch, 승인 규칙을 분리하면 테스트 설정이 운영에 섞이는 사고를 줄이고 배포 기록도 구분할 수 있다.
GitHub Actions 배포 환경을 staging과 production으로 분리하는 핵심 항목
1. 두 Environment 만들기
- 준비: 저장소의 Settings에 접근할 권한과 현재 배포 대상 목록을 확인한다.
- 단계: Environments 메뉴에서
staging,production을 각각 생성한다. - 주의점: 이름 표기를 워크플로와 동일하게 유지한다. 존재하지 않는 이름을 워크플로에서 참조하면 의도하지 않은 빈 환경이 만들어질 수 있다.
- 완료 기준: 두 환경이 별도 설정 페이지와 배포 기록을 가진다.
2. 값과 인증 정보 분리하기
- 준비: 현재 Secrets와 Variables를 민감도와 대상 환경으로 분류한다.
- 단계: 운영 API 토큰은 production Secret, 테스트 토큰은 staging Secret으로 등록한다. 공개 가능한 URL·버킷 이름은 각 환경 Variable로 둔다.
- 주의점: 저장소 수준에 운영·테스트 값을 함께 두면 job이 잘못된 값을 선택해도 발견하기 어렵다.
- 완료 기준: 각 환경이 자기 배포에 필요한 값만 보유한다.
3. job에 environment 연결하기
- 준비: 빌드와 배포 job을 구분한다.
- 단계: staging과 production 배포 job에 각각 environment 이름을 지정하고 공통 테스트 job 이후 실행되게 한다.
- 주의점: 환경을 연결하지 않은 job은 환경 수준 Secret에 접근할 수 없다.
- 완료 기준: Actions 실행 화면과 Deployments 기록에 대상 환경이 표시된다.
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm test
deploy-staging:
needs: test
if: github.ref == 'refs/heads/develop'
environment: staging
runs-on: ubuntu-latest
steps:
- run: ./scripts/deploy.sh
env:
API_TOKEN: ${{ secrets.API_TOKEN }}
PUBLIC_ORIGIN: ${{ vars.PUBLIC_ORIGIN }}
deploy-production:
needs: test
if: github.ref == 'refs/heads/main'
environment: production
concurrency: production
runs-on: ubuntu-latest
steps:
- run: ./scripts/deploy.sh
env:
API_TOKEN: ${{ secrets.API_TOKEN }}
PUBLIC_ORIGIN: ${{ vars.PUBLIC_ORIGIN }}
4. branch와 승인 규칙 설정하기
- 준비: 어떤 branch 또는 tag가 각 환경에 배포될 수 있는지 정한다.
- 단계: staging은 develop, production은 main 또는 릴리스 tag처럼 허용 범위를 제한한다. 운영 환경에는 필요하면 required reviewer를 설정한다.
- 주의점: 플랜과 저장소 공개 여부에 따라 사용할 수 있는 보호 기능이 다를 수 있으므로 현재 계정에서 실제 옵션을 확인한다.
- 완료 기준: 허용하지 않은 branch에서는 production job이 환경 보호 규칙을 통과하지 못한다.
5. 동시 배포 막기
- 준비: 같은 환경으로 동시에 배포될 때 발생할 위험을 검토한다.
- 단계: production job에 고정 concurrency group을 두고 운영 배포를 직렬화한다.
- 주의점:
cancel-in-progress는 진행 중 배포를 취소해도 안전한 경우에만 사용한다. - 완료 기준: 두 운영 배포가 동시에 리소스를 변경하지 않는다.
6. 배포 후 환경별 검증 넣기
- 준비: 각 환경의 health URL과 확인할 핵심 기능을 정한다.
- 단계: 배포가 끝난 뒤 환경 Variable의 URL을 호출해 상태 코드와 버전을 확인한다.
- 주의점: 배포 명령 성공만으로 사용자 요청이 정상이라는 보장은 없다.
- 완료 기준: 검증 실패 시 workflow가 실패하고 운영 롤백 판단에 필요한 로그가 남는다.
전체 실행 순서
현재 인증 정보와 설정값을 목록화한다. 두 Environment를 생성하고 값을 옮긴다. 공통 test job과 환경별 deploy job을 분리하고 branch 조건을 설정한다. production에 보호 규칙과 concurrency를 적용한다. 마지막으로 staging에서 먼저 배포·검증한 뒤 production 승격 흐름을 실제로 한 번 실행한다.
주의점과 실패하기 쉬운 지점
Environment 이름 오타, 저장소 Secret과 환경 Secret의 중복, branch 조건과 보호 규칙의 불일치가 흔한 원인이다. Fork PR의 코드가 운영 Secret에 접근하지 않도록 이벤트와 job을 분리해야 한다. 재사용 워크플로를 사용한다면 Secret 전달 방식도 별도로 확인한다.
완료 확인 체크리스트
- [ ] staging과 production Environment가 분리되어 있다.
- [ ] 두 환경이 서로 다른 Secrets와 Variables를 가진다.
- [ ] test 성공 후에만 배포 job이 실행된다.
- [ ] production은 허용한 branch 또는 tag에서만 접근된다.
- [ ] 운영 배포가 concurrency로 직렬화된다.
- [ ] 배포 후 health 검증이 실패를 감지한다.
- [ ] Actions와 Deployments에서 대상 환경과 결과를 추적할 수 있다.
참고 자료
- GitHub Docs, Deployment environments
- GitHub Docs, Managing environments
- GitHub Docs, Deploying to a specific environment
