기존 CI/CD에서는 프론트/백엔드 중 하나만 바뀌어도
전체를 다시 빌드해서 시간이 오래 걸리는 문제가 있습니다.
이번 글에서는
변경된 서비스만 빌드하도록 최적화한 CI/CD 구조
를 소개합니다.

아키텍처 개요
이번 구조는 다음 흐름으로 동작합니다.
1. 코드 Push
2. GitHub 에서 CI 실행
3. 변경된 서비스만 Docker Build
4. 이미지를 Amazon Web Services ECR 저장
5. Kubernetes YAML 이미지 태그 자동 업데이트
6. Git 자동 Commit & Push
<결과>
✔ 빌드 시간 단축
✔ 불필요한 리소스 낭비 감소
✔ GitOps 자동화 완성
GitHub에 AWS 자격 증명 저장 (Secrets)
CI에서 AWS 접근하려면 Key가 필요합니다.
설정 방법
1. IAM 계정 생성

2. GitHub에 AWS 열쇠(Secrets) 맡기기
Repository → Settings -> Secrets and variables → Actions
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_REGION = ap-northeast-2


GitHub Actions 파일 만들기
이제 GitHub에게 "일하는 순서"를 적어줍니다.
프로젝트 폴더 안에 .github/workflows/deploy.yml 파일을 만들고 아래 내용을 그대로 복사
name: CI/CD to ECR & GitOps
on:
push:
branches: [ "main" ]
# GitOps 폴더 수정 시에는 파이프라인 돌지 않음 (무한 루프 방지)
paths-ignore:
- 'gitops/**'
- 'README.md'
permissions:
contents: write # GitOps 레포지토리에 커밋하기 위해 필수
jobs:
# =========================================================
# 1. 백엔드 빌드 & 배포 (Matrix 전략)
# =========================================================
build-backend:
runs-on: ubuntu-latest
strategy:
matrix:
service: [auth-service, chat-service, live-service, product-service, order-service]
steps:
- name: Checkout code
uses: actions/checkout@v4
# 변경 사항 감지
- name: Check for changes
uses: dorny/paths-filter@v2
id: changes
with:
filters: |
src:
- 'backend/${{ matrix.service }}/**'
# AWS 자격 증명 설정
- name: Configure AWS credentials
if: steps.changes.outputs.src == 'true'
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
# ECR 로그인
- name: Login to Amazon ECR
if: steps.changes.outputs.src == 'true'
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
# 빌드 및 푸시
- name: Build, tag, and push image to Amazon ECR
if: steps.changes.outputs.src == 'true'
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: ${{ matrix.service }}
IMAGE_TAG: ${{ github.sha }}
run: |
# 해당 서비스 폴더로 이동해서 빌드
cd backend/${{ matrix.service }}
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \
-t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
# GitOps 매니페스트 업데이트
- name: Update Kubernetes Manifest
if: steps.changes.outputs.src == 'true'
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: ${{ matrix.service }}
IMAGE_TAG: ${{ github.sha }}
run: |
cd gitops/services
# 기존 image 주소를 새로운 ECR 주소로 교체 (sed 명령 사용)
# 기존에 어떤 주소가 있든 통째로 image: registry/repo:tag 형태로 변경
sed -i "s|image: .*|image: $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG|g" ${{ matrix.service }}.yaml
cat ${{ matrix.service }}.yaml
- name: Commit and Push Manifest
if: steps.changes.outputs.src == 'true'
run: |
git config --global user.email "github-actions@github.com"
git config --global user.name "GitHub Actions"
git add gitops/services/${{ matrix.service }}.yaml
git commit -m "Update ${{ matrix.service }} to ${{ github.sha }}" || echo "No changes to commit"
# [핵심 수정] 충돌 방지를 위해 pull --rebase를 반복 시도
# 다른 잡이 먼저 푸시했을 수 있으므로, 최신 코드를 가져와서 내 커밋을 그 위에 얹음
for i in {1..5}; do
git pull --rebase origin main && git push origin main && break || sleep 5;
done
# =========================================================
# 2. 프론트엔드 빌드 & 배포
# =========================================================
build-frontend:
runs-on: ubuntu-latest
needs: build-backend
if: always()
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Check for changes
uses: dorny/paths-filter@v2
id: changes
with:
filters: |
src:
- 'frontend/**'
- name: Configure AWS credentials
if: steps.changes.outputs.src == 'true'
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Login to Amazon ECR
if: steps.changes.outputs.src == 'true'
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and Push Frontend
if: steps.changes.outputs.src == 'true'
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: live-commerce-client # 프론트엔드 리포지토리 이름
IMAGE_TAG: ${{ github.sha }}
run: |
cd frontend/client
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \
-t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
# 프론트엔드 GitOps YAML 업데이트 (필요 시 추가)
# 현재 gitops/services/ 폴더에 프론트엔드 YAML은 없어서 생략했습니다.
# [추가됨] GitOps 매니페스트 업데이트
- name: Update Kubernetes Manifest
if: steps.changes.outputs.src == 'true'
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: live-commerce-client
IMAGE_TAG: ${{ github.sha }}
run: |
cd gitops/services
# live-commerce-client.yaml 파일의 이미지 주소 변경
sed -i "s|image: .*|image: $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG|g" live-commerce-client.yaml
cat live-commerce-client.yaml
- name: Commit and Push Manifest
if: steps.changes.outputs.src == 'true'
run: |
git config --global user.email "github-actions@github.com"
git config --global user.name "GitHub Actions"
git add gitops/services/live-commerce-client.yaml
git commit -m "Update frontend image to ${{ github.sha }}" || echo "No changes to commit"
# 충돌 방지 로직
for i in {1..5}; do
git pull --rebase origin main && git push origin main && break || sleep 5;
done
- Frontend.yaml (Cilium을 설치한 점은 참고!)
apiVersion: v1
kind: Service
metadata:
name: chat-backend-svc
namespace: default
annotations:
# AWS NLB 생성 및 Cilium ENI 모드 최적화 설정
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
spec:
type: LoadBalancer
selector:
app: chat-backend # backend.yaml의 Deployment 레이블과 반드시 일치해야 함
ports:
- port: 80
targetPort: 4000
apiVersion: apps/v1
kind: Deployment
metadata:
name: chat-backend
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: chat-backend # Service의 selector와 일치해야 함
template:
metadata:
labels:
app: chat-backend
spec:
containers:
- name: backend
# ▼ 본인의 백엔드 ECR 주소로 변경!
image: 189100467486.dkr.ecr.ap-northeast-2.amazonaws.com/live-commerce-backend:latest
ports:
- containerPort: 4000
'Cloud > CICD' 카테고리의 다른 글
| [CICD] Github Token 생성 (0) | 2026.03.03 |
|---|---|
| [CICD] GitOps 환경구축 (ECR) (0) | 2026.02.15 |
| [CICD] Local GitOps 환경 구축 #2 (0) | 2026.02.14 |
| [CICD] Local GitOps 환경 구축 #1 (0) | 2026.02.13 |