

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Amazon EC2에 대한 프로그래밍 방식 액세스
<a name="ec2-api-intro"></a>

AWS Management Console 또는 프로그래밍 인터페이스를 사용하여 Amazon EC2 리소스를 생성하고 관리할 수 있습니다. Amazon EC2 콘솔 사용에 대한 자세한 내용은 [Amazon EC2 사용 설명서](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)를 참조하세요.

**작동 방법**
+ [Amazon EC2 엔드포인트](ec2-endpoints.md)
+ [최종 일관성](eventual-consistency.md).
+ [멱등성](ec2-api-idempotency.md)
+ [요청 제한](ec2-api-throttling.md)
+ [페이지 매김](ec2-api-pagination.md)

**프로그래밍 인터페이스**
+ [AWS Command Line Interface (AWS CLI)](ec2-aws-cli.md)
+ [AWS CloudFormation](ec2-cloudformation.md)
+ [AWS SDK](sdk-general-information-section.md)
+ [하위 수준 API](ec2-low-level-api.md)

**시작하기**
+ [코드 예제](service_code_examples.md)
+ [콘솔 투 코드](console-to-code.md)

**모니터링**
+ [AWS CloudTrail](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitor-with-cloudtrail.html)
+ [요청 모니터링](monitor.md)

# Amazon EC2 서비스 엔드포인트
<a name="ec2-endpoints"></a>

