

# 교차 오리진 리소스 공유(CORS) 구성
<a name="enabling-cors-examples"></a>

CORS(Cross-origin 리소스 공유)는 한 도메인에서 로드되어 다른 도메인에 있는 리소스와 상호 작용하는 클라이언트 웹 애플리케이션에 대한 방법을 정의합니다. CORS 지원을 통해 Amazon S3으로 다양한 기능의 클라이언트 측 웹 애플리케이션을 구축하고, Amazon S3 리소스에 대한 Cross-Origin 액세스를 선택적으로 허용할 수 있습니다.

이 섹션에서는 Amazon S3 콘솔, Amazon S3 REST API 및 AWS SDK를 사용하여 CORS를 사용하는 방법을 보여줍니다. 교차 오리진 요청을 허용하도록 버킷을 구성하려면 해당 버킷에 CORS 구성을 추가합니다. CORS 구성은 버킷에 대한 액세스를 허용할 오리진과 각 오리진에 대해 지원되는 작업(HTTP 메서드) 그리고 기타 작업별 정보를 각각 식별하는 규칙과 기타 작업별 정보를 포함하는 문서입니다. S3 콘솔에서 CORS 구성은 JSON 문서여야 합니다.

JSON 및 XML의 CORS 구성 예제는 [CORS 구성의 요소](ManageCorsUsing.md) 섹션을 참조하십시오.

## S3 콘솔 사용
<a name="add-cors-configuration"></a>

이 섹션에서는 Amazon S3 콘솔을 사용하여 S3 버킷에 CORS(Cross-Origin 리소스 공유) 구성을 추가하는 방법을 설명합니다.

버킷에 대해 CORS를 사용 설정하면 ACL(액세스 제어 목록)과 기타 액세스 권한 정책이 계속 적용됩니다.

**중요**  
S3 콘솔에서 CORS 구성은 JSON이어야 합니다. JSON 및 XML의 CORS 구성 예제는 [CORS 구성의 요소](ManageCorsUsing.md) 섹션을 참조하십시오.

**S3 버킷에 CORS 구성 추가**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)에서 Amazon S3 콘솔을 엽니다.

1. 왼쪽 탐색 창에서 **범용 버킷**을 선택합니다.

1. 버킷 목록에서 버킷 정책을 만들 버킷의 이름을 선택합니다.

1. **Permissions**를 선택합니다.

1. **CORS(Cross-Origin 리소스 공유)** 섹션에서 **편집**을 선택합니다.

1. **CORS 구성 편집기** 텍스트 상자에 새 CORS 구성을 입력하거나 복사하여 붙여넣거나, 기존 구성을 편집합니다.

   CORS 구성은 JSON 파일입니다. 편집기에 입력하는 텍스트는 유효한 JSON이어야 합니다. 자세한 내용은 [CORS 구성의 요소](ManageCorsUsing.md) 섹션을 참조하세요.

1. [**변경 사항 저장(Save changes)**]을 선택합니다.
**참고**  
Amazon S3는 **CORS 구성 편집기** 제목 옆에 버킷의 Amazon 리소스 이름(ARN)을 표시합니다. ARN에 대한 자세한 내용은 *Amazon Web Services 일반 참조*의 [Amazon 리소스 이름(ARN) 및 AWS 서비스 네임스페이스](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)를 참조하세요.

## AWS SDK 사용
<a name="ManageCorsUsingSDK"></a>

AWS SDK를 사용하여 버킷에 대한 cross-origin 리소스 공유(CORS)를 관리할 수 있습니다. CORS에 대한 자세한 내용은 [교차 오리진 리소스 공유(CORS) 사용](cors.md) 섹션을 참조하십시오.

 다음 예제를 고려하십시오.
+ CORS 구성을 만들고 버킷에 구성 설정
+ 구성을 검색하고 규칙을 추가하여 구성 수정
+ 버킷에 수정된 구성 추가
+ 구성 삭제

------
#### [ Java ]

**Example**  

