
GitHub Actions는 공개 Action을 조합해 CI/CD를 구성할 수 있지만, 실무에서는 “우리 팀만의 표준 동작”을 재사용 가능한 Action으로 만들어야 한다.
Custom Action은 Composite / JavaScript / Docker Action 세 종류이며, 구조적 차이를 이해하면 선택과 구현이 명확해진다.
이 글은 Custom Actions의 구조를 기능 단위로 분해하고, 가장 많이 요구되는 AWS S3 배포용 Action 예제까지 제공한다.
| 종류 | 실행 방식 | 장점 | 단점 |
|---|---|---|---|
| Composite Action | 여러 Step을 YAML로 묶음 | 개발 가장 쉬움 | 복잡한 로직에는 부적합 |
| JavaScript Action | Node 환경에서 JS 실행 | 빠름, 로직 구현 용이 | Node 런타임 필요 |
| Docker Action | Docker 컨테이너에서 실행 | 실행환경 완전 제어 | 빌드·이미지 관리 필요 |
세 종류 모두 동일한 Action 메타데이터 파일(action.yml)로 정의된다.
Composite Action은 “여러 Step을 하나의 Action처럼 묶는 기능”이다.
Team 단위 공통 빌드·포맷·테스트 흐름을 통합할 때 적합하다.
my-action/action.yml
name: "My Composite Action"
runs:
using: "composite"
steps:
- run: echo "Hello ${{ inputs.name }}"
inputs:
name:
required: true
steps:
- uses: ./.github/actions/my-action
with:
name: "World"
Composite Action의 핵심:
JavaScript Action은 Node.js 환경에서 JS 파일을 실행하는 방식이다.
외부 API 호출·파일 처리·데이터 변환 등 “로직 중심” 구현에 적합하다.
name: "JS Action"
runs:
using: "node20"
main: "index.js"
inputs:
message:
required: true
const core = require("@actions/core");
function run() {
const msg = core.getInput("message");
console.log(`Message: ${msg}`);
}
run();
steps:
- uses: ./.github/actions/js-action
with:
message: "Hello JS Action"
장점:
단점:
node_modules 포함해 배포해야 함Docker Action은 컨테이너 내부에서 실행되므로 OS·언어·패키지 버전을 완전히 통제할 수 있다.
name: "Docker Action"
runs:
using: "docker"
image: "Dockerfile"
inputs:
path:
required: true
FROM node:18
WORKDIR /app
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
#!/bin/sh
echo "Path: $1"
steps:
- uses: ./.github/actions/docker-action
with:
path: "./dist"
Docker Action은 다음 상황에서 필수다.
| 기능 | Composite | JS | Docker |
|---|---|---|---|
| 개발 난이도 | 가장 쉬움 | 중간 | 높음 |
| 실행 속도 | 빠름 | 매우 빠름 | 느림 |
| 실행환경 제어 | 낮음 | 중간 | 매우 높음 |
| 복잡한 로직 | 어려움 | 적합 | 적합 |
| 시스템 패키지 필요 | 불가능 | Node 패키지만 | 가능 |
선택 기준:
Custom Action에서 Secrets를 받는 경우 반드시 inputs로 받아 env로 전달해야 한다.
# action.yml
inputs:
token:
required: true
runs:
using: composite
steps:
- run: echo "Using token"
env:
TOKEN: ${{ inputs.token }}
주의:
AWS CLI가 runner에 설치되어 있으므로 Composite Action이 가장 적합하다.
.github/actions/s3-deploy/action.yml
name: "Deploy to S3"
inputs:
bucket:
required: true
region:
required: true
dist-path:
required: true
aws-access-key-id:
required: true
aws-secret-access-key:
required: true
runs:
using: "composite"
steps:
- run: aws configure set aws_access_key_id ${{ inputs.aws-access-key-id }}
- run: aws configure set aws_secret_access_key ${{ inputs.aws-secret-access-key }}
- run: aws s3 sync ${{ inputs.dist-path }} s3://${{ inputs.bucket }} --region ${{ inputs.region }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/s3-deploy
with:
bucket: "my-app"
region: "ap-northeast-2"
dist-path: "./dist"
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
실무 적용 가능하며 S3 정적 배포 환경에 바로 사용된다.
Custom Action 내부에서도 echo 금지.
런타임에 npm install을 시키면 Actions 속도가 크게 느려짐.
이미지를 GitHub Container Registry(GHCR)에 미리 푸시하는 방식을 고려.
필요한 위치에서만 사용.
Action 재사용 시 @v1, @v1.1.0 등 버전 태그 필수.
Custom Action은 CI/CD 플랫폼을 “팀 내부 개발 플랫폼”으로 확장하는 핵심 기술이다.
Custom Actions를 정확히 이해하면 팀 전체의 자동화 품질을 높은 수준으로 통일할 수 있다.