엔드포인트는 AWS 웹 서비스의 진입점 역할을 하는 URL입니다. Amazon EC2는 다음과 같은 엔드포인트 유형을 지원합니다.
+ [IPv4 엔드포인트](#ipv4)
+ [듀얼 스택 엔드포인트](#ipv6)(IPv4 및 IPv6를 모두 지원)
+ [ FIPS 엔드포인트](https://docs.aws.amazon.com/general/latest/gr/rande.html#FIPS-endpoints)

요청 시에, 사용할 엔드포인트를 지정할 수 있습니다. 엔드포인트를 지정하지 않으면 기본적으로 IPv4 엔드포인트가 사용됩니다. 다른 엔드포인트 유형을 사용하려면 요청에서 이를 지정해야 합니다. 이렇게 하는 방법의 예제는 [엔드포인트 지정](#examples) 섹션을 참조하세요. 사용 가능한 엔드포인트 표는 [리전별 서비스 엔드포인트](#service-endpoints) 섹션을 참조하세요.

## IPv4 엔드포인트
<a name="ipv4"></a>

IPv4 엔드포인트는 IPv4 트래픽만 지원합니다. IPv4 엔드포인트는 모든 리전에 사용할 수 있습니다.

범용 엔드포인트 `ec2.amazonaws.com`을 지정하면 `us-east-1`의 엔드포인트를 사용합니다. 다른 리전을 사용하려면 연결된 엔드포인트를 지정해야 합니다. 예를 들어 `ec2.us-east-2.amazonaws.com`을 엔드포인트로 지정하면 요청이 `us-east-2` 엔드포인트로 전달됩니다.

IPv4 엔드포인트 이름에는 다음 명명 규칙이 사용됩니다.
+ `service.region.amazonaws.com`

예를 들어 `eu-west-1` 리전의 IPv4 엔드포인트 이름은 `ec2.eu-west-1.amazonaws.com`입니다.

## 이중 스택(IPv4 및 IPv6) 엔드포인트
<a name="ipv6"></a>

이중 스택 엔드포인트는 IPv4 트래픽과 IPv6 트래픽을 모두 지원합니다. 이중 스택 엔드포인트에 요청하는 경우, 엔드포인트 URL이 네트워크 및 클라이언트에서 사용하는 프로토콜에 따라 IPv6 또는 IPv4 주소로 확인됩니다.

Amazon EC2는 리전별 듀얼 스택 엔드포인트만 지원합니다. 따라서 엔드포인트 이름의 일부로 리전을 지정해야 합니다. 이중 스택 엔드포인트 이름에는 다음 명명 규칙이 사용됩니다.
+ `ec2.region.api.aws`

예를 들어 `eu-west-1` 리전의 이중 스택 엔드포인트 이름은 `ec2.eu-west-1.api.aws`입니다.

## 리전별 서비스 엔드포인트
<a name="service-endpoints"></a>

다음은 Amazon EC2에 대한 서비스 엔드포인트입니다. 리전에 대한 자세한 내용은 Amazon EC2 사용 설명서의 [리전 및 가용 영역](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html)을 참조하세요.**

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/ec2/latest/devguide/ec2-endpoints.html)

## 엔드포인트 지정
<a name="examples"></a>

이 섹션에서는 요청 시에 엔드포인트를 지정하는 방법을 몇 가지 예로 보여줍니다.

------
#### [ AWS CLI ]

다음 예는 AWS CLI를 사용하여 `us-east-2` 리전의 엔드포인트를 지정하는 방법을 보여줍니다.
+ **이중 스택**

  ```
  aws ec2 describe-regions --region us-east-2 --endpoint-url https://ec2.us-east-2.api.aws
  ```
+ **IPv4**

  ```
  aws ec2 describe-regions --region us-east-2 --endpoint-url https://ec2.us-east-2.amazonaws.com
  ```

------
#### [ AWS SDK for Java 2.x ]

다음 예는 AWS SDK for Java 2.x를 사용하여 `us-east-2` 리전의 엔드포인트를 지정하는 방법을 보여줍니다.
+ **이중 스택**

  ```
  Ec2Client client = Ec2Client.builder()
      .region(Region.US_EAST_2)
      .endpointOverride(URI.create("https://ec2.us-east-2.api.aws"))
      .build();
  ```
+ **IPv4**

  ```
  Ec2Client client = Ec2Client.builder()
      .region(Region.US_EAST_2)
      .endpointOverride(URI.create("https://ec2.us-east-2.amazonaws.com"))
      .build();
  ```

------
#### [ AWS SDK for Java 1.x ]

다음 예제에서는 AWS SDK for Java 1.x를 사용하여 `eu-west-1` 리전의 엔드포인트를 지정하는 방법을 보여줍니다.
+ **이중 스택**

  ```
  AmazonEC2 s3 = AmazonEC2ClientBuilder.standard()
       .withEndpointConfiguration(new EndpointConfiguration(
            "https://ec2.eu-west-1.api.aws",
            "eu-west-1"))
       .build();
  ```
+ **IPv4**

  ```
  AmazonEC2 s3 = AmazonEC2ClientBuilder.standard()
       .withEndpointConfiguration(new EndpointConfiguration(
            "https://ec2.eu-west-1.amazonaws.com",
            "eu-west-1"))
       .build();
  ```

------
#### [ AWS SDK for Go ]

다음 예는 AWS SDK for Go를 사용하여 `us-east-1` 리전의 엔드포인트를 지정하는 방법을 보여줍니다.
+ **이중 스택**

  ```
  sess := session.Must(session.NewSession())
  svc := ec2.New(sess, &aws.Config{
      Region: aws.String(endpoints.UsEast1RegionID),
      Endpoint: aws.String("https://ec2.us-east-1.api.aws")
  })
  ```
+ **IPv4**

  ```
  sess := session.Must(session.NewSession())
  svc := ec2.New(sess, &aws.Config{
      Region: aws.String(endpoints.UsEast1RegionID),
      Endpoint: aws.String("https://ec2.us-east-1.amazonaws.com")
  })
  ```

------

# Amazon EC2 API의 최종 일관성
<a name="eventual-consistency"></a>

Amazon EC2 PI를 지원하는 시스템의 분산 특성으로 인해 API는 결과적 일관성 모델을 따릅니다. 이는 Amazon EC2 리소스에 영향을 미치는 API 명령을 실행한 결과가 모든 후속 명령에 즉시 표시되지 않을 수 있음을 의미합니다. 이전 API 명령 바로 다음에 API 명령을 실행할 때는 이 점을 염두에 두어야 합니다.

최종 일관성은 리소스 관리 방식에 영향을 미칠 수 있습니다. 예를 들어, 명령을 실행하여 리소스를 생성하면 결국 다른 명령에 표시됩니다. 즉, 방금 생성한 리소스를 수정하거나 설명하는 명령을 실행하면 ID가 시스템 전체에 전파되지 않았을 수 있으며 리소스가 존재하지 않는다고 응답하는 오류가 발생합니다.

최종 일관성을 관리하려면 다음을 수행할 수 있습니다.
+ 명령을 실행하여 수정하기 전에 리소스의 상태를 확인합니다. 이전 명령이 시스템에 전파될 시간이 충분하도록 지수 백오프 알고리즘을 사용하여 적절한 `Describe` 명령을 실행합니다. 이렇게 하려면 몇 초의 대기 시간으로 시작하여 몇 분까지 점진적으로 증가하는 `Describe` 명령을 반복적으로 실행합니다.
+ `Describe` 명령이 정확한 응답을 반환하더라도 후속 명령 사이에 대기 시간을 추가합니다. 몇 초의 대기 시간으로 시작하는 지수 백오프 알고리즘을 적용하고 몇 분까지 점진적으로 증가시킵니다.

**최종 일관성 오류 예제**  
다음은 최종 일관성의 결과로 발생할 수 있는 오류 코드의 예제입니다.
+ `InvalidInstanceID.NotFound`

  `RunInstances` 명령을 성공적으로 실행한 다음, `RunInstances`의 응답에 제공된 인스턴스 ID를 사용하여 다른 명령을 즉시 실행하면 `InvalidInstanceID.NotFound` 오류가 반환될 수 있습니다. 이는 인스턴스가 존재하지 않는다는 의미는 아닙니다.

  영향을 받을 수 있는 특정 명령은 다음과 같습니다.
  + `DescribeInstances`: 인스턴스의 실제 상태를 확인하려면 지수 백오프 알고리즘을 사용하여 이 명령을 실행합니다.
  + `TerminateInstances`: 인스턴스의 상태를 확인하려면 먼저 지수 백오프 알고리즘을 사용하여 `DescribeInstances` 명령을 실행합니다.
**중요**  
`TerminateInstances` 실행 후 `InvalidInstanceID.NotFound` 오류가 발생한다고 해서 인스턴스가 종료되거나 종료될 것임을 의미하지는 않습니다. 인스턴스가 계속 실행 중일 수 있습니다. 따라서 먼저 `DescribeInstances`를 사용하여 인스턴스의 상태를 확인하는 것이 중요합니다.
+ `InvalidGroup.NotFound`

  `CreateSecurityGroup` 명령을 성공적으로 실행한 다음, `CreateSecurityGroup`의 응답에 제공된 보안 그룹 ID를 사용하여 다른 명령을 즉시 실행하면 `InvalidGroup.NotFound` 오류가 반환될 수 있습니다. 보안 그룹의 상태를 확인하려면 지수 백오프 알고리즘을 사용하여 `DescribeSecurityGroups` 명령을 실행합니다.
+ `InstanceLimitExceeded`

  지정된 인스턴스 유형에 대해 현재 인스턴스 한도가 허용하는 것보다 많은 인스턴스를 요청했습니다. 인스턴스가 종료된 후 잠시 동안 인스턴스 한도에 포함되므로 인스턴스를 빠르게 시작하고 종료하는 경우 예기치 않게 한도에 도달할 수 있습니다.

# Ensuring idempotency in Amazon EC2 API requests
<a name="ec2-api-idempotency"></a>

변형 API 요청을 만들 때 요청은 일반적으로 작업의 비동기 워크플로가 완료되기 전에 결과를 반환합니다. 요청이 이미 결과를 반환했더라도 작업이 완료되기 전에 시간이 초과되거나 다른 서버 문제가 발생할 수도 있습니다. 이로 인해 요청의 성공 여부를 판단하기 어려울 수 있으며 작업이 성공적으로 완료되었는지 확인하기 위해 여러 번의 재시도가 발생할 수 있습니다. 그러나 원래 요청과 후속 재시도가 성공하면 작업이 여러 번 완료됩니다. 즉, 의도한 것보다 더 많은 리소스를 생성할 수 있습니다.

*멱등성*은 API 요청이 한 번만 완료되도록 합니다. 멱등성 요청을 사용하면 원래 요청이 성공적으로 완료되면 추가 작업을 수행하지 않고 후속 재시도가 성공적으로 완료됩니다. 그러나 결과에는 현재 생성 상태와 같은 업데이트된 정보가 포함될 수 있습니다.

**Topics**
+ [Amazon EC2의 멱등성](#client-tokens)
+ [RunInstances 멱등성](#run-instances-idempotency)
+ [예시](#Run_Instance_Idempotency_CLI)
+ [멱등적인 요청에 대한 재시도 권장 사항](#recommended-actions)

## Amazon EC2의 멱등성
<a name="client-tokens"></a>

다음 API 작업은 기본적으로 멱등적이며 추가 구성이 필요하지 않습니다. 해당하는 AWS CLI 명령 또한 기본적으로 멱등성을 지원합니다.

**기본적으로 제공되는 멱등성**
+ AssociateAddress
+ CreateVpnConnection
+ DisassociateAddress
+ ReplaceNetworkAclAssociation
+ TerminateInstances

다음 API 작업은 필요에 따라 *클라이언트 토큰*을 사용하여 멱등성을 지원합니다. 해당하는 AWS CLI 명령 또한 클라이언트 토큰을 사용하여 멱등성을 지원합니다. 클라이언트 토큰은 대소문자를 구분하며 최대 64자리의 ASCII 문자로 구성된 고유한 문자열입니다. 이러한 작업 중 하나를 사용하여 멱등적인 API 요청을 수행하려면 요청에 클라이언트 토큰을 지정하면 됩니다. 동일한 클라이언트 토큰을 다른 API 요청에 재사용해서는 안 됩니다. 동일한 클라이언트 토큰과 동일한 파라미터를 사용하여 성공적으로 완료된 요청을 재시도하면 추가 작업을 수행하지 않고 재시도가 성공합니다. 동일한 클라이언트 토큰을 사용하여 성공적인 요청을 재시도하는데, 리전 또는 가용 영역 외에 다른 파라미터 중 하나 이상이 다르면 `IdempotentParameterMismatch` 오류와 함께 재시도가 실패합니다.

**클라이언트 토큰을 사용하는 멱등성**
+ AllocateHosts
+ AllocateIpamPoolCidr
+ AssociateClientVpnTargetNetwork
+ AssociateIpamResourceDiscovery
+ AttachVerifiedAccessTrustProvider
+ AuthorizeClientVpnIngress
+ CopyFpgaImage
+ CopyImage
+ CreateCapacityReservation
+ CreateCapacityReservationFleet
+ CreateClientVpnEndpoint
+ CreateClientVpnRoute
+ CreateEgressOnlyInternetGateway
+  CreateFleet 
+ CreateFlowLogs
+ CreateFpgaImage
+ CreateInstanceConnectEndpoint
+ CreateIpam
+ CreateIpamPool
+ CreateIpamResourceDiscovery
+ CreateIpamScope
+ CreateLaunchTemplate
+ CreateLaunchTemplateVersion
+ CreateManagedPrefixList
+ CreateNatGateway
+ CreateNetworkAcl
+ CreateNetworkInsightsAccessScope
+ CreateNetworkInsightsPath
+ CreateNetworkInterface
+ CreateReplaceRootVolumeTask
+ CreateReservedInstancesListing
+ CreateRouteTable
+ CreateTrafficMirrorFilter
+ CreateTrafficMirrorFilterRule
+ CreateTrafficMirrorSession
+ CreateTrafficMirrorTarget
+ CreateVerifiedAccessEndpoint
+ CreateVerifiedAccessGroup
+ CreateVerifiedAccessInstance
+ CreateVerifiedAccessTrustProvider
+ CreateVolume
+ CreateVpcEndpoint
+ CreateVpcEndpointConnectionNotification
+ CreateVpcEndpointServiceConfiguration
+ DeleteVerifiedAccessEndpoint
+ DeleteVerifiedAccessGroup
+ DeleteVerifiedAccessInstance
+ DeleteVerifiedAccessTrustProvider
+ DetachVerifiedAccessTrustProvider
+ ExportImage
+ ImportImage
+ ImportSnapshot
+ ModifyInstanceCreditSpecification
+ ModifyLaunchTemplate
+ ModifyReservedInstances
+ ModifyVerifiedAccessEndpoint
+ ModifyVerifiedAccessEndpointPolicy
+ ModifyVerifiedAccessGroup
+ ModifyVerifiedAccessGroupPolicy
+ ModifyVerifiedAccessInstance
+ ModifyVerifiedAccessInstanceLoggingConfiguration
+ ModifyVerifiedAccessTrustProvider
+ ProvisionIpamPoolCidr
+ PurchaseHostReservation
+ RequestSpotFleet
+ RequestSpotInstances
+ RunInstances
+ StartNetworkInsightsAccessScopeAnalysis
+ StartNetworkInsightsAnalysis

**멱등성 유형**
+ 리전 - 요청은 각 리전에서 멱등적입니다. 그러나 다른 리전에서는 동일한 클라이언트 토큰을 포함하는 같은 요청을 사용할 수 있습니다.
+ 영역 - 요청은 리전의 각 가용 영역에서 멱등적입니다. 예를 들어, 동일한 리전의 **AllocateHosts**에 대한 두 직접 호출에서 동일한 클라이언트 토큰을 지정하는 경우 **AvailabilityZone** 파라미터에 대해 다른 값을 지정하면 직접 호출이 성공합니다.

## RunInstances 멱등성
<a name="run-instances-idempotency"></a>

[RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html) API 작업은 리전 및 영역 멱등성을 모두 사용합니다.

사용되는 멱등성 유형은 RunInstances API 요청에서 가용 영역을 지정하는 방법에 따라 달라집니다. 요청은 다음과 같은 경우에 **영역 멱등성**을 사용합니다.
+ **배치** 데이터 유형에서 **AvailabilityZone** 파라미터를 사용하여 가용 영역을 명시적으로 지정하는 경우
+ **SubnetId** 파라미터를 사용하여 가용 영역을 암시적으로 지정하는 경우

가용 영역을 명시적으로 또는 암시적으로 지정하지 않으면 요청은 **리전 멱등성**을 사용합니다.

### 영역 멱등성
<a name="zonal-idempotency"></a>

영역 멱등성은 리전의 각 가용 영역에서 RunInstances API 요청이 멱등성을 갖도록 합니다. 이렇게 하면 동일한 클라이언트 토큰을 사용하는 요청이 리전의 각 가용 영역 내에서 한 번만 완료될 수 있습니다. 그러나 리전의 다른 가용 영역에서는 동일한 클라이언트 토큰을 사용하여 인스턴스를 시작할 수 있습니다.

예를 들어, `us-east-1a` 가용 영역에서 인스턴스를 시작하기 위해 멱등적인 요청을 보낸 다음 `us-east-1b` 가용 영역의 요청에 동일한 클라이언트 토큰을 사용하는 경우 각 가용 영역에서 인스턴스를 시작합니다. 하나 이상의 파라미터가 다른 경우 해당 가용 영역에서 동일한 클라이언트 토큰을 사용한 후속 재시도는 추가 작업을 수행하지 않고 성공적으로 반환되거나 `IdempotentParameterMismatch` 오류와 함께 실패합니다.

### 리전 멱등성
<a name="regional-idempotency"></a>

리전 멱등성은 리전에서 RunInstances API 요청이 멱등성을 갖도록 합니다. 이렇게 하면 동일한 클라이언트 토큰을 사용하는 요청이 리전 내에서 한 번만 완료될 수 있습니다. 그러나 다른 리전에서는 동일한 클라이언트 토큰으로 정확히 같은 요청을 사용하여 인스턴스를 시작할 수 있습니다.

예를 들어, `us-east-1` 리전에서 인스턴스를 시작하기 위해 멱등적인 요청을 보낸 다음 `eu-west-1` 리전의 요청에 동일한 클라이언트 토큰을 사용하는 경우 각 리전에서 인스턴스를 시작합니다. 하나 이상의 파라미터가 다른 경우 해당 리전에서 동일한 클라이언트 토큰을 사용한 후속 재시도는 추가 작업을 수행하지 않고 성공적으로 반환되거나 `IdempotentParameterMismatch` 오류와 함께 실패합니다.

**작은 정보**  
요청된 리전의 가용 영역 중 하나를 사용할 수 없는 경우 리전 멱등성을 사용하는 RunInstances 요청이 실패할 수 있습니다. AWS 인프라에서 제공하는 가용 영역 기능을 활용하려면 인스턴스를 시작할 때 영역 멱등성을 사용하는 것이 좋습니다. 영역 멱등성을 사용하고 지원되는 가용 영역을 대상으로 하는 RunInstances 요청은 요청된 리전의 다른 가용 영역을 사용할 수 없는 경우에도 성공합니다.

## 예시
<a name="Run_Instance_Idempotency_CLI"></a>

### AWS CLI 명령 예제
<a name="cli-example"></a>

AWS CLI 명령을 멱등적으로 만들려면 `--client-token` 옵션을 추가합니다.

**예제 1: 멱등성**  
다음 [allocate-hosts](https://docs.aws.amazon.com/cli/latest/reference/ec2/allocate-hosts.html) 명령은 클라이언트 토큰을 포함하므로 멱등성을 사용합니다.

```
aws ec2 allocate-hosts  --instance-type m5.large  --availability-zone eu-west-1a  --auto-placement on  --quantity 1 --client-token 550e8400-e29b-41d4-a716-446655440000
```

**예제 2: run-instances 리전 멱등성**  
다음 [run-instances](https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html) 명령은 클라이언트 토큰을 포함하지만, 가용 영역을 명시적으로 또는 암시적으로 지정하지 않으므로 리전 멱등성을 사용합니다.

```
aws ec2 run-instances --image-id ami-b232d0db --count 1 --key-name my-key-pair --client-token 550e8400-e29b-41d4-a716-446655440000
```

**예제 3: run-instances 영역 멱등성**  
다음 [run-instances](https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html) 명령은 클라이언트 토큰과 명시적으로 지정된 가용 영역을 포함하므로 영역 멱등성을 사용합니다.

```
aws ec2 run-instances  --placement "AvailabilityZone=us-east-1a" --image-id ami-b232d0db --count 1 --key-name my-key-pair --client-token 550e8400-e29b-41d4-a716-446655440000
```

### API 요청 예제
<a name="api-example"></a>

API 요청을 멱등적으로 만들려면 `ClientToken` 파라미터를 추가합니다.

**예제 1: 멱등성**  
다음 [AllocateHosts](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_AllocateHosts.html) API 요청은 클라이언트 토큰을 포함하므로 멱등성을 사용합니다.

```
https://ec2.amazonaws.com/?Action=AllocateHosts
&AvailabilityZone=us-east-1b
&InstanceType=m5.large
&Quantity=1
&AutoPlacement=off
&ClientToken=550e8400-e29b-41d4-a716-446655440000
&AUTHPARAMS
```

**예제 2: RunInstances 리전 멱등성**  
다음 [RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html) API 요청은 클라이언트 토큰을 포함하지만, 가용 영역을 명시적으로 또는 암시적으로 지정하지 않으므로 리전 멱등성을 사용합니다.

```
https://ec2.amazonaws.com/?Action=RunInstances
&ImageId=ami-3ac33653
&MaxCount=1
&MinCount=1
&KeyName=my-key-pair
&ClientToken=550e8400-e29b-41d4-a716-446655440000
&AUTHPARAMS
```

**예제 3: RunInstances 영역 멱등성**  
다음 [RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html) API 요청은 클라이언트 토큰과 명시적으로 지정된 가용 영역을 포함하므로 영역 멱등성을 사용합니다.

```
https://ec2.amazonaws.com/?Action=RunInstances
&Placement.AvailabilityZone=us-east-1d
&ImageId=ami-3ac33653
&MaxCount=1
&MinCount=1
&KeyName=my-key-pair
&ClientToken=550e8400-e29b-41d4-a716-446655440000
&AUTHPARAMS
```

## 멱등적인 요청에 대한 재시도 권장 사항
<a name="recommended-actions"></a>

다음 테이블은 멱등성 API 요청에 대해 얻을 수 있는 몇 가지 일반적인 응답을 보여주고 재시도 권장 사항을 제공합니다.


| 응답 | 권장 사항 | 설명 | 
| --- | --- | --- | 
|  200 OK  |  다시 시도하지 않음  |  원래 요청이 성공적으로 완료되었습니다. 이후의 모든 재시도는 성공적으로 반환됩니다.  | 
|  400 시리즈 응답 코드([클라이언트 오류](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html#CommonErrors))  |  다시 시도하지 않음  |  다음 중에서는 요청에 문제가 있습니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/ec2/latest/devguide/ec2-api-idempotency.html) 요청에 상태 변경 프로세스에 있는 리소스가 포함된 경우 요청 재시도가 성공할 수 있습니다.  | 
|  500 시리즈 응답 코드([서버 오류](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html#api-error-codes-table-server))  |  다시 해 보십시오  |  이 오류는 AWS 서버 측 문제로 인해 발생하며 일반적으로 일시적입니다. 적절한 백오프 전략으로 요청을 반복합니다.  | 

# Amazon EC2 API에 대한 요청 스로틀링
<a name="ec2-api-throttling"></a>

Amazon EC2는 리전별로 각 AWS 계정에 대한 EC2 API 요청을 제한합니다. 당사는 서비스 수행을 돕고 모든 Amazon EC2 고객에게 공정한 사용을 보장하기 위해 이를 수행합니다. 스로틀링을 통해 Amazon EC2 API에 대한 요청이 허용되는 최대 API 요청 제한을 초과하지 않도록 할 수 있습니다. API 요청에는 다음에서 시작되었는지 여부에 관계없이 요청 제한이 적용됩니다.
+ 타사 애플리케이션
+ 명령줄 도구
+ Amazon EC2 콘솔

API 스로틀링 제한을 초과하면 `RequestLimitExceeded` 오류 코드가 표시됩니다.

**Topics**
+ [제한 적용 방법](#throttling-how)
+ [요청 토큰 제한](#throttling-limits-rate-based)
+ [리소스 토큰 제한](#throttling-limits-cost-based)
+ [API 스로틀링 모니터링](#throttling-monitor)
+ [재시도 및 지수 백오프](#api-backoff)
+ [한도 증가 요청](#throttling-increase)

## 제한 적용 방법
<a name="throttling-how"></a>

Amazon EC2는 [토큰 버킷 알고리즘](https://en.wikipedia.org/wiki/Token_bucket)을 사용하여 API 스로틀링을 구현합니다. 이 알고리즘을 사용하면 계정에 특정 수의 *토큰*을 보관하는 *버킷*이 있습니다. 버킷의 토큰 수는 지정된 초당 스로틀링 제한을 나타냅니다.

Amazon EC2는 두 유형의 API 스로틀링을 구현합니다.

**Topics**
+ [요청 속도 제한](#throttling-rate-based)
+ [리소스 속도 제한](#throttling-cost-based)

### 요청 속도 제한
<a name="throttling-rate-based"></a>

요청 속도 제한을 사용하면 각 API가 개별적으로 평가되며 API별로 수행하는 요청 수에 따라 스로틀링됩니다. 제출한 각 요청은 API 버킷에서 하나의 토큰을 제거합니다. 예를 들어, *변경되지 않는* API 작업인 `DescribeHosts`의 토큰 버킷 크기는 토큰 100개입니다. 1초에 최대 100개까지 `DescribeHosts`를 요청할 수 있습니다. 1초에 100개의 요청을 초과하면 해당 API에 스로틀링이 발생하고 해당 초 내의 나머지 요청은 실패하지만, 다른 API에 대한 요청은 영향을 받지 않습니다.

버킷은 설정된 속도로 자동으로 다시 채워집니다. 버킷이 최대 용량 미만이면 최대 용량에 도달할 때까지 매초마다 정해진 수의 토큰이 버킷에 다시 추가됩니다. 다시 채우기 토큰이 도착했을 때 버킷이 다 차면 토큰은 폐기됩니다. 버킷은 최대 토큰 수를 초과하여 보관할 수 없습니다. 예를 들어, *변경되지 않는* API 작업인 `DescribeHosts`의 버킷 크기는 토큰 100개이며, 다시 채우기 속도는 초당 토큰 20개입니다. 1초에 100개의 `DescribeHosts`를 요청하면 버킷이 토큰 0개로 줄어듭니다. 그러면 토큰이 최대 용량 100개에 도달할 때까지 매초마다 20개의 토큰이 버킷에 다시 채워집니다. 즉, 해당 시간 동안 요청이 없는 경우 빈 버킷은 5초 후에 최대 용량에 도달합니다.

API 요청을 하기 전에 버킷이 완전히 꽉 찰 때까지 기다릴 필요가 없습니다. 버킷에 추가된 다시 채우기 토큰은 그대로 사용할 수 있습니다. 다시 채우기 토큰을 즉시 사용하는 경우 버킷이 최대 용량에 도달하지 않습니다. 예를 들어, *변경되지 않는* API 작업인 `DescribeHosts`의 버킷 크기는 토큰 100개이며, 다시 채우기 속도는 초당 토큰 20개입니다. 1초에 100개의 API 요청을 수행하여 버킷을 고갈시키는 경우 버킷에 추가되는 다시 채우기 토큰을 사용하여 초당 20개의 API 요청을 계속 수행할 수 있습니다. 버킷은 초당 20개 미만의 API 요청을 할 경우에만 최대 용량으로 다시 채울 수 있습니다.

자세한 내용은 [요청 토큰 버킷 크기 및 다시 채우기 속도](#throttling-limits-rate-based) 단원을 참조하십시오.

### 리소스 속도 제한
<a name="throttling-cost-based"></a>

다음 표에 설명된 대로 `TerminateInstances` 및 `RunInstances`와 같은 일부 API 작업은 요청 속도 제한 외에도 리소스 속도 제한을 사용합니다. 이러한 API 작업에는 요청의 영향을 받는 리소스 수에 따라 고갈되는 별도의 리소스 토큰 버킷이 있습니다. 요청 토큰 버킷과 마찬가지로 리소스 토큰 버킷에는 버스트할 수 있는 버킷 최대값과 필요한 기간 동안 일정한 요청 속도를 유지할 수 있는 다시 채우기 속도가 있습니다. 다음 API 요청을 지원하기 위해 버킷이 아직 다시 채워지지 않은 경우를 포함하여 API에 대한 특정 버킷 제한을 초과하는 경우 총 API 스로틀 제한에 도달하지 않았더라도 API의 작업이 제한됩니다.

예를 들어, `RunInstances`의 리소스 토큰 버킷 크기는 토큰 1,000개이고 다시 채우기 속도는 초당 토큰 2개입니다. 따라서 1,000개의 인스턴스에 대한 요청 하나 또는 250개의 인스턴스에 대한 요청 4개와 같은 API 요청을 사용하여 즉시 1,000개의 인스턴스를 실행할 수 있습니다. 리소스 토큰 버킷이 비어 있으면 인스턴스 2개에 대해 요청 1개 또는 인스턴스 1개에 대해 요청 2개를 사용하여 초당 최대 2개의 인스턴스를 시작할 수 있습니다.

자세한 내용은 [리소스 토큰 버킷 크기 및 다시 채우기 속도](#throttling-limits-cost-based) 단원을 참조하십시오.

## 요청 토큰 버킷 크기 및 다시 채우기 속도
<a name="throttling-limits-rate-based"></a>

요청 속도 제한을 위해 API 작업은 다음 범주로 그룹화됩니다.
+ **변경되지 않는 작업** - 리소스에 대한 데이터를 검색하는 API 작업입니다. 이 범주에는 일반적으로 `DescribeRouteTables`, `SearchTransitGatewayRoutes`, `GetIpamPoolCidrs` 등의 모든 `Describe*`, `List*`, `Search*`, `Get*` API 작업이 포함됩니다. 이러한 API 작업에는 일반적으로 API 스로틀링 제한이 가장 높습니다.
+ **필터링 및 페이지 매김되지 않은 변경 없는 작업** -[페이지 매김](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-pagination.html) 또는 [필터](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/Using_Filtering.html#Filtering_Resources_CLI)를 지정하지 않고 요청 시 더 작은 토큰 버킷의 토큰을 사용하는 변경 없는 API 작업의 특정 하위 집합입니다. 토큰이 표준(더 큰) 토큰 버킷에서 공제되도록 페이지 매김 및 필터링을 사용하는 것이 좋습니다.
+ **변경 작업** - 리소스를 생성, 수정 또는 삭제하는 API 작업입니다. 이 범주에는 일반적으로 `AllocateHosts`, `ModifyHosts`, `CreateCapacityReservation` 등 *변경되지 않는 작업*으로 분류되지 않는 모든 API 작업이 포함됩니다. 이러한 작업의 스로틀링 제한은 변경되지 않는 API 작업보다 낮습니다.
+ **리소스 집약적 작업** -완료하는 데 가장 많은 시간이 걸리고 가장 많은 리소스를 소비하는 API 변경 작업입니다. 이러한 작업의 스로틀링 제한은 *변경 작업*보다 훨씬 낮습니다. 다른 *변경 작업*과 별도로 스로틀링됩니다.
+ **콘솔 비변경 작업** - Amazon EC2 콘솔에서 요청되는 변경되지 않는 API 작업입니다. 이러한 API 작업은 변경되지 않는 다른 API 작업과 별도로 스로틀링됩니다.
+ **분류되지 않은 작업** - 정의상 다른 범주 중 하나에 해당하더라도 자체 토큰 버킷 크기와 다시 채우기 속도를 수신하는 API 작업입니다.


| API 작업 범주 | 작업 | 버킷 최대 용량 | 버킷 다시 채우기 속도 | 
| --- | --- | --- | --- | 
| 변경되지 않는 작업 |  다른 범주에 포함되지 않은 `Describe*`, `List*`, `Search*`, `Get*` API 작업입니다.  | 100 | 20 | 
| 필터링 및 페이지 매김되지 않은 변경 없는 작업 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/ec2/latest/devguide/ec2-api-throttling.html)  | 50 | 10 | 
| 변경 작업 | *리소스 집약적인 작업* 또는 *분류되지 않은 작업*이 아닌 모든 변경 API 작업입니다. | 50 | 5 | 
| 리소스 집약적인 작업 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/ec2/latest/devguide/ec2-api-throttling.html)  | 50 | 5 | 
| 콘솔 비변경 작업 |  Amazon EC2 콘솔에서 직접 호출하지만, 다른 범주에는 포함되지 않는 `Describe*`, `List*`, `Search*`, `Get*` API 작업입니다.  | 100 | 10 | <a name="uncategorized"></a>


| 분류되지 않은 작업 | 버킷 최대 용량 | 버킷 다시 채우기 속도 | 
| --- | --- | --- | 
| AcceptVpcEndpointConnections | 10 | 1 | 
| AdvertiseByoipCidr | 1 | 0.1 | 
| AssignIpv6Addresses | 100 | 5 | 
| AssignPrivateIpAddresses | 100 | 5 | 
| AssignPrivateNatGatewayAddress | 10 | 1 | 
| AssociateCapacityReservationBillingOwner | 1 | 0.5 | 
| AssociateEnclaveCertificateIamRole | 10 | 1 | 
| AssociateIamInstanceProfile | 100 | 5 | 
| AssociateNatGatewayAddress | 10 | 1 | 
| AttachVerifiedAccessTrustProvider | 10 | 2 | 
| AuthorizeClientVpnIngress | 5 | 2 | 
| CancelDeclarativePoliciesReport | 1 | 1 | 
| CopyImage | 100 | 1 | 
| CreateClientVpnRoute | 5 | 2 | 
| CreateCoipCidr | 5 | 1 | 
| CreateCoipPool | 5 | 1 | 
| CreateDefaultSubnet | 1 | 1 | 
| CreateDefaultVpc | 1 | 1 | 
| CreateLaunchTemplateVersion | 100 | 5 | 
| CreateNatGateway | 10 | 1 | 
| CreateNetworkInterface | 100 | 5 | 
| CreateRestoreImageTask | 50 | 0.1 | 
| CreateSnapshot | 100 | 5 | 
| CreateSnapshots | 100 | 5 | 
| CreateSpotDatafeedSubscription | 50 | 3 | 
| CreateStoreImageTask | 50 | 0.1 | 
| CreateSubnetCidrReservation | 5 | 1 | 
| CreateTags | 100 | 10 | 
| CreateVerifiedAccessEndpoint | 20 | 4 | 
| CreateVerifiedAccessGroup | 10 | 2 | 
| CreateVerifiedAccessInstance | 10 | 2 | 
| CreateVerifiedAccessTrustProvider | 10 | 2 | 
| CreateVolume | 100 | 5 | 
| CreateVpcEndpoint | 4 | 0.3 | 
| CreateVpcEndpointServiceConfiguration | 10 | 1 | 
| DeleteClientVpnRoute | 5 | 2 | 
| DeleteCoipCidr | 5 | 1 | 
| DeleteCoipPool | 5 | 1 | 
| DeleteCoipPoolPermission | 5 | 1 | 
| DeleteNatGateway | 10 | 1 | 
| DeleteNetworkInterface | 100 | 5 | 
| DeleteSnapshot | 100 | 5 | 
| DeleteSpotDatafeedSubscription | 50 | 3 | 
| DeleteSubnetCidrReservation | 5 | 1 | 
| DeleteQueuedReservedInstances | 5 | 5 | 
| DeleteTags | 100 | 10 | 
| DeleteVerifiedAccessEndpoint | 20 | 4 | 
| DeleteVerifiedAccessGroup | 10 | 2 | 
| DeleteVerifiedAccessInstance | 10 | 2 | 
| DeleteVerifiedAccessTrustProvider | 10 | 2 | 
| DeleteVolume | 100 | 5 | 
| DeleteVpcEndpoints | 4 | 0.3 | 
| DeleteVpcEndpointServiceConfigurations | 10 | 1 | 
| DeprovisionByoipCidr | 1 | 0.1 | 
| DeregisterImage | 100 | 5 | 
| DescribeAggregateIdFormat | 10 | 10 | 
| DescribeByoipCidrs | 1 | 0.5 | 
| DescribeCapacityBlockExtensionOfferings | 10 | 0.15 | 
| DescribeCapacityBlockOfferings | 10 | 0.15 | 
| DescribeDeclarativePoliciesReports | 5 | 5 | 
| DescribeHostReservations | 5 | 2 | 
| DescribeHostReservationOfferings | 5 | 2 | 
| DescribeIdentityIdFormat | 10 | 10 | 
| DescribeIdFormat | 10 | 10 | 
| DescribeInstanceTopology | 1 | 1 | 
| DescribeMovingAddresses | 1 | 1 | 
| DescribePrincipalIdFormat | 10 | 10 | 
| DescribeReservedInstancesOfferings | 10 | 10 | 
| DescribeSecurityGroupReferences | 20 | 5 | 
| DescribeSpotDatafeedSubscription | 100 | 13 | 
| DescribeSpotFleetInstances | 100 | 5 | 
| DescribeSpotFleetRequestHistory | 100 | 5 | 
| DescribeSpotFleetRequests | 50 | 3 | 
| DescribeStaleSecurityGroups | 20 | 5 | 
| DescribeStoreImageTasks | 50 | 0.5 | 
| DescribeVerifiedAccessInstanceLoggingConfigurations | 10 | 2 | 
| DetachVerifiedAccessTrustProvider | 10 | 2 | 
| DisableFastLaunch | 5 | 2 | 
| DisableImageBlockPublicAccess | 1 | 0.1 | 
| DisableSnapshotBlockPublicAccess | 1 | 0.1 | 
| DisassociateCapacityReservationBillingOwner | 1 | 0.5 | 
| DisassociateEnclaveCertificateIamRole | 10 | 1 | 
| DisassociateIamInstanceProfile | 100 | 5 | 
| DisassociateNatGatewayAddress | 10 | 1 | 
| EnableFastLaunch | 5 | 2 | 
| EnableImageBlockPublicAccess | 1 | 0.1 | 
| EnableSnapshotBlockPublicAccess | 1 | 0.1 | 
| GetAssociatedEnclaveCertificateIamRoles | 10 | 1 | 
| GetDeclarativePoliciesReportSummary | 5 | 5 | 
| GetHostReservationPurchasePreview | 5 | 2 | 
| ModifyImageAttribute | 100 | 5 | 
| ModifyInstanceMetadataDefaults | 2 | 2 | 
| ModifyInstanceMetadataOptions | 100 | 5 | 
| ModifyLaunchTemplate | 100 | 5 | 
| ModifyNetworkInterfaceAttribute | 100 | 5 | 
| ModifySnapshotAttribute | 100 | 5 | 
| ModifyVerifiedAccessEndpoint | 20 | 4 | 
| ModifyVerifiedAccessEndpointPolicy | 20 | 4 | 
| ModifyVerifiedAccessGroup | 10 | 2 | 
| ModifyVerifiedAccessGroupPolicy | 20 | 4 | 
| ModifyVerifiedAccessInstance | 10 | 2 | 
| ModifyVerifiedAccessInstanceLoggingConfiguration | 10 | 2 | 
| ModifyVerifiedAccessTrustProvider | 10 | 2 | 
| ModifyVpcEndpoint | 4 | 0.3 | 
| ModifyVpcEndpointServiceConfiguration | 10 | 1 | 
| MoveAddressToVpc | 1 | 1 | 
| ProvisionByoipCidr | 1 | 0.1 | 
| PurchaseCapacityBlock | 10 | 0.15 | 
| PurchaseCapacityBlockExtension | 10 | 0.15 | 
| PurchaseHostReservation | 5 | 2 | 
| PurchaseReservedInstancesOffering | 5 | 5 | 
| RejectVpcEndpointConnections | 10 | 1 | 
| RestoreAddressToClassic | 1 | 1 | 
| RevokeClientVpnIngress | 5 | 2 | 
| RunInstances | 5 | 2 | 
| StartDeclarativePoliciesReport | 1 | 1 | 
| StartInstances | 5 | 2 | 
| TerminateInstances | 100 | 5 | 
| UnassignPrivateIpAddresses | 100 | 5 | 
| UnassignPrivateNatGatewayAddress | 10 | 1 | 
| WithdrawByoipCidr | 1 | 0.1 | 

## 리소스 토큰 버킷 크기 및 다시 채우기 속도
<a name="throttling-limits-cost-based"></a>

다음 표에는 리소스 속도 제한을 사용하는 API 작업에 대한 리소스 토큰 버킷 크기 및 다시 채우기 속도가 나열되어 있습니다.


| API 작업 | 버킷 최대 용량 | 버킷 다시 채우기 속도 | 
| --- | --- | --- | 
| RunInstances | 1000 | 2 | 
| TerminateInstances | 1000 | 20 | 
| StartInstances | 1000 | 2 | 
| StopInstances | 1000 | 20 | 

## API 스로틀링 모니터링
<a name="throttling-monitor"></a>

Amazon CloudWatch를 사용하여 Amazon EC2 API 요청을 모니터링하고 API 스로틀링에 대한 지표를 수집하고 추적할 수 있습니다. API 스로틀링 제한에 근접했을 때 경고하는 경보를 생성할 수도 있습니다. 자세한 내용은 [Amazon CloudWatch를 사용하여 Amazon EC2 API 요청 모니터링CloudWatch를 사용하여 API 요청 모니터링](monitor.md) 단원을 참조하십시오.

## 재시도 및 지수 백오프
<a name="api-backoff"></a>

애플리케이션에서 API 요청을 다시 시도해야 할 수도 있습니다. 예:
+ 리소스 상태의 업데이트 확인
+ 대량의 리소스 열거(예: 모든 볼륨)
+ 서버 오류(5xx) 또는 스로틀링 오류로 실패한 후 요청 재시도

그러나 클라이언트 오류(4xx)의 경우, 요청을 다시 시도하기 전에 문제를 수정하도록 요청을 수정해야 합니다.

**리소스 상태 변경**  
상태 업데이트를 확인하기 위해 폴링을 시작하기 전에 요청이 완료될 수 있도록 시간을 주세요. 예를 들어, 인스턴스가 활성 상태인지 확인하기 전에 몇 분 정도 기다립니다. 폴링을 시작할 때는 연속적인 요청 사이의 적절한 휴면 간격을 적용하여 API 요청 속도를 낮추세요. 최상의 결과를 얻으려면 휴면 간격을 늘리거나 가변적으로 사용하세요.

또는 Amazon EventBridge를 사용하여 일부 리소스의 상태를 알릴 수 있습니다. 예를 들어, **EC2 인스턴스 상태 변경 알림** 이벤트를 사용하여 인스턴스의 상태 변경을 알릴 수 있습니다. 자세한 내용은 [EventBridge를 사용하여 Amazon EC2 자동화](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/automating_with_eventbridge.html)를 참조하세요.

**재시도**  
API 요청을 폴링하거나 재시도해야 하는 경우 지수 백오프 알고리즘을 사용하여 API 직접 요청 간 휴면 간격을 계산하는 것이 좋습니다. 지수 백오프의 기본 개념은 오류 응답이 연이어 나올 때마다 재시도 간 대기 시간을 점진적으로 늘리는 것입니다. 최대 지연 간격과 최대 재시도 횟수를 구현해야 합니다. 지터(무작위 지연)를 사용하여 연속적인 충돌을 방지할 수도 있습니다. 자세한 내용은 [시간 제한, 재시도 및 지터를 사용한 백오프](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/)를 참조하세요.

각 AWS SDK는 자동 재시도 로직을 구현합니다. 자세한 정보는AWS SDK 및 도구 참조 설명서**의 [재시도 동작](https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html)을 참조하세요.

## 한도 증가 요청
<a name="throttling-increase"></a>

 AWS 계정에 대해 API 스로틀링 제한 증가를 요청할 수 있습니다.

**권장 사항**
+ 단일 요청에서 기존 제한의 최대 3배를 요청합니다.
+ 버킷 최대 용량을 늘리기 전에 버킷 다시 채우기 속도 증가를 우선시합니다.
+ 요청된 버킷 다시 채우기 속도가 버킷 최대 용량을 초과하는 경우 버킷 최대 용량을 동시에 늘립니다.
+ 증가가 필요한 모든 API 작업을 제공합니다. 제한은 API 작업 범주가 아닌 개별 API 작업에 적용됩니다.
+ 다음 `RunInstances`, `StartInstances`, `StopInstances`, `TerminateInstances` API 작업에는 요청 속도와 리소스 속도 제한이 모두 적용됩니다. 어떤 제한을 늘려야 하는지 표시해야 합니다.

**이 기능에 대한 액세스를 요청하려면**

1. [AWS Support 센터](https://console.aws.amazon.com/support/home#/)를 엽니다.

1. **사례 생성**을 선택합니다.

1. **계정 및 결제 지원**을 선택합니다.

1. **서비스**에서 **일반 정보 및 시작하기**를 선택합니다.

1. **범주**에서 **사용 AWS 및 서비스를** 선택합니다.

1. **다음 단계: 추가 정보**를 선택합니다

1. **제목**에 **Request an increase in my Amazon EC2 API throttling limits**을 입력합니다.

1. **설명**에서 다음 템플릿을 복사하고 필요한 정보를 제공합니다.

   ```
   Please increase the API throttling limits for my account. 
   Related page: https://docs.aws.amazon.com/ec2/latest/devguide/ec2-api-throttling.html
   Description: Brief notes about your use case. If available, include the IDs
       of a few Amazon EC2 requests that were throttled.
   Time window: One-hour window when peak throttling or usage occurred.
   region_1 request rate increases:
       action: new_bucket_maximum_capacity
       action: new_bucket_refill_rate
       action: new_bucket_maximum_capacity|new_bucket_refill_rate
   region_1 resource rate increases:
       action: new_bucket_maximum_capacity
       action: new_bucket_refill_rate
       action: new_bucket_maximum_capacity|new_bucket_refill_rate
   region_2 request rate increases:
       action: new_bucket_maximum_capacity
       action: new_bucket_refill_rate
       action: new_bucket_maximum_capacity|new_bucket_refill_rate
   region_2 resource rate increases:
       action: new_bucket_maximum_capacity
       action: new_bucket_refill_rate
       action: new_bucket_maximum_capacity|new_bucket_refill_rate
   ```

1. **다음 단계: 지금 해결하거나 AWS에 문의하기**를 선택합니다.

1. **문의하기** 탭에서 연락 시 사용하고 싶은 언어와 연락 방법을 선택합니다.

1. **제출**을 선택합니다.

# Amazon EC2 API의 페이지 매김
<a name="ec2-api-pagination"></a>

`DescribeInstances`와 같이 잠재적으로 많은 결과를 반환할 수 있는 설명 작업을 직접 호출할 때 페이지 매김을 사용하는 것이 좋습니다. 페이지 매김을 사용하면 설명 직접 호출에서 반환되는 항목 수와 직접 호출이 반환되는 데 걸리는 시간이 제한됩니다. 리소스가 많은 경우 페이지가 지정되지 않은 직접 호출이 스로틀링되어 시간이 초과될 수 있습니다. 따라서 페이지가 매겨진 직접 호출은 페이지가 매겨지지 않은 직접 호출보다 전체 지연 시간이 더 우수합니다. 페이지가 매겨진 직접 호출은 일관되게 성공하기 때문입니다.

자세한 내용은 *Amazon EC2 API Reference*(Amazon EC2 API 레퍼런스)의 [Pagination](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Query-Requests.html#api-pagination)(페이지네이션)을 참조하세요.

## 모범 사례
<a name="pagination-best-practices"></a>

가능하면 설명 직접 호출에 리소스 ID 목록을 지정합니다. 이는 많은 리소스를 설명하는 가장 빠른 방법입니다. 단, 직접 호출 한 번에 1,000개 이상의 ID를 지정해서는 안 됩니다. 다음은 예입니다.

```
private List<Reservation> describeMyInstances(List<String> ids){
    if (ids == null || ids.isEmpty()) {
        return ImmutableList.of();
    }
        
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withInstanceIds(ids);

    return ec2.describeInstances(request).getReservations();
}
```

설명 직접 호출에 리소스 ID를 지정할 수 없는 경우 페이지 매김을 사용하는 것이 좋습니다. 다음은 예입니다.

```
private List<Reservation> describeMyInstances(final Collection<Filter> filters){
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withFilters(filters)
            .withMaxResults(1000);

    List<Reservation> reservations = new ArrayList<>();
    String nextToken = null;
    do {
        request.setNextToken(nextToken);
        final DescribeInstancesResult response = ec2.describeInstances(request);
        reservations.addAll(response.getReservations());
        nextToken = response.getNextToken();
    } while (nextToken != null);

    return reservations;
}
```

페이지가 매겨진 직접 호출을 다시 시도해야 하는 경우 [지터와 함께 지수 백오프](ec2-api-throttling.md#api-backoff)를 사용합니다.

## 일반적인 문제
<a name="pagination-common-issues"></a>

다음은 실수로 페이지가 지정되지 않은 직접 호출을 수행하는 코드의 예제입니다.

**Example 예제 문제: 빈 리소스 ID 목록 전달**  
다음 코드는 ID 목록을 사용합니다. 그러나 목록이 비어 있으면 페이지가 지정되지 않은 직접 호출이 발생합니다.  

```
private List<Reservation> describeMyInstances(List<String> ids){
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withInstanceIds(ids);

    return ec2.describeInstances(request).getReservations();
}
```
이 문제를 해결하려면 설명 직접 호출을 수행하기 전에 목록이 비어 있지 않은지 확인합니다.  

```
private List<Reservation> describeMyInstances(List<String> ids){
    if (ids == null || ids.isEmpty()) {
        return ImmutableList.of();
        // OR
        return Lists.newArrayList();
        // OR
        return new ArrayList<>();
    }
        
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withInstanceIds(ids);

    return ec2.describeInstances(request).getReservations();
}
```

**Example 예제 문제: MaxResults가 설정되지 않음**  
다음 코드는 `nextToken`을 확인하고 사용하지만, `MaxResults`를 설정하지는 않습니다.  

```
private List<Reservation> describeMyInstances(final Collection<Filter> filters){
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withFilters(filters);

    List<Reservation> reservations = new ArrayList<>();
    String nextToken = null;
    do {
        request.setNextToken(nextToken);
        final DescribeInstancesResult response = ec2.describeInstances(request);
        reservations.addAll(response.getReservations());
        nextToken = response.getNextToken();
    } while (nextToken != null);

    return reservations;
}
```
이 문제를 해결하려면 다음과 같이 `withMaxResults`를 추가합니다.  

```
private List<Reservation> describeMyInstances(final Collection<Filter> filters){
    final DescribeInstancesRequest request = new DescribeInstancesRequest()
            .withFilters(filters)
            .withMaxResults(1000);

    List<Reservation> reservations = new ArrayList<>();
    String nextToken = null;
    do {
        request.setNextToken(nextToken);
        final DescribeInstancesResult response = ec2.describeInstances(request);
        reservations.addAll(response.getReservations());
        nextToken = response.getNextToken();
    } while (nextToken != null);

    return reservations;
}
```