> ## Documentation Index
> Fetch the complete documentation index at: https://docs.casebender.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS에 배포하기

> Amazon Web Services(AWS)에 CaseBender 배포하기

## 개요

이 가이드는 사전 구축된 Docker 이미지를 사용하여 Amazon ECS(Elastic Container Service) 및 Fargate로 AWS에 CaseBender를 배포하는 과정을 안내합니다.

## 사전 요구 사항

1. [AWS 계정](https://aws.amazon.com/)
2. [AWS CLI](https://aws.amazon.com/cli/) 설치 및 구성
3. [Docker](https://docs.docker.com/get-docker/) 설치

## 1단계: 초기 설정

### AWS CLI 설치 및 구성

<CodeGroup>
  ```bash macOS theme={null}
  # Homebrew 사용
  brew install awscli

  # AWS CLI 구성

  aws configure

  # ECR용 Docker 구성

  aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $(aws sts get-caller-identity --query Account --output text).dkr.ecr.us-east-1.amazonaws.com

  ```

  ```bash Linux theme={null}
  # AWS CLI 설치
  curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
  unzip awscliv2.zip
  sudo ./aws/install

  # AWS CLI 구성
  aws configure

  # ECR용 Docker 구성
  aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $(aws sts get-caller-identity --query Account --output text).dkr.ecr.us-east-1.amazonaws.com
  ```

  ```powershell Windows theme={null}
  # AWS CLI MSI 설치 프로그램 다운로드 및 실행
  # https://awscli.amazonaws.com/AWSCLIV2.msi

  # AWS CLI 구성
  aws configure

  # ECR용 Docker 구성
  aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $(aws sts get-caller-identity --query Account --output text).dkr.ecr.us-east-1.amazonaws.com
  ```
</CodeGroup>

## 2단계: AWS 인프라 설정

### 스토리지용 S3 버킷 생성

```bash theme={null}
# S3 버킷 생성
aws s3 create-bucket \
  --bucket casebender-storage \
  --region us-east-1

# 버전 관리 활성화 (선택 사항)
aws s3api put-bucket-versioning \
  --bucket casebender-storage \
  --versioning-configuration Status=Enabled

# S3 접근용 IAM 사용자 생성
aws iam create-user --user-name casebender-storage-user

# 정책 생성 및 연결
aws iam create-policy \
  --policy-name casebender-storage-policy \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::casebender-storage",
                "arn:aws:s3:::casebender-storage/*"
            ]
        }
    ]
}'

# 사용자에게 정책 연결
aws iam attach-user-policy \
  --user-name casebender-storage-user \
  --policy-arn arn:aws:iam::YOUR_ACCOUNT_ID:policy/casebender-storage-policy

# 액세스 키 생성
aws iam create-access-key --user-name casebender-storage-user
```

### VPC 생성

```bash theme={null}
# VPC 생성
aws ec2 create-vpc \
  --cidr-block 10.0.0.0/16 \
  --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=casebender-vpc}]'

# DNS 호스트 이름 활성화
aws ec2 modify-vpc-attribute \
  --vpc-id <vpc-id> \
  --enable-dns-hostnames
```

### 서브넷 생성

```bash theme={null}
# 퍼블릭 서브넷 생성
aws ec2 create-subnet \
  --vpc-id <vpc-id> \
  --cidr-block 10.0.1.0/24 \
  --availability-zone us-east-1a \
  --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=casebender-public-1a}]'

aws ec2 create-subnet \
  --vpc-id <vpc-id> \
  --cidr-block 10.0.2.0/24 \
  --availability-zone us-east-1b \
  --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=casebender-public-1b}]'
```

### RDS(PostgreSQL) 설정

```bash theme={null}
# DB 서브넷 그룹 생성
aws rds create-db-subnet-group \
  --db-subnet-group-name casebender-db-subnet \
  --db-subnet-group-description "Subnet group for CaseBender RDS" \
  --subnet-ids "<subnet-1-id>" "<subnet-2-id>"

# RDS 인스턴스 생성
aws rds create-db-instance \
  --db-instance-identifier casebender-db \
  --db-instance-class db.t3.medium \
  --engine postgres \
  --master-username superadmin \
  --master-user-password <your-secure-password> \
  --allocated-storage 20 \
  --db-subnet-group-name casebender-db-subnet
```

### ElastiCache(Redis) 설정

```bash theme={null}
# 캐시 서브넷 그룹 생성
aws elasticache create-cache-subnet-group \
  --cache-subnet-group-name casebender-cache-subnet \
  --cache-subnet-group-description "Subnet group for CaseBender Redis" \
  --subnet-ids "<subnet-1-id>" "<subnet-2-id>"

# Redis 클러스터 생성
aws elasticache create-cache-cluster \
  --cache-cluster-id casebender-redis \
  --engine redis \
  --cache-node-type cache.t3.micro \
  --num-cache-nodes 1 \
  --cache-subnet-group-name casebender-cache-subnet
```

## 3단계: ECR 리포지토리 생성

```bash theme={null}
# 각 서비스에 대한 리포지토리 생성
aws ecr create-repository --repository-name casebender/app
aws ecr create-repository --repository-name casebender/workflow-processor
aws ecr create-repository --repository-name casebender/misp-processor

# AWS 계정 ID 가져오기
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

# CaseBender 이미지 가져오기
docker pull casebender/casebender:latest
docker pull casebender/workflow-processor:latest
docker pull casebender/misp-processor:latest

# ECR용 이미지 태그 지정
docker tag casebender/casebender:latest ${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/casebender/app:latest
docker tag casebender/workflow-processor:latest ${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/casebender/workflow-processor:latest
docker tag casebender/misp-processor:latest ${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/casebender/misp-processor:latest

# ECR에 이미지 푸시
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/casebender/app:latest
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/casebender/workflow-processor:latest
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/casebender/misp-processor:latest
```

## 4단계: ECS 클러스터 생성

```bash theme={null}
# ECS 클러스터 생성
aws ecs create-cluster --cluster-name casebender-cluster

# 태스크 실행 역할 생성
aws iam create-role \
  --role-name ecsTaskExecutionRole \
  --assume-role-policy-document file://task-execution-assume-role.json

# 정책 연결
aws iam attach-role-policy \
  --role-name ecsTaskExecutionRole \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
```

## 5단계: 태스크 정의 생성

각 서비스에 대한 태스크 정의 JSON 파일 생성:

```json theme={null}
{
  "family": "casebender-app",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "1024",
  "memory": "2048",
  "executionRoleArn": "arn:aws:iam::<aws-account-id>:role/ecsTaskExecutionRole",
  "containerDefinitions": [
    {
      "name": "app",
      "image": "<aws-account-id>.dkr.ecr.us-east-1.amazonaws.com/casebender/app:latest",
      "portMappings": [
        {
          "containerPort": 3000,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "POSTGRES_PRISMA_URL",
          "value": "postgresql://superadmin:password@casebender-db.xxxxx.region.rds.amazonaws.com:5432/casebender"
        },
        {
          "name": "REDIS_URL",
          "value": "redis://casebender-redis.xxxxx.region.cache.amazonaws.com:6379"
        },
        {
          "name": "AWS_S3_BUCKET",
          "value": "casebender-storage"
        },
        {
          "name": "AWS_S3_REGION",
          "value": "us-east-1"
        }
      ],
      "secrets": [
        {
          "name": "AUTH_SECRET",
          "valueFrom": "arn:aws:secretsmanager:region:account:secret:auth-secret"
        },
        {
          "name": "AUTH_SALT",
          "valueFrom": "arn:aws:secretsmanager:region:account:secret:auth-salt"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/casebender",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "app"
        }
      }
    }
  ]
}
```

태스크 정의 등록:

```bash theme={null}
# 태스크 정의 등록
aws ecs register-task-definition --cli-input-json file://app-task-definition.json
aws ecs register-task-definition --cli-input-json file://workflow-processor-task-definition.json
aws ecs register-task-definition --cli-input-json file://misp-processor-task-definition.json
```

## 6단계: 애플리케이션 로드 밸런서 생성

```bash theme={null}
# ALB 생성
aws elbv2 create-load-balancer \
  --name casebender-alb \
  --subnets <subnet-1-id> <subnet-2-id> \
  --security-groups <security-group-id>

# 대상 그룹 생성
aws elbv2 create-target-group \
  --name casebender-tg \
  --protocol HTTP \
  --port 3000 \
  --vpc-id <vpc-id> \
  --target-type ip

# 리스너 생성
aws elbv2 create-listener \
  --load-balancer-arn <alb-arn> \
  --protocol HTTPS \
  --port 443 \
  --certificates CertificateArn=<certificate-arn> \
  --default-actions Type=forward,TargetGroupArn=<target-group-arn>
```

## 7단계: ECS 서비스 생성

```bash theme={null}
# 메인 앱용 서비스 생성
aws ecs create-service \
  --cluster casebender-cluster \
  --service-name casebender-app \
  --task-definition casebender-app \
  --desired-count 2 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[<subnet-1-id>,<subnet-2-id>],securityGroups=[<security-group-id>],assignPublicIp=ENABLED}" \
  --load-balancers "targetGroupArn=<target-group-arn>,containerName=app,containerPort=3000"

# 프로세서용 서비스 생성
aws ecs create-service \
  --cluster casebender-cluster \
  --service-name workflow-processor \
  --task-definition casebender-workflow-processor \
  --desired-count 1 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[<subnet-1-id>,<subnet-2-id>],securityGroups=[<security-group-id>],assignPublicIp=ENABLED}"

aws ecs create-service \
  --cluster casebender-cluster \
  --service-name misp-processor \
  --task-definition casebender-misp-processor \
  --desired-count 1 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[<subnet-1-id>,<subnet-2-id>],securityGroups=[<security-group-id>],assignPublicIp=ENABLED}"
```

## 8단계: Route 53 설정 (선택 사항)

사용자 정의 도메인을 사용하는 경우:

```bash theme={null}
# 호스팅 영역 생성 (존재하지 않는 경우)
aws route53 create-hosted-zone \
  --name yourdomain.com \
  --caller-reference $(date +%s)

# A 레코드 생성
aws route53 change-resource-record-sets \
  --hosted-zone-id <zone-id> \
  --change-batch '{
    "Changes": [{
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "yourdomain.com",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "<alb-hosted-zone-id>",
          "DNSName": "<alb-dns-name>",
          "EvaluateTargetHealth": true
        }
      }
    }]
  }'
```

## 모니터링 및 유지 관리

### CloudWatch 경보 설정

```bash theme={null}
# CPU 사용률 경보 생성
aws cloudwatch put-metric-alarm \
  --alarm-name casebender-cpu-alarm \
  --alarm-description "CPU 사용률이 80%를 초과했습니다" \
  --metric-name CPUUtilization \
  --namespace AWS/ECS \
  --statistic Average \
  --period 300 \
  --threshold 80 \
  --comparison-operator GreaterThanThreshold \
  --dimensions Name=ClusterName,Value=casebender-cluster \
  --evaluation-periods 2 \
  --alarm-actions <sns-topic-arn>
```

### 로그 보기

```bash theme={null}
# 서비스 로그 보기
aws logs get-log-events \
  --log-group-name /ecs/casebender \
  --log-stream-name app/<container-id>
```

### 서비스 업데이트

```bash theme={null}
# 새 태스크 정의로 서비스 업데이트
aws ecs update-service \
  --cluster casebender-cluster \
  --service casebender-app \
  --task-definition casebender-app:NEW_REVISION
```

## 비용 최적화

1. 중요하지 않은 워크로드에 Fargate Spot 사용
2. 메트릭 기반 자동 확장 구현
3. 적절한 인스턴스 크기 선택
4. 예측 가능한 워크로드에 예약 인스턴스 사용

## 보안 모범 사례

1. 민감한 데이터에 AWS Secrets Manager 사용
2. WAF 규칙 구현
3. VPC 흐름 로그 활성화
4. 정기적인 보안 그룹 감사
5. AWS GuardDuty 활성화

## 다음 단계

* AWS CodePipeline으로 CI/CD 파이프라인 설정
* 백업 전략 구성
* 모니터링 및 경고 구현
* 보안 모범 사례 검토
