Github Actions
Github Actions를 이용하면 GitHub 안에서 CI/CD를 끝낼 수 있다. 개인 프로젝트, 포트폴리오, 초기 스타트업, 오픈소스는 GitHub Actions로 충분히 처리할 수 있다.
장점
GitHub와 통합이 강하다.
- PR 검사, 리뷰, 브랜치 보호 룰, secrets, 배포 기록을 한 곳에서 관리하기 쉽다.
진입 장벽이 낮다.
- Jenkins처럼 서버를 직접 설치하고 플러그인 관리하고 보안 패치할 필요가 적다.
YAML 기반이라 프로젝트 안에 CI/CD 설정을 같이 보관 가능하다.
- .github/workflows/ci.yml 자체가 코드처럼 버전 관리된다.
Marketplace Action이 많음
- actions/checkout, setup-node, setup-java, setup-python, Docker 관련 Action 등을 조합하기 쉽다.
public repo는 표준 GitHub-hosted runner 사용이 무료이고, private repo는 플랜별 무료 분량 이후 과금된다.
- 무료버전의 경우 월 2000분, 아티팩트 스토리지 500MB와 캐시 스토리지 10GB를 기본 제공한다.
- job이 병렬로 실행될 때는 각각 계산되어 차감된다.
한계 (별도의 CI가 필요한 단계)
빌드 시간이 길고 비용이 커질 때
- 매번 GitHub-hosted runner에서 빌드하면 편하지만, 대규모 프로젝트에서는 minutes 비용과 대기 시간이 문제가 된다.
사내망, 폐쇄망, 내부 서버 접근이 필요할 때
- DB, 내부 Kubernetes, 사내 Nexus/Artifactory, VPN 뒤의 서버에 접근해야 하면 self-hosted runner나 별도 CI 서버가 필요해진다.
빌드 머신을 세밀하게 통제해야 할 때
- 특정 OS, GPU, 특수 SDK, 고정된 캐시, 라이선스 서버, 로컬 네트워크 장비 테스트 등이 필요하면 Jenkins 같은 도구가 유리하다.
여러 저장소, 여러 팀, 복잡한 배포 승인 흐름이 필요할 때
- GitHub Actions도 가능하지만, 파이프라인이 복잡해질수록 YAML이 길어지고 관리가 어려워진다.
CI와 CD를 분리하고 싶을 때
- 예를 들어 GitHub Actions는 test/build까지만 하고, 실제 Kubernetes 배포는 Argo CD가 GitOps 방식으로 담당하게 하는 구조가 실무에서 자주 나온다.
그래서 프로젝트가 커지면
- Github Actions는 테스트, 빌드, Docker image push를 담당하고
- Argo CD, Jenkins, GitLab CI 등으로 실제 서버 배포를 관리 한다.
폴더구조
필수 규칙
.github/workflows/*.yml
이 경로가 아니면 GitHub Actions가 아예 실행 안 한다.
workflow는 기본 브랜치(main)에 있어야 제대로 동작한다.
기본 구조
project-root/
├── .github/
│ └── workflows/
│ └── ci.yml
GitHub가 이렇게 설계한 이유는:
- 자동 탐색 (Auto discovery)
- 보안 (임의 위치 실행 방지)
- 표준화
좋은 네이밍 규칙
ci.yml
ci-python.yml
ci-node.yml
deploy-prod.yml
deploy-staging.yml
이름만 보고 역할 바로 알게 해야한다.
실무형 폴더 구조
1. reusable workflow
.github/workflows/
├── ci.yml
├── deploy.yml
└── reusable/
└── test.yml
공통 로직 재사용 가능
2. composite action (완전 고급)
.github/
├── workflows/
│ └── ci.yml
└── actions/
└── setup-env/
└── action.yml
직접 Action 만들어서 재사용
팁
1. CI / CD 분리
ci.yml → PR용
cd.yml → main push용
2. 환경 분리
deploy-staging.yml
deploy-prod.yml
3. 최소 단위로 쪼개기
lint.yml
test.yml
build.yml
실패 원인 빠르게 찾음
기본 개념
실행 흐름
Event 발생
↓
Workflow 실행
↓
Job 실행 (병렬 가능)
↓
Step 실행 (순차 실행)
↓
Runner 위에서 실행됨
↓
Action / shell 명령 수행
Workflow (가장 큰 단위)
정의
- 자동화 작업 전체
- .github/workflows/*.yml 파일 하나 = workflow 하나
역할
- “언제 실행되고 무엇을 할지” 정의
예시
name: CI Pipeline
핵심 포인트
- 프로젝트 단위 자동화
- 여러 개 만들어도 됨
ci.yml → 테스트
cd.yml → 배포
lint.yml → 코드 검사
Event (트리거)
정의
- workflow를 실행시키는 조건
예시
on:
pull_request:
branches: [main]
자주 쓰는 이벤트
on:
push
pull_request
workflow_dispatch
schedule
의미
push → 코드 푸쉬하면 실행
PR → PR 생성/수정하면 실행
manual → 버튼 눌러 실행
cron → 정기 실행
Job (작업 단위)
정의
- workflow 안에서 실행되는 “묶음 작업”
특징
- 서로 병렬 실행 가능
- 각각 별도의 환경(runner)에서 실행됨
예시
jobs:
test:
runs-on: ubuntu-latest
build:
runs-on: ubuntu-latest
test랑 build는 동시에 실행됨 (병렬)
순서 제어 (needs)
build:
needs: test
test 끝나야 build 실행
Step (실행 단계)
정의
- job 안에서 실행되는 하나의 작업
- 가장 작은 실행 단위
특징
- 순차 실행
- 같은 runner 환경 공유
예시
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install
run: npm install
- name: Test
run: npm test
Runner (실행 환경)
정의
- 코드가 실제로 실행되는 서버
종류
runs-on: ubuntu-latest
- ubuntu
- windows
- macOS
특징
- 매번 새로 생성됨 (stateless)
- 이전 실행과 상태 공유 안 됨
그래서 매번 install 해야 하는 이유가 이것 때문이다.
Action (재사용 가능한 작업)
정의
- 다른 사람이 만들어둔 자동화 기능
예시
uses: actions/checkout@v4
내부적으로는:
git clone 해주는 코드
대표 Action
- actions/checkout
- actions/setup-node
- actions/setup-python
run과 차이점
uses: ... → 외부 기능
run: ... → 직접 명령 실행
실제 연결 예제
name: CI
on: push # Event
jobs:
test: # Job
runs-on: ubuntu-latest # Runner
steps:
- name: Checkout # Step
uses: actions/checkout@v4 # Action
- name: Install
run: npm install # shell 실행
- name: Test
run: npm test
Yaml 작성 방법
name (워크플로우 이름)
역할
- GitHub Actions UI에 표시되는 이름
name: Python CI
포인트
- 체크 이름에도 영향을 줌 (Branch Protection에서 선택됨)
- 명확하게 쓰는 게 중요
CI / CD / Deploy / Test 등
on (트리거)
역할
- 언제 실행할지 정의
on:
push:
branches: [main]
다양한 형태
on:
pull_request:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
포인트
- CI → pull_request
- CD → push (main)
- 수동 실행 → workflow_dispatch
jobs (작업 묶음)
역할
- 실행할 작업 정의
jobs:
test:
runs-on: ubuntu-latest
여러 개 가능
jobs:
test:
build:
deploy:
포인트
- job은 병렬 실행
- needs로 순서 제어
deploy:
needs: build
runs-on (실행 환경)
역할
- 어떤 OS에서 실행할지
runs-on: ubuntu-latest
옵션
- ubuntu-latest (가장 많이 씀)
- windows-latest
- macos-latest
포인트
- 대부분 ubuntu 사용
- OS마다 환경 다름 → 버그 발생 가능
steps (실행 단계)
역할
- job 안에서 실행되는 순서
steps:
- name: Install
run: npm install
특징
- 순차 실행
- 같은 환경 공유
uses (Action 사용)
역할
- 외부 action 실행
- uses: actions/checkout@v4
구조
owner/repo@version
포인트
- 항상 version 명시 (@v4)
- 최신 major 버전 사용
run (명령 실행)
역할
- shell 명령 실행
- run: npm test
여러 줄
- run: |
npm install
npm test
포인트
- 디버깅은 대부분 여기서 함
- 실패하면 job 전체 실패
with (Action 옵션)
역할
- action에 값 전달
- uses: actions/setup-node@v4
with:
node-version: 20
포인트
- action마다 옵션 다름
- 공식 문서 반드시 확인
env (환경 변수)
역할
- 변수 설정
env:
NODE_ENV: production
범위
- workflow 전체
- job 단위
- step 단위
steps:
- run: echo $MY_VAR
env:
MY_VAR: hello
포인트
- config 값 넣기 좋음
- secret과 구분 필요
secrets (민감 정보)
역할
- 비밀번호 / API 키 등
${{ secrets.API_KEY }}
예시
env:
DB_URL: ${{ secrets.DB_URL }}
설정 위치
Repo → Settings → Secrets → Actions
포인트
- 절대 로그에 출력 금지
- .env 대신 사용
CI 단계
PR 생성
↓
lint (코드 규칙 검사 / 잠재적 버그 탐지)
↓
format check (코드 스타일 자동 정렬 여부 검사)
↓
type check (타입 안정성 검사 / 런타임 오류 사전 방지)
↓
unit test (함수/클래스 단위 기능 검증)
↓
integration test (모듈 간 연동 / 시스템 흐름 검증)
↓
coverage (테스트가 코드 얼마나 커버하는지 측정)
↓
build (실제 실행/배포 가능한 상태인지 확인)
↓
✔ 전부 통과 → merge 허용 (품질 기준 충족)
CI 예제
name: Python CI
on:
pull_request:
branches: [main]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.13
- name: Install deps
run: |
pip install -r requirements.txt
pip install ruff black mypy pytest pytest-cov
# 1. lint
- name: Lint
run: ruff check .
# 2. format
- name: Format check
run: black --check .
# 3. type
- name: Type check
run: mypy src
# 4. unit test + 5. coverage
- name: Test + Coverage
run: pytest --cov=src
# 6. coverage threshold
- name: Coverage threshold
run: coverage report --fail-under=90
# 7. build
- name: Build
run: python -m build
Branch Protection / Rulesets
개발자가 PR 생성
↓
GitHub Actions (CI 실행)
↓
Branch Protection / Rulesets 검사
↓
조건 통과?
├─ YES → merge 가능
└─ NO → merge 차단
CI 결과를 “정책으로 묶어서 강제”
PR 필수
(Require a pull request before merging)
직접 main push ❌
반드시 PR 통해서만 merge ⭕
효과
- 코드 리뷰 강제
- CI 반드시 실행됨
"아무도 main에 바로 코드 못 넣는다"
리뷰 승인 필수
(Require approvals)
PR → 리뷰어 승인 필요
설정 예
최소 1명 승인
or
2명 승인
효과
- 코드 품질 향상
- 실수 방지
status check 통과 필수
(Require status checks to pass)
CI랑 직접 연결되는 핵심
lint 실패 → merge ❌
test 실패 → merge ❌
coverage 부족 → merge ❌
연결 구조
GitHub Actions job 성공 → status = success
GitHub Actions job 실패 → status = failed
포인트
- 특정 job만 선택 가능
python-ci
coverage
build
체크 이름 = workflow/job 이름
최신 main 기준 필수
(Require branches to be up to date)
PR 브랜치가 오래됨 → merge ❌
상황
main ← 다른 사람이 먼저 merge
내 PR은 옛날 기준 코드
강제:
git pull origin main
or
rebase 필요
효과
- 충돌 사전 방지
- 최신 상태에서 테스트 보장
force push 금지
git push --force ❌
히스토리 날아감
커밋 추적 불가
“협업 환경에서는 거의 필수로 막는다”
direct push 금지
(Restrict who can push)
main 브랜치 직접 push ❌
효과
- 모든 변경은 PR 통해서만
- CI + 리뷰 강제
실제 설정 위치
Repository → Settings → Rules → Rulesets
기본 세팅
✔ PR 필수
✔ 리뷰 승인 1명 이상
✔ status check 필수
✔ 최신 main 기준 필수
✔ force push 금지
✔ direct push 금지
CD 단계
CD (Continuous Deployment / Delivery)
├─ SSH 배포
│ └─ GitHub Actions가 서버에 SSH 접속 → git pull / build / restart 실행
│ 예: 개인 VPS, EC2, 라이트세일, 사내 서버
│
├─ Docker 배포
│ └─ Docker image 빌드 → Registry에 push → 서버에서 pull 후 컨테이너 재시작
│ 예: Docker Hub, GHCR, AWS ECR
│
├─ Cloud 배포
│ └─ 클라우드 서비스에 자동 배포
│ 예: AWS EC2, ECS, Elastic Beanstalk, Lambda, GCP Cloud Run, Azure App Service
│
├─ Vercel / Netlify
│ └─ 프론트엔드/Next.js 프로젝트를 Git push 기반으로 자동 배포
│ 예: Next.js, React, Vue, Svelte
│
├─ Kubernetes
│ └─ 이미지 push 후 Kubernetes 클러스터의 Deployment 업데이트
│ 예: kubectl apply, Helm, Argo CD
│
└─ package publish
└─ 라이브러리/패키지를 레지스트리에 배포
예: npm, PyPI, Maven Central, crates.io, Docker image
Env / Secrets
Env → 공개 가능한 설정값
Secrets → 절대 노출되면 안 되는 민감 정보
구조 이해
GitHub Actions 실행
↓
env (환경 변수)
↓
secrets (암호화된 값)
↓
step에서 사용
env (환경 변수)
역할
- 일반 설정값
예
env:
NODE_ENV: production
APP_NAME: my-app
특징
로그 출력 가능
노출돼도 문제 없음
secrets (민감 정보)
역할
- 비밀번호 / 키 / 토큰
사용 방법
env:
DB_URL: ${{ secrets.DB_URL }}
또는
- run: echo "deploy"
env:
API_KEY: ${{ secrets.API_KEY }}
특징
암호화 저장됨
로그에서 자동 마스킹 (****)
직접 출력하면 위험
항목
1. API key
외부 서비스 인증 키
절대 공개되면 안 됨
예
- OpenAI API
- Stripe
- Firebase
2. DB URL
데이터베이스 접속 문자열
예
postgres://user:password@host:5432/db
비밀번호가 포함되어 있으면 → secrets
3. SSH key
서버 접속용 개인 키
구조
private key → GitHub Secrets 저장
public key → 서버에 등록
사용
- name: SSH
run: ssh user@server
CD에서 핵심
4. deploy token
배포 권한을 가진 토큰
예
- Docker registry 로그인
- npm publish
- cloud deploy 인증
설정 위치
GitHub에서:
Repository → Settings → Secrets and variables → Actions
여기서 추가:
API_KEY
DB_URL
SSH_KEY
DEPLOY_TOKEN
고급 기능
- matrix → 여러 환경 테스트
- cache → 속도 최적화
- artifact → 결과물 저장
- environment approval → 배포 승인
- concurrency → 중복 실행 방지
- reusable workflow → workflow 재사용
- manual trigger → 수동 실행
- schedule → 정기 실행
우선순위
1. cache (속도)
2. matrix (호환성)
3. concurrency (배포 안정성)
4. environment (production 보호)
5. artifact (파이프라인 연결)
6. reusable (규모 커질 때)
7. manual/schedule (보조 기능)
matrix (다중 환경 테스트)
역할
- 여러 환경에서 동시에 테스트
strategy:
matrix:
python-version: [3.10, 3.11, 3.12]
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
의미
한 번 실행 → 여러 버전에서 테스트
포인트
- 라이브러리/SDK 필수
- OS + 버전 조합 가능
matrix:
os: [ubuntu-latest, windows-latest]
python-version: [3.10, 3.11]
cache (속도 최적화 핵심)
역할
- 의존성 설치 시간 줄이기
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
효과
매번 pip install → ❌ 느림
캐시 사용 → ⭕ 빠름
포인트
- CI 속도 2~10배 차이 남
- key 설계가 중요
artifact (결과물 저장)
역할
- 빌드 결과를 저장하고 다른 job에서 사용
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
사용 예
- build → artifact 생성
- deploy → artifact 사용
포인트
job 간 파일 공유
environment approval (배포 승인)
역할
- 배포 전에 사람 승인 필요
environment: production
설정
GitHub:
Settings → Environments → production
→ Required reviewers 설정
흐름
deploy job 실행
↓
승인 대기
↓
승인 → 배포 진행
포인트
- production 배포에 필수
- 실수 방지
concurrency (중복 실행 방지)
역할
- 동시에 여러 실행 막기
concurrency:
group: deploy
cancel-in-progress: true
의미
이전 deploy 실행 중 → 새 실행 오면 취소
포인트
- 배포 중복 방지
- race condition 방지
reusable workflow (재사용)
역할
- 공통 workflow를 다른 workflow에서 호출
jobs:
call-test:
uses: ./.github/workflows/test.yml
구조
.github/workflows/
├── ci.yml
└── test.yml ← 재사용
실무 포인트
- 조직 단위 CI 표준화
- 중복 제거
manual trigger (수동 실행)
역할
- 버튼 클릭으로 실행
on:
workflow_dispatch:
UI
- GitHub Actions → Run workflow 버튼
포인트
- 긴급 배포
- 테스트 실행
- 롤백
schedule (정기 실행)
역할
- cron 기반 자동 실행
on:
schedule:
- cron: "0 0 * * *"
의미
매일 자정 실행
실무 사용
- 보안 스캔
- 데이터 정리
- 배치 작업
예제
name: Advanced CI
on:
pull_request:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.10, 3.11]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-${{ hashFiles('**/requirements.txt') }}
- run: pip install -r requirements.txt
- run: pytest
deploy:
needs: test
runs-on: ubuntu-latest
concurrency:
group: deploy
cancel-in-progress: true
environment: production
steps:
- run: echo "Deploying..."
'Deployment > GitHub' 카테고리의 다른 글
| Learn Git Branching (2) remote (0) | 2026.05.01 |
|---|---|
| GitHub Skills (0) | 2026.04.30 |
| Learn Git Branching (1) main (0) | 2026.04.30 |
| 버전 관리와 깃(Git) (0) | 2025.12.01 |
| Git 기본 사용법 (CLI) (0) | 2025.04.09 |