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

# AWS 배포하기

> A2를 Amazon Web Service(이하 AWS)에 배포하는 방법에 대해 설명합니다.

AWS에 도커 이미지를 배포할 수 있는 플랫폼에는 [AWS EC2](https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/concepts.html), [AWS App Runner](https://docs.aws.amazon.com/ko_kr/apprunner/latest/dg/what-is-apprunner.html), [AWS Lightsail](https://docs.aws.amazon.com/ko_kr/lightsail/latest/userguide/amazon-lightsail-container-services.html), [AWS EKS](https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/what-is-eks.html) 등 다양한 방법이 있습니다. 이 중 가장 간단한 [AWS ECS](https://docs.aws.amazon.com/ko_kr/AmazonECS/latest/developerguide/Welcome.html)를 활용하여 배포하는 방법을 설명합니다.

### 도커 이미지 ECR에 등록하기

AWS에서 도커 이미지를 활용하기 위해서는 Elastic Container Registry(이하 ECR)에 이미지를 등록해야 합니다. 이미지 등록과 관련된 자세한 내용은 [AWS 공식 문서](https://docs.aws.amazon.com/ko_kr/AmazonECR/latest/userguide/docker-push-ecr-image.html)를 참고하여 리포지토리 생성부터 도커 이미지 푸시까지 진행하십시오.

모든 과정을 마치면 ECR 리포지토리에서 다음과 같은 화면을 볼 수 있습니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_ecs_cluster.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=c1cd3670130ace73be70c116ea0d2ee3" alt="image" width="1806" height="2604" data-path="images/deployment-aws/aws_ecs_cluster.png" />

앞으로는 URI 컬럼에 있는 값을 활용하여 이미지를 배포합니다.

### AWS ECS 설정하기

#### 1. 클러스터 생성하기

AWS Elastic Container Service(ECS)를 사용하려면 먼저 클러스터를 생성해야 합니다. ECS의 `Clusters` > `Create Cluster` 메뉴에서 아래와 같은 화면을 볼 수 있습니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_ecs_cluster.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=c1cd3670130ace73be70c116ea0d2ee3" alt="image" width="1806" height="2604" data-path="images/deployment-aws/aws_ecs_cluster.png" />

1. `Cluster name`에 적절한 이름을 입력합니다.
2. Volume 유지를 위해 Amazon EC2 instances를 선택하고, 인스턴스 유형은 `c5.2xlarge` (8 vCPU, 16GB RAM) 이상을 권장합니다.
3. Desired capacity는 Minimum: 1, Maximum: 1로 설정합니다.
4. 클러스터를 생성합니다.

#### 2. 태스크 정의하기

이미지를 사용하려면 태스크를 먼저 정의해야 합니다. ECS의 `Task definition` > `Create new task definition` 메뉴에서 다음을 설정합니다.

1. **Task definition configuration**

   * 적절한 태스크 이름을 입력합니다.

2. **Infrastructure requirements**

   * `Launch type`은 `AWS EC2 Instances`로 선택합니다.
   * `Operating system/Architecture`는 `Linux/X86_64`로 선택합니다.
   * `Task size`는 빈칸으로 비워둡니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_ecs_task_infra.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=5f9245c759762bf4b9422b6c400b915c" alt="image" width="2364" height="2112" data-path="images/deployment-aws/aws_ecs_task_infra.png" />

3. **Container**

   * 적절한 컨테이너 이름과 ECR에 등록된 이미지 URI를 입력합니다.
   * 서비스 포트로 8000번 포트를 엽니다.
   * 태스크에 포함된 컨테이너에 모든 리소스를 할당합니다.
   * `Logging`에서 `Use log collection` 옵션을 활성화합니다.
   * CPU/GPU 설정은 빈칸으로 둡니다.
   * 메모리 제한은 다음과 같이 설정합니다.
     * EC2 인스턴스 메모리 크기가 N GB(예: 16GB)일 경우, hard limit은 N, soft limit은 N/2 - 1로 설정합니다.
     * soft limit을 이렇게 설정하는 이유는 롤링 배포 시 두 개의 태스크가 일시적으로 실행되기 때문입니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_ecs_task_container.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=60ae2e4d31afdcdd01705f17aa64c3cc" alt="image" width="2408" height="2128" data-path="images/deployment-aws/aws_ecs_task_container.png" />

4. **Volume**
   * A2의 데이터는 `/data`에 저장됩니다. 데이터를 유지하려면 적당한 크기의 스토리지를 정의하고 해당 경로에 마운트합니다.
   * AWS EBS를 사용해 데이터를 유지하려면 `Configuration Type`을 `Configure at task definition creation`으로 지정하고, 볼륨 타입은 bind mount로 선택합니다.
   * Source path에 `/data`를 입력합니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_ecs_task_volume.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=dd4e32c91ef0eb5e4532317e39acac86" alt="image" width="1912" height="1582" data-path="images/deployment-aws/aws_ecs_task_volume.png" />

#### 3. 보안 그룹 생성하기

이제 각 마이크로서비스 간의 인바운드 규칙을 설정하기 위해 두 개의 보안 그룹을 생성합니다. 하나는 태스크용 보안 그룹이고, 다른 하나는 로드 밸런서용입니다.

AWS 콘솔에서 상단의 검색창에 'security group'을 입력하면 보안 그룹 페이지로 이동할 수 있습니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_sg_icon.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=16613ca54ea13f4f3cebe56b116ca048" alt="image" width="1282" height="168" data-path="images/deployment-aws/aws_sg_icon.png" />

우측 상단의 'Create security group' 버튼을 클릭하여 설정을 시작합니다.

1. **로드 밸런서용 보안 그룹**

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_sg_lb.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=62f9849c18e3794db0587a560e0d0ed8" alt="image" width="3270" height="2480" data-path="images/deployment-aws/aws_sg_lb.png" />

* 보안 그룹 이름과 인바운드 규칙을 설정합니다.
  * 예시: `security-lb`
  * 포트 8000 에 대한 인바운드 규칙을 추가합니다.
    * 예시에서는 Source를 `Anywhere`로 설정했지만, 보안을 위해 특정 IP를 지정하는 것이 좋습니다.

2. **태스크용 보안 그룹**

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_sg_task.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=037a87daf4adceb9872a68f7c33de319" alt="image" width="3276" height="1834" data-path="images/deployment-aws/aws_sg_task.png" />

* 8000에 대해 인바운드 규칙을 추가하고, Source는 로드 밸런서의 보안 그룹을 지정합니다.

#### 4. 타겟 그룹 생성하기

로드 밸런서가 요청을 전달할 타겟 그룹을 생성합니다. `Target group`을 검색한 뒤 페이지로 이동합니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_tg_icon.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=90907190e714476ad63852202e88c441" alt="image" width="1028" height="144" data-path="images/deployment-aws/aws_tg_icon.png" />

1. **태스크용 타겟 그룹**

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_tg_basic.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=ae6fc06e96ffcef41a77831866c424f2" alt="image" width="1926" height="2532" data-path="images/deployment-aws/aws_tg_basic.png" />

* 포트8000에 대한 타겟 그룹을 생성합니다.
* 타겟 타입은 IP addresses로 선택하고, 포트는 8000으로 설정합니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_tg_health_cms.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=f6189662808bbefd8529495fc10565e1" alt="image" width="1320" height="596" data-path="images/deployment-aws/aws_tg_health_cms.png" />

* Health check path는 `/api/health`로 입력합니다.
* `Next`를 누르고 타겟 그룹 생성을 완료합니다.

#### 5. Load Balancer 생성하기

AWS 콘솔 좌측 상단의 검색창에 `Load Balancers`를 입력하고 해당 페이지로 이동합니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_lb_icon.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=f8411c6f8089344cda1e845ba7f7776f" alt="image" width="1024" height="138" data-path="images/deployment-aws/aws_lb_icon.png" />

우측 상단의 `Create Load Balancer` 버튼을 누른 후, `Application Load Balancer`를 선택합니다.

1. **기본 설정 (Basic Configuration)**

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_lb_basic.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=ccb6b0e3f2280d20629eb1a970201a24" alt="image" width="1796" height="946" data-path="images/deployment-aws/aws_lb_basic.png" />

* Scheme은 `Internet-facing`을 선택합니다.
* IP 주소 유형은 `IPv4`를 선택합니다.

2. **네트워크 매핑 및 보안 그룹 (Network Mapping & Security Groups)**

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_lb_network.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=75ab00eb17a98047ca656c60c59ffef1" alt="image" width="1762" height="2114" data-path="images/deployment-aws/aws_lb_network.png" />

* 가용 영역(Availability Zone)은 해당 리전(예: ap-northeast-2)의 모든 가용 영역을 선택합니다.
* VPC ID와 Subnet ID는 서비스 생성 시 필요하므로 복사하여 저장해 둡니다.
* 보안 그룹은 이전에 생성했던 로드 밸런서용 보안 그룹을 선택합니다.

3. **리스너 설정 (Listeners)**

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_lb_listener.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=2b8f009503c80c8793654d4e6cd260dd" alt="image" width="1774" height="2000" data-path="images/deployment-aws/aws_lb_listener.png" />

* 리스너는 생성한 타겟 그룹들과 연결합니다.

4. **완료 (Finished)**

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_lb_finished.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=459abc70bf8bfc920f4a626ec7765ac8" alt="image" width="3736" height="2414" data-path="images/deployment-aws/aws_lb_finished.png" />

* 로드 밸런서가 생성되면, 위 이미지에서 빨간 박스로 표시된 DNS 이름을 저장합니다. 서비스의 엔드포인트(ADM 등)에 접속할 때 이 주소를 사용하게 됩니다.

#### 6. 서비스 생성하기

여기서는 콘솔의 GUI 대신 CloudFormation을 이용하여 서비스를 생성합니다. 이유는 GUI에서는 컨테이너의 여러 포트를 로드 밸런서에 연동하는 것을 지원하지 않기 때문입니다. 자세한 내용은 [Medium](https://medium.com/@faisalsuhail1/exposing-multiple-ports-for-an-aws-ecs-service-64b9821c09e8)에서 확인할 수 있습니다.

AWS 콘솔 좌측 상단의 검색창에 `CloudFormation`을 입력하고 해당 페이지로 이동합니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_ecs_cloudformation_icon.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=a834cfff8cefaf7bae62eceddc91155c" alt="image" width="1260" height="178" data-path="images/deployment-aws/aws_ecs_cloudformation_icon.png" />

1. **스택 생성하기 (Create Stack)**

* 우측 상단의 `Create Stack` 버튼을 클릭합니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_ecs_cloudformation_create.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=4072859c3d4fc3c68c6827ed5fc5b2ed" alt="image" width="2390" height="2270" data-path="images/deployment-aws/aws_ecs_cloudformation_create.png" />

* `Choosing an existing template`을 선택한 후, `Upload a template file`을 클릭합니다.
* 아래 JSON 형식을 사용해 템플릿 파일을 저장하고, 파일을 업로드합니다. 주석으로 표시된 부분은 사용자의 환경에 맞게 수정해야 합니다. (앞서 복사해 두었던 값들을 입력합니다.)
* `SecurityGroupIDs`에는 이전에 생성한 태스크 보안 그룹의 ID를 입력합니다.

```json theme={null}
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "The template used to create an ECS Service from the ECS Console.",
  "Parameters": {
    "SecurityGroupIDs": {
      "Type": "CommaDelimitedList"
      // "Default": "sg-0f21b327b83e33c46"
    },
    "SubnetIDs": {
      "Type": "CommaDelimitedList"
      // "Default": "subnet-0b7b40c10645ff898,subnet-059809f716cb81e9e,subnet-013907b4eb89d521f,subnet-020323a92b4d44e1e"
    },
    "VpcID": {
      "Type": "String"
      // "Default": "vpc-0ab885f61636987ee"
    },
    "LoadBalancerName": {
      "Type": "String"
      // "Default": "lb-test"
    }
  },
  "Resources": {
    "ECSService": {
      "Type": "AWS::ECS::Service",
      "Properties": {
        // "Cluster": "cluster-test",
        // "TaskDefinition": "arn:aws:ecs:ap-northeast-2:339...",
        "LaunchType": "EC2",
        // "ServiceName": "service-test",
        "SchedulingStrategy": "REPLICA",
        "DesiredCount": 1,
        "LoadBalancers": [
          {
            // "ContainerName": "container-test",
            "ContainerPort": 8000,
            "LoadBalancerName": {
              "Ref": "AWS::NoValue"
            }
            // "TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-2:339..."
          }
        ],
        "NetworkConfiguration": {
          "AwsvpcConfiguration": {
            "SecurityGroups": {
              "Ref": "SecurityGroupIDs"
            },
            "Subnets": {
              "Ref": "SubnetIDs"
            }
          }
        },
        "DeploymentConfiguration": {
          "MaximumPercent": 200,
          "MinimumHealthyPercent": 100,
          "DeploymentCircuitBreaker": {
            "Enable": true,
            "Rollback": true
          }
        },
        "DeploymentController": {
          "Type": "ECS"
        },
        "ServiceConnectConfiguration": {
          "Enabled": false
        },
        "PlacementStrategies": [
          {
            "Field": "attribute:ecs.availability-zone",
            "Type": "spread"
          },
          {
            "Field": "instanceId",
            "Type": "spread"
          }
        ],
        "PlacementConstraints": [],
        "Tags": [],
        "EnableECSManagedTags": true
      }
    }
  },
  "Outputs": {
    "ECSService": {
      "Description": "The created service.",
      "Value": {
        "Ref": "ECSService"
      }
    }
  }
}
```

2. **헬스 체크 (Health Check)**

* `Next`를 클릭한 뒤 스택 이름을 입력하고, `Next`를 계속 클릭하여 `Submit`을 누르면 서비스 생성 요청이 완료됩니다.
* 클러스터 페이지로 이동하여 생성된 서비스의 페이지로 들어갑니다. 아래 이미지에서 빨간 박스로 표시된 버튼을 클릭합니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_ecs_service_icon.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=0a0f6e2ab868085b44fcd3a1c7e2026b" alt="image" width="3782" height="1828" data-path="images/deployment-aws/aws_ecs_service_icon.png" />

* 서비스가 성공적으로 생성되면, 아래 이미지에서 빨간 박스로 표시된 모든 항목이 `healthy`로 표시됩니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_ecs_service_page.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=7761f36c21198f430922e07dcefe6954" alt="image" width="3724" height="1786" data-path="images/deployment-aws/aws_ecs_service_page.png" />

#### 7. 완료

이제 앞서 저장한 `<Load Balancer의 DNS>:8000`으로 접속하면 아래와 같이 ADM 페이지가 잘 작동하는 것을 확인할 수 있습니다.

<img src="https://mintcdn.com/aiderx/tjHtaiAN__Ai-ZM-/images/deployment-aws/aws_cms_login.png?fit=max&auto=format&n=tjHtaiAN__Ai-ZM-&q=85&s=bbeb833ca29e5d9047438cedc01a1207" alt="image" width="2798" height="1832" data-path="images/deployment-aws/aws_cms_login.png" />

모든 설정이 완료되었으며, 배포 후 할당된 DNS를 통해 A2를 사용할 수 있습니다.

***

이 매뉴얼을 통해 A2를 AWS에 성공적으로 배포할 수 있습니다. 추가 문의 사항이 있으면 언제든지 지원팀에 연락해 주세요.
