본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 28. · 66 Views
AWS 배포 자동화 완벽 가이드
GitHub Actions를 활용하여 AWS 서비스에 자동으로 배포하는 방법을 알아봅니다. S3, EC2, ECS, Lambda, CloudFront까지 실무에서 가장 많이 사용하는 배포 시나리오를 다룹니다.
목차
1. AWS 자격 증명 설정
김개발 씨는 드디어 첫 프로젝트의 배포를 맡게 되었습니다. 로컬에서는 잘 돌아가는 코드인데, 이걸 어떻게 AWS에 올려야 할지 막막했습니다.
선배 박시니어 씨가 다가와 말했습니다. "자동 배포 해본 적 있어요?
먼저 AWS 자격 증명부터 설정해야 해요."
AWS 자격 증명 설정은 GitHub Actions가 여러분의 AWS 계정에 접근할 수 있도록 허가증을 발급하는 과정입니다. 마치 회사 건물에 들어가려면 사원증이 필요한 것처럼, GitHub Actions도 AWS에 접근하려면 적절한 자격 증명이 필요합니다.
이 설정을 제대로 해두면 안전하게 자동 배포를 수행할 수 있습니다.
다음 코드를 살펴봅시다.
name: AWS 배포 워크플로우
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
# AWS 자격 증명 구성
- name: Configure AWS Credentials
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: ap-northeast-2
# 자격 증명 확인
- name: Verify credentials
run: aws sts get-caller-identity
김개발 씨는 입사 3개월 차 주니어 개발자입니다. 오늘 팀장님께서 "이번 스프린트부터는 자동 배포를 적용해보자"라고 말씀하셨습니다.
자동 배포라니, 뭔가 멋있어 보이지만 어디서부터 시작해야 할지 막막했습니다. 선배 개발자 박시니어 씨가 김개발 씨 옆으로 다가왔습니다.
"자동 배포의 첫 단계는 AWS 자격 증명 설정이에요. 이게 없으면 GitHub Actions가 AWS에 접근조차 못해요." 그렇다면 AWS 자격 증명이란 정확히 무엇일까요?
쉽게 비유하자면, AWS 자격 증명은 마치 회사 사원증과 같습니다. 여러분이 회사 건물에 들어가려면 사원증을 찍어야 하듯이, GitHub Actions도 AWS라는 건물에 들어가려면 사원증이 필요합니다.
이 사원증이 바로 Access Key ID와 Secret Access Key입니다. AWS 콘솔에서 IAM 사용자를 생성하면 이 두 가지 키를 발급받을 수 있습니다.
하지만 여기서 중요한 점이 있습니다. 이 키를 절대로 코드에 직접 작성하면 안 됩니다.
마치 사원증 비밀번호를 벽에 붙여놓는 것처럼 위험한 행동입니다. 그래서 GitHub에서는 Secrets라는 기능을 제공합니다.
Repository 설정에서 Secrets에 저장한 값은 암호화되어 안전하게 보관됩니다. 워크플로우 파일에서는 ${{ secrets.AWS_ACCESS_KEY_ID }} 형태로 참조만 하면 됩니다.
위의 코드를 한 줄씩 살펴보겠습니다. 먼저 aws-actions/configure-aws-credentials@v4 액션을 사용합니다.
이 액션은 AWS에서 공식적으로 제공하는 것으로, 자격 증명 설정을 아주 간편하게 해줍니다. aws-access-key-id와 aws-secret-access-key에 Secrets에서 가져온 값을 넣어줍니다.
aws-region은 사용할 AWS 리전을 지정합니다. 한국에서 서비스한다면 보통 ap-northeast-2(서울 리전)를 사용합니다.
마지막 단계에서 aws sts get-caller-identity 명령어를 실행합니다. 이 명령어는 현재 설정된 자격 증명이 누구인지 확인하는 것입니다.
성공적으로 실행되면 자격 증명이 제대로 설정된 것입니다. 실제 현업에서는 더 안전한 방법으로 **OIDC(OpenID Connect)**를 사용하기도 합니다.
Access Key 대신 임시 자격 증명을 발급받는 방식인데, 보안이 더 강화됩니다. 하지만 초기 설정이 조금 복잡하므로, 처음에는 Access Key 방식으로 시작해도 괜찮습니다.
주의할 점이 있습니다. IAM 사용자를 생성할 때 최소 권한 원칙을 지켜야 합니다.
배포에 필요한 권한만 부여하세요. 만약 S3에만 배포한다면 S3 관련 권한만 주면 됩니다.
AdministratorAccess 같은 과도한 권한은 보안 사고의 원인이 됩니다. 박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다.
"아, 그래서 Secrets에 저장하는 거군요!" 이제 AWS 자격 증명 설정의 기초를 이해했으니, 본격적인 배포 자동화를 시작할 준비가 되었습니다.
실전 팁
💡 - IAM 사용자에게는 배포에 필요한 최소한의 권한만 부여하세요
- Access Key는 정기적으로 교체하고, 사용하지 않는 키는 비활성화하세요
- 가능하다면 OIDC 방식으로 전환하여 보안을 강화하세요
2. S3 정적 사이트 배포
김개발 씨가 React로 만든 첫 번째 프로젝트가 완성되었습니다. 이제 이 웹사이트를 세상에 공개해야 하는데, 서버 비용이 걱정되었습니다.
박시니어 씨가 웃으며 말했습니다. "정적 사이트는 S3에 올리면 돼요.
거의 공짜나 다름없어요."
S3 정적 사이트 배포는 HTML, CSS, JavaScript로 구성된 웹사이트를 AWS S3 버킷에 업로드하여 호스팅하는 방법입니다. 마치 파일을 클라우드 저장소에 올려두면 누구나 접근할 수 있는 것처럼, S3에 올린 웹 파일들도 전 세계 어디서든 접근할 수 있게 됩니다.
서버 관리 없이 저렴한 비용으로 웹사이트를 운영할 수 있는 장점이 있습니다.
다음 코드를 살펴봅시다.
name: S3 정적 사이트 배포
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install and Build
run: |
npm ci
npm run build
- name: Configure AWS Credentials
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: ap-northeast-2
# S3에 빌드 결과물 동기화
- name: Deploy to S3
run: aws s3 sync ./dist s3://${{ secrets.S3_BUCKET_NAME }} --delete
김개발 씨는 열심히 만든 포트폴리오 웹사이트를 세상에 공개하고 싶었습니다. 하지만 서버를 직접 운영하자니 비용도 부담되고, 관리도 어려울 것 같았습니다.
그때 박시니어 씨가 S3를 추천해주었습니다. **S3(Simple Storage Service)**는 AWS의 객체 스토리지 서비스입니다.
쉽게 말해 클라우드에 있는 거대한 USB 메모리라고 생각하면 됩니다. 그런데 이 USB 메모리에 특별한 기능이 있습니다.
바로 정적 웹사이트 호스팅 기능입니다. 정적 웹사이트란 무엇일까요?
React, Vue, Next.js 같은 프레임워크로 만든 SPA(Single Page Application)를 빌드하면 HTML, CSS, JavaScript 파일이 생성됩니다. 이런 파일들은 서버 로직 없이 브라우저에서 바로 실행됩니다.
이것이 바로 정적 웹사이트입니다. S3에 이 파일들을 올려두면, AWS가 알아서 전 세계 어디서든 접근할 수 있게 해줍니다.
마치 공용 드라이브에 파일을 올려두면 링크만 있으면 누구나 다운로드할 수 있는 것과 같습니다. 위의 워크플로우를 살펴보겠습니다.
먼저 actions/checkout@v4로 코드를 가져오고, Node.js 환경을 설정합니다. 그 다음 npm ci와 npm run build로 프로젝트를 빌드합니다.
핵심은 마지막 단계입니다. aws s3 sync 명령어는 로컬의 ./dist 폴더와 S3 버킷을 동기화합니다.
마치 Dropbox나 Google Drive처럼 폴더 내용을 그대로 복사하는 것입니다. --delete 옵션은 S3에는 있지만 로컬에는 없는 파일을 삭제합니다.
이렇게 하면 항상 최신 상태를 유지할 수 있습니다. S3 버킷을 정적 웹사이트로 사용하려면 AWS 콘솔에서 몇 가지 설정이 필요합니다.
버킷의 정적 웹사이트 호스팅을 활성화하고, 퍼블릭 액세스를 허용해야 합니다. 또한 버킷 정책에서 GetObject 권한을 열어줘야 합니다.
실무에서는 S3 단독으로 사용하기보다 CloudFront와 함께 사용하는 경우가 많습니다. CloudFront는 CDN 서비스로, 전 세계에 캐시 서버를 두어 더 빠른 응답 속도를 제공합니다.
또한 HTTPS도 쉽게 설정할 수 있습니다. 주의할 점도 있습니다.
S3 버킷 이름은 전 세계적으로 고유해야 합니다. 또한 정적 웹사이트 URL은 버킷이름.s3-website.리전.amazonaws.com 형태로 길고 복잡합니다.
실제 서비스에서는 Route 53으로 도메인을 연결하는 것이 좋습니다. 김개발 씨는 이 워크플로우를 적용한 뒤, main 브랜치에 푸시할 때마다 자동으로 웹사이트가 업데이트되는 것을 보고 감탄했습니다.
"이게 바로 CI/CD의 힘이군요!"
실전 팁
💡 - S3 버킷 정책에서 퍼블릭 읽기 권한을 설정해야 웹사이트에 접근할 수 있습니다
- SPA의 경우 에러 문서도 index.html로 설정하면 클라이언트 라우팅이 정상 작동합니다
- 프로덕션 환경에서는 반드시 CloudFront와 함께 사용하세요
3. EC2 SSH 배포
김개발 씨의 팀에서는 Node.js 백엔드 서버를 운영하고 있었습니다. 매번 배포할 때마다 SSH로 접속해서 git pull 하고, npm install 하고, pm2 restart 하는 게 너무 번거로웠습니다.
"이것도 자동화할 수 있을까요?" 김개발 씨가 물었습니다.
EC2 SSH 배포는 GitHub Actions에서 SSH를 통해 원격 EC2 서버에 접속하여 배포 명령을 실행하는 방식입니다. 마치 원격 데스크톱으로 다른 컴퓨터를 조작하는 것처럼, GitHub Actions가 여러분의 서버에 접속하여 필요한 명령어를 대신 실행해줍니다.
전통적이지만 여전히 많이 사용되는 배포 방식입니다.
다음 코드를 살펴봅시다.
name: EC2 SSH 배포
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy to EC2
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
port: 22
script: |
cd /home/ubuntu/my-app
git fetch origin main
git reset --hard origin/main
npm ci --production
pm2 reload ecosystem.config.js --env production
김개발 씨 팀의 백엔드 서버는 EC2 인스턴스에서 돌아가고 있었습니다. 매번 배포할 때마다 터미널을 열고, SSH 접속하고, 여러 명령어를 입력하는 것은 정말 지루한 작업이었습니다.
게다가 실수로 잘못된 명령어를 입력하면 서비스가 중단될 수도 있었습니다. **SSH(Secure Shell)**는 원격 서버에 안전하게 접속하는 프로토콜입니다.
평소에는 터미널에서 ssh ubuntu@서버주소 명령어로 접속했을 것입니다. GitHub Actions에서도 똑같은 방식으로 서버에 접속할 수 있습니다.
appleboy/ssh-action은 SSH 접속을 쉽게 해주는 액션입니다. 마치 로봇 비서에게 "이 서버에 접속해서 이 명령어들을 실행해줘"라고 시키는 것과 같습니다.
로봇 비서는 정확하게, 빠르게, 실수 없이 명령을 수행합니다. 위의 코드에서 중요한 부분을 살펴보겠습니다.
host는 EC2 인스턴스의 퍼블릭 IP 또는 도메인입니다. username은 보통 ubuntu 또는 ec2-user입니다.
key는 EC2 인스턴스에 접속할 때 사용하는 프라이빗 키입니다. 여기서 잠깐, 프라이빗 키를 GitHub Secrets에 어떻게 저장할까요?
.pem 파일의 내용 전체를 복사해서 붙여넣으면 됩니다. -----BEGIN RSA PRIVATE KEY-----부터 -----END RSA PRIVATE KEY-----까지 전부 포함해야 합니다.
script 부분이 실제로 서버에서 실행될 명령어들입니다. 하나씩 살펴보겠습니다.
cd /home/ubuntu/my-app으로 프로젝트 디렉토리로 이동합니다. git fetch origin main으로 최신 코드를 가져오고, git reset --hard origin/main으로 로컬을 최신 상태로 맞춥니다.
npm ci --production은 npm install보다 빠르고 일관된 설치를 보장합니다. --production 플래그는 devDependencies를 제외하여 설치 시간을 단축합니다.
마지막으로 pm2 reload로 무중단 배포를 수행합니다. restart 대신 reload를 사용하면 서비스 중단 없이 새 버전이 적용됩니다.
실무에서 주의할 점이 있습니다. EC2 보안 그룹에서 GitHub Actions의 IP를 허용해야 합니다.
하지만 GitHub Actions의 IP는 고정되어 있지 않습니다. 따라서 22번 포트를 완전히 열어두거나, 배포 시작 시 동적으로 IP를 허용하고 배포 후 다시 제거하는 방식을 사용합니다.
더 안전한 방법도 있습니다. AWS Systems Manager Session Manager를 사용하면 SSH 포트를 열지 않고도 서버에 접속할 수 있습니다.
보안이 중요한 프로덕션 환경에서는 이 방식을 고려해보세요. 김개발 씨는 이 워크플로우를 설정한 뒤, 더 이상 수동 배포를 하지 않아도 되었습니다.
코드를 푸시하면 몇 분 뒤 자동으로 서버에 반영되었습니다. "시간이 이렇게 절약될 줄이야!"
실전 팁
💡 - SSH 키는 Secrets에 저장할 때 줄바꿈이 유지되도록 주의하세요
- pm2 reload를 사용하면 무중단 배포가 가능합니다
- 보안 그룹 설정 시 GitHub Actions IP 범위를 고려하세요
4. ECS 서비스 업데이트
회사가 성장하면서 트래픽이 늘어났습니다. 단일 EC2로는 감당이 안 되어 컨테이너 기반으로 전환하기로 했습니다.
김개발 씨는 Docker는 어느 정도 알지만, ECS 배포는 처음이었습니다. "ECS 배포 자동화, 어렵지 않아요?" 박시니어 씨가 말했습니다.
"오히려 더 깔끔해요."
ECS 서비스 업데이트는 Docker 컨테이너화된 애플리케이션을 AWS ECS(Elastic Container Service)에 배포하는 방식입니다. 마치 컨테이너 선박이 규격화된 컨테이너를 효율적으로 운반하듯이, ECS는 Docker 컨테이너를 효율적으로 관리하고 실행합니다.
스케일링과 롤링 업데이트가 자동으로 처리되어 안정적인 배포가 가능합니다.
다음 코드를 살펴봅시다.
name: ECS 배포
on:
push:
branches: [main]
env:
AWS_REGION: ap-northeast-2
ECR_REPOSITORY: my-app
ECS_CLUSTER: my-cluster
ECS_SERVICE: my-service
CONTAINER_NAME: my-app-container
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS Credentials
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: ${{ env.AWS_REGION }}
# ECR 로그인
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
# Docker 이미지 빌드 및 푸시
- name: Build and push Docker image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
# ECS 서비스 업데이트
- name: Update ECS service
run: |
aws ecs update-service \
--cluster $ECS_CLUSTER \
--service $ECS_SERVICE \
--force-new-deployment
김개발 씨 팀의 서비스가 성장하면서 단일 서버로는 트래픽을 감당하기 어려워졌습니다. 오토 스케일링이 필요했고, 팀은 컨테이너 기반 인프라로 전환하기로 결정했습니다.
**ECS(Elastic Container Service)**는 AWS에서 제공하는 컨테이너 오케스트레이션 서비스입니다. 쉽게 말해 Docker 컨테이너들의 지휘자라고 생각하면 됩니다.
오케스트라에서 지휘자가 각 악기 파트를 조율하듯이, ECS는 여러 컨테이너의 실행, 중지, 스케일링을 조율합니다. ECS 배포 과정은 크게 세 단계로 나뉩니다.
첫째, Docker 이미지를 빌드합니다. 둘째, 이미지를 **ECR(Elastic Container Registry)**에 푸시합니다.
셋째, ECS 서비스를 업데이트하여 새 이미지를 사용하도록 합니다. ECR은 AWS에서 제공하는 Docker 이미지 저장소입니다.
Docker Hub와 비슷하지만, AWS 내에서 사용할 때 더 빠르고 보안이 강화됩니다. 마치 회사 전용 창고에 물건을 보관하는 것과 같습니다.
위의 워크플로우를 살펴보겠습니다. 먼저 amazon-ecr-login 액션으로 ECR에 로그인합니다.
이 단계에서 registry 주소가 출력되어 다음 단계에서 사용됩니다. docker build 명령어로 이미지를 빌드합니다.
태그로 github.sha를 사용하는데, 이것은 커밋의 고유 해시값입니다. 이렇게 하면 어떤 커밋으로 빌드된 이미지인지 추적할 수 있습니다.
docker push로 빌드된 이미지를 ECR에 업로드합니다. 마지막으로 aws ecs update-service 명령어로 서비스를 업데이트합니다.
--force-new-deployment 옵션은 새로운 배포를 강제로 시작합니다. ECS는 자동으로 롤링 업데이트를 수행합니다.
기존 컨테이너를 하나씩 새 버전으로 교체하므로 서비스 중단이 없습니다. 더 정교한 배포를 원한다면 **태스크 정의(Task Definition)**를 직접 업데이트하는 방식을 사용할 수 있습니다.
새 이미지 태그로 태스크 정의를 수정하고, 그 정의를 서비스에 적용하는 것입니다. AWS에서 제공하는 amazon-ecs-deploy-task-definition 액션이 이 과정을 도와줍니다.
주의할 점도 있습니다. ECS 배포는 시간이 좀 걸립니다.
새 태스크가 시작되고, 헬스 체크를 통과하고, 로드 밸런서에 등록되기까지 몇 분이 소요됩니다. 워크플로우가 성공했다고 해서 바로 배포가 완료된 것은 아닙니다.
김개발 씨는 ECS 배포를 설정한 뒤, 트래픽이 늘어나도 자동으로 컨테이너가 추가되는 것을 보고 감탄했습니다. "이제 새벽에 서버 다운 알림 받을 일이 없겠네요!"
실전 팁
💡 - 이미지 태그로 커밋 해시를 사용하면 배포 이력 추적이 쉬워집니다
- 롤링 업데이트 설정을 통해 배포 중 최소 가용 태스크 수를 조절할 수 있습니다
- 배포 후 ECS 콘솔에서 서비스 이벤트를 확인하여 배포 상태를 모니터링하세요
5. Lambda 함수 배포
팀에서 이미지 리사이징 기능이 필요했습니다. 24시간 서버를 돌리기엔 비효율적이라 Lambda로 구현하기로 했습니다.
김개발 씨는 Lambda 콘솔에서 코드를 직접 수정하다가 실수로 프로덕션 코드를 망가뜨린 적이 있었습니다. "이제는 GitHub으로 관리해야겠어요."
Lambda 함수 배포는 서버리스 함수를 GitHub Actions를 통해 자동으로 배포하는 방식입니다. 마치 자판기가 필요할 때만 음료를 제공하듯이, Lambda는 요청이 있을 때만 실행되어 비용을 절감합니다.
코드를 zip으로 압축하여 업로드하거나 컨테이너 이미지를 사용할 수 있습니다.
다음 코드를 살펴봅시다.
name: Lambda 배포
on:
push:
branches: [main]
paths:
- 'lambda/**'
jobs:
deploy:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./lambda
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci --production
- name: Create deployment package
run: zip -r ../function.zip .
- name: Configure AWS Credentials
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: ap-northeast-2
# Lambda 함수 코드 업데이트
- name: Deploy to Lambda
run: |
aws lambda update-function-code \
--function-name ${{ secrets.LAMBDA_FUNCTION_NAME }} \
--zip-file fileb://../function.zip
김개발 씨는 이미지 업로드 시 자동으로 썸네일을 생성하는 기능을 만들어야 했습니다. 이 작업은 간헐적으로 발생하므로 24시간 서버를 돌리는 것은 비효율적이었습니다.
Lambda는 이런 상황에 딱 맞는 솔루션이었습니다. Lambda는 AWS의 서버리스 컴퓨팅 서비스입니다.
서버리스라고 해서 서버가 없는 것은 아닙니다. AWS가 서버를 알아서 관리해주고, 여러분은 코드만 신경 쓰면 된다는 뜻입니다.
마치 택시와 같습니다. 목적지만 말하면 되지, 차량 정비나 주유는 신경 쓸 필요가 없습니다.
Lambda의 가장 큰 장점은 사용한 만큼만 비용을 지불한다는 것입니다. 함수가 실행된 시간에 대해서만 과금됩니다.
트래픽이 없으면 비용도 없습니다. 스타트업이나 사이드 프로젝트에 특히 유용합니다.
위의 워크플로우를 살펴보겠습니다. 먼저 paths 필터에 주목하세요.
lambda/** 경로의 파일이 변경될 때만 이 워크플로우가 실행됩니다. 불필요한 배포를 방지하는 좋은 방법입니다.
working-directory를 ./lambda로 설정하여 모든 명령이 해당 디렉토리에서 실행되도록 합니다. npm ci --production으로 프로덕션 의존성만 설치합니다.
devDependencies는 Lambda에서 필요 없으므로 제외합니다. zip -r ../function.zip . 명령으로 현재 디렉토리의 모든 파일을 압축합니다.
Lambda는 이 zip 파일을 받아서 실행 환경을 구성합니다. 파일 크기가 50MB를 초과하면 S3를 통해 업로드해야 합니다.
aws lambda update-function-code 명령이 실제 배포를 수행합니다. --zip-file fileb:// 접두사는 로컬 파일을 바이너리로 읽어 업로드하겠다는 의미입니다.
이 명령이 성공하면 즉시 새 코드가 적용됩니다. Lambda 함수의 설정(메모리, 타임아웃, 환경 변수 등)도 업데이트하고 싶다면 update-function-configuration 명령을 추가로 사용할 수 있습니다.
하지만 인프라 설정은 Terraform이나 AWS SAM 같은 IaC 도구로 관리하는 것이 더 좋습니다. 주의할 점이 있습니다.
Lambda 함수가 VPC 내에 있다면 배포 후 활성화까지 시간이 걸릴 수 있습니다. 또한 동시 배포가 발생하면 충돌이 생길 수 있으므로, concurrency 설정으로 동시 실행을 제한하는 것이 좋습니다.
김개발 씨는 Lambda 배포 자동화를 설정한 뒤, 더 이상 콘솔에서 직접 코드를 수정하지 않게 되었습니다. 모든 변경 사항이 Git에 기록되어 추적과 롤백이 쉬워졌습니다.
"이제야 제대로 된 개발 프로세스가 갖춰진 것 같아요!"
실전 팁
💡 - Lambda 패키지 크기를 줄이려면 불필요한 파일을 .zipignore나 스크립트로 제외하세요
- 레이어(Layer)를 활용하면 공통 의존성을 재사용할 수 있습니다
- 별칭(Alias)과 버전을 활용하면 롤백과 트래픽 분산이 쉬워집니다
6. CloudFront 캐시 무효화
김개발 씨가 긴급 버그 수정을 배포했는데, 사용자들이 여전히 이전 버전을 보고 있다고 했습니다. "분명히 S3에는 새 파일이 올라갔는데..." 박시니어 씨가 말했습니다.
"CloudFront 캐시 때문이에요. 무효화를 해줘야 해요."
CloudFront 캐시 무효화는 CDN에 캐시된 이전 버전의 파일을 강제로 갱신하는 작업입니다. 마치 도서관에서 오래된 책을 새 책으로 교체하는 것처럼, 엣지 서버에 저장된 캐시를 무효화하여 최신 콘텐츠가 제공되도록 합니다.
배포 직후 사용자에게 최신 버전을 보여주기 위해 필수적인 단계입니다.
다음 코드를 살펴봅시다.
name: S3 + CloudFront 배포
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup and Build
run: |
npm ci
npm run build
- name: Configure AWS Credentials
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: ap-northeast-2
- name: Deploy to S3
run: aws s3 sync ./dist s3://${{ secrets.S3_BUCKET_NAME }} --delete
# CloudFront 캐시 무효화
- name: Invalidate CloudFront cache
run: |
aws cloudfront create-invalidation \
--distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \
--paths "/*"
김개발 씨는 긴급하게 버그를 수정하고 배포했습니다. S3에 새 파일이 올라간 것도 확인했습니다.
그런데 고객센터에서 전화가 왔습니다. "아직도 버그가 그대로예요!" 무엇이 문제였을까요?
범인은 바로 CloudFront 캐시였습니다. CloudFront는 AWS의 CDN(Content Delivery Network) 서비스입니다.
전 세계 수백 개의 엣지 로케이션에 콘텐츠를 캐시하여 사용자에게 빠르게 제공합니다. 문제는 이 캐시가 한번 저장되면 설정된 TTL(Time To Live) 동안 유지된다는 것입니다.
비유하자면, CloudFront는 전 세계에 퍼져 있는 편의점 체인과 같습니다. 본사(S3)에서 새 상품(파일)을 출시해도, 각 편의점(엣지 서버)에 있는 기존 재고(캐시)가 소진되기 전까지는 새 상품이 진열되지 않습니다.
캐시 무효화는 "각 편의점에 있는 기존 재고를 폐기하고 새 상품을 가져오라"고 지시하는 것입니다. aws cloudfront create-invalidation 명령어가 이 작업을 수행합니다.
--distribution-id는 CloudFront 배포의 고유 ID입니다. AWS 콘솔의 CloudFront 페이지에서 확인할 수 있습니다.
--paths는 무효화할 경로를 지정합니다. "/*"는 모든 파일을 무효화하겠다는 의미입니다.
간편하지만, 무효화 요청 1,000건까지는 무료이고 그 이후부터 비용이 발생합니다. 모든 파일을 무효화하면 1건으로 계산되지만, 개별 경로를 지정하면 각각 1건씩 계산됩니다.
무효화는 즉각적이지 않습니다. 전 세계 엣지 서버에 전파되는 데 보통 몇 분에서 최대 15분 정도 걸립니다.
긴급한 상황이라면 이 시간이 길게 느껴질 수 있습니다. 더 효율적인 방법도 있습니다.
빌드 시 파일명에 해시값을 포함시키는 것입니다. 예를 들어 main.js 대신 main.a1b2c3d4.js처럼 생성합니다.
파일 내용이 바뀌면 해시도 바뀌므로, 브라우저는 새 파일을 요청하게 됩니다. 이렇게 하면 캐시 무효화 없이도 최신 버전이 제공됩니다.
하지만 index.html은 해시를 붙일 수 없습니다. 사용자가 직접 접근하는 진입점이기 때문입니다.
따라서 index.html만 짧은 TTL을 설정하거나, 배포 시 무효화하는 전략을 사용합니다. 실무에서는 보통 두 가지를 조합합니다.
정적 자산(JS, CSS, 이미지)은 해시 파일명을 사용하고 긴 캐시 TTL을 설정합니다. HTML 파일은 짧은 TTL을 설정하고 배포 시 무효화합니다.
이렇게 하면 캐시의 성능 이점을 누리면서도 최신 버전을 빠르게 제공할 수 있습니다. 김개발 씨는 배포 워크플로우에 캐시 무효화 단계를 추가한 뒤, 더 이상 "캐시 때문에 안 보여요" 문제를 겪지 않게 되었습니다.
"이제야 배포가 배포다워졌네요!"
실전 팁
💡 - 모든 파일 무효화보다는 변경된 파일만 무효화하면 비용을 절감할 수 있습니다
- 정적 자산에는 파일명 해싱을 적용하여 캐시 효율을 높이세요
- 무효화 완료까지 시간이 걸리므로 긴급 수정 시 이를 고려하세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
UX와 협업 패턴 완벽 가이드
AI 에이전트와 사용자 간의 효과적인 협업을 위한 UX 패턴을 다룹니다. 프롬프트 핸드오프부터 인터럽트 처리까지, 현대적인 에이전트 시스템 설계의 핵심을 배웁니다.
빌드와 배포 자동화 완벽 가이드
Flutter 앱 개발에서 GitHub Actions를 활용한 CI/CD 파이프라인 구축부터 앱 스토어 자동 배포까지, 초급 개발자도 쉽게 따라할 수 있는 빌드 자동화의 모든 것을 다룹니다.
실전 인프라 자동화 프로젝트 완벽 가이드
Ansible을 활용하여 멀티 티어 웹 애플리케이션 인프라를 자동으로 구축하는 실전 프로젝트입니다. 웹 서버, 데이터베이스, 로드 밸런서를 코드로 관리하며 반복 가능한 인프라 배포를 경험합니다.
CI/CD 파이프라인 통합 완벽 가이드
Jenkins, GitLab CI와 Ansible을 연동하여 자동화된 배포 파이프라인을 구축하는 방법을 다룹니다. Ansible Tower/AWX의 활용법과 실무에서 바로 적용 가능한 워크플로우 설계 패턴을 단계별로 설명합니다.
Ansible 성능 최적화와 디버깅 완벽 가이드
Ansible 플레이북의 실행 속도를 극적으로 향상시키고, 문제 발생 시 효과적으로 디버깅하는 방법을 다룹니다. 병렬 실행, 캐싱, SSH 최적화부터 디버그 모드와 프로파일링까지 실무에서 바로 적용할 수 있는 기법들을 소개합니다.