GitHub Actions 강좌 #2 문법 핵심: 컨텍스트와 표현식, if 조건, 값 전달
지난 편의 워크플로는 위에서 아래로 흐르기만 했습니다. 실전 워크플로는 조건에 따라 스텝을 건너뛰고, 앞 스텝의 결과를 뒤에서 쓰고, 잡끼리 순서와 값을 주고받습니다. 이번 편은 그것을 가능하게 하는 문법 네 가지, 컨텍스트, 표현식, if 조건, 값 전달을 다룹니다. 이 네 가지가 손에 익으면 이후 편의 어떤 워크플로도 문법 때문에 막히는 일은 없습니다.
컨텍스트: 실행 정보가 담긴 객체들 #
워크플로 안에서 ${{ ... }}로 감싸면 표현식이 되고, 표현식 안에서 실행 정보를 담은 컨텍스트에 접근할 수 있습니다. 자주 쓰는 것부터 나열합니다.
| 컨텍스트 | 담긴 것 | 대표 사용 예 |
|---|---|---|
github | 이벤트·저장소·브랜치 정보 | github.ref, github.event_name, github.sha |
env | 환경 변수 | env.MY_VAR |
steps | 앞 스텝들의 출력·결과 | steps.build.outputs.version |
needs | 앞 잡들의 출력·결과 | needs.test.result |
secrets | 시크릿(다음 편) | secrets.AWS_ROLE_ARN |
runner | 러너 정보 | runner.os, runner.temp |
예를 들어 github.event_name은 이 실행을 깨운 이벤트 이름이라, 같은 워크플로가 push로 왔는지 pull_request로 왔는지를 구분할 수 있습니다. 컨텍스트 전체 목록을 외울 필요는 없고, “지금 실행에 관한 정보는 어딘가의 컨텍스트에 있다"라는 감각과 함께 필요할 때 문서를 찾으면 됩니다. 디버깅 요령 하나를 곁들이면, ${{ toJSON(github) }}을 run: echo로 찍어 보는 것이 컨텍스트 내용을 통째로 확인하는 가장 빠른 방법입니다.
if 조건: 스텝과 잡을 골라 실행 #
if는 스텝과 잡 양쪽에 붙습니다. 대표 패턴 세 가지면 실전의 대부분이 풀립니다.
jobs:
deploy:
# 1. main 브랜치의 push일 때만 잡 실행
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh
# 2. 앞 스텝이 실패했을 때만 실행
- run: ./rollback.sh
if: failure()
# 3. 성공이든 실패든 항상 실행 (정리 작업)
- run: ./cleanup.sh
if: always()if 안에서는 ${{ }}를 생략해도 표현식으로 해석됩니다. 상태 함수 네 가지의 구분이 중요합니다. 기본값은 success()(앞이 전부 성공했을 때만)라서 아무것도 안 붙인 스텝은 앞이 실패하면 건너뜁니다. failure()는 실패 시에만, always()는 취소가 아닌 한 항상, cancelled()는 취소 시에만 실행합니다. 실패 알림과 정리 작업이 이 함수들의 단골 용도입니다.
스텝 사이의 값 전달: GITHUB_OUTPUT #
앞 스텝에서 계산한 값(버전 번호, 이미지 태그)을 뒤 스텝에서 쓰려면 출력으로 선언합니다. 스텝에 id를 붙이고, $GITHUB_OUTPUT 파일에 이름=값을 쓰는 방식입니다.
- name: version 계산
id: meta
run: echo "version=1.4.$(date +%Y%m%d)" >> "$GITHUB_OUTPUT"
- name: 빌드
run: ./build.sh --version "${{ steps.meta.outputs.version }}"받는 쪽 주소는 steps.<id>.outputs.<이름>입니다. 환경 변수로 넘기는 $GITHUB_ENV(이후 모든 스텝의 env에 주입)도 있는데, 구분 기준은 단순합니다. 특정 값을 특정 스텝에 넘기면 OUTPUT, 이후 전체에서 환경 변수로 쓰고 싶으면 ENV입니다. 출력 쪽이 출처가 명시적이라 기본값으로 권합니다.
잡 사이의 순서와 값: needs와 outputs #
잡은 기본이 병렬이므로, 순서가 필요하면 needs로 선언합니다. 값을 넘기려면 잡 수준의 outputs로 스텝 출력을 올려 줍니다.
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.meta.outputs.version }}
steps:
- id: meta
run: echo "version=1.4.0" >> "$GITHUB_OUTPUT"
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "배포 버전 ${{ needs.build.outputs.version }}"needs: build가 순서(build 성공 후 deploy)와 데이터 통로(needs.build.outputs) 둘 다를 만듭니다. 잡은 서로 다른 러너에서 돌기 때문에 파일은 자동으로 넘어가지 않는다는 점만 주의합니다. 문자열 값은 outputs로, 빌드 산출물 같은 파일은 #4에서 다룰 아티팩트로 넘깁니다.
env: 세 층의 환경 변수 #
환경 변수는 워크플로, 잡, 스텝 세 수준에 선언할 수 있고 안쪽이 이깁니다.
env:
APP_NAME: myapp # 워크플로 전체
jobs:
test:
env:
STAGE: ci # 이 잡 전체
steps:
- run: echo "$APP_NAME / $STAGE / $DEBUG"
env:
DEBUG: "true" # 이 스텝만셸에서 쓸 값은 이렇게 env로 선언하고 $이름으로 읽는 것이 안전합니다. ${{ }}를 run 스크립트 안에 직접 보간하는 방식은 편해 보이지만 #9에서 다룰 스크립트 인젝션의 입구가 되므로, 외부에서 온 값은 반드시 env를 거쳐 셸 변수로 읽는 습관을 지금부터 들이는 것이 좋습니다.
정리 #
이번 글에서 다룬 내용입니다.
${{ }}표현식 안에서 github, env, steps, needs 같은 컨텍스트로 실행 정보에 접근합니다.toJSON()출력이 디버깅 지름길입니다- if는 스텝·잡 양쪽에 붙고, 기본은 success()입니다. failure()로 실패 대응, always()로 정리 작업을 겁니다
- 스텝 간 값은
$GITHUB_OUTPUT에 쓰고steps.<id>.outputs.<이름>으로 받습니다 - 잡 간에는 needs가 순서와 값 통로를 만들며, 파일은 자동으로 넘어가지 않습니다
- 환경 변수는 워크플로·잡·스텝 세 층이고, 외부 값은 env를 거쳐 셸 변수로 읽는 것이 인젝션을 막는 습관입니다
다음 글(#3 시크릿·변수·환경)에서는 워크플로에 비밀 값을 안전하게 넣는 방법을 다룹니다. secrets와 vars의 구분, 그리고 배포 승인 관문을 만드는 environment입니다.