React 애플리케이션을 운영하면서 가장 많이 겪는 고민은 배포 과정의 일관성과 버전 관리입니다. 수동으로 빌드하고 서버에 업로드하면 실수 위험이 크고, 배포 로그가 흩어져 추적이 어려워집니다. 이번 글에서는 GitHub Actions를 활용해 CI/CD 파이프라인을 구축하고, 자동 버전 태깅까지 포함한 워크플로우를 설계하는 방법을 실무 중심으로 살펴보겠습니다.
1. 프로젝트 구조와 사전 준비
먼저, 기본적인 React 프로젝트 구조를 가정합니다. create-react-app 혹은 Vite로 생성된 프로젝트라면 별다른 설정 없이도 CI/CD를 적용할 수 있습니다.
my-react-app/
├─ .github/
│ └─ workflows/
│ └─ deploy.yml
├─ src/
├─ public/
├─ package.json
└─ README.md
필요한 사전 작업은 다음과 같습니다.
- GitHub 레포지토리 생성 및
main브랜치 보호 설정 - 배포 대상 서버에 SSH 키를 생성하고,
~/.ssh/authorized_keys에 공개키를 등록 - GitHub Secrets에 아래 항목 추가
SSH_PRIVATE_KEY # 배포 서버 접근용 개인키
SERVER_HOST # 예: example.com
SERVER_USER # 배포 사용자, 보통 ubuntu 혹은 ec2-user
DEPLOY_PATH # /var/www/my-react-app
2. GitHub Actions 워크플로우 기본 틀
다음은 가장 기본적인 배포 워크플로우 예시입니다. push 이벤트가 main 브랜치에 발생하면 자동으로 빌드하고, SSH를 통해 서버에 복사합니다.
name: Deploy React to Server
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Prepare SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
- name: Deploy via rsync
run: |
rsync -avz --delete ./build/ ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ secrets.DEPLOY_PATH }}
위 워크플로우는 npm ci 로 의존성을 설치하고, npm run build 로 정적 파일을 생성한 뒤 rsync 로 서버에 동기화합니다.
3. 자동 버전 태깅 전략
배포와 동시에 Git 태그를 자동 생성하면 릴리즈 히스토스를 관리하기 쉬워집니다. 여기서는 semantic-release 대신 간단히 git tag 를 활용하는 방법을 소개합니다.
- name: Determine next version
id: version
run: |
# 현재 가장 최근 태그 가져오기
git fetch --tags
LATEST_TAG=$(git describe --tags `git rev-list --tags --max-count=1` 2>/dev/null || echo "v0.0.0")
echo "Latest tag: $LATEST_TAG"
# npm version 명령어를 이용해 패치 버전 증가
NEW_TAG=$(npm version patch --no-git-tag-version)
echo "New tag: $NEW_TAG"
echo "::set-output name=tag::$NEW_TAG"
- name: Push new tag
run: |
git config user.name "github-actions"
git config user.email "actions@github.com"
git tag ${{ steps.version.outputs.tag }}
git push origin ${{ steps.version.outputs.tag }}
위 단계는 현재 태그를 조회한 뒤 npm version patch 로 vX.Y.Z 형식의 새 버전을 생성하고, 이를 원격에 푸시합니다. 필요에 따라 major, minor 로 바꿀 수 있습니다.
4. 배포 전후 검증 (Optional)
자동 배포가 성공했는지 확인하려면 간단한 curl 검증을 추가합니다.
- name: Verify deployment
run: |
URL="https://${{ secrets.SERVER_HOST }}"
for i in {1..5}; do
STATUS=$(curl -o /dev/null -s -w "%{http_code}" $URL)
if [ "$STATUS" -eq 200 ]; then
echo "✅ Deployment verified"
exit 0
fi
echo "⏳ Waiting for app... ($i)"
sleep 10
done
echo "❌ Deployment verification failed"
exit 1
위 검증은 배포 후 5번 시도하며 200 응답을 받으면 성공으로 간주합니다.
5. 전체 워크플로우 파일
앞서 소개한 모든 파트를 하나로 합치면 아래와 같습니다.
name: CI/CD for React
on:
push:
branches: [main]
jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run build
- name: Prepare SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
- name: Deploy via rsync
run: |
rsync -avz --delete ./build/ ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ secrets.DEPLOY_PATH }}
- name: Verify deployment
run: |
URL="https://${{ secrets.SERVER_HOST }}"
for i in {1..5}; do
STATUS=$(curl -o /dev/null -s -w "%{http_code}" $URL)
if [ "$STATUS" -eq 200 ]; then
echo "✅ Deployment verified"
exit 0
fi
sleep 10
done
echo "❌ Verification failed" && exit 1
- name: Determine next version
id: version
run: |
git fetch --tags
LATEST_TAG=$(git describe --tags `git rev-list --tags --max-count=1` 2>/dev/null || echo "v0.0.0")
echo "Latest tag: $LATEST_TAG"
NEW_TAG=$(npm version patch --no-git-tag-version)
echo "::set-output name=tag::$NEW_TAG"
- name: Push new tag
run: |
git config user.name "github-actions"
git config user.email "actions@github.com"
git tag ${{ steps.version.outputs.tag }}
git push origin ${{ steps.version.outputs.tag }}
위 파일을 .github/workflows/deploy.yml 로 저장하면, main 브랜치에 푸시될 때마다 자동으로 빌드 → 배포 → 검증 → 버전 태깅이 순차적으로 실행됩니다.
6. 마무리 팁
- 분기별 배포:
staging브랜치를 별도 워크플로우에 연결해 사전 검증 환경을 운영합니다. - 환경 변수 관리:
dotenv파일은 서버에만 존재하도록 하고, GitHub Secrets 로 API 키 등을 관리합니다. - 배포 롤백: 이전 태그를 체크아웃하고 동일한 워크플로우를 재실행하면 손쉽게 롤백할 수 있습니다.
자동화된 CI/CD 파이프라인을 구축하면 배포 실수를 크게 줄이고, 버전 관리가 투명해집니다. 오늘 소개한 워크플로우를 기반으로 프로젝트에 맞게 커스터마이징해 보세요.
'React' 카테고리의 다른 글
| React에서 CSS 변수와 JavaScript를 연동해 런타임 테마 커스터마이징 구현하기 (0) | 2026.09.30 |
|---|---|
| React와 Recoil로 비동기 상태 흐름 관리하고 selectorFamily 활용하기 (0) | 2026.09.30 |
| React와 VitePress를 결합해 컴포넌트 문서화 사이트 구축하기 (0) | 2026.09.29 |
| React 앱에 GraphQL Code Generator 적용하기 (0) | 2026.09.27 |
| React에서 Headless UI와 Radix UI 컴포넌트를 비교하고 선택하는 가이드 (0) | 2026.09.23 |