**Example**  
 실제 예제를 작성하여 테스트하는 방법에 대한 자세한 내용은 AWS SDK for Java 개발자 안내서에서 [시작하기](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html) 섹션을 참조하세요.  

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.BucketCrossOriginConfiguration;
import com.amazonaws.services.s3.model.CORSRule;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CORS {

    public static void main(String[] args) throws IOException {
        Regions clientRegion = Regions.DEFAULT_REGION;
        String bucketName = "*** Bucket name ***";

        // Create two CORS rules.
        List<CORSRule.AllowedMethods> rule1AM = new ArrayList<CORSRule.AllowedMethods>();
        rule1AM.add(CORSRule.AllowedMethods.PUT);
        rule1AM.add(CORSRule.AllowedMethods.POST);
        rule1AM.add(CORSRule.AllowedMethods.DELETE);
        CORSRule rule1 = new CORSRule().withId("CORSRule1").withAllowedMethods(rule1AM)
                .withAllowedOrigins(Arrays.asList("http://*.example.com"));

        List<CORSRule.AllowedMethods> rule2AM = new ArrayList<CORSRule.AllowedMethods>();
        rule2AM.add(CORSRule.AllowedMethods.GET);
        CORSRule rule2 = new CORSRule().withId("CORSRule2").withAllowedMethods(rule2AM)
                .withAllowedOrigins(Arrays.asList("*")).withMaxAgeSeconds(3000)
                .withExposedHeaders(Arrays.asList("x-amz-server-side-encryption"));

        List<CORSRule> rules = new ArrayList<CORSRule>();
        rules.add(rule1);
        rules.add(rule2);

        // Add the rules to a new CORS configuration.
        BucketCrossOriginConfiguration configuration = new BucketCrossOriginConfiguration();
        configuration.setRules(rules);

        try {
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withCredentials(new ProfileCredentialsProvider())
                    .withRegion(clientRegion)
                    .build();

            // Add the configuration to the bucket.
            s3Client.setBucketCrossOriginConfiguration(bucketName, configuration);

            // Retrieve and display the configuration.
            configuration = s3Client.getBucketCrossOriginConfiguration(bucketName);
            printCORSConfiguration(configuration);

            // Add another new rule.
            List<CORSRule.AllowedMethods> rule3AM = new ArrayList<CORSRule.AllowedMethods>();
            rule3AM.add(CORSRule.AllowedMethods.HEAD);
            CORSRule rule3 = new CORSRule().withId("CORSRule3").withAllowedMethods(rule3AM)
                    .withAllowedOrigins(Arrays.asList("http://www.example.com"));

            rules = configuration.getRules();
            rules.add(rule3);
            configuration.setRules(rules);
            s3Client.setBucketCrossOriginConfiguration(bucketName, configuration);

            // Verify that the new rule was added by checking the number of rules in the
            // configuration.
            configuration = s3Client.getBucketCrossOriginConfiguration(bucketName);
            System.out.println("Expected # of rules = 3, found " + configuration.getRules().size());

            // Delete the configuration.
            s3Client.deleteBucketCrossOriginConfiguration(bucketName);
            System.out.println("Removed CORS configuration.");

            // Retrieve and display the configuration to verify that it was
            // successfully deleted.
            configuration = s3Client.getBucketCrossOriginConfiguration(bucketName);
            printCORSConfiguration(configuration);
        } catch (AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process
            // it, so it returned an error response.
            e.printStackTrace();
        } catch (SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }

    private static void printCORSConfiguration(BucketCrossOriginConfiguration configuration) {
        if (configuration == null) {
            System.out.println("Configuration is null.");
        } else {
            System.out.println("Configuration has " + configuration.getRules().size() + " rules\n");

            for (CORSRule rule : configuration.getRules()) {
                System.out.println("Rule ID: " + rule.getId());
                System.out.println("MaxAgeSeconds: " + rule.getMaxAgeSeconds());
                System.out.println("AllowedMethod: " + rule.getAllowedMethods());
                System.out.println("AllowedOrigins: " + rule.getAllowedOrigins());
                System.out.println("AllowedHeaders: " + rule.getAllowedHeaders());
                System.out.println("ExposeHeader: " + rule.getExposedHeaders());
                System.out.println();
            }
        }
    }
}
```

------
#### [ .NET ]

**Example**  
코드 예제 설정 및 실행에 대한 자세한 내용은 *AWS SDK for .NET 개발자 안내서*의 [AWS SDK for .NET 시작하기](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)를 참조하세요.  

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class CORSTest
    {
        private const string bucketName = "*** bucket name ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2; 
        private static IAmazonS3 s3Client;

        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            CORSConfigTestAsync().Wait();
        }
        private static async Task CORSConfigTestAsync()
        {
            try
            {
                // Create a new configuration request and add two rules    
                CORSConfiguration configuration = new CORSConfiguration
                {
                    Rules = new System.Collections.Generic.List<CORSRule>
                        {
                          new CORSRule
                          {
                            Id = "CORSRule1",
                            AllowedMethods = new List<string> {"PUT", "POST", "DELETE"},
                            AllowedOrigins = new List<string> {"http://*.example.com"}
                          },
                          new CORSRule
                          {
                            Id = "CORSRule2",
                            AllowedMethods = new List<string> {"GET"},
                            AllowedOrigins = new List<string> {"*"},
                            MaxAgeSeconds = 3000,
                            ExposeHeaders = new List<string> {"x-amz-server-side-encryption"}
                          }
                        }
                };

                // Add the configuration to the bucket. 
                await PutCORSConfigurationAsync(configuration);

                // Retrieve an existing configuration. 
                configuration = await RetrieveCORSConfigurationAsync();

                // Add a new rule.
                configuration.Rules.Add(new CORSRule
                {
                    Id = "CORSRule3",
                    AllowedMethods = new List<string> { "HEAD" },
                    AllowedOrigins = new List<string> { "http://www.example.com" }
                });

                // Add the configuration to the bucket. 
                await PutCORSConfigurationAsync(configuration);

                // Verify that there are now three rules.
                configuration = await RetrieveCORSConfigurationAsync();
                Console.WriteLine();
                Console.WriteLine("Expected # of rulest=3; found:{0}", configuration.Rules.Count);
                Console.WriteLine();
                Console.WriteLine("Pause before configuration delete. To continue, click Enter...");
                Console.ReadKey();

                // Delete the configuration.
                await DeleteCORSConfigurationAsync();

                // Retrieve a nonexistent configuration.
                configuration = await RetrieveCORSConfigurationAsync();
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }

        static async Task PutCORSConfigurationAsync(CORSConfiguration configuration)
        {

            PutCORSConfigurationRequest request = new PutCORSConfigurationRequest
            {
                BucketName = bucketName,
                Configuration = configuration
            };

            var response = await s3Client.PutCORSConfigurationAsync(request);
        }

        static async Task<CORSConfiguration> RetrieveCORSConfigurationAsync()
        {
            GetCORSConfigurationRequest request = new GetCORSConfigurationRequest
            {
                BucketName = bucketName

            };
            var response = await s3Client.GetCORSConfigurationAsync(request);
            var configuration = response.Configuration;
            PrintCORSRules(configuration);
            return configuration;
        }

        static async Task DeleteCORSConfigurationAsync()
        {
            DeleteCORSConfigurationRequest request = new DeleteCORSConfigurationRequest
            {
                BucketName = bucketName
            };
            await s3Client.DeleteCORSConfigurationAsync(request);
        }

        static void PrintCORSRules(CORSConfiguration configuration)
        {
            Console.WriteLine();

            if (configuration == null)
            {
                Console.WriteLine("\nConfiguration is null");
                return;
            }

            Console.WriteLine("Configuration has {0} rules:", configuration.Rules.Count);
            foreach (CORSRule rule in configuration.Rules)
            {
                Console.WriteLine("Rule ID: {0}", rule.Id);
                Console.WriteLine("MaxAgeSeconds: {0}", rule.MaxAgeSeconds);
                Console.WriteLine("AllowedMethod: {0}", string.Join(", ", rule.AllowedMethods.ToArray()));
                Console.WriteLine("AllowedOrigins: {0}", string.Join(", ", rule.AllowedOrigins.ToArray()));
                Console.WriteLine("AllowedHeaders: {0}", string.Join(", ", rule.AllowedHeaders.ToArray()));
                Console.WriteLine("ExposeHeader: {0}", string.Join(", ", rule.ExposeHeaders.ToArray()));
            }
        }
    }
}
```

------

## REST API 사용
<a name="EnableCorsUsingREST"></a>

버킷에 CORS 구성을 설정하려면 AWS Management Console을 사용할 수 있습니다. 하지만 애플리케이션에서 요구할 경우 REST 요청을 직접 전송할 수도 있습니다. *Amazon Simple Storage Service API 참조*의 다음 섹션에서는 CORS 구성과 관련된 REST API 작업에 대해 설명합니다.
+ [PutBucketCors](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTcors.html)
+ [GetBucketCors](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETcors.html)
+ [DeleteBucketCors](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketDELETEcors.html)
+ [OPTIONS 객체](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTOPTIONSobject.html)