도입: 재사용 워크플로와 Composite Action 선택 기준 한 줄 정의
GitHub Actions에서 재사용 가능한 워크플로(Reusable Workflow)와 Composite Action은 모두 반복되는 CI/CD 로직을 재사용하기 위한 메커니즘이며, 선택 기준은 **호출 위치(워크플로 레벨 vs 스텝 레벨)**와 **필요한 제어 범위(Job 단위 vs Step 단위)**에 따라 결정된다.
재사용 워크플로(Reusable Workflow)
정의
재사용 워크플로는 하나 이상의 Job을 포함하는 완전한 워크플로 파일로, 다른 워크플로에서 workflow_call 트리거를 통해 호출할 수 있다. GitHub Docs에 따르면 재사용 워크플로는 .github/workflows 디렉터리에 위치하며 on: workflow_call을 선언해야 한다.
원리
재사용 워크플로는 호출하는 워크플로의 Job 레벨에서 uses 키워드로 참조된다. 호출 시 inputs와 secrets를 전달할 수 있으며, 재사용 워크플로 내부의 Job들은 별도의 러너에서 실행된다. 각 Job은 독립적인 환경을 가지므로 매트릭스 전략, 조건부 실행, 의존성 관리 등 워크플로 레벨 기능을 모두 활용할 수 있다.
예시
다음은 재사용 워크플로를 정의하고 호출하는 구조다.
재사용 워크플로 파일 .github/workflows/reusable-build.yml:
name: Reusable Build
on:
workflow_call:
inputs:
node-version:
required: true
type: string
secrets:
npm-token:
required: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ inputs.node-version }}
- run: npm ci
env:
NPM_TOKEN: ${{ secrets.npm-token }}
- run: npm run build
호출하는 워크플로:
jobs:
call-build:
uses: ./.github/workflows/reusable-build.yml
with:
node-version: '18'
secrets:
npm-token: ${{ secrets.NPM_TOKEN }}
오해
재사용 워크플로가 단순히 "큰 단위의 Composite Action"이라고 생각하는 경우가 있다. 하지만 재사용 워크플로는 Job 레벨에서 호출되며, 여러 Job을 포함할 수 있고, 각 Job이 다른 러너에서 실행될 수 있다는 점에서 근본적으로 다르다. Composite Action은 Step 레벨에서만 작동하며 단일 러너 내에서 실행된다.
Composite Action
정의
Composite Action은 여러 Step을 하나의 Action으로 묶어 재사용할 수 있게 하는 메커니즘이다. action.yml 파일에 runs.using: composite를 선언하고, 내부에 runs.steps 배열로 실행할 Step들을 정의한다.
원리
Composite Action은 워크플로의 Step 레벨에서 uses 키워드로 호출된다. 호출 시 with 파라미터로 입력값을 전달할 수 있으며, Action 내부의 모든 Step은 호출한 Job의 러너 환경에서 순차적으로 실행된다. GitHub Docs에 따르면 Composite Action 내부에서는 run Step과 다른 Action을 조합할 수 있지만, Job 레벨 기능(매트릭스, 조건부 Job 등)은 사용할 수 없다.
예시
다음은 Composite Action을 정의하고 호출하는 구조다.
Composite Action 파일 .github/actions/setup-and-test/action.yml:
name: 'Setup and Test'
description: 'Install dependencies and run tests'
inputs:
node-version:
description: 'Node.js version'
required: true
default: '18'
runs:
using: composite
steps:
- uses: actions/setup-node@v3
with:
node-version: ${{ inputs.node-version }}
- run: npm ci
shell: bash
- run: npm test
shell: bash
호출하는 워크플로:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/setup-and-test
with:
node-version: '18'
오해
Composite Action에서 shell 지정을 생략할 수 있다고 생각하는 경우가 있다. GitHub Docs에 따르면 Composite Action 내부의 run Step에는 반드시 shell 키를 명시해야 한다. 이는 호출하는 워크플로의 기본 shell 설정과 무관하게 명시적으로 지정해야 하는 요구사항이다.
핵심 선택 기준
Job 레벨 제어가 필요한 경우
여러 Job을 조율하거나, 각 Job이 다른 러너(운영체제, 아키텍처)에서 실행되어야 하거나, Job 간 의존성(needs)을 설정해야 한다면 재사용 워크플로를 선택한다. 재사용 워크플로는 완전한 워크플로 구조를 가지므로 매트릭스 전략, 조건부 Job 실행, Job 레벨 타임아웃 등을 모두 활용할 수 있다.
Step 레벨 재사용이 목적인 경우
하나의 Job 내에서 반복되는 Step 시퀀스를 재사용하려면 Composite Action을 선택한다. 예를 들어 "의존성 설치 → 캐시 복원 → 빌드" 같은 일련의 Step을 여러 Job에서 반복한다면, 이를 Composite Action으로 추출하면 각 Job의 Step 목록이 간결해진다.
비밀값과 환경 변수 전달 방식
재사용 워크플로는 secrets 파라미터를 통해 비밀값을 명시적으로 전달받는다. Composite Action은 호출하는 Job의 환경 변수와 비밀값을 직접 참조할 수 있지만, 명시적으로 inputs를 통해 전달하는 것이 권장된다. 비밀값 관리가 복잡하거나 여러 Job에 걸쳐 일관되게 전달해야 한다면 재사용 워크플로가 더 명확한 인터페이스를 제공한다.
배포 위치와 버전 관리
재사용 워크플로는 동일 리포지토리 또는 공개 리포지토리의 .github/workflows 디렉터리에 위치해야 하며, 참조 시 브랜치나 태그를 지정할 수 있다. Composite Action은 .github/actions 또는 별도 리포지토리의 루트에 위치하며, 마찬가지로 브랜치나 태그로 버전을 지정할 수 있다. 조직 전체에서 재사용할 CI/CD 파이프라인을 중앙 관리하려면 재사용 워크플로를 별도 리포지토리에 두고 버전 태그로 참조하는 방식이 적합하다.
핵심 원리 정리
재사용 워크플로와 Composite Action의 선택은 추상화 레벨에 따라 결정된다. 재사용 워크플로는 Job 레벨에서 작동하며 여러 Job, 다중 러너, Job 간 의존성을 포함할 수 있는 완전한 워크플로 단위다. Composite Action은 Step 레벨에서 작동하며 단일 러너 내에서 실행되는 Step 시퀀스를 캡슐화한다.
선택 시 고려할 핵심 요소는 다음과 같다:
- 실행 단위: Job 레벨 제어가 필요하면 재사용 워크플로, Step 레벨 재사용이면 Composite Action
- 러너 다양성: 여러 운영체제나 러너가 필요하면 재사용 워크플로
- 인터페이스 명확성: 비밀값과 입력을 명시적으로 관리하려면 재사용 워크플로
- 재사용 범위: 조직 전체 파이프라인은 재사용 워크플로, 개별 작업 시퀀스는 Composite Action
흔한 오해
"Composite Action이 더 가볍고 빠르다"
Composite Action과 재사용 워크플로는 실행 성능 자체에서 본질적인 차이가 없다. 둘 다 결국 Step을 실행하는 것이며, 성능은 실제 작업 내용에 달려 있다. 차이는 추상화 레벨과 제어 범위에 있다.
"재사용 워크플로는 같은 리포지토리에서만 사용 가능하다"
GitHub Docs에 따르면 재사용 워크플로는 동일 리포지토리뿐 아니라 공개 리포지토리, 조직 내부 리포지토리에서도 참조할 수 있다. 참조 형식은 {owner}/{repo}/.github/workflows/{filename}@{ref}이다.
"Composite Action 내부에서 다른 Job을 호출할 수 있다"
Composite Action은 Step 레벨에서만 작동하므로 Job을 정의하거나 호출할 수 없다. Job 레벨 기능이 필요하다면 재사용 워크플로를 사용해야 한다.
"재사용 워크플로에서 secrets를 자동으로 상속받는다"
재사용 워크플로는 호출 시 secrets 파라미터로 명시적으로 전달받아야 한다. secrets: inherit 구문을 사용하면 모든 비밀값을 상속할 수 있지만, 이는 명시적인 선언이 필요하다.
이해 확인 요약
GitHub Actions에서 재사용 워크플로는 Job 레벨에서 작동하며 여러 Job과 러너를 포함할 수 있는 완전한 워크플로 단위다. Composite Action은 Step 레벨에서 작동하며 단일 러너 내에서 실행되는 Step 시퀀스를 캡슐화한다. 선택 기준은 필요한 제어 범위와 추상화 레벨에 달려 있다.
Job 간 의존성, 다중 러너, 매트릭스 전략이 필요하면 재사용 워크플로를 선택한다. 반복되는 Step 시퀀스를 간결하게 재사용하려면 Composite Action을 선택한다. 두 메커니즘은 상호 배타적이지 않으며, 재사용 워크플로 내부에서 Composite Action을 호출하는 등 조합해서 사용할 수 있다.
