
이번 시간에는 로컬 클러스터에서의 시험 배포를 마치고 실제 AWS 클라우드 환경에 프로젝트를 배포하는 과정을 진행했습니다. AWS 활용 계획 수립부터 배포 환경 설정, 배포 도구 구성, 그리고 최종 배포 환경 테스트까지 전체 흐름을 정리했습니다.
AWS(Amazon Web Services)는 전 세계에서 가장 널리 사용되는 클라우드 플랫폼입니다. 다양한 서비스를 제공하고 레퍼런스가 풍부해 처음 클라우드 배포를 경험하기에 적합합니다.
| AWS 서비스 | 역할 |
|---|---|
| EKS (Elastic Kubernetes Service) | 쿠버네티스 클러스터를 관리형으로 운영합니다 |
| ECR (Elastic Container Registry) | 도커 이미지를 저장하는 프라이빗 레지스트리입니다 |
| RDS (Relational Database Service) | MySQL 데이터베이스를 관리형으로 운영합니다 |
| ALB (Application Load Balancer) | 트래픽을 여러 포드로 분산합니다 |
| Route 53 | 도메인 네임 서비스를 관리합니다 |
| IAM | 서비스 간 접근 권한을 관리합니다 |
사용자
↓ HTTPS 요청
Route 53 (도메인)
↓
ALB (로드 밸런서)
↓
EKS 클러스터
├── FE Pod (Nginx + React 빌드)
└── BE Pod (Node.js API 서버)
↓
RDS (MySQL)
AWS는 사용한 만큼 비용이 발생합니다. 개발·테스트 단계에서 비용을 최소화하기 위해 다음과 같은 전략을 세웠습니다.
로컬에서 빌드한 도커 이미지를 AWS ECR에 업로드합니다.
# AWS CLI 로그인
aws ecr get-login-password --region ap-northeast-2 | \
docker login --username AWS --password-stdin \
<계정ID>.dkr.ecr.ap-northeast-2.amazonaws.com
# ECR 레포지토리 생성
aws ecr create-repository --repository-name document-editor-backend
aws ecr create-repository --repository-name document-editor-frontend
# 이미지 태그 및 푸시
docker tag document-editor-backend:latest \
<계정ID>.dkr.ecr.ap-northeast-2.amazonaws.com/document-editor-backend:latest
docker push \
<계정ID>.dkr.ecr.ap-northeast-2.amazonaws.com/document-editor-backend:latest
eksctl 을 활용하면 EKS 클러스터를 간편하게 생성할 수 있습니다.
# eksctl로 클러스터 생성
eksctl create cluster \
--name document-editor \
--region ap-northeast-2 \
--nodegroup-name standard-workers \
--node-type t3.medium \
--nodes 2 \
--nodes-min 1 \
--nodes-max 3
# kubectl 컨텍스트 업데이트
aws eks update-kubeconfig --name document-editor --region ap-northeast-2
데이터베이스는 EKS 클러스터와 동일한 VPC 내에 RDS를 생성하여 네트워크 통신이 가능하도록 설정합니다.
# RDS MySQL 인스턴스 생성 (AWS 콘솔 또는 CLI)
aws rds create-db-instance \
--db-instance-identifier document-editor-db \
--db-instance-class db.t3.micro \
--engine mysql \
--master-username admin \
--master-user-password <비밀번호> \
--allocated-storage 20
AWS 리소스를 콘솔에서 직접 생성하는 대신 Terraform 으로 코드화하면 재현 가능하고 버전 관리가 가능한 인프라를 구성할 수 있습니다.
# main.tf
provider "aws" {
region = "ap-northeast-2"
}
# VPC 생성
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 3.0"
name = "document-editor-vpc"
cidr = "10.0.0.0/16"
azs = ["ap-northeast-2a", "ap-northeast-2c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
}
# Terraform 초기화 및 적용
terraform init
terraform plan # 변경 사항 미리 확인
terraform apply # 실제 리소스 생성
코드가 main 브랜치에 병합되면 자동으로 빌드·테스트·배포가 이루어지도록 파이프라인을 구성합니다.
# .github/workflows/deploy.yml
name: Deploy to AWS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: AWS 자격증명 설정
uses: aws-actions/configure-aws-credentials@v2
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: ECR 로그인
uses: aws-actions/amazon-ecr-login@v1
- name: 도커 이미지 빌드 및 푸시
run: |
docker build -t $ECR_REGISTRY/document-editor-backend:${{ github.sha }} ./backend
docker push $ECR_REGISTRY/document-editor-backend:${{ github.sha }}
- name: EKS에 배포
run: |
aws eks update-kubeconfig --name document-editor
kubectl set image deployment/backend \
backend=$ECR_REGISTRY/document-editor-backend:${{ github.sha }}
kubectl rollout status deployment/backend
AWS 환경에서의 민감한 정보는 쿠버네티스 Secret에 저장합니다.
kubectl create secret generic app-secret \
--from-literal=db-host=<RDS 엔드포인트> \
--from-literal=db-password=<비밀번호> \
--from-literal=jwt-secret=<JWT 시크릿>
# 포드 상태 확인
kubectl get pods -A
# 서비스 외부 IP 확인
kubectl get service -n ingress-nginx
# 로그 확인
kubectl logs -f deployment/backend
kubectl logs -f deployment/frontend
배포 환경에서 BE 서버가 정상 동작하는지 확인하기 위한 헬스 체크 엔드포인트를 추가합니다.
// BE 헬스 체크 라우트
app.get('/health', (req, res) => {
res.status(200).json({ status: 'ok', timestamp: new Date().toISOString() });
});
k8s 매니페스트에도 Liveness Probe 와 Readiness Probe 를 설정해 포드 이상 시 자동으로 재시작하도록 구성합니다.
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
로컬에서 작성한 E2E 테스트를 실제 배포 환경 URL로 변경하여 실행합니다.
# 배포 환경 URL로 E2E 테스트 실행
BASE_URL=https://document-editor.example.com pytest tests/e2e/
정상 동작을 확인한 뒤 실제 트래픽을 감당할 수 있는지 부하 테스트를 진행합니다.
# k6를 이용한 간단한 부하 테스트
k6 run --vus 50 --duration 30s load_test.js
// load_test.js
import http from 'k6/http';
import { check } from 'k6';
export default function () {
const res = http.get('https://document-editor.example.com/health');
check(res, { 'status is 200': (r) => r.status === 200 });
}