[LLM 경제 뉴스 요약 서비스] # 04. 서버 CI/CD (ECR, ECS)
2026. 1. 17. 01:46ㆍProgramming/Project
이번 포스팅에서는 저번에 구축한 배포환경의 CI/CD를 구성해보려합니다.
작업 순서
1. 배포 전용 IAM 사용자 생성
2. Git Secret 생성
3. Git Actions Workflow 작성
1. 배포 전용 IAM 사용자 생성
Github Actions에서 AWS에 액션을 취하기 위해서는,
권한이 있는 IAM 사용자로 인증을 거쳐야 합니다.
아래 3가지 정책이 ECS/ECR 관련해서 필요한 정책들이니 추가해주세요.

2. Github Secret 생성
Workflow에서 AWS인증을 위해서는
1번에서 만든 IAM 사용자의 ACCESS_KEY와 SECRET_ACCESS_KEY가 필요합니다.
...
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{secrets.AWS_ACCESS_KEY}}
aws-secret-access-key: ${{secrets.AWS_SECRET_ACCESS_KEY}}
aws-region: us-west-2
mask-aws-account-id: no
...
Workflow는 노출되는 코드이기에 Github의 Secret에 정의해서 사용합니다.
repo > Settings > Security > Secret and Variables > Actions

3. Github Actions Workflow 작성
이제 본격적으로 Workflow를 작성해보겠습니다-
env 선언
하위에 중복적으로 사용될 환경변수를 선언합니다.
name: Backend CD Dev
on:
push:
branches:
- main
workflow_dispatch:
concurrency:
group: backend-cd-dev
cancel-in-progress: true
jobs:
cd:
name: CD
runs-on: ubuntu-latest
env:
ECS_CLUSTER_NAME: <> # 배포하고자 하는 cluster 명
ECS_CONTAINER_NAME: <> # ecs -> 태스크정의 내의 컨테이너 이름
ECS_SERVICE_NAME: <> # ecs에서 사용하는 서비스명
TASK_DEFINITION_NAME: <> # ecs -> 태스크 정의 명
...
AWS 인증
앞서 추가한 secret 키를 아래와 같이 선언하고,
작업한 aws의 region을 적어줍니다.
여기서 mask-aws-account-id는 로그에 account id 노출 여부를 나타냅니다.
다만 저는 디버깅 단계라 no로 지정했고, 프로덕션 단계에서는 true 설정하는 것이 보안상 안전하다고 합니다-
...
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{secrets.AWS_ACCESS_KEY}}
aws-secret-access-key: ${{secrets.AWS_SECRET_ACCESS_KEY}}
aws-region: us-west-2
mask-aws-account-id: no // 디버깅용
...
ECR Push
이어서는 ECR에 로그인해주고,
ECR에 만들어뒀던 레포에 연결합니다.
Docker의 push 액션을 사용해
repo:tag 해시코드(version)의 이미지를 push 해줍니다-
...
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Set tag
id: tag
run: |
TAG=$(echo ${{ github.sha }} | cut -c1-8)
echo TAG=$TAG
echo "tag=$TAG" >> $GITHUB_OUTPUT
- name: Set image.repository
id: image
run: |
echo "repository=${{ steps.login-ecr.outputs.registry }}/llm-economy/backend" >> $GITHUB_OUTPUT
- name: Build and push image to Amazon ECR
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.image.outputs.repository }}:${{ steps.tag.outputs.tag }}
cache-from: type=gha
cache-to: type=gha,mode=max
...
TaskDefinition 다운로드
이제 ECS에 사용할 TaskDefinition을 AWS에서 가져와야합니다.
AWS를 조회해서 선언한 TaskDefinition을 가져오고,
task-definition.json으로 저장합니다.
...
- name: Download Task Definition Template
run: |
aws ecs describe-task-definition \
--task-definition ${{ env.TASK_DEFINITION_NAME }} \
--query taskDefinition \
> task-definition.json
...
ECS 배포
앞서 다운받은 TaskDefinition과 container, image를 가지고 태스크를 정의합니다.
마지막으로, 서비스를 배포해주면 끝입니다-
여기서 wait-for-service-stability 옵션은
태스크가 실행된 이후에 안전상태까지 기다린다는 의미입니다.
...
- name: Render ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: task-definition.json
container-name: ${{ env.ECS_CONTAINER_NAME }}
image: ${{ steps.image.outputs.repository }}:${{ steps.tag.outputs.tag }}
- name: Deploy to Amazon ECS
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE_NAME }}
cluster: ${{ env.ECS_CLUSTER_NAME }}
wait-for-service-stability: true
Workflow 전체 코드
name: Backend CD Dev
on:
push:
branches:
- main
workflow_dispatch:
concurrency:
group: backend-cd-dev
cancel-in-progress: true
jobs:
cd:
name: CD
runs-on: ubuntu-latest
env:
ECS_CLUSTER_NAME: <> # 배포하고자 하는 cluster 명
ECS_CONTAINER_NAME: <> # ecs -> 태스크정의 내의 컨테이너 이름
ECS_SERVICE_NAME: <> # ecs에서 사용하는 서비스명
TASK_DEFINITION_NAME: <> # ecs -> 태스크 정의 명
outputs:
imageRepository: ${{ steps.image.outputs.repository }}
imageTag: ${{ steps.tag.outputs.tag }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{secrets.AWS_ACCESS_KEY}}
aws-secret-access-key: ${{secrets.AWS_SECRET_ACCESS_KEY}}
aws-region: us-west-2
mask-aws-account-id: no
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Set tag
id: tag
run: |
TAG=$(echo ${{ github.sha }} | cut -c1-8)
echo TAG=$TAG
echo "tag=$TAG" >> $GITHUB_OUTPUT
- name: Set image.repository
id: image
run: |
echo "repository=${{ steps.login-ecr.outputs.registry }}/llm-economy/backend" >> $GITHUB_OUTPUT
- name: Build and push image to Amazon ECR
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.image.outputs.repository }}:${{ steps.tag.outputs.tag }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Download Task Definition Template
run: |
aws ecs describe-task-definition \
--task-definition ${{ env.TASK_DEFINITION_NAME }} \
--query taskDefinition \
> task-definition.json
- name: Render ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: task-definition.json
container-name: ${{ env.ECS_CONTAINER_NAME }}
image: ${{ steps.image.outputs.repository }}:${{ steps.tag.outputs.tag }}
- name: Deploy to Amazon ECS
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE_NAME }}
cluster: ${{ env.ECS_CLUSTER_NAME }}
wait-for-service-stability: true
해당 Workflow로 실행 완료한 화면입니다-

간단 회고
이번엔 Actions 입장에서 AWS를 다루는 과정을 살펴봤는데
작업하던 과정을 그대로 Action이라는 형식으로 옮기는 느낌이었어요-
크게 어려운 점은 없었고,
다음 포스팅에서는 n8n 배포로 돌아오겠습니다!
반응형
'Programming > Project' 카테고리의 다른 글
| [LLM 경제 뉴스 요약 서비스] # 06. React/Next js로 프론트엔드 구축 with 모노레포 (0) | 2026.01.27 |
|---|---|
| [LLM 경제 뉴스 요약 서비스] # 05. N8N 배포 (ECR, ECS) (0) | 2026.01.19 |
| [LLM 경제 뉴스 요약 서비스] # 03. FastAPI 서버 배포 (ECR, ECS) (0) | 2026.01.07 |
| [LLM 경제 뉴스 요약 서비스] # 02. FastAPI + PostgreSQL로 데이터 적재 REST API 구축 (0) | 2026.01.03 |
| [LLM 경제 뉴스 요약 서비스] # 01. n8n 워크플로우 구축 (n8n 사용법) (0) | 2025.12.18 |