

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

# Amazon SNS 및 Amazon S3 S3를 사용하여 대용량 메시지 게시
<a name="large-message-payloads"></a>

대용량 Amazon SNS 메시지를 게시하려면 [Java용 Amazon SNS 확장 클라이언트 라이브러리](https://github.com/awslabs/amazon-sns-java-extended-client-lib/) 또는 [Python용 Amazon SNS 확장 클라이언트 라이브러리](https://github.com/awslabs/amazon-sns-python-extended-client-lib)를 사용할 수 있습니다. 이 라이브러리는 현재 최대값인 256KB(최대 2GB)보다 큰 메시지에 유용합니다. 모든 라이브러리는 실제 페이로드를 Amazon S3 버킷에 저장하고 저장된 Amazon S3 객체의 참조를 Amazon SNS 주제에 게시합니다. 구독한 Amazon SQS 대기열은 [Java용 Amazon SQS 확장 클라이언트 라이브러리](https://github.com/awslabs/amazon-sqs-java-extended-client-lib)를 사용하여 Amazon S3에서 페이로드를 역참조하고 검색할 수 있습니다. Lambda와 같은 다른 엔드포인트는 [AWS용 페이로드 오프로딩 Java 공통 라이브러리](https://github.com/awslabs/payload-offloading-java-common-lib-for-aws)를 사용하여 페이로드를 역참조 및 검색할 수 있습니다.

**참고**  
Amazon SNS 확장 클라이언트 라이브러리는 표준 및 FIFO 주제와 호환됩니다.

# Java용 Amazon SNS 확장 클라이언트 라이브러리
<a name="extended-client-library-java"></a>

## 사전 조건
<a name="prereqs-sns-extended-client-library"></a>

다음은 [Java용 Amazon SNS 확장 클라이언트 라이브러리](https://github.com/awslabs/amazon-sns-java-extended-client-lib) 사용을 위한 사전 조건입니다.
+  AWS SDK. 이 페이지의 예제에서는 AWS Java SDK를 사용합니다. SDK를 설치하고 설정하려면 *AWS SDK for Java 개발자 안내서*[의 Java용 AWS SDK 설정을](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-install.html) 참조하세요.
+ 적절한 자격 증명이 AWS 계정 있는 . 를 생성하려면 [AWS 홈 페이지로](https://aws.amazon.com/) AWS 계정이동한 다음 ** AWS 계정 생성을** 선택합니다. 지침을 따릅니다.

  자격 증명에 대한 자세한 내용은 *AWS SDK for Java 개발자 안내서*의 [개발을 위한 AWS 자격 증명 및 리전 설정을](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-credentials.html) 참조하세요.
+ Java 8 이상.
+ Java용 Amazon SNS 확장 클라이언트 라이브러리([Maven](https://maven.apache.org/)에서도 사용 가능).

## 메시지 스토리지 구성
<a name="large-message-configure-storage"></a>

Amazon SNS 확장 클라이언트 라이브러리는 메시지 저장 및 검색을 AWS 위해 용 페이로드 오프로딩 Java 공통 라이브러리를 사용합니다. 다음 Amazon S3 [메시지 스토리지 옵션](https://github.com/awslabs/amazon-sns-java-extended-client-lib/blob/main/src/main/java/software/amazon/sns/SNSExtendedClientConfiguration.java)을 구성할 수 있습니다.
+ **사용자 지정 메시지 크기 임곗값** – 페이로드 및 속성이 이 크기를 초과하는 메시지는 Amazon S3에 자동으로 저장됩니다.
+ **`alwaysThroughS3` 플래그** - 이 값을 `true`로 설정하여 모든 메시지 페이로드가 Amazon S3에 강제로 저장되도록 합니다. 예:

  ```
  SNSExtendedClientConfiguration snsExtendedClientConfiguration = new
  SNSExtendedClientConfiguration() .withPayloadSupportEnabled(s3Client, BUCKET_NAME).withAlwaysThroughS3(true);
  ```
+ **사용자 지정 KMS 키** – Amazon S3 버킷에서 서버 측 암호화에 사용할 키입니다.
+ **버킷 이름** - 메시지 페이로드를 저장하기 위한 Amazon S3 버킷의 이름입니다.

## 예: Amazon S3에 저장된 페이로드로 Amazon SNS에 메시지 게시
<a name="example-s3-large-payloads"></a>

다음 코드 예제에서는 다음과 같은 작업을 수행하는 방법을 보여줍니다.
+ 샘플 주제 및 대기열을 만듭니다.
+ 대기열에서 구독하여 주제의 메시지를 수신합니다.
+ 테스트 메시지를 게시합니다.

메시지 페이로드는 Amazon S3에 저장되고 이에 대한 참조가 게시됩니다. Amazon SQS 확장 클라이언트는 메시지를 수신하는 데 사용됩니다.

**Java 1.x용 SDK**  
 GitHub에 더 많은 내용이 있습니다. [AWS 코드 예 리포지토리](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/java/example_code/sns#code-examples)에서 전체 예를 찾고 설정 및 실행하는 방법을 배워보세요.
대용량 메시지를 게시하려면 Java용 Amazon SNS 확장 클라이언트 라이브러리를 사용하세요. 보내는 메시지는 실제 메시지 내용이 포함된 Amazon S3 객체를 참조합니다.  

```
import com.amazon.sqs.javamessaging.AmazonSQSExtendedClient;
import com.amazon.sqs.javamessaging.ExtendedClientConfiguration;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.sns.AmazonSNS;
import com.amazonaws.services.sns.AmazonSNSClientBuilder;
import com.amazonaws.services.sns.model.CreateTopicRequest;
import com.amazonaws.services.sns.model.PublishRequest;
import com.amazonaws.services.sns.model.SetSubscriptionAttributesRequest;
import com.amazonaws.services.sns.util.Topics;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
import com.amazonaws.services.sqs.model.CreateQueueRequest;
import com.amazonaws.services.sqs.model.ReceiveMessageResult;
import software.amazon.sns.AmazonSNSExtendedClient;
import software.amazon.sns.SNSExtendedClientConfiguration;

public class Example {

        public static void main(String[] args) {
                final String BUCKET_NAME = "extended-client-bucket";
                final String TOPIC_NAME = "extended-client-topic";
                final String QUEUE_NAME = "extended-client-queue";
                final Regions region = Regions.DEFAULT_REGION;

                // Message threshold controls the maximum message size that will be allowed to
                // be published
                // through SNS using the extended client. Payload of messages exceeding this
                // value will be stored in
                // S3. The default value of this parameter is 256 KB which is the maximum
                // message size in SNS (and SQS).
                final int EXTENDED_STORAGE_MESSAGE_SIZE_THRESHOLD = 32;

                // Initialize SNS, SQS and S3 clients
                final AmazonSNS snsClient = AmazonSNSClientBuilder.standard().withRegion(region).build();
                final AmazonSQS sqsClient = AmazonSQSClientBuilder.standard().withRegion(region).build();
                final AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion(region).build();

                // Create bucket, topic, queue and subscription
                s3Client.createBucket(BUCKET_NAME);
                final String topicArn = snsClient.createTopic(
                                new CreateTopicRequest().withName(TOPIC_NAME)).getTopicArn();
                final String queueUrl = sqsClient.createQueue(
                                new CreateQueueRequest().withQueueName(QUEUE_NAME)).getQueueUrl();
                final String subscriptionArn = Topics.subscribeQueue(
                                snsClient, sqsClient, topicArn, queueUrl);

                // To read message content stored in S3 transparently through SQS extended
                // client,
                // set the RawMessageDelivery subscription attribute to TRUE
                final SetSubscriptionAttributesRequest subscriptionAttributesRequest = new SetSubscriptionAttributesRequest();
                subscriptionAttributesRequest.setSubscriptionArn(subscriptionArn);
                subscriptionAttributesRequest.setAttributeName("RawMessageDelivery");
                subscriptionAttributesRequest.setAttributeValue("TRUE");
                snsClient.setSubscriptionAttributes(subscriptionAttributesRequest);

                // Initialize SNS extended client
                // PayloadSizeThreshold triggers message content storage in S3 when the
                // threshold is exceeded
                // To store all messages content in S3, use AlwaysThroughS3 flag
                final SNSExtendedClientConfiguration snsExtendedClientConfiguration = new SNSExtendedClientConfiguration()
                                .withPayloadSupportEnabled(s3Client, BUCKET_NAME)
                                .withPayloadSizeThreshold(EXTENDED_STORAGE_MESSAGE_SIZE_THRESHOLD);
                final AmazonSNSExtendedClient snsExtendedClient = new AmazonSNSExtendedClient(snsClient,
                                snsExtendedClientConfiguration);

                // Publish message via SNS with storage in S3
                final String message = "This message is stored in S3 as it exceeds the threshold of 32 bytes set above.";
                snsExtendedClient.publish(topicArn, message);

                // Initialize SQS extended client
                final ExtendedClientConfiguration sqsExtendedClientConfiguration = new ExtendedClientConfiguration()
                                .withPayloadSupportEnabled(s3Client, BUCKET_NAME);
                final AmazonSQSExtendedClient sqsExtendedClient = new AmazonSQSExtendedClient(sqsClient,
                                sqsExtendedClientConfiguration);

                // Read the message from the queue
                final ReceiveMessageResult result = sqsExtendedClient.receiveMessage(queueUrl);
                System.out.println("Received message is " + result.getMessages().get(0).getBody());
        }
}
```

## 기타 엔드포인트 프로토콜
<a name="large-payloads-other-protocols"></a>

Amazon SNS 및 Amazon SQS 라이브러리는 모두 [AWS용 페이로드 오프로딩 Java 공통 라이브러리](https://github.com/awslabs/payload-offloading-java-common-lib-for-aws)를 사용하여 Amazon S3로 메시지 페이로드를 저장하고 검색합니다. 모든 Java 지원 엔드포인트(예: Java로 구현된 HTTPS 엔드포인트)는 동일한 라이브러리를 사용하여 메시지 콘텐츠를 역참조할 수 있습니다.

용 페이로드 오프로딩 Java 공통 라이브러리를 사용할 수 없는 엔드포인트는 여전히 Amazon S3에 저장된 페이로드가 있는 메시지를 게시할 AWS 수 있습니다. 다음은 위의 코드 예제에서 게시한 Amazon S3 참조의 예입니다.

```
[
  "software.amazon.payloadoffloading.PayloadS3Pointer",
  {
    "s3BucketName": "extended-client-bucket",
    "s3Key": "xxxx-xxxxx-xxxxx-xxxxxx"
  }
]
```

# Python용 Amazon SNS 확장 클라이언트 라이브러리
<a name="extended-client-library-python"></a>

## 사전 조건
<a name="prereqs-sns-extended-client-library-python"></a>

다음은 [Python용 Amazon SNS 확장 클라이언트 라이브러리](https://github.com/awslabs/amazon-sns-python-extended-client-lib) 사용을 위한 사전 조건입니다.
+  AWS SDK. 이 페이지의 예제에서는 AWS Python SDK Boto3를 사용합니다. SDK를 설치하고 설정하려면 [https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html) 설명서를 참조하세요.
+ 적절한 자격 증명이 AWS 계정 있는 . 를 생성하려면 [AWS 홈 페이지로](https://aws.amazon.com/) AWS 계정이동한 다음 ** AWS 계정 생성을** 선택합니다. 지침을 따릅니다.

  자격 증명에 대한 자세한 내용은 *Python용AWS SDK 개발자 안내서*에서 [자격 증명](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html)을 참조하세요.
+ Python 3.x (또는 이후 버전) 및 pip.
+ Python용 Amazon SNS 확장 클라이언트 라이브러리([PyPI](https://pypi.org/project/amazon-sns-extended-client/)에서도 사용 가능).

## 메시지 스토리지 구성
<a name="large-message-configure-storage-python"></a>

아래 속성은 Boto3 Amazon SNS [클라이언트](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sns.html#client), [주제](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sns/topic/index.html) 및 [PlatformEndpoint](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sns/platformendpoint/index.html) 객체에서 사용할 수 있어 Amazon S3 메시지 스토리지 옵션을 구성할 수 있습니다.
+ **`large_payload_support`** - 대용량 메시지를 저장하는 Amazon S3 버킷 이름입니다.
+ **`use_legacy_attribute`**: `True`인 경우 게시된 모든 메시지는 현재 예약된 메시지 속성(`ExtendedPayloadSize`) 대신 이전 예약 메시지 속성(`SQSLargePayloadSize`)을 사용합니다.
+ **`message_size_threshold`** — 대용량 메시지 버킷에 메시지를 저장하기 위한 임계값입니다. 값은 `0` 이하 또는 `262144` 이상이면 안 됩니다. 기본값은 `262144`입니다.
+ **`always_through_s3`** - `True`인 경우 모든 메시지가 Amazon S3에 저장됩니다. 기본값은 `False`입니다.
+ **`s3_client`** - Amazon S3에 `client` 객체를 저장하는 데 사용되는 Boto3 Amazon S3 객체입니다. Amazon S3 클라이언트(예: 사용자 지정 Amazon S3 구성 또는 자격 증명)를 제어하려면 이 옵션을 사용하세요. 처음 사용할 때 이전에 설정하지 않은 경우 기본값은 `boto3.client("s3")`입니다.

## 예: Amazon S3에 저장된 페이로드로 Amazon SNS에 메시지 게시
<a name="example-s3-large-payloads-python"></a>

다음 코드 예제에서는 다음과 같은 작업을 수행하는 방법을 보여줍니다.
+ 샘플 Amazon SNS 주제 및 Amazon SQS 대기열을 생성합니다.
+ 정책을 Amazon SQS 대기열에 연결하여 Amazon SNS 주제에서 메시지를 수신합니다.
+ 대기열에서 구독하여 주제의 메시지를 수신합니다.
+ Amazon SNS 확장 클라이언트, 주제 리소스 및 PlatformEndpoint 리소스를 사용하여 테스트 메시지를 게시합니다.
+ 메시지 페이로드는 Amazon S3에 저장되고 이에 대한 참조가 게시됩니다.
+ 대기열에 게시된 메시지를 Amazon S3에서 검색된 원본 메시지와 함께 인쇄합니다.

대용량 메시지를 게시하려면 Python용 Amazon SNS 확장 클라이언트 라이브러리를 사용하세요. 보내는 메시지는 실제 메시지 내용이 포함된 Amazon S3 객체를 참조합니다.

```
import boto3
from sns_extended_client import SNSExtendedClientSession
from json import loads

s3_extended_payload_bucket = "extended-client-bucket-store"  # S3 bucket with the given bucket name is a resource which is created and accessible with the given AWS credentials
TOPIC_NAME = "---TOPIC-NAME---"
QUEUE_NAME = "---QUEUE-NAME---"

def allow_sns_to_write_to_sqs(topicarn, queuearn):
    policy_document = """{{
        "Version": "2012-10-17",		 	 	 
        "Statement":[
            {{
            "Sid":"MyPolicy",
            "Effect":"Allow",
            "Principal" : {{"AWS" : "*"}},
            "Action":"SQS:SendMessage",
            "Resource": "{}",
            "Condition":{{
                "ArnEquals":{{
                "aws:SourceArn": "{}"
                }}
            }}
            }}
        ]
        }}""".format(queuearn, topicarn)

    return policy_document

def get_msg_from_s3(body,sns_extended_client):
    """Handy Helper to fetch message from S3"""
    json_msg = loads(body)
    s3_object = sns_extended_client.s3_client.get_object(
        Bucket=json_msg[1].get("s3BucketName"), Key=json_msg[1].get("s3Key")
    )
    msg = s3_object.get("Body").read().decode()
    return msg


def fetch_and_print_from_sqs(sqs, queue_url,sns_extended_client):
    sqs_msg = sqs.receive_message(
        QueueUrl=queue_url,
        AttributeNames=['All'],
        MessageAttributeNames=['All'],
        VisibilityTimeout=0,
        WaitTimeSeconds=0,
        MaxNumberOfMessages=1
    ).get("Messages")[0]
    
    message_body = sqs_msg.get("Body")
    print("Published Message: {}".format(message_body))
    print("Message Stored in S3 Bucket is: {}\n".format(get_msg_from_s3(message_body,sns_extended_client)))

    # Delete the Processed Message
    sqs.delete_message(
        QueueUrl=queue_url,
        ReceiptHandle=sqs_msg['ReceiptHandle']
    )


sns_extended_client = boto3.client("sns", region_name="us-east-1")
create_topic_response = sns_extended_client.create_topic(Name=TOPIC_NAME)
sns_topic_arn = create_topic_response.get("TopicArn")

# create and subscribe an sqs queue to the sns client
sqs = boto3.client("sqs",region_name="us-east-1")
demo_queue_url = sqs.create_queue(QueueName=QUEUE_NAME).get("QueueUrl")
sqs_queue_arn = sqs.get_queue_attributes(
    QueueUrl=demo_queue_url, AttributeNames=["QueueArn"]
)["Attributes"].get("QueueArn")

# Adding policy to SQS queue such that SNS topic can send msg to SQS queue
policy_json = allow_sns_to_write_to_sqs(sns_topic_arn, sqs_queue_arn)
response = sqs.set_queue_attributes(
    QueueUrl = demo_queue_url,
    Attributes = {
        'Policy' : policy_json
    }
)

# Set the RawMessageDelivery subscription attribute to TRUE if you want to use
# SQSExtendedClient to help with retrieving msg from S3
sns_extended_client.subscribe(TopicArn=sns_topic_arn, Protocol="sqs", 
Endpoint=sqs_queue_arn
, Attributes={"RawMessageDelivery":"true"}
)

sns_extended_client.large_payload_support = s3_extended_payload_bucket

# Change default s3_client attribute of sns_extended_client to use 'us-east-1' region
sns_extended_client.s3_client = boto3.client("s3", region_name="us-east-1")


# Below is the example that all the messages will be sent to the S3 bucket
sns_extended_client.always_through_s3 = True
sns_extended_client.publish(
    TopicArn=sns_topic_arn, Message="This message should be published to S3"
)
print("\n\nPublished using SNS extended client:")
fetch_and_print_from_sqs(sqs, demo_queue_url,sns_extended_client)  # Prints message stored in s3

# Below is the example that all the messages larger than 32 bytes will be sent to the S3 bucket
print("\nUsing decreased message size threshold:")

sns_extended_client.always_through_s3 = False
sns_extended_client.message_size_threshold = 32
sns_extended_client.publish(
    TopicArn=sns_topic_arn,
    Message="This message should be published to S3 as it exceeds the limit of the 32 bytes",
)

fetch_and_print_from_sqs(sqs, demo_queue_url,sns_extended_client)  # Prints message stored in s3


# Below is the example to publish message using the SNS.Topic resource
sns_extended_client_resource = SNSExtendedClientSession().resource(
    "sns", region_name="us-east-1"
)

topic = sns_extended_client_resource.Topic(sns_topic_arn)
topic.large_payload_support = s3_extended_payload_bucket

# Change default s3_client attribute of topic to use 'us-east-1' region
topic.s3_client = boto3.client("s3", region_name="us-east-1")

topic.always_through_s3 = True
# Can Set custom S3 Keys to be used to store objects in S3
topic.publish(
    Message="This message should be published to S3 using the topic resource",
    MessageAttributes={
        "S3Key": {
            "DataType": "String",
            "StringValue": "347c11c4-a22c-42e4-a6a2-9b5af5b76587",
        }
    },
)
print("\nPublished using Topic Resource:")
fetch_and_print_from_sqs(sqs, demo_queue_url,topic)

# Below is the example to publish message using the SNS.PlatformEndpoint resource
sns_extended_client_resource = SNSExtendedClientSession().resource(
    "sns", region_name="us-east-1"
)

platform_endpoint = sns_extended_client_resource.PlatformEndpoint(sns_topic_arn)
platform_endpoint.large_payload_support = s3_extended_payload_bucket

# Change default s3_client attribute of platform_endpoint to use 'us-east-1' region
platform_endpoint.s3_client = boto3.client("s3", region_name="us-east-1")

platform_endpoint.always_through_s3 = True
# Can Set custom S3 Keys to be used to store objects in S3
platform_endpoint.publish(
    Message="This message should be published to S3 using the PlatformEndpoint resource",
    MessageAttributes={
        "S3Key": {
            "DataType": "String",
            "StringValue": "247c11c4-a22c-42e4-a6a2-9b5af5b76587",
        }
    },
)
print("\nPublished using PlatformEndpoint Resource:")
fetch_and_print_from_sqs(sqs, demo_queue_url,platform_endpoint)
```

**출력**

```
Published using SNS extended client:
Published Message: ["software.amazon.payloadoffloading.PayloadS3Pointer", {"s3BucketName": "extended-client-bucket-store", "s3Key": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}]
Message Stored in S3 Bucket is: This message should be published to S3

Using decreased message size threshold:
Published Message: ["software.amazon.payloadoffloading.PayloadS3Pointer", {"s3BucketName": "extended-client-bucket-store", "s3Key": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}]
Message Stored in S3 Bucket is: This message should be published to S3 as it exceeds the limit of the 32 bytes

Published using Topic Resource:
Published Message: ["software.amazon.payloadoffloading.PayloadS3Pointer", {"s3BucketName": "extended-client-bucket-store", "s3Key": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}]
Message Stored in S3 Bucket is: This message should be published to S3 using the topic resource

Published using PlatformEndpoint Resource:
Published Message: ["software.amazon.payloadoffloading.PayloadS3Pointer", {"s3BucketName": "extended-client-bucket-store", "s3Key": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}]
Message Stored in S3 Bucket is: This message should be published to S3 using the PlatformEndpoint resource
```