

# AWS Glue for Spark ETL 스크립트 프로그래밍을 위한 기능 및 최적화
<a name="aws-glue-programming-general"></a>

다음 섹션은 어떤 언어든지 AWS Glue for Spark 추출, 전환 및 적재(ETL) 프로그래밍에 일반적으로 적용되는 기술 및 값을 설명합니다.

**Topics**
+ [

# AWS Glue for Spark에서 ETL에 대한 연결 유형 및 옵션
](aws-glue-programming-etl-connect.md)
+ [

# AWS Glue for Spark에서 입력 및 출력의 데이터 형식 옵션
](aws-glue-programming-etl-format.md)
+ [

# Spark SQL 작업에 대해 AWS Glue Data Catalog 지원
](aws-glue-programming-etl-glue-data-catalog-hive.md)
+ [

# 작업 북마크 사용
](programming-etl-connect-bookmarks.md)
+ [

# AWS Glue Studio 외부에서 민감한 데이터 감지 사용
](aws-glue-api-sensitive-data-example.md)
+ [

# AWS Glue Visual Job API
](visual-job-api-chapter.md)

# AWS Glue for Spark에서 ETL에 대한 연결 유형 및 옵션
<a name="aws-glue-programming-etl-connect"></a>

AWS Glue for Spark에서 다양한 PySpark와 Scala 메서드 및 변환은 `connectionType` 파라미터를 사용하여 연결 유형을 지정합니다. `connectionOptions` 또는 `options` 파라미터를 사용하여 연결 옵션을 지정합니다.

`connectionType` 파라미터는 다음 표에 표시된 값을 사용할 수 있습니다. 각 유형에 대한 연관된 `connectionOptions`(또는 `options`) 파라미터 값은 다음 섹션에 설명되어 있습니다. 별도의 언급이 없으면 이 파라미터는 연결이 소스 또는 싱크로 사용될 때 적용됩니다.

연결 옵션을 설정하고 사용하는 방법을 보여주는 샘플 코드는 각 연결 유형별 홈페이지를 참조하세요.


| `connectionType` | 연결 대상 | 
| --- | --- | 
| [dynamodb](aws-glue-programming-etl-connect-dynamodb-home.md) | [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/) 데이터베이스 | 
| [kinesis](aws-glue-programming-etl-connect-kinesis-home.md) | [Amazon Kinesis Data Streams](https://docs.aws.amazon.com/streams/latest/dev/introduction.html) | 
| [s3](aws-glue-programming-etl-connect-s3-home.md) | [Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/dev/) | 
| [documentdb](aws-glue-programming-etl-connect-documentdb-home.md#aws-glue-programming-etl-connect-documentdb) | [Amazon DocumentDB(MongoDB와 호환)](https://docs.aws.amazon.com/documentdb/latest/developerguide/) 데이터베이스 | 
| [OpenSearch](aws-glue-programming-etl-connect-opensearch-home.md) | [Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/). | 
| [redshift](aws-glue-programming-etl-connect-redshift-home.md) | [Amazon Redshift](https://aws.amazon.com/redshift/) 데이터베이스 | 
| [kafka](aws-glue-programming-etl-connect-kafka-home.md) |  [Kafka](https://kafka.apache.org/) 또는 [Amazon Managed Streaming for Apache Kafka](https://docs.aws.amazon.com/msk/latest/developerguide/what-is-msk.html) | 
| [azurecosmos](aws-glue-programming-etl-connect-azurecosmos-home.md) | NoSQL용 Azure Cosmos. | 
| [azuresql](aws-glue-programming-etl-connect-azuresql-home.md) | Azure SQL. | 
| [bigquery](aws-glue-programming-etl-connect-bigquery-home.md) | Google BigQuery. | 
| [mongodb](aws-glue-programming-etl-connect-mongodb-home.md) | MongoDB Atlas를 포함한 [MongoDB](https://www.mongodb.com/what-is-mongodb) 데이터베이스. | 
| [sqlserver](aws-glue-programming-etl-connect-jdbc-home.md) |  Microsoft SQL Server 데이터베이스([JDBC 연결](aws-glue-programming-etl-connect-jdbc-home.md) 참조) | 
| [mysql](aws-glue-programming-etl-connect-jdbc-home.md) | [MySQL](https://www.mysql.com/) 데이터베이스([JDBC 연결](aws-glue-programming-etl-connect-jdbc-home.md) 참조) | 
| [oracle](aws-glue-programming-etl-connect-jdbc-home.md) | [Oracle](https://www.oracle.com/database/) Database([JDBC 연결](aws-glue-programming-etl-connect-jdbc-home.md) 참조) | 
| [postgresql](aws-glue-programming-etl-connect-jdbc-home.md) |  [PostgreSQL](https://www.postgresql.org/) 데이터베이스([JDBC 연결](aws-glue-programming-etl-connect-jdbc-home.md) 참조) | 
| [saphana](aws-glue-programming-etl-connect-saphana-home.md) | SAP HANA. | 
| [snowflake](aws-glue-programming-etl-connect-snowflake-home.md) | [Snowflake](https://www.snowflake.com/) 데이터 레이크 | 
| [Teradata](aws-glue-programming-etl-connect-teradata-home.md) | Teradata Vantage. | 
| [vertica](aws-glue-programming-etl-connect-vertica-home.md) | Vertica. | 
| [custom.\$1](#aws-glue-programming-etl-connect-market) | Spark, Athena 또는 JDBC 데이터 원본([사용자 정의 및 AWS Marketplace 연결 유형 값](#aws-glue-programming-etl-connect-market) 참조)  | 
| [marketplace.\$1](#aws-glue-programming-etl-connect-market) | Spark, Athena 또는 JDBC 데이터 원본([사용자 정의 및 AWS Marketplace 연결 유형 값](#aws-glue-programming-etl-connect-market) 참조)  | 

# DynamoDB 연결
<a name="aws-glue-programming-etl-connect-dynamodb-home"></a>

AWS Glue for Spark를 사용하여 AWS Glue에서 DynamoDB의 테이블을 읽고 쓸 수 있습니다. AWS Glue 작업에 연결된 IAM 권한을 사용하여 DynamoDB에 연결합니다. AWS Glue는 다른 AWS 계정의 DynamoDB 테이블에 데이터 쓰기를 지원합니다. 자세한 내용은 [DynamoDB 테이블에 대한 교차 계정 교차 리전 액세스](aws-glue-programming-etl-dynamo-db-cross-account.md) 섹션을 참조하세요.

원래 DynamoDB 커넥터는 DynamoDB에서 추출된 데이터 작업 시 Glue DynamicFrame 객체를 사용합니다. AWS Glue 5.0 이상은 네이티브 Spark DataFrame 지원을 제공하는 새로운 [Spark DataFrame이 지원되는 DynamoDB 커넥터](aws-glue-programming-etl-connect-dynamodb-dataframe-support.md)를 도입합니다.

AWS Glue DynamoDB ETL 커넥터 외에도 DynamoDB `ExportTableToPointInTime` 요청을 호출하여 사용자가 제공한 Amazon S3 위치에 [DynamoDB JSON](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataExport.Output.html) 형식으로 저장하는 DynamoDB 내보내기 커넥터를 사용하여 DynamoDB에서 읽을 수 있습니다. 그런 다음 AWS Glue는 Amazon S3 내보내기 위치에서 데이터를 읽어서 DynamicFrame 객체를 생성합니다.

DynamoDB 기록기는 AWS Glue 버전 1.0 이상에서 지원됩니다. AWS Glue DynamoDB 내보내기 커넥터는 AWS Glue 버전 2.0 이상 버전에서 사용할 수 있습니다. 새로운 DataFrame 기반 DynamoDB 커넥터는 AWS Glue 버전 5.0 이상에서 사용할 수 있습니다.

DynamoDB에 대한 자세한 내용은 [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/) 설명서를 참조하세요.

**참고**  
DynamoDB ETL 리더는 필터 또는 푸시다운 조건자를 지원하지 않습니다.

## DynamoDB 연결 구성
<a name="aws-glue-programming-etl-connect-dynamodb-configure"></a>

AWS Glue에서 DynamoDB에 연결하려면 AWS Glue 작업과 관련된 IAM 역할에 DynamoDB와 상호 작용할 수 있는 권한을 부여합니다. DynamoDB에서 읽거나 쓰는 데 필요한 권한에 대한 자세한 내용은 IAM 설명서에서 [DynamoDB에 사용되는 작업, 리소스 및 조건 키](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazondynamodb.html)를 참조하세요.

다음과 같은 상황에서는 추가 구성이 필요할 수도 있습니다.
+ DynamoDB 내보내기 커넥터를 사용하는 경우에는 작업에서 DynamoDB 테이블 내보내기를 요청할 수 있도록 IAM을 구성해야 합니다. 또한 내보내기를 위한 Amazon S3 버킷을 식별하고 DynamoDB가 이 버킷에 쓸 수 있고 AWS Glue 작업이 이 버킷에서 읽을 수 있도록 IAM에서 적절한 권한을 제공해야 합니다. 자세한 내용은 [DynamoDB에서 테이블 내보내기 요청](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/S3DataExport_Requesting.html)을 참조하세요.
+ AWS Glue 작업에 특정 Amazon VPC 연결 요구 사항이 있는 경우 `NETWORK` AWS Glue 연결 유형을 사용하여 네트워크 옵션을 제공하세요. DynamoDB에 대한 액세스는 IAM에 의해 권한이 부여되므로 AWS Glue DynamoDB 연결 유형이 필요하지 않습니다.

## DynamoDB에서 읽고 쓰기
<a name="aws-glue-programming-etl-connect-dynamodb-read-write"></a>

다음 코드 예제에서는 ETL 커넥터를 통해 DynamoDB 테이블에서 읽고, DynamoDB 테이블에 쓰는 방법을 보여줍니다. 한 테이블에서 읽고 다른 테이블에 쓰는 것을 보여줍니다.

------
#### [ Python ]

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

dyf = glue_context.create_dynamic_frame.from_options(
    connection_type="dynamodb",
    connection_options={"dynamodb.input.tableName": test_source,
        "dynamodb.throughput.read.percent": "1.0",
        "dynamodb.splits": "100"
    }
)
print(dyf.getNumPartitions())

glue_context.write_dynamic_frame_from_options(
    frame=dyf,
    connection_type="dynamodb",
    connection_options={"dynamodb.output.tableName": test_sink,
        "dynamodb.throughput.write.percent": "1.0"
    }
)

job.commit()
```

------
#### [ Scala ]

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamoDbDataSink
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._


object GlueApp {

  def main(sysArgs: Array[String]): Unit = {
    val glueContext = new GlueContext(SparkContext.getOrCreate())
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    
    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType = "dynamodb",
      options = JsonOptions(Map(
        "dynamodb.input.tableName" -> test_source,
        "dynamodb.throughput.read.percent" -> "1.0",
        "dynamodb.splits" -> "100"
      ))
    ).getDynamicFrame()
    
    print(dynamicFrame.getNumPartitions())

    val dynamoDbSink: DynamoDbDataSink =  glueContext.getSinkWithFormat(
      connectionType = "dynamodb",
      options = JsonOptions(Map(
        "dynamodb.output.tableName" -> test_sink,
        "dynamodb.throughput.write.percent" -> "1.0"
      ))
    ).asInstanceOf[DynamoDbDataSink]
    
    dynamoDbSink.writeDynamicFrame(dynamicFrame)

    Job.commit()
  }

}
```

------

## DynamoDB 내보내기 커넥터 사용
<a name="aws-glue-programming-etl-connect-dynamodb-export-connector"></a>

내보내기 커넥터는 DynamoDB 테이블 크기가 80GB보다 큰 경우 ETL 커넥터보다 성능이 우수합니다. 또한 내보내기 요청이 AWS Glue 작업의 Spark 프로세스 외부에서 수행된다는 점을 고려할 때, [AWS Glue 작업의 Auto Scaling](https://docs.aws.amazon.com/glue/latest/dg/auto-scaling.html)을 사용 설정하여 내보내기 요청이 진행되는 동안 DPU 사용량을 줄일할 수 있습니다. 내보내기 커넥터를 사용하면 Spark 실행기 병렬 처리 또는 DynamoDB 처리량 읽기 비율에 대한 분할 수를 구성할 필요가 없습니다.

**참고**  
DynamoDB에는 `ExportTableToPointInTime` 요청을 호출하기 위한 특정 요구 사항이 있습니다. 자세한 내용은 [DynamoDB에서 테이블 내보내기 요청](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataExport.Requesting.html)을 참조하세요. 예를 들어, 이 커넥터를 사용하려면 테이블에서 PITR(특정 시점으로 복구)을 사용 설정해야 합니다. 또한 DynamoDB 커넥터는 Amazon S3으로의 DynamoDB 내보내기 작업에 대해 AWS KMS 암호화를 지원합니다. AWS Glue 작업 구성에서 보안 구성을 제공하면 DynamoDB 내보내기에 대한 AWS KMS 암호화가 사용 설정됩니다. KMS 키는 Amazon S3 버킷과 동일한 리전에 있어야 합니다.  
DynamoDB 내보내기 및 Amazon S3 스토리지 비용에 대한 추가 요금이 부과됩니다. Amazon S3에서 내보낸 데이터는 작업 실행이 완료된 후에도 유지되므로 추가 DynamoDB 내보내기 없이 다시 사용할 수 있습니다. 이 커넥터 사용 시 요구 사항은 테이블에 대해 PITR(특정 시점으로 복구)을 사용 설정하는 것입니다.  
DynamoDB ETL 커넥터 또는 내보내기 커넥터는 DynamoDB 소스에 적용할 필터 또는 푸시다운 조건자를 지원하지 않습니다.

다음 코드 예제에서는 내보내기 커넥터를 통해 파티션 수를 읽고, 파티션 수를 인쇄하는 방법을 보여줍니다.

------
#### [ Python ]

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

dyf = glue_context.create_dynamic_frame.from_options(
    connection_type="dynamodb",
    connection_options={
        "dynamodb.export": "ddb",
        "dynamodb.tableArn": test_source,
        "dynamodb.s3.bucket": bucket_name,
        "dynamodb.s3.prefix": bucket_prefix,
        "dynamodb.s3.bucketOwner": account_id_of_bucket,
    }
)
print(dyf.getNumPartitions())

job.commit()
```

------
#### [ Scala ]

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamoDbDataSink
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._


object GlueApp {

  def main(sysArgs: Array[String]): Unit = {
    val glueContext = new GlueContext(SparkContext.getOrCreate())
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    
    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType = "dynamodb",
      options = JsonOptions(Map(
        "dynamodb.export" -> "ddb",
        "dynamodb.tableArn" -> test_source,
        "dynamodb.s3.bucket" -> bucket_name,
        "dynamodb.s3.prefix" -> bucket_prefix,
        "dynamodb.s3.bucketOwner" -> account_id_of_bucket,
      ))
    ).getDynamicFrame()
    
    print(dynamicFrame.getNumPartitions())

    Job.commit()
  }

}
```

------

다음 예제에서는 내보내기 커넥터를 통해 `dynamodb` 분류가 있는 AWS Glue 데이터 카탈로그 테이블에서 읽기 작업을 수행하고 파티션 수를 인쇄하는 방법을 보여줍니다.

------
#### [ Python ]

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

dynamicFrame = glue_context.create_dynamic_frame.from_catalog(
        database=catalog_database,
        table_name=catalog_table_name,
        additional_options={
            "dynamodb.export": "ddb", 
            "dynamodb.s3.bucket": s3_bucket,
            "dynamodb.s3.prefix": s3_bucket_prefix
        }
    )
print(dynamicFrame.getNumPartitions())

job.commit()
```

------
#### [ Scala ]

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamoDbDataSink
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._


object GlueApp {

  def main(sysArgs: Array[String]): Unit = {
    val glueContext = new GlueContext(SparkContext.getOrCreate())
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    
    val dynamicFrame = glueContext.getCatalogSource(
        database = catalog_database,
        tableName = catalog_table_name,
        additionalOptions = JsonOptions(Map(
            "dynamodb.export" -> "ddb", 
            "dynamodb.s3.bucket" -> s3_bucket,
            "dynamodb.s3.prefix" -> s3_bucket_prefix
        ))
    ).getDynamicFrame()
    print(dynamicFrame.getNumPartitions())
)
```

------

## DynamoDB 내보내기 JSON 사용 간소화
<a name="etl-connect-dynamodb-traversing-structure"></a>

AWS Glue DynamoDB 내보내기 커넥터를 사용하여 DynamoDB 내보내기를 수행하면 특정 중첩 구조의 JSON 파일이 생성됩니다. 자세한 내용은 [데이터 객체](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/S3DataExport.Output.html)를 참조하세요. AWS Glue는 이러한 구조를 다운스트림 애플리케이션에서 사용하기 쉬운 형태로 중첩 해제를 수행할 수 있는 DynamicFrame 변환을 제공합니다.

두 가지 방법 중 하나로 변환을 호출할 수 있습니다. DynamoDB에서 읽을 메서드를 직접적으로 호출할 때 `"true"` 값을 사용하여 `"dynamodb.simplifyDDBJson"` 연결 옵션을 설정할 수 있습니다. AWS Glue 라이브러리에서 독립적으로 사용할 수 있는 메서드로 변환을 직접적으로 호출할 수도 있습니다.

DynamoDB 내보내기로 생성된 다음 스키마를 고려해 보세요.

```
root
|-- Item: struct
|    |-- parentMap: struct
|    |    |-- M: struct
|    |    |    |-- childMap: struct
|    |    |    |    |-- M: struct
|    |    |    |    |    |-- appName: struct
|    |    |    |    |    |    |-- S: string
|    |    |    |    |    |-- packageName: struct
|    |    |    |    |    |    |-- S: string
|    |    |    |    |    |-- updatedAt: struct
|    |    |    |    |    |    |-- N: string
|    |-- strings: struct
|    |    |-- SS: array
|    |    |    |-- element: string
|    |-- numbers: struct
|    |    |-- NS: array
|    |    |    |-- element: string
|    |-- binaries: struct
|    |    |-- BS: array
|    |    |    |-- element: string
|    |-- isDDBJson: struct
|    |    |-- BOOL: boolean
|    |-- nullValue: struct
|    |    |-- NULL: boolean
```

`simplifyDDBJson` 변환은 이를 다음과 같이 간소화합니다.

```
root
|-- parentMap: struct
|    |-- childMap: struct
|    |    |-- appName: string
|    |    |-- packageName: string
|    |    |-- updatedAt: string
|-- strings: array
|    |-- element: string
|-- numbers: array
|    |-- element: string
|-- binaries: array
|    |-- element: string
|-- isDDBJson: boolean
|-- nullValue: null
```

**참고**  
`simplifyDDBJson`은 AWS Glue 3.0 이상 버전에서 사용할 수 있습니다. `unnestDDBJson` 변환은 DynamoDB 내보내기 JSON을 간소화하는 데도 사용할 수 있습니다. 사용자가 `simplifyDDBJson`에서 `unnestDDBJson`으로 전환할 것을 권장합니다.

## DynamoDB 작업의 병렬 처리 구성
<a name="aws-glue-programming-etl-connect-dynamodb-parallelism"></a>

성능을 향상시키기 위해 DynamoDB 커넥터에 사용할 수 있는 특정 파라미터를 조정할 수 있습니다. 병렬 처리 파라미터를 조정할 때 목표는 프로비저닝된 AWS Glue 작업자의 사용을 극대화하는 것입니다. 더 높은 성능이 필요한 경우 DPU 수를 늘려 작업을 스케일 아웃하는 것이 좋습니다.

 ETL 커넥터를 사용할 때 `dynamodb.splits` 파라미터를 사용하여 DynamoDB 읽기 작업의 병렬 처리를 변경할 수 있습니다. 내보내기 커넥터를 사용하여 읽을 때는 Spark 실행기 병렬 처리를 위한 분할 횟수를 구성할 필요가 없습니다. `dynamodb.output.numParallelTasks`를 사용하여 DynamoDB 쓰기 작업의 병렬 처리를 변경할 수 있습니다.

**DynamoDB ETL 커넥터를 사용하여 읽기**

작업 구성에 설정된 최대 작업자 수와 다음 `numSlots` 계산을 기준으로 `dynamodb.splits`를 계산하는 것이 좋습니다. 자동 스케일링의 경우 실제 사용 가능한 작업자 수는 해당 한도 내에서 변경될 수 있습니다. 최대 작업자 수 설정에 대한 자세한 내용은 [AWS Glue에서 Spark 작업에 대한 작업 속성 구성](add-job.md)의 **작업자 수**(`NumberOfWorkers`)를 참조하세요.
+ `numExecutors = NumberOfWorkers - 1`

   상황에 따라 한 실행기는 Spark 드라이버용으로 예약되어 있고 다른 실행기는 데이터 처리에 사용됩니다.
+ `numSlotsPerExecutor =`

------
#### [ AWS Glue 3.0 and later versions ]
  + `WorkerType`이 `G.1X`일 경우 `4`
  + `WorkerType`이 `G.2X`일 경우 `8`
  + `WorkerType`이 `G.4X`일 경우 `16`
  + `WorkerType`이 `G.8X`일 경우 `32`

------
#### [ AWS Glue 2.0 and legacy versions ]
  + `WorkerType`이 `G.1X`일 경우 `8`
  + `WorkerType`이 `G.2X`일 경우 `16`

------
+ `numSlots = numSlotsPerExecutor * numExecutors`

사용 가능한 슬롯 수인 `numSlots`에 `dynamodb.splits`를 설정하는 것이 좋습니다.

**DynamoDB에 쓰기**

`dynamodb.output.numParallelTasks` 파라미터는 다음 계산을 사용하여 Spark 태스크당 WCU를 결정하는 데 사용됩니다.

`permittedWcuPerTask = ( TableWCU * dynamodb.throughput.write.percent ) / dynamodb.output.numParallelTasks`

구성이 DynamoDB에 쓰는 Spark 태스크의 수를 정확하게 나타내는 경우 DynamoDB 작성기가 가장 잘 작동합니다. 경우에 따라 쓰기 성능을 개선하기 위해 기본 계산을 재정의해야 할 수 있습니다. 해당 파라미터를 지정하지 않으면 Spark 태스크당 허용되는 WCU는 다음 공식에 따라 자동으로 계산됩니다.
+ 
  + `numPartitions = dynamicframe.getNumPartitions()`
  + `numSlots`(이 섹션에서 이전에 정의한 대로)
  + `numParallelTasks = min(numPartitions, numSlots)`
+ 예시 1. DPU=10, WorkerType=Standard. 입력 DynamicFrame에는 100개의 RDD 파티션이 있습니다.
  + `numPartitions = 100`
  + `numExecutors = (10 - 1) * 2 - 1 = 17`
  + `numSlots = 4 * 17 = 68`
  + `numParallelTasks = min(100, 68) = 68`
+ 예시 2. DPU=10, WorkerType=Standard. 입력 DynamicFrame에는 20개의 RDD 파티션이 있습니다.
  + `numPartitions = 20`
  + `numExecutors = (10 - 1) * 2 - 1 = 17`
  + `numSlots = 4 * 17 = 68`
  + `numParallelTasks = min(20, 68) = 20`

**참고**  
레거시 AWS Glue 버전의 작업과 Standard 작업자를 사용하는 작업은 슬롯 수를 계산하는 방법이 다릅니다. 이러한 작업의 성능을 조정해야 하는 경우 지원되는 AWS Glue 버전으로 전환하는 것이 좋습니다.

## DynamoDB 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-dynamodb"></a>

Amazon DynamoDB에 대한 연결을 지정합니다.

연결 옵션은 소스 연결 및 싱크 연결에 따라 다릅니다.

### ETL 커넥터를 소스로 사용하는 "connectionType": "dynamodb"
<a name="etl-connect-dynamodb-as-source"></a>

AWS Glue DynamoDB ETL 커넥터 사용 시 `"connectionType": "dynamodb"`를 소스로 사용하여 다음 연결 옵션을 사용합니다.
+ `"dynamodb.input.tableName"`: (필수 사항) 읽을 DynamoDB 테이블입니다.
+ `"dynamodb.throughput.read.percent"`: (선택 사항) 사용할 읽기 용량 유닛(RCU)의 백분율. 기본값은 "0.5"로 설정되어 있습니다. 허용되는 값은 "0.1"에서 "1.5"(포함)입니다.
  + `0.5`는 기본 읽기 속도입니다. 즉, AWS Glue가 테이블 읽기 용량의 절반을 사용하려고 시도합니다. 값을 `0.5`보다 높게 설정할 경우 AWS Glue가 요청 속도를 높이고, 값을 `0.5`보다 낮게 설정할 경우 읽기 요청 속도를 낮춥니다. (실제 읽기 속도는 DynamoDB 테이블의 키 분포가 균일한지 여부와 같은 요소에 따라 달라집니다.)
  + DynamoDB 테이블이 온디맨드 모드인 경우 AWS Glue는 테이블의 읽기 용량을 40,000으로 처리합니다. 큰 테이블을 내보내려면 DynamoDB 테이블을 온디맨드 모드로 전환하는 것이 좋습니다.
+ `"dynamodb.splits"`: (선택 사항) 읽는 동안 이 DynamoDB 테이블을 몇 개의 분할로 파티셔닝하는지 정의합니다. 기본값은 "1"로 설정되어 있습니다. 허용되는 값은 "1"에서 "1,000,000"(포함)입니다.

  `1`은 병렬 처리가 없음을 나타냅니다. 아래 공식을 사용하여 더 나은 성능을 위해 더 큰 값을 지정하는 것이 좋습니다. 값을 적절하게 설정하는 방법에 대한 자세한 내용은 [DynamoDB 작업의 병렬 처리 구성](#aws-glue-programming-etl-connect-dynamodb-parallelism) 섹션을 참조하세요.
+ `"dynamodb.sts.roleArn"`: (선택 사항) 교차 계정 액세스를 위해 수임할 IAM 역할 ARN입니다. 이 파라미터는 AWS Glue 1.0 이상에서 사용 가능합니다.
+ `"dynamodb.sts.roleSessionName"`: (선택 사항) STS 세션 이름입니다. 기본값은 "glue-dynamodb-read-sts-session"으로 설정됩니다. 이 파라미터는 AWS Glue 1.0 이상에서 사용 가능합니다.

### AWS Glue DynamoDB 내보내기 커넥터를 소스로 사용하는 "connectionType": "dynamodb"
<a name="etl-connect-dynamodb-as-source-export-connector"></a>

AWS Glue 버전 2.0 이상에서만 사용할 수 있는 AWS Glue DynamoDB 내보내기 커넥터 사용 시 "connectionType": "dynamodb"를 소스로 사용하는 다음 연결 옵션을 사용합니다.
+ `"dynamodb.export"`: (필수) 문자열 값:
  + `ddb`로 설정한 경우 AWS Glue 작업 중 새 `ExportTableToPointInTimeRequest`가 호출되는 AWS Glue DynamoDB 내보내기 커넥터가 사용 설정됩니다. `dynamodb.s3.bucket` 및 `dynamodb.s3.prefix`에서 전달된 위치로 새 내보내기가 생성됩니다.
  + `s3`로 설정한 경우 AWS Glue DynamoDB 내보내기 커넥터가 사용 설정되지만, 새 DynamoDB 내보내기 생성을 건너뛰고 대신 `dynamodb.s3.bucket` 및 `dynamodb.s3.prefix`를 해당 테이블의 과거 내보내기 Amazon S3 위치로 사용합니다.
+ `"dynamodb.tableArn"`: (필수 사항) 읽을 DynamoDB 테이블입니다.
+ `"dynamodb.unnestDDBJson"`: (선택 사항) 기본값: false. 유효 값: 부울. true로 설정된 경우 내보내기에 있는 DynamoDB JSON 구조의 비중첩 변환을 수행합니다. `"dynamodb.unnestDDBJson"`과 `"dynamodb.simplifyDDBJson"`을 동시에 true로 설정하면 오류가 발생합니다. AWS Glue 3.0 이상 버전에서는 DynamoDB 맵 유형을 간소화할 때 더 나은 동작을 위해 `"dynamodb.simplifyDDBJson"`을 사용하는 것이 좋습니다. 자세한 내용은 [DynamoDB 내보내기 JSON 사용 간소화](#etl-connect-dynamodb-traversing-structure) 섹션을 참조하세요.
+ `"dynamodb.simplifyDDBJson"`: (선택 사항) 기본값: false. 유효 값: 부울. true로 설정하면 변환을 수행하여 내보내기에 있는 DynamoDB JSON 구조의 스키마를 간소화합니다. `"dynamodb.unnestDDBJson"` 옵션과 용도는 동일하지만 DynamoDB 맵 유형 또는 DynamoDB 테이블의 중첩된 맵 유형에 대한 지원을 강화합니다. 이 옵션은 AWS Glue 3.0 이상 버전에서 사용할 수 있습니다. `"dynamodb.unnestDDBJson"`과 `"dynamodb.simplifyDDBJson"`을 동시에 true로 설정하면 오류가 발생합니다. 자세한 내용은 [DynamoDB 내보내기 JSON 사용 간소화](#etl-connect-dynamodb-traversing-structure) 섹션을 참조하세요.
+ `"dynamodb.s3.bucket"`: (선택 사항) DynamoDB `ExportTableToPointInTime` 프로세스가 수행될 Amazon S3 버킷 위치를 나타냅니다. 내보내기의 파일 형식은 DynamoDB JSON입니다.
  + `"dynamodb.s3.prefix"`: (선택 사항) DynamoDB `ExportTableToPointInTime` 로드가 저장될 Amazon S3 버킷 내부의 Amazon S3 접두사 위치를 나타냅니다. `dynamodb.s3.prefix`와 `dynamodb.s3.bucket`을 모두 지정하지 않을 경우 이 값은 기본적으로 AWS Glue 작업 구성에 지정된 임시 디렉터리 위치로 설정됩니다. 자세한 내용은 [AWS Glue가 사용하는 특수 파라미터](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-glue-arguments.html)를 참조하세요.
  + `"dynamodb.s3.bucketOwner"`: 교차 계정 Amazon S3 액세스를 위해 필요한 버킷 소유자를 나타냅니다.
+ `"dynamodb.sts.roleArn"`: (선택 사항) DynamoDB 테이블에 대한 교차 계정 액세스 및/또는 교차 리전 액세스에 대해 수임될 IAM 역할 ARN입니다. 참고: 동일한 IAM 역할 ARN은 `ExportTableToPointInTime` 요청에 대해 지정된 Amazon S3 위치에 액세스하는 데 사용됩니다.
+ `"dynamodb.sts.roleSessionName"`: (선택 사항) STS 세션 이름입니다. 기본값은 "glue-dynamodb-read-sts-session"으로 설정됩니다.
+ `"dynamodb.exportTime"`(선택 사항) 유효 값: ISO-8601 인스턴트를 나타내는 문자열. 내보내기를 수행해야 하는 시점입니다.
+ `"dynamodb.sts.region"`: (리전 엔드포인트를 사용하여 리전 간 직접 호출하는 경우 필수임) 읽으려는 DynamoDB 테이블을 호스팅하는 지역입니다.

### 싱크로 ETL 커넥터를 사용하는 "connectionType": "dynamodb"
<a name="etl-connect-dynamodb-as-sink"></a>

싱크로서의 `"connectionType": "dynamodb"`에는 다음 연결 옵션을 사용합니다.
+ `"dynamodb.output.tableName"`: (필수) 쓸 대상 DynamoDB 테이블입니다.
+ `"dynamodb.throughput.write.percent"`: (선택 사항) 사용할 쓰기 용량 유닛(WCU)의 백분율입니다. 기본값은 "0.5"로 설정되어 있습니다. 허용되는 값은 "0.1"에서 "1.5"(포함)입니다.
  + `0.5`는 기본 쓰기 속도입니다. 즉, AWS Glue가 테이블 쓰기 용량의 절반을 사용하려고 시도합니다. 값을 0.5보다 높게 설정할 경우 AWS Glue가 요청 속도를 높이고, 값을 0.5보다 낮게 설정할 경우 쓰기 요청 속도를 낮춥니다. (실제 쓰기 속도는 DynamoDB 테이블의 키 분포가 균일한지 여부와 같은 요소에 따라 달라집니다.)
  + DynamoDB 테이블이 온디맨드 모드인 경우 AWS Glue는 테이블의 쓰기 용량을 `40000`으로 처리합니다. 큰 테이블을 가져오려면 DynamoDB 테이블을 온디맨드 모드로 전환하는 것이 좋습니다.
+ `"dynamodb.output.numParallelTasks"`: (선택 사항) 동시에 DynamoDB에 쓰는 병렬 태스크 수를 정의합니다. Spark 태스크당 허용되는 WCU를 계산하는 데 사용됩니다. 대부분의 경우 AWS Glue는 해당 값에 대해 적절한 기본값을 계산합니다. 자세한 내용은 [DynamoDB 작업의 병렬 처리 구성](#aws-glue-programming-etl-connect-dynamodb-parallelism) 섹션을 참조하세요.
+ `"dynamodb.output.retry"`: (선택 사항) DynamoDB에서 `ProvisionedThroughputExceededException`이 있을 때 수행할 재시도 횟수를 정의합니다. 기본값은 "10"으로 설정됩니다.
+ `"dynamodb.sts.roleArn"`: (선택 사항) 교차 계정 액세스를 위해 수임할 IAM 역할 ARN입니다.
+ `"dynamodb.sts.roleSessionName"`: (선택 사항) STS 세션 이름입니다. 기본값은 "glue-dynamodb-write-sts-session"으로 설정됩니다.

# DynamoDB 테이블에 대한 교차 계정 교차 리전 액세스
<a name="aws-glue-programming-etl-dynamo-db-cross-account"></a>

AWS Glue ETL 작업은 DynamoDB 테이블에 대한 교차 리전 및 교차 계정 액세스를 지원합니다. AWS Glue ETL 작업은 다른 AWS 계정의 DynamoDB 테이블에서 데이터 읽기와 다른 AWS 계정의 DynamoDB 테이블에 데이터 쓰기를 모두 지원합니다. AWS Glue는 또한 다른 리전의 DynamoDB 테이블에서 읽기와 다른 리전의 DynamoDB 테이블에 쓰기를 모두 지원합니다. 이 섹션에서는 액세스 설정에 대한 지침과 예제 스크립트를 제공합니다.

이 섹션의 절차에서는 IAM 역할을 생성하고 역할에 대한 액세스 권한을 부여하는 IAM 튜토리얼을 참조합니다. 이 튜토리얼에서는 역할 수임에 대해서도 설명하지만 여기서는 대신 작업 스크립트를 사용하여 AWS Glue에서 역할을 수임합니다. 이 튜토리얼에는 일반적인 교차 계정 사례에 대한 정보도 들어 있습니다. 자세한 내용은 *IAM User Guide*의 [Tutorial: Delegate Access Across AWS Accounts Using IAM Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html)를 참조하세요.

## 역할 생성
<a name="aws-glue-programming-etl-dynamo-db-create-role"></a>

[튜토리얼의 1단계](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html#tutorial_cross-account-with-roles-1)에 따라 계정 A에서 IAM 역할을 생성합니다. 역할의 권한을 정의할 때 역할이 DynamoDB를 읽고 쓸 수 있도록 `AmazonDynamoDBReadOnlyAccess` 또는 `AmazonDynamoDBFullAccess` 등의 기존 정책을 연결하도록 선택할 수 있습니다. 다음 예에서는 권한 정책 `AmazonDynamoDBFullAccess`를 사용하여 `DynamoDBCrossAccessRole`이라는 역할을 생성하는 방법을 보여줍니다.

## 역할에 대한 액세스 권한 부여
<a name="aws-glue-programming-etl-dynamo-db-grant-access"></a>

*IAM User Guide*의 [튜토리얼의 1단계](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html#tutorial_cross-account-with-roles-2)에 따라 계정 B가 새로 생성된 역할로 전환하도록 허용할 수 있습니다. 다음 예에서는 다음 문을 사용하여 새 정책을 생성합니다.

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": "arn:aws:iam::111122223333:role/DynamoDBCrossAccessRole"
  }
}
```

------

그런 다음 이 정책을 DynamoDB에 액세스하는 데 사용할 그룹/역할/사용자에 연결할 수 있습니다.

## AWS Glue 작업 스크립트에서 역할 수임
<a name="aws-glue-programming-etl-dynamo-db-assume-role"></a>

이제 B 계정에 로그인하여 AWS Glue 작업을 생성할 수 있습니다. 작업을 생성하려면 [AWS Glue에서 Spark 작업에 대한 작업 속성 구성](add-job.md)의 지침을 참조하세요.

작업 스크립트에서 `DynamoDBCrossAccessRole` 역할을 수임하려면 `dynamodb.sts.roleArn` 파라미터를 사용해야 합니다. 이 역할을 수임하면 계정 B의 DynamoDB에 액세스하는 데 필요한 임시 자격 증명을 얻을 수 있습니다. 다음 예제 스크립트를 검토하세요.

리전 간 교차 계정 읽기의 경우(ETL 커넥터):

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

dyf = glue_context.create_dynamic_frame_from_options(
    connection_type="dynamodb",
    connection_options={
    "dynamodb.region": "us-east-1",
    "dynamodb.input.tableName": "test_source",
    "dynamodb.sts.roleArn": "<DynamoDBCrossAccessRole's ARN>"
    }
)
dyf.show()
job.commit()
```

리전 간 교차 계정 읽기의 경우(ELT 커넥터):

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

dyf = glue_context.create_dynamic_frame_from_options(
    connection_type="dynamodb",
    connection_options={
        "dynamodb.export": "ddb",
        "dynamodb.tableArn": "<test_source ARN>",
        "dynamodb.sts.roleArn": "<DynamoDBCrossAccessRole's ARN>"
    }
)
dyf.show()
job.commit()
```

리전 간 읽기 및 교차 계정 쓰기의 경우:

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions
 
args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
job = Job(glue_context)
job.init(args["JOB_NAME"], args)
 
dyf = glue_context.create_dynamic_frame_from_options(
    connection_type="dynamodb",
    connection_options={
        "dynamodb.region": "us-east-1",
        "dynamodb.input.tableName": "test_source"
    }
)
dyf.show()
 
glue_context.write_dynamic_frame_from_options(
    frame=dyf,
    connection_type="dynamodb",
    connection_options={
        "dynamodb.region": "us-west-2",
        "dynamodb.output.tableName": "test_sink",
        "dynamodb.sts.roleArn": "<DynamoDBCrossAccessRole's ARN>"
    }
)
 
job.commit()
```

# Spark DataFrame이 지원되는 DynamoDB 커넥터
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-support"></a>

Spark DataFrame이 지원되는 DynamoDB 커넥터를 사용하면 Spark DataFrame API를 사용하여 DynamoDB의 테이블에서 읽고 쓸 수 있습니다. 커넥터 설정 단계는 DynamicFrame 기반 커넥터와 동일하며 [여기](aws-glue-programming-etl-connect-dynamodb-home.md#aws-glue-programming-etl-connect-dynamodb-configure)에서 찾을 수 있습니다.

DataFrame 기반 커넥터 라이브러리에서 로드하려면 DynamoDB 연결을 Glue 작업에 연결해야 합니다.

**참고**  
Glue 콘솔 UI는 현재 DynamoDB 연결 생성을 지원하지 않습니다. Glue CLI([CreateConnection](https://docs.aws.amazon.com/cli/latest/reference/glue/create-connection.html))를 사용하여 DynamoDB 연결을 생성할 수 있습니다.  

```
        aws glue create-connection \
            --connection-input '{ \
                "Name": "my-dynamodb-connection", \
                "ConnectionType": "DYNAMODB", \
                "ConnectionProperties": {}, \
                "ValidateCredentials": false, \
                "ValidateForComputeEnvironments": ["SPARK"] \
            }'
```

DynamoDB 연결 생성 시 CLI([CreateJob](https://docs.aws.amazon.com/cli/latest/reference/glue/create-job.html), [UpdateJob](https://docs.aws.amazon.com/cli/latest/reference/glue/update-job.html))를 통해 또는 ‘작업 세부 정보’ 페이지에서 이 연결을 직접 Glue 작업에 연결할 수 있습니다.

![\[alt text not found\]](http://docs.aws.amazon.com/ko_kr/glue/latest/dg/images/dynamodb-dataframe-connector.png)


DYNAMODB 유형과의 연결이 Glue 작업에 연결되도록 하면 DataFrame 기반 커넥터에서 다음과 같은 읽기, 쓰기, 내보내기 작업을 활용할 수 있습니다.

## DataFrame 기반 커넥터를 사용하여 DynamoDB에서 읽기 및 쓰기
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-read-write"></a>

다음 코드 예제는 DataFrame 기반 커넥터를 통해 DynamoDB 테이블에서 읽고 쓰는 방법을 보여줍니다. 한 테이블에서 읽고 다른 테이블에 쓰는 것을 보여줍니다.

------
#### [ Python ]

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME"])
glue_context= GlueContext(SparkContext.getOrCreate())
spark = glueContext.spark_session
job = Job(glue_context)
job.init(args["JOB_NAME"], args)

# Read from DynamoDB
df = spark.read.format("dynamodb") \
    .option("dynamodb.input.tableName", "test-source") \
    .option("dynamodb.throughput.read.ratio", "0.5") \
    .option("dynamodb.consistentRead", "false") \
    .load()

print(df.rdd.getNumPartitions())

# Write to DynamoDB
df.write \
  .format("dynamodb") \
  .option("dynamodb.output.tableName", "test-sink") \
  .option("dynamodb.throughput.write.ratio", "0.5") \
  .option("dynamodb.item.size.check.enabled", "true") \
  .save()

job.commit()
```

------
#### [ Scala ]

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    
    val glueContext = new GlueContext(SparkContext.getOrCreate())
    val spark = glueContext.getSparkSession
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)

    val df = spark.read
      .format("dynamodb")
      .option("dynamodb.input.tableName", "test-source")
      .option("dynamodb.throughput.read.ratio", "0.5")
      .option("dynamodb.consistentRead", "false")
      .load()

    print(df.rdd.getNumPartitions)

    df.write
      .format("dynamodb")
      .option("dynamodb.output.tableName", "test-sink")
      .option("dynamodb.throughput.write.ratio", "0.5")
      .option("dynamodb.item.size.check.enabled", "true")
      .save()

    job.commit()
  }
}
```

------

## DataFrame 기반 커넥터를 통한 DynamoDB 내보내기 사용
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-export"></a>

80GB보다 큰 DynamoDB 테이블의 경우 읽기 작업보다 내보내기 작업이 선호됩니다. 다음 코드 예제는 테이블에서 읽고, S3로 내보내고, DataFrame 기반 커넥터를 통해 파티션 수를 인쇄하는 방법을 보여줍니다.

**참고**  
DynamoDB 내보내기 기능은 Scala `DynamoDBExport` 객체를 통해 사용할 수 있습니다. Python 사용자는 Spark의 JVM 인터럽을 통해 액세스하거나 DynamoDB `ExportTableToPointInTime` API와 함께 AWS SDK for Python(boto3)을 사용할 수 있습니다.

------
#### [ Scala ]

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.{GlueArgParser, Job}
import org.apache.spark.SparkContext
import glue.spark.dynamodb.DynamoDBExport
import scala.collection.JavaConverters._

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val glueContext = new GlueContext(SparkContext.getOrCreate())
    val spark = glueContext.getSparkSession
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    
    val options = Map(
      "dynamodb.export" -> "ddb",
      "dynamodb.tableArn" -> "arn:aws:dynamodb:us-east-1:123456789012:table/my-table",
      "dynamodb.s3.bucket" -> "my-s3-bucket",
      "dynamodb.s3.prefix" -> "my-s3-prefix",
      "dynamodb.simplifyDDBJson" -> "true"
    )
    val df = DynamoDBExport.fullExport(spark, options)
    
    print(df.rdd.getNumPartitions)
    df.count()
    
    Job.commit()
  }
}
```

------

## 구성 옵션
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-options"></a>

### 읽기 옵션
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-read-options"></a>


| 옵션 | 설명 | 기본값 | 
| --- | --- | --- | 
| dynamodb.input.tableName | DynamoDB 테이블 이름(필수) | - | 
| dynamodb.throughput.read | 사용할 읽기 용량 단위(RCU)입니다. 지정하지 않으면 dynamodb.throughput.read.ratio가 계산에 사용됩니다. | - | 
| dynamodb.throughput.read.ratio | 사용할 읽기 용량 단위(RCU)의 비율 | 0.5 | 
| dynamodb.table.read.capacity | 처리량을 계산하는 데 사용되는 온디맨드 테이블의 읽기 용량입니다. 이 파라미터는 온디맨드 용량 테이블에서만 유효합니다. 기본값은 웜 처리량 읽기 단위입니다. | - | 
| dynamodb.splits | 병렬 스캔 작업에 사용되는 세그먼트 수를 정의합니다. 제공하지 않으면 커넥터가 적절한 기본값을 계산합니다. | - | 
| dynamodb.consistentRead | 강력하게 일관된 읽기 사용 여부 | FALSE | 
| dynamodb.input.retry | 재시도 가능한 예외가 있을 때 수행하는 재시도 횟수를 정의합니다. | 10 | 

### 쓰기 옵션
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-write-options"></a>


| 옵션 | 설명 | 기본값 | 
| --- | --- | --- | 
| dynamodb.output.tableName | DynamoDB 테이블 이름(필수) | - | 
| dynamodb.throughput.write | 사용할 쓰기 용량 단위(WCU)입니다. 지정하지 않으면 dynamodb.throughput.write.ratio가 계산에 사용됩니다. | - | 
| dynamodb.throughput.write.ratio | 사용할 쓰기 용량 단위(WCU)의 비율 | 0.5 | 
| dynamodb.table.write.capacity | 처리량을 계산하는 데 사용되는 온디맨드 테이블의 쓰기 용량입니다. 이 파라미터는 온디맨드 용량 테이블에서만 유효합니다. 기본값은 웜 처리량 쓰기 단위입니다. | - | 
| dynamodb.item.size.check.enabled | true인 경우 커넥터는 항목 크기를 계산하고 크기가 최대 크기를 초과하면 항목을 DynamoDB 테이블에 쓰기 전에 중단합니다. | TRUE | 
| dynamodb.output.retry | 재시도 가능한 예외가 있을 때 수행하는 재시도 횟수를 정의합니다. | 10 | 

### 내보내기 옵션
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-export-options"></a>


| 옵션 | 설명 | 기본값 | 
| --- | --- | --- | 
| dynamodb.export | ddb로 설정하면 AWS Glue 작업 중에 새 ExportTableToPointInTimeRequet가 간접적으로 호출되는 AWS Glue DynamoDB 내보내기 커넥터가 활성화됩니다. dynamodb.s3.bucket 및 dynamodb.s3.prefix에서 전달된 위치로 새 내보내기가 생성됩니다. s3로 설정하면 AWS Glue DynamoDB 내보내기 커넥터가 활성화되지만, 새 DynamoDB 내보내기 생성을 건너뛰고 대신 dynamodb.s3.bucket 및 dynamodb.s3.prefix를 해당 테이블의 과거 내보내기 Amazon S3 위치로 사용합니다. | ddb | 
| dynamodb.tableArn | 읽을 DynamoDB 테이블입니다. dynamodb.export이 ddb로 설정된 경우 필수입니다. |  | 
| dynamodb.simplifyDDBJson | true로 설정하면 변환을 수행하여 내보내기에 있는 DynamoDB JSON 구조의 스키마를 간소화합니다. | FALSE | 
| dynamodb.s3.bucket | DynamoDB 내보내기 중에 임시 데이터를 저장할 S3 버킷(필수) |  | 
| dynamodb.s3.prefix | DynamoDB 내보내기 중에 임시 데이터를 저장할 S3 접두사 |  | 
| dynamodb.s3.bucketOwner | 교차 계정 Amazon S3 액세스를 위해 필요한 버킷 소유자를 나타냅니다. |  | 
| dynamodb.s3.sse.algorithm | 임시 데이터가 저장될 버킷에 사용되는 암호화 유형입니다. 유효 값은 AES256 및 KMS입니다. |  | 
| dynamodb.s3.sse.kmsKeyId | 임시 데이터가 저장될 S3 버킷을 암호화하는 데 사용되는 AWS KMS 관리형 키의 ID입니다(해당하는 경우). |  | 
| dynamodb.exportTime | 내보내기를 수행해야 하는 시점입니다. 유효 값: ISO-8601 인스턴트를 나타내는 문자열. |  | 

### 일반 옵션
<a name="aws-glue-programming-etl-connect-dynamodb-dataframe-general-options"></a>


| 옵션 | 설명 | 기본값 | 
| --- | --- | --- | 
| dynamodb.sts.roleArn | 교차 계정 액세스를 위해 수임할 IAM 역할 ARN | - | 
| dynamodb.sts.roleSessionName | STS 세션 이름 | glue-dynamodb-sts-session | 
| dynamodb.sts.region | STS 클라이언트의 리전(교차 리전 역할 수임용) | region 옵션과 동일 | 

# Kinesis 연결
<a name="aws-glue-programming-etl-connect-kinesis-home"></a>

Data Catalog 테이블에 저장된 정보를 사용하거나 데이터 스트림에 직접 액세스할 수 있는 정보를 제공하여 Kinesis 연결을 통해 Amazon Kinesis 데이터 스트림에서 읽고 쓸 수 있습니다. Kinesis의 정보를 Spark DataFrame으로 읽은 다음 AWS Glue DynamicFrame으로 변환할 수 있습니다. DynamicFrame을 JSON 형식으로 Kinesis에 쓸 수 있습니다. 데이터 스트림에 직접 액세스하는 경우 이러한 옵션을 사용하여 데이터 스트림에 액세스하는 방법에 대한 정보를 제공합니다.

`getCatalogSource` 또는 `create_data_frame_from_catalog`를 통해 Kinesis 스트리밍 소스의 레코드를 사용하는 경우 작업에 데이터 카탈로그 데이터베이스 및 테이블 이름 정보가 있으며, 해당 정보를 사용하여 Kinesis 스트리밍 소스에서 읽기 위한 몇 가지 기본 파라미터를 얻을 수 있습니다. `getSource`, `getSourceWithFormat`, `createDataFrameFromOptions` 또는 `create_data_frame_from_options`를 사용하는 경우 여기에 설명된 연결 옵션을 통해 이러한 기본 파라미터를 지정해야 합니다.

`GlueContext` 클래스에 지정된 메서드에 대해 다음 인수를 사용하여 Kinesis에 대한 연결 옵션을 지정할 수 있습니다.
+ Scala
  + `connectionOptions`: `getSource`, `createDataFrameFromOptions`, `getSink`와(과) 함께 사용 
  + `additionalOptions`: `getCatalogSource`, `getCatalogSink`와 함께 사용
  + `options`: `getSourceWithFormat`, `getSinkWithFormat`와 함께 사용
+ Python
  + `connection_options`: `create_data_frame_from_options`, `write_dynamic_frame_from_options`와 함께 사용
  + `additional_options`: `create_data_frame_from_catalog`, `write_dynamic_frame_from_catalog`와 함께 사용
  + `options`: `getSource`, `getSink`와 함께 사용

스트리밍 ETL 작업에 대한 참고 및 제한 사항은 [스트리밍 ETL 참고 사항 및 제한 사항](add-job-streaming.md#create-job-streaming-restrictions) 섹션을 참조하세요.

## Kinesis 구성
<a name="aws-glue-programming-etl-connect-kinesis-configure"></a>

AWS Glue Spark 작업에서 Kinesis 데이터 스트림을 연결하려면 몇 가지 필수 조건이 필요합니다.
+ 읽는 경우 AWS Glue 작업에는 Kinesis 데이터 스트림에 대한 읽기 액세스 수준의 IAM 권한이 있어야 합니다.
+ 쓰는 경우 AWS Glue 작업에는 Kinesis 데이터 스트림에 대한 쓰기 액세스 수준의 IAM 권한이 있어야 합니다.

경우에 따라 추가 필수 조건을 구성해야 합니다.
+ AWS Glue 작업이 **추가 네트워크 연결**(일반적으로 다른 데이터 세트에 연결)로 구성되었고 이러한 연결 중 하나에서 Amazon VPC **네트워크 옵션**을 제공하는 경우 작업에 Amazon VPC를 통해 통신하도록 지시합니다. 이 경우 Amazon VPC를 통해 통신하도록 Kinesis 데이터 스트림도 구성해야 합니다. Amazon VPC와 Kinesis 데이터 스트림 사이에서 인터페이스 VPC 엔드포인트를 생성하면 됩니다. 자세한 내용은 [Using Kinesis Data Streams with Interface VPC Endpoints](https://docs.aws.amazon.com//streams/latest/dev/vpc.html)를 참조하세요.
+ 다른 계정에서 Amazon Kinesis Data Streams를 지정할 때 크로스 계정 액세스를 허용하도록 역할과 정책을 설정해야 합니다. 자세한 내용은 [예: 다른 계정의 Kinesis 스트림에서 읽기](https://docs.aws.amazon.com/kinesisanalytics/latest/java/examples-cross.html)를 참조하세요.

스트리밍 ETL 작업 필수 조건에 대한 자세한 내용은 [AWS Glue에서 스트리밍 ETL 작업](add-job-streaming.md) 섹션을 참조하세요.

## 예제: Kinesis 스트림에서 읽기
<a name="aws-glue-programming-etl-connect-kinesis-read"></a>

### 예제: Kinesis 스트림에서 읽기
<a name="section-etl-connect-kinesis-read"></a>

[forEachBatch](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-forEachBatch)과(와) 함께 사용합니다.

Amazon Kinesis 스트리밍 소스의 예:

```
kinesis_options =
   { "streamARN": "arn:aws:kinesis:us-east-2:777788889999:stream/fromOptionsStream",
     "startingPosition": "TRIM_HORIZON", 
     "inferSchema": "true", 
     "classification": "json" 
   }
data_frame_datasource0 = glueContext.create_data_frame.from_options(connection_type="kinesis", connection_options=kinesis_options)
```

## 예: Kinesis 스트림에 쓰기
<a name="aws-glue-programming-etl-connect-kinesis-write"></a>

### 예제: Kinesis 스트림에서 읽기
<a name="section-etl-connect-kinesis-read"></a>

[forEachBatch](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-forEachBatch)과(와) 함께 사용합니다.

Amazon Kinesis 스트리밍 소스의 예:

```
kinesis_options =
   { "streamARN": "arn:aws:kinesis:us-east-2:777788889999:stream/fromOptionsStream",
     "startingPosition": "TRIM_HORIZON", 
     "inferSchema": "true", 
     "classification": "json" 
   }
data_frame_datasource0 = glueContext.create_data_frame.from_options(connection_type="kinesis", connection_options=kinesis_options)
```

## Kinesis 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-kinesis"></a>

Amazon Kinesis Data Streams에 대한 연결 옵션을 지정합니다.

Kinesis 스트리밍 데이터 원본에 대한 다음 연결 옵션을 사용합니다.
+ `"streamARN"` (필수) 읽기/쓰기에 사용됩니다. Kinesis 데이터 스트림의 ARN.
+ `"classification"` (읽기 필수) 읽기에 사용됩니다. 레코드의 데이터에서 사용하는 파일 형식. 데이터 카탈로그를 통해 제공되지 않는 한 필수입니다.
+ `"streamName"` – (선택 사항) 읽기에 사용됩니다. 읽을 Kinesis 데이터 스트림의 이름. `endpointUrl`와(과) 함께 사용됩니다.
+ `"endpointUrl"` – (선택 사항) 읽기에 사용됩니다. 기본값: "https://kinesis.us-east-1.amazonaws.com". Kinesis 스트림의 AWS 엔드포인트. 특정 지역에 연결하는 경우가 아니면 변경하지 않아도 됩니다.
+ `"partitionKey"` – (선택 사항) 쓰기에 사용됩니다. 레코드를 생성할 때 사용되는 Kinesis 파티션 키.
+ `"delimiter"` (선택 사항) 읽기에 사용됩니다. `classification`이(가) CSV일 때 사용되는 값 구분 기호입니다. 기본값은 '`,`'입니다.
+ `"startingPosition"`: (선택 사항) 읽기에 사용됩니다. 데이터를 읽을 Kinesis 데이터 스트림의 시작 위치입니다. 가능한 값은 `yyyy-mm-ddTHH:MM:SSZ` 패턴에서 UTC 형식의 타임스탬프 문자열이나 `"latest"`, `"trim_horizon"` 또는 `"earliest"`입니다(여기서, `Z`는 UTC 시간대 오프셋(\$1/-)임, 예: '2023-04-04T08:00:00-04:00'). 기본값은 `"latest"`입니다. 참고: `"startingPosition"`에 대한 UTC 형식의 타임스탬프 문자열은 AWS Glue 버전 4.0 이상에서만 지원됩니다.
+ `"failOnDataLoss"`: (선택 사항) 활성 샤드가 누락되거나 만료된 경우 작업이 실패합니다. 기본값은 `"false"`입니다.
+ `"awsSTSRoleARN"`: (선택 사항) 읽기/쓰기에 사용됩니다. AWS Security Token Service(AWS STS)을(를) 사용하여 맡을 역할의 Amazon 리소스 이름(ARN). 이 역할에는 Kinesis 데이터 스트림에 대한 레코드 작업을 설명하거나 읽을 수 있는 권한이 있어야 합니다. 다른 계정의 데이터 스트림에 액세스할 때 이 파라미터를 사용해야 합니다. `"awsSTSSessionName"`과(와) 함께 사용합니다.
+ `"awsSTSSessionName"`: (선택 사항) 읽기/쓰기에 사용됩니다. AWS STS을(를) 사용하여 역할을 맡는 세션의 식별자입니다. 다른 계정의 데이터 스트림에 액세스할 때 이 파라미터를 사용해야 합니다. `"awsSTSRoleARN"`과(와) 함께 사용합니다.
+ `"awsSTSEndpoint"`: (선택 사항) 위임 받은 역할을 사용하여 Kinesis에 연결할 때 사용할 AWS STS 엔드포인트. 이를 통해 VPC에서 리전의 AWS STS 엔드포인트를 사용할 수 있지만, 기본 글로벌 엔드포인트로는 불가능합니다.
+ `"maxFetchTimeInMs"`: (선택 사항) 읽기에 사용됩니다. 작업 실행기가 Kinesis 데이터 스트림에서 현재 배치에 대한 레코드를 읽는 데 걸리는 최대 시간(밀리초(ms) 단위로 지정)입니다. 이 시간 내에 여러 개의 `GetRecords` API 호출을 할 수 있습니다. 기본값은 `1000`입니다.
+ `"maxFetchRecordsPerShard"`: (선택 사항) 읽기에 사용됩니다. 마이크로 배치에 따라 Kinesis 데이터 스트림에서 샤드당 가져올 최대 레코드 수입니다. 참고: 스트리밍 작업이 이미 Kinesis의 동일한 get-records 호출에서 추가 레코드를 읽은 경우 클라이언트가 이 제한을 초과할 수 있습니다. `maxFetchRecordsPerShard`가 엄격해야 한다면 `maxRecordPerRead`의 배수여야 합니다. 기본값은 `100000`입니다.
+ `"maxRecordPerRead"`: (선택 사항) 읽기에 사용됩니다. 각 `getRecords` 작업에서 Kinesis 데이터 스트림에서 가져올 최대 레코드 수. 기본값은 `10000`입니다.
+ `"addIdleTimeBetweenReads"`: (선택 사항) 읽기에 사용됩니다. 연속 두 `getRecords` 작업 사이에 시간 지연을 추가합니다. 기본값은 `"False"`입니다. 이 옵션은 Glue 버전 2.0 이상에서만 구성할 수 있습니다.
+ `"idleTimeBetweenReadsInMs"`: (선택 사항) 읽기에 사용됩니다. 연속 두 `getRecords` 작업 사이의 최소 시간 지연으로, ms 단위로 지정됩니다. 기본값은 `1000`입니다. 이 옵션은 Glue 버전 2.0 이상에서만 구성할 수 있습니다.
+ `"describeShardInterval"`: (선택 사항) 읽기에 사용됩니다. 스크립트가 리샤딩을 고려하기 위한 두 `ListShards` API 호출 사이의 최소 시간 간격. 자세한 내용은 *Amazon Kinesis Data Streams Developer Guide*의 [Strategies for Resharding](https://docs.aws.amazon.com//streams/latest/dev/kinesis-using-sdk-java-resharding-strategies.html)을 참조하세요. 기본값은 `1s`입니다.
+ `"numRetries"`: (선택 사항) 읽기에 사용됩니다. Kinesis Data Streams API 요청의 최대 재시도 횟수입니다. 기본값은 `3`입니다.
+ `"retryIntervalMs"`: (선택 사항) 읽기에 사용됩니다. Kinesis Data Streams API 호출을 재시도하기 전의 휴지 기간(ms 단위로 지정)입니다. 기본값은 `1000`입니다.
+ `"maxRetryIntervalMs"`: (선택 사항) 읽기에 사용됩니다. Kinesis Data Streams API 호출을 두 번 재시도하는 사이의 최대 휴지 시간(ms 단위로 지정)입니다. 기본값은 `10000`입니다.
+ `"avoidEmptyBatches"`: (선택 사항) 읽기에 사용됩니다. 배치가 시작되기 전에 Kinesis 데이터 스트림에서 읽지 않은 데이터를 확인하여 빈 마이크로 배치 작업 생성을 방지합니다. 기본값은 `"False"`입니다.
+ `"schema"`: (inferSchema가 거짓으로 설정된 경우 필수 사항) 읽기에 사용됩니다. 페이로드를 처리하는 데 사용하는 스키마. 분류가 `avro`인 경우 제공된 스키마는 Avro 스키마 형식이어야 합니다. 분류가 `avro`가 아닌 경우 제공된 스키마는 DDL 스키마 형식이어야 합니다.

  다음은 스키마의 예입니다.

------
#### [ Example in DDL schema format ]

  ```
  `column1` INT, `column2` STRING , `column3` FLOAT
  ```

------
#### [ Example in Avro schema format ]

  ```
  {
    "type":"array",
    "items":
    {
      "type":"record",
      "name":"test",
      "fields":
      [
        {
          "name":"_id",
          "type":"string"
        },
        {
          "name":"index",
          "type":
          [
            "int",
            "string",
            "float"
          ]
        }
      ]
    }
  }
  ```

------
+ `"inferSchema"`: (선택 사항) 읽기에 사용됩니다. 기본값은 'false'입니다. 'true'로 설정하면 스키마가 런타임 시 `foreachbatch` 내의 페이로드에서 감지됩니다.
+ `"avroSchema"`: (더 이상 사용되지 않음) 읽기에 사용됩니다. Avro 형식을 사용할 때 Avro 데이터의 스키마를 지정하는 데 사용되는 파라미터입니다. 이 파라미터는 이제 사용 중단되었습니다. `schema` 파라미터를 사용합니다.
+ `"addRecordTimestamp"`: (선택 사항) 읽기에 사용됩니다. 이 옵션이 'true'로 설정되면 데이터 출력에는 이름이 '\$1\$1src\$1timestamp'라는 추가 열이 포함됩니다. 이 열은 스트림에서 해당 레코드를 수신한 시간을 나타냅니다. 기본값은 'false'입니다. 이 옵션은 AWS Glue 버전 4.0 이상에서 지원됩니다.
+ `"emitConsumerLagMetrics"`: (선택 사항) 읽기에 사용됩니다. 옵션을 '참'으로 설정하면 각 배치에 대해 스트림에서 수신한 가장 오래된 레코드와 AWS Glue에 도착한 시간 사이의 지표를 CloudWatch로 내보냅니다. 지표의 이름은 'glue.driver.streaming.maxConsumerLagInMs'입니다. 기본값은 'false'입니다. 이 옵션은 AWS Glue 버전 4.0 이상에서 지원됩니다.
+ `"fanoutConsumerARN"`: (선택 사항) 읽기에 사용됩니다. `streamARN`에서 지정된 스트림에 대한 Kinesis 스트림 소비자의 ARN. Kinesis 연결에 대해 향상된 팬아웃 모드를 활성화하는 데 사용됩니다. 향상된 팬아웃과 함께 Kinesis 스트림을 사용하는 방법에 대한 자세한 내용은 [Kinesis 스트리밍 작업에서 향상된 팬아웃 사용](aws-glue-programming-etl-connect-kinesis-efo.md) 섹션을 참조하세요.
+ `"recordMaxBufferedTime"` – (선택 사항) 쓰기에 사용됩니다. 기본값: 1000(ms). 레코드 쓰기를 대기하는 중 레코드가 버퍼링되는 최대 시간.
+ `"aggregationEnabled"` – (선택 사항) 쓰기에 사용됩니다. 기본값: true. Kinesis로 보내기 전에 레코드를 집계해야 하는지 여부를 지정합니다.
+ `"aggregationMaxSize"` – (선택 사항) 쓰기에 사용됩니다. 기본값: 51200(바이트). 레코드가 이 한도보다 크면 애그리게이터를 우회합니다. 참고 Kinesis는 레코드 크기를 50KB로 제한합니다. 이 값이 50KB를 초과하도록 설정하면 Kinesis에서 크기가 초과된 레코드를 거부합니다.
+ `"aggregationMaxCount"` – (선택 사항) 쓰기에 사용됩니다. 기본값: 4294967295. 집계된 레코드에 포함할 최대 항목 수.
+ `"producerRateLimit"` – (선택 사항) 쓰기에 사용됩니다. 기본값: 150(%). 단일 생성자(예: 작업)에서 보내는 샤드당 처리량을 백엔드 한도의 백분율로 제한합니다.
+ `"collectionMaxCount"` – (선택 사항) 쓰기에 사용됩니다. 기본값: 500. PutRecords 요청에 포함할 최대 항목 수.
+ `"collectionMaxSize"` – (선택 사항) 쓰기에 사용됩니다. 기본값: 5242880(바이트). PutRecords 요청으로 전송할 수 있는 데이터 최대량.

# Kinesis 스트리밍 작업에서 향상된 팬아웃 사용
<a name="aws-glue-programming-etl-connect-kinesis-efo"></a>

향상된 팬아웃 소비자는 일반 소비자보다 더 높은 전용 처리량으로 Kinesis 스트림에서 레코드를 수신할 수 있습니다. 이는 Kinesis 소비자에게 데이터(예: 작업)를 제공하는 데 사용되는 전송 프로토콜을 최적화하는 방식으로 지원됩니다. Kinesis의 향상된 팬아웃에 대한 자세한 내용은 [Kinesis 설명서](https://docs.aws.amazon.com//streams/latest/dev/enhanced-consumers.html)를 참조하세요.

향상된 팬아웃 모드에서는 `maxRecordPerRead` 및 `idleTimeBetweenReadsInMs` 연결 옵션이 더 이상 적용되지 않습니다. 향상된 팬아웃을 사용할 때 해당 파라미터는 구성할 수 없기 때문입니다. 재시도를 위한 구성 옵션은 설명한 대로 수행됩니다.

다음 절차를 사용하여 스트리밍 작업에 대한 향상된 팬아웃을 활성화 및 비활성화합니다. 스트림에서 데이터를 소비하는 각 작업에 대해 스트림 소비자를 등록해야 합니다.

**작업에서 향상된 팬아웃 소비를 활성화하려면:**

1. Kinesis API를 사용하여 작업에 대한 스트림 소비자를 등록합니다. [Kinesis 설명서](https://docs.aws.amazon.com//streams/latest/dev/building-enhanced-consumers-api)의 *register a consumer with enhanced fan-out using the Kinesis Data Streams API*에 대한 지침을 따릅니다. 첫 번째 단계인 [RegisterStreamConsumer](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_RegisterStreamConsumer.html)를 직접적으로 호출합니다. 요청은 ARN, *consumerARN*을 반환해야 합니다.

1. 연결 메서드 인수에서 `fanoutConsumerARN` 연결 옵션을 *consumerARN*으로 설정합니다.

1. 작업을 다시 시작합니다.

**작업에서 향상된 팬아웃 소비를 비활성화하려면:**

1. 메서드 직접 호출에서 `fanoutConsumerARN` 연결 옵션을 제거합니다.

1. 작업을 다시 시작합니다.

1. [Kinesis 설명서](https://docs.aws.amazon.com/streams/latest/dev/building-enhanced-consumers-console.html)의 *deregister a consumer*에 대한 지침을 따릅니다. 이 지침은 콘솔에도 적용되지만 Kinesis API를 통해서도 수행할 수 있습니다. Kinesis API를 통한 스트림 소비자 등록 취소에 대한 자세한 내용은 Kinesis 설명서의 [DeregisterStreamConsumer](https://docs.aws.amazon.com//kinesis/latest/APIReference/API_DeregisterStreamConsumer.html)를 참조하세요.

# Amazon S3 연결
<a name="aws-glue-programming-etl-connect-s3-home"></a>

AWS Glue for Spark를 사용하여 Amazon S3에서 파일을 읽고 쓸 수 있습니다. AWS Glue for Spark는 CSV, Avro, JSON, Orc, Parquet을 포함하여 기본적으로 Amazon S3에 저장되는 여러 가지 공통 데이터 형식을 지원합니다. 지원되는 데이터 형식에 대한 자세한 내용은 [AWS Glue for Spark에서 입력 및 출력의 데이터 형식 옵션](aws-glue-programming-etl-format.md) 섹션을 참조하세요. 각 데이터 형식은 AWS Glue 기능의 여러 가지 세트를 지원할 수 있습니다. 특정 기능 지원에 대해서는 해당 데이터 형식 페이지를 참조하세요. 또한 Hudi, Iceberg 및 Delta Lake 데이터 레이크 프레임워크에 저장되는 버전 관리되는 파일을 읽고 쓸 수 있습니다. 데이터 레이크 프레임워크에 대한 자세한 내용은 [AWS Glue ETL 작업에서 데이터 레이크 프레임워크 사용](aws-glue-programming-etl-datalake-native-frameworks.md) 섹션을 참조하세요.

AWS Glue를 사용하면 쓰는 동안 Amazon S3 객체를 폴더 구조로 파티셔닝한 다음 파티션별로 검색하여 간단한 구성으로 성능을 개선할 수 있습니다. 성능을 개선하기 위해 데이터를 변환할 때 작은 파일을 함께 그룹화하도록 구성을 설정할 수도 있습니다. Amazon S3에서 `bzip2` 및 `gzip` 아카이브를 읽고 쓸 수 있습니다.

**Topics**
+ [

## S3 연결 구성
](#aws-glue-programming-etl-connect-s3-configure)
+ [

## Amazon S3 연결 옵션 참조
](#aws-glue-programming-etl-connect-s3)
+ [

## 데이터 형식에 대한 연결 구문은 더 이상 사용되지 않습니다.
](#aws-glue-programming-etl-connect-legacy-format)
+ [

# Amazon S3 스토리지 클래스 제외
](aws-glue-programming-etl-storage-classes.md)
+ [

# AWS Glue에서 ETL 출력의 파티션 관리
](aws-glue-programming-etl-partitions.md)
+ [

# 입력 파일을 더 큰 그룹에서 읽기
](grouping-input-files.md)
+ [

# Amazon S3용 Amazon VPC 엔드포인트
](vpc-endpoints-s3.md)

## S3 연결 구성
<a name="aws-glue-programming-etl-connect-s3-configure"></a>

AWS Glue에서 Spark 작업으로 Amazon S3에 연결하려면 몇 가지 필수 조건이 필요합니다.
+ AWS Glue 작업에는 관련 Amazon S3 버킷에 대한 IAM 권한이 있어야 합니다.

경우에 따라 추가 필수 조건을 구성해야 합니다.
+ 크로스 계정 액세스를 구성할 때 Amazon S3 버킷에서 적절한 액세스 제어.
+ 보안상의 이유로 Amazon S3 요청을 Amazon VPC를 통해 라우팅하도록 선택할 수 있습니다. 단, 이러한 접근 방식은 대역폭 및 가용성 문제를 일으킬 수 있습니다. 자세한 내용은 [Amazon S3용 Amazon VPC 엔드포인트](vpc-endpoints-s3.md) 섹션을 참조하세요.

## Amazon S3 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-s3"></a>

Amazon S3에 대한 연결을 지정합니다.

Amazon S3에서는 테이블이 아닌 파일을 관리하므로 이 문서에 제공된 연결 속성을 지정하는 것 외에도 파일 유형에 대한 추가 구성을 지정해야 합니다. 데이터 형식 옵션을 통해 이 정보를 지정합니다. 형식 옵션에 대한 자세한 내용은 [AWS Glue for Spark에서 입력 및 출력의 데이터 형식 옵션](aws-glue-programming-etl-format.md) 섹션을 참조하세요. AWS Glue 데이터 카탈로그와 통합하여 이 정보를 지정할 수도 있습니다.

연결 옵션과 형식 옵션 간의 차이점에 대한 예로, [create\$1dynamic\$1frame\$1from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 메서드에서 `connection_type`, `connection_options`, `format` 및 `format_options`를 사용하는 방법을 고려합니다. 이 섹션에서는 `connection_options`에 제공된 파라미터에 대해 자세히 논의합니다.

`"connectionType": "s3"`에는 다음 연결 옵션을 사용합니다.
+ `"paths"`: (필수 사항) 읽을 소스 Amazon S3 경로 목록입니다.
+ `"exclusions"`: (선택사항) 배제할 Unix 식 glob 패턴의 JSON 목록이 포함된 문자열. 예를 들어 `"[\"**.pdf\"]"`는 모든 PDF 파일을 제외합니다. AWS Glue에서 지원하는 glob 구문에 대한 자세한 내용은 [포함 및 제외 패턴](https://docs.aws.amazon.com/glue/latest/dg/define-crawler.html#crawler-data-stores-exclude)을 참조하십시오.
+ `"compressionType"`: 또는 "`compression`": (선택 사항) 데이터 압축 방식을 지정합니다. Amazon S3 소스에는 `"compressionType"`을 사용하고 Amazon S3 대상에는 `"compression"`을 사용합니다. 이 작업은 데이터에 표준 파일 확장자가 있는 경우에는 필요하지 않습니다. 가능한 값은 `"gzip"` 및 `"bzip2"`입니다). 특정 형식에 대해 추가 압축 형식이 지원될 수 있습니다. 자세한 기능 지원은 데이터 형식 페이지를 참조하세요.
+ `"groupFiles"`: (선택 사항) 입력에 50,000개 이상의 파일이 포함된 경우에는 기본적으로 파일 그룹화가 설정됩니다. 파일이 50,000개 미만일 때 그룹화를 설정하려면 이 파라미터를 `"inPartition"`으로 설정합니다. 파일이 50,000개 이상일 때 그룹화를 비활성화하려면 이 파라미터를 `"none"`으로 설정합니다.
+ `"groupSize"`: (선택사항) 대상 그룹 크기(바이트). 입력 데이터 크기와 클러스터 크기에 따라 기본값을 계산합니다. 입력 파일이 50,000개 미만일 때는 `"groupFiles"`을 `"inPartition"`으로 설정해야 적용됩니다.
+ `"recurse"`: (선택사항) true로 설정할 경우 지정된 경로의 모든 하위 디렉터리에 있는 파일을 반복적으로 읽습니다.
+ `"maxBand"`: (선택 사항, 고급) 이 옵션은 `s3` 목록이 일정할 것으로 예상하는 시간(밀리초)을 제어합니다. 마지막 `maxBand`밀리초에 속하는 수정 타임스탬프가 있는 파일은 특히 `JobBookmarks`를 사용하여 Amazon S3 최종 일관성을 고려할 때 추적됩니다. 대부분의 사용자는 이 옵션을 설정할 필요가 없습니다. 기본값은 900,000밀리초 또는 15분입니다.
+ `"maxFilesInBand"`: (선택 사항, 고급) 이 옵션은 마지막 `maxBand`초부터 저장할 최대 파일 수를 지정합니다. 이 수를 초과할 경우 추가 파일은 건너뛰고 다음 작업 실행에서만 처리됩니다. 대부분의 사용자는 이 옵션을 설정할 필요가 없습니다.
+ `"isFailFast"`: (선택 사항) 이 옵션은 AWS Glue ETL 작업에서 리더 구문 분석 예외가 발생하는지 여부를 결정합니다. `true`로 설정하면 Spark 태스크의 4번 재시도가 데이터를 제대로 구문 분석하지 못하면 작업이 빠르게 실패합니다.
+ `"catalogPartitionPredicate"`: (선택 사항) 읽기에 사용됩니다. SQL `WHERE` 절의 콘텐츠입니다. 파티션 수가 매우 많은 데이터 카탈로그 테이블에서 읽을 때 사용됩니다. 데이터 카탈로그 인덱스에서 일치하는 파티션을 검색합니다. [create\$1dynamic\$1frame\$1from\$1catalog](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_catalog) 메서드 및 기타 유사한 메서드의 옵션인 `push_down_predicate`와 함께 사용됩니다. 자세한 내용은 [카탈로그 파티션 조건자를 사용한 서버 측 필터링](aws-glue-programming-etl-partitions.md#aws-glue-programming-etl-partitions-cat-predicates) 섹션을 참조하세요.
+ `"partitionKeys"`: (선택 사항) 쓰기에 사용됩니다. 열 레이블 문자열의 배열입니다. AWS Glue는 이 구성에 지정된 대로 데이터를 파티셔닝합니다. 자세한 내용은 [파티션 작성](aws-glue-programming-etl-partitions.md#aws-glue-programming-etl-partitions-writing) 섹션을 참조하세요.
+ `"excludeStorageClasses"`: (선택 사항) 읽기에 사용됩니다. Amazon S3 스토리지 클래스를 지정하는 문자열 배열입니다. AWS Glue는 이 구성을 기반으로 Amazon S3 객체를 제외합니다. 자세한 내용은 [Amazon S3 스토리지 클래스 제외](aws-glue-programming-etl-storage-classes.md) 섹션을 참조하세요.

## 데이터 형식에 대한 연결 구문은 더 이상 사용되지 않습니다.
<a name="aws-glue-programming-etl-connect-legacy-format"></a>

특정 연결 유형 구문을 사용하여 특정 데이터 형식에 액세스할 수 있습니다. 이 구문은 더 이상 사용되지 않습니다. 대신 [AWS Glue for Spark에서 입력 및 출력의 데이터 형식 옵션](aws-glue-programming-etl-format.md)에 제공된 `s3` 연결 유형과 형식 옵션을 사용하여 형식을 지정하는 것이 좋습니다.

### "connectionType": "Orc"
<a name="aws-glue-programming-etl-connect-orc"></a>

Amazon S3에 저장된 파일에 [Apache ORC(Hive Optimized Row Columnar)](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC) 파일 포맷으로 연결을 지정합니다.

`"connectionType": "orc"`에는 다음 연결 옵션을 사용합니다.
+ `paths`: (필수 사항) 읽을 소스 Amazon S3 경로 목록입니다.
+ *(기타 옵션 이름/값 페어)*: 형식 지정 옵션을 포함한 모든 추가 옵션이 SparkSQL `DataSource`에 직접 전달됩니다.

### "connectionType": "parquet"
<a name="aws-glue-programming-etl-connect-parquet"></a>

Amazon S3에 [Apache Parquet](https://parquet.apache.org/docs/) 파일 포맷으로 저장된 파일에 대한 연결을 지정합니다.

`"connectionType": "parquet"`에는 다음 연결 옵션을 사용합니다.
+ `paths`: (필수 사항) 읽을 소스 Amazon S3 경로 목록입니다.
+ *(기타 옵션 이름/값 페어)*: 형식 지정 옵션을 포함한 모든 추가 옵션이 SparkSQL `DataSource`에 직접 전달됩니다.

# Amazon S3 스토리지 클래스 제외
<a name="aws-glue-programming-etl-storage-classes"></a>

Amazon Simple Storage Service(Amazon S3)에서 파일 또는 파티션을 읽는 AWS Glue ETL 작업을 실행하는 경우 일부 Amazon S3 스토리지 클래스 유형을 제외할 수 있습니다.

Amazon S3에서 제공되는 스토리지 클래스는 다음과 같습니다.
+ `STANDARD` - 자주 액세스하는 데이터의 범용 스토리지일 때
+ `INTELLIGENT_TIERING` - 액세스 패턴이 불확실하거나 바뀌는 데이터일 때
+ `STANDARD_IA` 및 `ONEZONE_IA` - 저장 기간이 길지만 액세스 횟수가 비교적 적은 데이터일 때
+ `GLACIER`, `DEEP_ARCHIVE` 및 `REDUCED_REDUNDANCY` - 장기 아카이브 및 디지털 보존이 필요할 때

자세한 내용은 *Amazon S3 Developer Guide*의 [Amazon S3 Storage Classes](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html)를 참조하세요.

이번 단원의 예제는 `GLACIER` 및 `DEEP_ARCHIVE` 스토리지 클래스를 제외하는 방법을 나타낸 것입니다. 두 클래스는 파일을 나열하는 데 사용되지만 복원하지 않을 경우 파일을 읽어오지는 못합니다. 자세한 내용은 *Amazon S3 Developer Guide*의 [Restoring Archived Objects](https://docs.aws.amazon.com/AmazonS3/latest/dev/restoring-objects.html)를 참조하세요.

스토리지 클래스 제외를 사용하면 해당 스토리지 클래스 계층에서 파티션이 포함된 테이블에 대해 AWS Glue 작업을 실행할 수 있습니다. 제외를 사용하지 않으면 해당 계층에서 데이터를 읽어오는 작업은 다음 오류와 함께 중단됩니다. AmazonS3Exception: The operation is not valid for the object's storage class.

AWS Glue에서 Amazon S3 스토리지 클래스를 필터링할 수 있는 여러 가지 방법이 있습니다.

**Topics**
+ [

## 동적 프레임 생성 시 Amazon S3 스토리지 클래스 제외
](#aws-glue-programming-etl-storage-classes-dynamic-frame)
+ [

## Data Catalog 테이블에서 Amazon S3 스토리지 클래스 제외
](#aws-glue-programming-etl-storage-classes-table)

## 동적 프레임 생성 시 Amazon S3 스토리지 클래스 제외
<a name="aws-glue-programming-etl-storage-classes-dynamic-frame"></a>

동적 프레임을 생성할 때 Amazon S3 스토리지 클래스를 제외하려면 `additionalOptions`에서 `excludeStorageClasses`를 사용합니다. AWS Glue는 자동으로 고유한 Amazon S3 `Lister` 구현을 사용하여 지정된 스토리지 클래스에 해당하는 파일을 나열하고 제외합니다.

다음 Python 및 Scala 예제는 동적 프레임을 생성할 때 `GLACIER` 및 `DEEP_ARCHIVE` 스토리지 클래스를 제외하는 방법을 나타낸 것입니다.

Python 예제:

```
glueContext.create_dynamic_frame.from_catalog(
    database = "my_database",
    tableName = "my_table_name",
    redshift_tmp_dir = "",
    transformation_ctx = "my_transformation_context",
    additional_options = {
        "excludeStorageClasses" : ["GLACIER", "DEEP_ARCHIVE"]
    }
)
```

Scala 예제:

```
val* *df = glueContext.getCatalogSource(
    nameSpace, tableName, "", "my_transformation_context",  
    additionalOptions = JsonOptions(
        Map("excludeStorageClasses" -> List("GLACIER", "DEEP_ARCHIVE"))
    )
).getDynamicFrame()
```

## Data Catalog 테이블에서 Amazon S3 스토리지 클래스 제외
<a name="aws-glue-programming-etl-storage-classes-table"></a>

AWS Glue ETL 작업에서 사용할 스토리지 클래스 제외를 AWS Glue Data Catalog의 테이블 파라미터로 지정할 수 있습니다. 이러한 파라미터는 AWS Command Line Interface(AWS CLI) 를 사용하거나 API에서 프로그래밍 방식으로 `CreateTable` 작업에 추가할 수 있습니다. 자세한 내용은 [테이블 구조](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-catalog-tables.html#aws-glue-api-catalog-tables-Table) 단원과 [CreateTable](https://docs.aws.amazon.com/glue/latest/webapi/API_CreateTable.html) 단원을 참조하십시오.

그 밖에 AWS Glue 콘솔에서 제외된 스토리지 클래스를 지정하는 방법도 있습니다.

**Amazon S3 스토리지 클래스를 제외하려면(콘솔)**

1. AWS Management Console에 로그인하여 [https://console.aws.amazon.com/glue/](https://console.aws.amazon.com/glue/)에서 AWS Glue 콘솔을 엽니다.

1. 왼쪽 탐색 창에서 **테이블**을 선택합니다.

1. 목록에서 테이블 이름과 **테이블 편집**을 차례대로 선택합니다.

1. **테이블 속성**에서 **excludeStorageClasses**를 키로, 그리고 **[\$1"GLACIER\$1",\$1"DEEP\$1ARCHIVE\$1"]**를 값으로 추가합니다.

1. **Apply(적용)**를 선택합니다.

# AWS Glue에서 ETL 출력의 파티션 관리
<a name="aws-glue-programming-etl-partitions"></a>

파티셔닝은 데이터 세트를 조직하기 위한 중요한 기술로써 효율적으로 데이터 세트를 쿼리할 수 있습니다. 하나 이상의 열에 대한 구별되는 값을 기반으로 계층적 디렉터리 구조에서 데이터를 정리합니다.

예를 들어, 날짜를 기준으로 Amazon Simple Storage Service(Amazon S3)에서 애플리케이션 로그를 분할하고 연, 월, 일을 기준으로 쪼갤 수 있습니다. 하루만큼의 데이터와 대응하는 파일은 `s3://my_bucket/logs/year=2018/month=01/day=23/`와 같은 접두사 아래 위치합니다. 이제 AWS Glue는 Amazon Athena, Amazon Redshift Spectru과 같은 시스템과 더불어 Amazon S3의 기본 데이터를 모두 읽지 않고도 이러한 파티션을 사용하여 파티션 값을 기준으로 데이터를 필터링할 수 있습니다.

크롤러는 파일 유형 및 스키마를 추론할 뿐만 아니라 크롤러가 AWS Glue Data Catalog를 채울 경우 데이터 집합의 파티션 구조를 자동적으로 확인합니다. 결과로 얻은 파티션 열을 AWS Glue ETL 작업 또는 Amazon Athena와 같은 쿼리 엔진에서 쿼리할 수 있습니다.

테이블을 크롤링한 후 크롤러가 생성한 파티션을 볼 수 있습니다. AWS Glue 콘솔의 왼쪽 탐색 창에서 **테이블(Tables)**을 선택합니다. 크롤러에서 생성한 테이블을 선택한 다음 [**파티션 보기(View Partitions)**]를 선택합니다.

`key=val` 스타일에서 Apache Hive 스타일로 분할된 경로의 경우, 크롤러는 열 이름에 자동으로 키 이름을 채웁니다. 그렇지 않은 경우에는 `partition_0`, `partition_1` 같은 기본 이름을 사용합니다. 콘솔에서 기본 이름을 변경할 수 있습니다. 이를 위해 테이블로 이동합니다. **인덱스** 탭 아래에 인덱스가 있는지 확인합니다. 인덱스가 있는 경우 계속 진행하려면 해당 인덱스를 삭제해야 합니다(이후 새 열 이름을 사용하여 다시 생성할 수 있음). 그런 다음 **스키마 편집**을 선택하고 여기에서 파티션 열의 이름을 수정합니다.

ETL 스크립트에서 파티션 열에 필터링합니다. 파티션 정보는 Data Catalog에 저장되므로 `from_catalog` API 호출을 사용하여 `DynamicFrame`에 파티션 열을 포함합니다. 예를 들어 `create_dynamic_frame.from_options` 대신 `create_dynamic_frame.from_catalog`을 사용하세요.

파티셔닝은 데이터 스캔을 줄이는 최적화 기법입니다. 이 기법이 적절한 시기를 식별하는 프로세스에 대한 자세한 내용은 AWS 권장 가이드의 *Apache Spark용 AWS Glue 작업 성능 조정 모범 사례* 가이드에 있는 [데이터 스캔량 감소](https://docs.aws.amazon.com/prescriptive-guidance/latest/tuning-aws-glue-for-apache-spark/reduce-data-scan.html)를 참조하세요.

## 푸시다운 조건자를 사용하여 예비 필터링
<a name="aws-glue-programming-etl-partitions-pushdowns"></a>

많은 경우, 조건자를 푸시다운하여 데이터 세트 내 모든 파일을 나열하거나 읽지 않아도 파티션에 필터링할 수 있습니다. 데이터 집합 전체를 읽는 대신 DynamicFrame에서 필터링한 다음 Data Catalog에서 파티션 메타데이터에 직접 필터링을 적용할 수 있습니다. 그런 다음 실제로 필요한 것을 DynamicFrame에서 나열하고 읽습니다.

예를 들어, Python에서는 다음을 작성할 수 있습니다.

```
glue_context.create_dynamic_frame.from_catalog(
    database = "my_S3_data_set",
    table_name = "catalog_data_table",
    push_down_predicate = my_partition_predicate)
```

조건자 표현식을 만족하는 Data Catalog의 파티션을 로딩만 하는 DynamicFrame을 생성합니다. 로딩하는 데이터의 서브셋이 얼마나 작은지에 따라 진행 시간을 많이 줄일 수 있습니다.

조건자 표현식은 Spark SQL가 지원한 부울 확장일 수 있습니다. Spark SQL 쿼리의 `WHERE`에 넣는 어떤 것도 만족할 수 있습니다. 예를 들어 조건자 표현식 `pushDownPredicate = "(year=='2017' and month=='04')"`는 `year`가 2017이고 `month`가 04인 Data Catalog의 파티션만 로드합니다. 자세한 내용은 [Apache Spark SQL 설명서](https://spark.apache.org/docs/2.1.1/sql-programming-guide.html), 특히 [Scala SQL 함수 참조](https://spark.apache.org/docs/2.1.1/api/scala/index.html#org.apache.spark.sql.functions$)를 참조하십시오.

## 카탈로그 파티션 조건자를 사용한 서버 측 필터링
<a name="aws-glue-programming-etl-partitions-cat-predicates"></a>

`push_down_predicate` 옵션은 카탈로그의 모든 파티션을 나열한 후 해당 파티션에 대한 Amazon S3의 파일을 나열하기 전에 적용됩니다. 테이블에 대한 파티션이 많은 경우 카탈로그 파티션 목록에 여전히 추가 시간 오버헤드가 발생할 수 있습니다. 이 오버헤드를 해결하기 위해 AWS Glue Data Catalog의 [파티션 인덱스](https://docs.aws.amazon.com/glue/latest/dg/partition-indexes.html)를 사용하는 `catalogPartitionPredicate` 옵션과 함께 서버 측 파티션 정리를 사용할 수 있습니다. 따라서 한 테이블에 수백만 개의 파티션이 있는 경우 파티션 필터링이 훨씬 빨라집니다. 카탈로그 파티션 인덱스에서 아직 지원되지 않는 조건자 구문이 `catalogPartitionPredicate`에 필요한 경우 `additional_options`에서 `push_down_predicate`와 `catalogPartitionPredicate`를 함께 사용할 수 있습니다.

Python:

```
dynamic_frame = glueContext.create_dynamic_frame.from_catalog(
    database=dbname, 
    table_name=tablename,
    transformation_ctx="datasource0",
    push_down_predicate="day>=10 and customer_id like '10%'",
    additional_options={"catalogPartitionPredicate":"year='2021' and month='06'"}
)
```

Scala:

```
val dynamicFrame = glueContext.getCatalogSource(
    database = dbname,
    tableName = tablename, 
    transformationContext = "datasource0",
    pushDownPredicate="day>=10 and customer_id like '10%'",
    additionalOptions = JsonOptions("""{
        "catalogPartitionPredicate": "year='2021' and month='06'"}""")
    ).getDynamicFrame()
```

**참고**  
`push_down_predicate`와 `catalogPartitionPredicate`는 다른 구문을 사용합니다. 전자는 Spark SQL 표준 구문을 사용하고 후자는 JSQL 구문 분석기를 사용합니다.

## 파티션 작성
<a name="aws-glue-programming-etl-partitions-writing"></a>

기본적으로 DynamicFrame은 작성될 때 파티션이 되지 않습니다. 출력 파일 모두는 지정된 출력 경로의 상위 수준에 작성됩니다. 최근까지 파티션에 DynamicFrame을 작성하는 유일한 방법은 작성 전에 DynamicFrame을 Spark SQL DataFrame으로 전환하는 방법이었습니다.

그러나 DynamicFrame은 싱크를 생성할 때 `partitionKeys` 옵션을 사용하여 키의 시퀀스를 사용한 본래 파티셔닝을 지원합니다. 예를 들어, 다음 Python 코드는 Parquet 포맷의 Amazon S3로 데이터 집합을 유형 필드로 분할된 디렉터리에 작성합니다. 그런 다음, Amazon Athena와 같은 다른 시스템을 사용하여 이런 파티션을 진행할 수 있습니다.

```
glue_context.write_dynamic_frame.from_options(
    frame = projectedEvents,
    connection_type = "s3",    
    connection_options = {"path": "$outpath", "partitionKeys": ["type"]},
    format = "parquet")
```

# 입력 파일을 더 큰 그룹에서 읽기
<a name="grouping-input-files"></a>

테이블에 속성을 설정하여 AWS Glue ETL 작업을 활성화하여 속성을 Amazon S3 데이터 스토어에서 읽을 때 파일을 모읍니다. 이 속성은 각 ETL 태스크이 입력 파일 그룹을 단일 인메모리 파티션으로 읽을 수 있도록 만듭니다. 이렇게 하는 것은 Amazon S3 데이터 스토어에 많은 수의 작은 파일을 있을 때 유용합니다. 특정 속성을 설정하면 AWS Glue에 지시를 내려 Amazon S3 데이터 파티션 내 파일을 모으고 읽을 그룹의 크기를 설정합니다. `create_dynamic_frame.from_options` 메서드로 Amazon S3 데이터 스토어에서 읽을 때 이러한 옵션을 설정할 수도 있습니다.

테이블 파일을 모으려면 테이블 구조의 파라미터 필드에서 키 값 페어를 설정합니다. JSON 표기법을 사용하여 테이블 파라미터 필드 값을 설정합니다. 테이블 속성을 편집하는 방법에 대한 더 자세한 정보는 [테이블 세부 정보 보기 및 편집](tables-described.md#console-tables-details)를 참조하십시오.

이 방법을 사용하여 Amazon S3 데이터 스토어로 Data Catalog의 테이블을 모을 수 있도록 합니다.

**groupFiles**  
**groupFiles**를 `inPartition`으로 설정하면 Amazon S3 데이터 파티션 내 파일 그룹화가 가능합니다. 입력 파일이 50,000개 이상일 경우 AWS Glue가 그룹화를 자동으로 활성화합니다.  

```
  'groupFiles': 'inPartition'
```

**groupSize**  
**groupSize**를 바이트 단위로 그룹의 대상 크기로 설정합니다. **groupSize** 속성은 조건부입니다. 제공되지 않으면 총 ETL 작업 수 및 인메모리 파티션을 줄이면서 AWS Glue는 크기를 계산하여 클러스터의 모든 CPU 코어를 사용합니다.  
예를 들어, 다음은 그룹 크기를 1MB로 설정합니다.  

```
  'groupSize': '1048576'
```
계산 결과로 `groupsize`를 설정해야 합니다. 예: 1024 \$1 1024 = 1048576.

**recurse**  
**recurse**를 `True`로 설정하여 `paths`를 경로 어레이로 지정할 때 모든 하위 디렉터리의 파일을 재귀적으로 읽을 수 있습니다. 다음 예와 같이 `paths`(이가) Amazon S3의 객체 키 배열이거나 입력 형식이 parquet/orc인 경우 **재귀**를 설정하지 않아도 됩니다.  

```
  'recurse':True
```

`create_dynamic_frame.from_options` 메서드를 사용하여 Amazon S3에서 직접 읽는 경우 이러한 연결 옵션을 추가합니다. 예를 들어, 다음과 같이 파일을 1MB 그룹으로 그룹화하려는 시도합니다.

```
df = glueContext.create_dynamic_frame.from_options("s3", {'paths': ["s3://s3path/"], 'recurse':True, 'groupFiles': 'inPartition', 'groupSize': '1048576'}, format="json")
```

**참고**  
`groupFiles`는 csv, ion, grokLog, json, xml 등의 데이터 포맷에서 생성된 DynamicFrames에서 지원됩니다. avro, parquet, orc에서는 이 옵션이 지원되지 않습니다.

# Amazon S3용 Amazon VPC 엔드포인트
<a name="vpc-endpoints-s3"></a>

보안상의 이유로 많은 AWS 고객은 Amazon Virtual Private Cloud 환경(Amazon VPC)에서 애플리케이션을 실행합니다. Amazon VPC를 통해 Amazon EC2 인스턴스를 퍼블릭 인터넷을 비롯한 다른 네트워크와 논리적으로 분리된 Virtual Private Cloud로 시작할 수 있습니다. Amazon VPC를 사용하면 IP 주소 범위, 서브넷, 라우팅 테이블, 네트워크 게이트웨이 및 보안 설정을 통제할 수 있습니다.

**참고**  
2013년 12월 4일 이후 AWS 계정을 생성했다면 각 AWS 리전에 기본 VPC가 갖춰져 있습니다. 별도의 구성 단계 없이 기본 VPC를 사용하여 즉시 시작할 수 있습니다.  
자세한 내용은 Amazon VPC 사용 설명서의 [기본 VPC 및 서브넷](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html)을 참조하세요.

많은 고객이 퍼블릭 인터넷을 통해 데이터를 주고받는 것에 대한 합법적인 개인 정보 보호 및 보안 문제를 우려합니다. 가상 사설 네트워크(VPN)를 사용하여 모든 Amazon S3 네트워크 트래픽을 자체 기업 네트워크 인프라를 통해 라우팅함으로써 이러한 문제를 해결할 수 있습니다. 그러나 이러한 접근 방식은 대역폭 및 가용성 문제를 일으킬 수 있습니다.

Amazon S3에 대한 VPC 엔드포인트는 이러한 문제를 완화할 수 있습니다. Amazon S3에 대한 VPC 엔드포인트를 사용하여 AWS Glue가 퍼블릭 인터넷에 노출되지 않고도 프라이빗 IP 주소를 사용하여 Amazon S3에 액세스할 수 있습니다. AWS Glue에 퍼블릭 IP 주소를 지정할 필요가 없으며 VPC에서 인터넷 게이트웨이, NAT 디바이스 또는 가상 프라이빗 게이트웨이가 필요 없습니다. 엔드포인트 정책을 사용하여 Amazon S3에 대한 액세스를 제어합니다. VPC와 AWS 서비스 간의 트래픽은 Amazon 네트워크를 벗어나지 않습니다.

Amazon S3에 대한 VPC 엔드포인트를 생성하면 리전 내의 Amazon S3 엔드포인트(예: *s3.us-west-2.amazonaws.com*)에 대한 요청이 Amazon 네트워크 내의 프라이빗 Amazon S3 엔드포인트로 라우팅됩니다. VPC의 Amazon EC2 인스턴스에서 실행되는 애플리케이션을 수정할 필요가 없습니다.엔드포인트 이름은 동일하게 남아있지만 Amazon S3에 대한 경로는 전적으로 Amazon 네트워크에 유지되며 퍼블릭 인터넷에 액세스하지 않습니다.

VPC 엔드포인트에 대한 자세한 내용은 Amazon VPC 사용 설명서의 [VPC 엔드포인트](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-endpoints.html)를 참조하세요.

다음 다이어그램은 AWS Glue가 Amazon S3에 액세스하기 위해 VPC 엔드포인트를 사용하는 방법을 보여줍니다.

![\[VPC 연결에서 Amazon S3까지 보여주는 네트워크 트래픽 흐름\]](http://docs.aws.amazon.com/ko_kr/glue/latest/dg/images/PopulateCatalog-vpc-endpoint.png)


**Amazon S3에 대한 액세스를 설정하려면**

1. AWS Management Console에 로그인하고 [https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/)에서 Amazon VPC 콘솔을 엽니다.

1. 왼쪽 탐색 창에서 **엔드포인트**를 선택합니다.

1. [**엔드포인트 생성(Create Endpoint)**]을 선택하고 단계에 따라 게이트웨이 유형의 Amazon S3 VPC 엔드포인트를 생성합니다.

# Amazon DocumentDB 연결
<a name="aws-glue-programming-etl-connect-documentdb-home"></a>

AWS Glue for Spark를 사용하여 Amazon DocumentDB 데이터베이스의 테이블에서 읽고 쓸 수 있습니다. AWS Glue 연결을 통해 AWS Secrets Manager에 저장된 보안 인증 정보를 사용하여 Amazon DocumentDB에 연결할 수 있습니다.

Amazon DocumentDB에 대한 자세한 내용은 [Amazon DocumentDB 설명서](https://docs.aws.amazon.com/documentdb/latest/developerguide/what-is.html)를 참조하세요.

**참고**  
Amazon DocumentDB Elastic Clusters는 현재 AWS Glue 커넥터를 사용하는 경우 지원되지 않습니다. Elastic Clusters에 대한 자세한 내용은 [Using Amazon DocumentDB elastic clusters](https://docs.aws.amazon.com/documentdb/latest/developerguide/docdb-using-elastic-clusters.html)를 참조하세요.

## Amazon DocumentDB 컬렉션 읽기 및 쓰기
<a name="aws-glue-programming-etl-connect-documentdb-read-write"></a>

**참고**  
Amazon DocumentDB에 연결하는 ETL 작업을 생성할 때 `Connections` 작업 속성에 대해 Amazon DocumentDB가 실행 중인 Virtual Private Cloud(VPC)를 지정하는 연결 객체를 지정해야 합니다. 연결 객체의 경우 연결 유형은 `JDBC`여야 하며 `JDBC URL`은 `mongo://<DocumentDB_host>:27017`이어야 합니다.

**참고**  
이 코드 샘플은 AWS Glue 3.0용으로 개발되었습니다. AWS Glue 4.0으로 마이그레이션하려면 [MongoDB](migrating-version-40.md#migrating-version-40-connector-driver-migration-mongodb) 섹션을 참조하세요. `uri` 파라미터가 변경되었습니다.

**참고**  
Amazon DocumentDB를 사용하는 경우 작성된 문서에서 `_id`를 지정하는 경우와 같은 특정 상황에서는 `retryWrites`를 false로 설정해야 합니다. 자세한 내용은 Amazon DocumentDB 설명서에서 [Functional Differences with MongoDB](https://docs.aws.amazon.com/documentdb/latest/developerguide/functional-differences.html#functional-differences.retryable-writes)를 참조하세요.

다음 Python 스크립트는 Amazon DocumentDB를 읽고 쓰기 위한 연결 유형 및 연결 옵션을 사용하는 방법을 보여줍니다.

```
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext, SparkConf
from awsglue.context import GlueContext
from awsglue.job import Job
import time

## @params: [JOB_NAME]
args = getResolvedOptions(sys.argv, ['JOB_NAME'])

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

job = Job(glueContext)
job.init(args['JOB_NAME'], args)

output_path = "s3://some_bucket/output/" + str(time.time()) + "/"
documentdb_uri = "mongodb://<mongo-instanced-ip-address>:27017"
documentdb_write_uri = "mongodb://<mongo-instanced-ip-address>:27017"

read_docdb_options = {
    "uri": documentdb_uri,
    "database": "test",
    "collection": "coll",
    "username": "username",
    "password": "1234567890",
    "ssl": "true",
    "ssl.domain_match": "false",
    "partitioner": "MongoSamplePartitioner",
    "partitionerOptions.partitionSizeMB": "10",
    "partitionerOptions.partitionKey": "_id"
}

write_documentdb_options = {
    "retryWrites": "false",
    "uri": documentdb_write_uri,
    "database": "test",
    "collection": "coll",
    "username": "username",
    "password": "pwd"
}

# Get DynamicFrame from  DocumentDB
dynamic_frame2 = glueContext.create_dynamic_frame.from_options(connection_type="documentdb",
                                                               connection_options=read_docdb_options)

# Write DynamicFrame to MongoDB and DocumentDB
glueContext.write_dynamic_frame.from_options(dynamic_frame2, connection_type="documentdb",
                                             connection_options=write_documentdb_options)

job.commit()
```

다음 Scala 스크립트는 Amazon DocumentDB를 읽고 쓰기 위한 연결 유형 및 연결 옵션을 사용하는 방법을 보여줍니다.

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.MappingSpec
import com.amazonaws.services.glue.errors.CallSite
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamicFrame
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._

object GlueApp {
  val DOC_URI: String = "mongodb://<mongo-instanced-ip-address>:27017"
  val DOC_WRITE_URI: String = "mongodb://<mongo-instanced-ip-address>:27017"
  lazy val documentDBJsonOption = jsonOptions(DOC_URI)
  lazy val writeDocumentDBJsonOption = jsonOptions(DOC_WRITE_URI)
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)

    // Get DynamicFrame from DocumentDB
    val resultFrame2: DynamicFrame = glueContext.getSource("documentdb", documentDBJsonOption).getDynamicFrame()

    // Write DynamicFrame to DocumentDB
    glueContext.getSink("documentdb", writeJsonOption).writeDynamicFrame(resultFrame2)

    Job.commit()
  }

  private def jsonOptions(uri: String): JsonOptions = {
    new JsonOptions(
      s"""{"uri": "${uri}",
         |"database":"test",
         |"collection":"coll",
         |"username": "username",
         |"password": "pwd",
         |"ssl":"true",
         |"ssl.domain_match":"false",
         |"partitioner": "MongoSamplePartitioner",
         |"partitionerOptions.partitionSizeMB": "10",
         |"partitionerOptions.partitionKey": "_id"}""".stripMargin)
  }
}
```

## Amazon DocumentDB 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-documentdb"></a>

Amazon DocumentDB에 대한 연결을 지정합니다(MongoDB와 호환).

연결 옵션은 소스 연결 및 싱크 연결에 따라 다릅니다.

### 소스로서의 "connectionType": "Documentdb"
<a name="etl-connect-documentdb-as-source"></a>

소스로서의 `"connectionType": "documentdb"`에는 다음 연결 옵션을 사용합니다.
+ `"uri"`: (필수 사항) 읽을 소스 Amazon DocumentDB 호스트로, `mongodb://<host>:<port>` 포맷입니다.
+ `"database"`: (필수) 읽을 소스 Amazon DocumentDB 데이터베이스입니다.
+ `"collection"`: (필수) 읽을 소스 Amazon DocumentDB 컬렉션입니다.
+ `"username"`: (필수) Amazon DocumentDB 사용자 이름입니다.
+ `"password"`: (필수) Amazon DocumentDB 암호입니다.
+ `"ssl"`: (SSL을 사용하는 경우 필수) 연결에서 SSL을 사용하는 경우 `"true"` 값과 함께 이 옵션을 포함해야 합니다.
+ `"ssl.domain_match"`: (SSL을 사용하는 경우 필수) 연결에서 SSL을 사용하는 경우 `"false"` 값과 함께 이 옵션을 포함해야 합니다.
+ `"batchSize"`: (선택 사항) 내부 배치의 커서 내에서 사용되는 배치당 반환할 문서 수입니다.
+ `"partitioner"`: (선택 사항) Amazon DocumentDB에서 입력 데이터를 읽는 파티셔너의 클래스 이름입니다. 커넥터는 다음 파티셔너를 제공합니다.
  + `MongoDefaultPartitioner`(기본값)(AWS Glue 4.0에서는 지원되지 않음)
  + `MongoSamplePartitioner`(AWS Glue 4.0에서는 지원되지 않음)
  + `MongoShardedPartitioner`
  + `MongoSplitVectorPartitioner`
  + `MongoPaginateByCountPartitioner`
  + `MongoPaginateBySizePartitioner`(AWS Glue 4.0에서는 지원되지 않음)
+ `"partitionerOptions"`: (선택 사항) 지정된 파티셔너에 대한 옵션입니다. 각 파티셔너에 대해 다음 옵션이 지원됩니다.
  + `MongoSamplePartitioner`: `partitionKey`, `partitionSizeMB`, `samplesPerPartition`
  + `MongoShardedPartitioner`: `shardkey`
  + `MongoSplitVectorPartitioner`: `partitionKey`, partitionSizeMB
  + `MongoPaginateByCountPartitioner`: `partitionKey`, `numberOfPartitions`
  + `MongoPaginateBySizePartitioner`: `partitionKey`, partitionSizeMB

  이러한 옵션에 대한 자세한 내용은 MongoDB 설명서의 [파티셔너 구성](https://docs.mongodb.com/spark-connector/master/configuration/#partitioner-conf)을 참조하십시오.

### 싱크로서의 "connectionType": "Documentdb"
<a name="etl-connect-documentdb-as-sink"></a>

싱크로서의 `"connectionType": "documentdb"`에는 다음 연결 옵션을 사용합니다.
+ `"uri"`: (필수 사항) 쓸 대상 Amazon DocumentDB 호스트로, `mongodb://<host>:<port>` 포맷입니다.
+ `"database"`: (필수) 쓸 대상 Amazon DocumentDB 데이터베이스입니다.
+ `"collection"`: (필수) 쓸 대상 소스 Amazon DocumentDB 컬렉션입니다.
+ `"username"`: (필수) Amazon DocumentDB 사용자 이름입니다.
+ `"password"`: (필수) Amazon DocumentDB 암호입니다.
+ `"extendedBsonTypes"`: (선택 사항) `true`이면 데이터를 Amazon DocumentDB에 쓸 때 확장 BSON 유형을 허용합니다. 기본값은 `true`입니다.
+ `"replaceDocument"`: (선택 사항) `true`이면 `_id` 필드가 포함된 데이터 세트를 저장할 때 전체 문서를 대체합니다. `false`이면 데이터 세트의 필드와 일치하는 문서의 필드만 업데이트됩니다. 기본값은 `true`입니다.
+ `"maxBatchSize"`: (선택 사항) 데이터를 저장할 때 대량 작업의 최대 배치 크기입니다. 기본값은 512입니다.
+ `"retryWrites"`: (선택 사항): AWS Glue에서 네트워크 오류가 발생하는 경우 특정 쓰기 작업을 한 번 자동으로 재시도합니다.

# OpenSearch Service 연결
<a name="aws-glue-programming-etl-connect-opensearch-home"></a>

AWS Glue for Spark를 사용하여 AWS Glue 4.0 이상 버전에서 OpenSearch Service의 테이블에서 읽고 쓸 수 있습니다. OpenSearch 쿼리를 사용하여 OpenSearch Service에서 읽을 내용을 정의할 수 있습니다. AWS Glue 연결을 통해 AWS Secrets Manager에 저장된 HTTP 기본 인증 보안 인증 정보를 사용하여 OpenSearch Service에 연결합니다. 이 기능은 OpenSearch Service 서버리스와 호환되지 않습니다.

Amazon OpenSearch Service에 대한 자세한 정보는 [Amazon OpenSearch Service 설명서](https://docs.aws.amazon.com/opensearch-service/)를 참조하십시오.

## OpenSearch Service 연결 구성
<a name="aws-glue-programming-etl-connect-opensearch-configure"></a>

AWS Glue에서 OpenSearch Service에 연결하려면 OpenSearch Service 보안 인증 정보를 생성하여 암호에 저장한 다음 해당 AWS Secrets Manager 암호를 OpenSearch Service AWS Glue 연결에 연결해야 합니다.

**사전 조건 ** 
+ Amazon OpenSearch Service 설명서의 지침에 따라 읽으려는 도메인 엔드포인트, *aosEndpoint* 및 포트, *aosPort*를 식별하거나 리소스를 생성하십시오. 도메인 생성에 관해 자세한 내용을 알아보려면 Amazon OpenSearch Service 설명서의 [Amazon OpenSearch Service 도메인 생성 및 관리](https://docs.aws.amazon.com//opensearch-service/latest/developerguide/createupdatedomains.html)를 참조하십시오.

  Amazon OpenSearch Service 도메인 엔드포인트는 기본 형식이 https://search-*domainName*-*unstructuredIdContent*.*region*.es.amazonaws.com입니다. 도메인 엔드포인트에 관해 자세한 내용을 알아보려면 Amazon OpenSearch Service 설명서의 [Amazon OpenSearch Service 도메인 생성 및 관리](https://docs.aws.amazon.com//opensearch-service/latest/developerguide/createupdatedomains.html)를 참조하십시오.

  도메인의 HTTP 기본 보안 인증 정보, *aosUser*와 *aosPassword*를 확인하거나 생성하십시오.

**OpenSearch Service에 대한 연결을 구성하는 방법:**

1. AWS Secrets Manager에서 OpenSearch 보안 인증을 사용하여 보안 암호를 생성합니다. Secrets Manager에서 보안 암호를 생성하려면 AWS Secrets Manager 설명서의 [Create an AWS Secrets Manager secret](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)에서 제공하는 자습서를 따릅니다. 보안 암호를 생성한 후에는 다음 단계를 위해 보안 암호 이름, *secretName*을 유지합니다.
   + **키/값 페어**를 선택하면 값 *aosUser*이 포함된 키 `USERNAME`에 대한 페어를 생성합니다.
   + **키/값 페어**를 선택하면 값 *aosPassword*이 포함된 키 `PASSWORD`에 대한 페어를 생성합니다.

1. AWS Glue 콘솔에서 [AWS Glue 연결 추가](console-connections.md)의 단계에 따라 연결을 생성합니다. 연결을 생성한 후에는 AWS Glue에서 이용하기 위해 연결 이름 *connectionName*을 유지합니다.
   + **연결 유형**을 선택할 때는 OpenSearch Service를 선택합니다.
   + 도메인 엔드포인트를 선택할 때는 *aosEndpoint*를 제공하십시오.
   + 포트를 선택할 때는 *aosPort*를 제공하십시오.
   + **AWS 보안 암호**를 선택할 때 *secretName*을 입력합니다.

AWS Glue OpenSearch Service 연결을 생성한 후에는 AWS Glue 작업을 실행하기 전에 다음 단계를 수행해야 합니다.
+ AWS Glue 작업과 연결된 IAM 역할에 *secretName*을 읽을 수 있는 권한을 부여합니다.
+ AWS Glue 작업 구성에서 **추가 네트워크 연결**로 *connectionName*을 제공합니다.

## OpenSearch Service 인덱스에서 읽기
<a name="aws-glue-programming-etl-connect-opensearch-read"></a>

**사전 조건 ** 
+ 읽으려는 OpenSearch Service 인덱스, *aosIndex*.
+ 인증 및 네트워크 위치 정보를 제공하도록 구성된 AWS Glue OpenSearch Service 연결입니다. 이 정보를 얻으려면 앞 절차인 *OpenSearch Service에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

이 예제는 Amazon OpenSearch Service에서 인덱스을 읽습니다. `pushdown` 파라미터를 제공해야 합니다.

예: 

```
opensearch_read = glueContext.create_dynamic_frame.from_options(
    connection_type="opensearch",
    connection_options={
        "connectionName": "connectionName",
        "opensearch.resource": "aosIndex",
        "pushdown": "true",
    }
)
```

DynamicFrame에 반환되는 결과를 필터링하는 쿼리 문자열을 제공할 수도 있습니다. `opensearch.query`를 구성해야 합니다.

`opensearch.query`는 URL 쿼리 매개 변수 문자열 *queryString* 또는 쿼리 DSL JSON 객체 *queryObject*를 사용할 수 있습니다. 쿼리 DSL에 대한 자세한 내용은 OpenSearch 설명서의 [쿼리 DSL](https://opensearch.org/docs/latest/query-dsl/index/)을 참조하십시오. URL 쿼리 매개 변수 문자열을 제공하려면 정규화된 URL에서처럼 쿼리 앞에 `?q=`를 추가하십시오. 쿼리 DSL 객체를 제공하려면 JSON 객체를 제공하기 전에 문자열을 이스케이프 처리해야 합니다.

예: 

```
            queryObject = "{ "query": { "multi_match": { "query": "Sample", "fields": [ "sample" ] } } }"
            queryString = "?q=queryString"
            
            opensearch_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="opensearch",
    connection_options={
        "connectionName": "connectionName",
        "opensearch.resource": "aosIndex",
        "opensearch.query": queryString,
        "pushdown": "true",
    }
)
```

특정 구문을 벗어나 쿼리를 작성하는 방법에 대한 자세한 내용은 OpenSearch 설명서의 [쿼리 문자열 구문](https://opensearch.org/docs/latest/query-dsl/full-text/query-string/#query-string-syntax)을 참조하십시오.

배열 형식 데이터가 포함된 OpenSearch 컬렉션에서 읽을 때는 `opensearch.read.field.as.array.include` 파라미터를 사용하여 메서드 직접 호출에서 어떤 필드가 배열 형식인지 지정해야 합니다.

예를 들어 다음 문서를 읽을 때 `genre` 및 `actor` 배열 필드가 나타납니다.

```
{
    "_index": "movies",
    "_id": "2",
    "_version": 1,
    "_seq_no": 0,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "director": "Frankenheimer, John",
        "genre": [
            "Drama",
            "Mystery",
            "Thriller",
            "Crime"
        ],
        "year": 1962,
        "actor": [
            "Lansbury, Angela",
            "Sinatra, Frank",
            "Leigh, Janet",
            "Harvey, Laurence",
            "Silva, Henry",
            "Frees, Paul",
            "Gregory, James",
            "Bissell, Whit",
            "McGiver, John",
            "Parrish, Leslie",
            "Edwards, James",
            "Flowers, Bess",
            "Dhiegh, Khigh",
            "Payne, Julie",
            "Kleeb, Helen",
            "Gray, Joe",
            "Nalder, Reggie",
            "Stevens, Bert",
            "Masters, Michael",
            "Lowell, Tom"
        ],
        "title": "The Manchurian Candidate"
    }
}
```

이 경우 메서드 직접 호출에 해당 필드 이름을 포함하면 됩니다. 예:

```
"opensearch.read.field.as.array.include": "genre,actor"
```

배열 필드가 문서 구조 안에 중첩되어 있는 경우 점 표기법(`"genre,actor,foo.bar.baz"`)을 사용하여 참조하세요. 이는 포함된 문서(`bar`)를 포함하는 포함된 문서(`foo`)를 통해 소스 문서에 포함된 배열(`baz`)을 지정합니다.

## OpenSearch Service 테이블에 쓰기
<a name="aws-glue-programming-etl-connect-opensearch-write"></a>

이 예제에서는 기존 DynamicFrame, *dynamicFrame*의 정보를 OpenSearch Service에 기록합니다. 인덱스에 이미 정보가 있는 경우 AWS Glue는 DynamicFrame의 데이터를 추가합니다. `pushdown` 파라미터를 제공해야 합니다.

**사전 조건 ** 
+ 쓰려는 OpenSearch Service 테이블. 테이블에 대한 식별 정보가 필요합니다. 이 *tableName*이라고 부르겠습니다.
+ 인증 및 네트워크 위치 정보를 제공하도록 구성된 AWS Glue OpenSearch Service 연결입니다. 이 정보를 얻으려면 앞 절차인 *OpenSearch Service에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예: 

```
glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="opensearch",
    connection_options={
      "connectionName": "connectionName",
      "opensearch.resource": "aosIndex",
    },
)
```

## OpenSearch Service 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-opensearch-reference"></a>
+ `connectionName` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 연결 방법에 인증 및 네트워크 위치 정보를 제공하도록 구성된 AWS Glue OpenSearch Service 연결의 이름입니다.
+ `opensearch.resource` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 유효한 값: OpenSearch 인덱스 이름. 연결 방법이 상호 작용하는 인덱스의 이름입니다.
+ `opensearch.query` — 읽기에 사용됩니다. 유효한 값: 문자열이 JSON으로 이스케이프되거나 이 문자열이 `?`로 시작되는 경우 URL의 검색 부분. 읽을 때 검색해야 하는 항목을 필터링하는 OpenSearch 쿼리입니다. 이 매개변수 사용에 대한 자세한 내용은 이전 섹션 [OpenSearch Service 인덱스에서 읽기](#aws-glue-programming-etl-connect-opensearch-read)를 참조하십시오.
+ `pushdown` - 다음과 같은 경우 필수입니다. 읽기에 사용됩니다. 유효 값: 부울. 데이터베이스가 관련 문서만 반환하도록 Spark가 읽기 쿼리를 OpenSearch에 전달하도록 지시합니다.
+ `opensearch.read.field.as.array.include` - 배열 유형 데이터를 읽을 때 필요합니다. 읽기에 사용됩니다. 유효 값: 쉼표로 구분된 필드 이름 목록. OpenSearch 문서에서 배열로 읽을 필드를 지정합니다. 이 매개변수 사용에 대한 자세한 내용은 이전 섹션 [OpenSearch Service 인덱스에서 읽기](#aws-glue-programming-etl-connect-opensearch-read)를 참조하십시오.

# Redshift 연결
<a name="aws-glue-programming-etl-connect-redshift-home"></a>

AWS Glue for Spark를 사용하여 Amazon Redshift 데이터베이스의 테이블에서 읽고 쓸 수 있습니다. Amazon Redshift 데이터베이스에 연결할 때 AWS Glue는 Amazon Redshift SQL `COPY` 및 `UNLOAD` 명령을 사용하여 Amazon S3를 통해 데이터를 이동함으로써 처리량을 극대화합니다. AWS Glue 4.0 이상에서는 [Apache Spark용 Amazon Redshift 통합](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)을 사용하여 이전 버전을 통해 연결할 때 사용할 수 있었던 기능 외에도 Amazon Redshift에서만 지원하는 기능 및 최적화를 사용하여 읽고 쓸 수 있습니다.

Amazon Redshift 사용자가 AWS Glue를 사용하여 서버리스 데이터 통합 및 ETL을 위해 보다 쉽게 AWS로 마이그레이션하는 방법에 대해 알아보세요.

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/ZapycBq8TKU/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/ZapycBq8TKU)


## Redshift 연결 구성
<a name="aws-glue-programming-etl-connect-redshift-configure"></a>

AWS Glue에서 Amazon Redshift 클러스터를 사용하려면 다음과 같은 몇 가지 필수 조건이 필요합니다.
+ 데이터베이스에서 읽고 쓸 때 임시 스토리지로 사용하는 Amazon S3 디렉터리.
+ Amazon Redshift 클러스터, AWS Glue 작업 및 Amazon S3 디렉터리 간 통신을 지원하는 Amazon VPC.
+ AWS Glue 작업 및 Amazon Redshift 클러스터에 대한 적절한 IAM 권한.

### IAM 역할 구성
<a name="aws-glue-programming-etl-redshift-config-iam"></a>

**Amazon Redshift 클러스터의 역할 설정**  
AWS Glue 작업과 통합하려면 Amazon Redshift 클러스터는 Amazon S3에서 읽고 쓸 수 있어야 합니다. 이를 허용하기 위해 연결하려는 Amazon Redshift 클러스터에 IAM 역할을 연결할 수 있습니다. 역할에는 Amazon S3 임시 디렉터리에서의 읽기 및 쓰기를 허용하는 정책이 있어야 합니다. 역할에는 `AssumeRole`을 위해 `redshift.amazonaws.com` 서비스를 허용하는 신뢰 관계가 있어야 합니다.

**IAM 역할을 Amazon Redshift에 연결하려면**

1. **필수 조건:** 파일의 임시 저장에 사용되는 Amazon S3 버킷 또는 디렉터리.

1. Amazon Redshift 클러스터에 필요한 Amazon S3 권한을 식별합니다. Amazon Redshift 클러스터 간에 데이터를 이동하는 경우 AWS Glue 작업이 Amazon Redshift에 대해 COPY 및 UNLOAD 문을 실행합니다. 작업에서 Amazon Redshift의 테이블을 수정하는 경우 AWS Glue는 CREATE LIBRARY 문도 실행합니다. Amazon Redshift에서 이러한 명령문을 실행하는 데 필요한 특정 Amazon S3 권한에 대한 자세한 내용은 Amazon Redshift 설명서, [Amazon Redshift: 다른 AWS 리소스에 대한 액세스 권한](https://docs.aws.amazon.com/redshift/latest/dg/copy-usage_notes-access-permissions.html)을 참조하세요.

1. IAM 콘솔에서 필요한 권한이 포함된 IAM 정책을 생성합니다. IAM 정책 생성에 대한 자세한 내용은 [IAM 정책 생성](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html)을 참조하세요.

1. IAM 콘솔에서 Amazon Redshift가 역할을 수임할 수 있는 역할 및 신뢰 관계를 생성합니다. IAM 설명서의 지침, [AWS 서비스에 대한 역할 생성(콘솔)](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html#roles-creatingrole-service-console)을 수행합니다.
   + AWS 서비스 사용 사례를 선택하라는 메시지가 표시되면 'Redshift - 사용자 지정 가능'을 선택합니다.
   + 정책을 연결하라는 메시지가 표시되면 이전에 정의한 정책을 선택합니다.
**참고**  
Amazon Redshift의 역할을 구성하는 방법에 대한 자세한 내용은 Amazon Redshift 설명서에서 [Amazon Redshift가 사용자를 대신하여 다른 AWS 서비스에 액세스할 수 있도록 권한 부여](https://docs.aws.amazon.com/redshift/latest/mgmt/authorizing-redshift-service.html)를 참조하세요.

1. Amazon Redshift 콘솔에서 Amazon Redshift 클러스터에 역할을 연결합니다. [Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/mgmt/copy-unload-iam-role.html) 설명서의 지침을 수행합니다.

   Amazon Redshift 콘솔에서 강조 표시된 옵션을 선택하여 다음 설정을 구성합니다.  
![\[Amazon Redshift 콘솔에서 IAM 권한을 관리하는 위치의 예제입니다.\]](http://docs.aws.amazon.com/ko_kr/glue/latest/dg/images/RS-role-config.png)

**참고**  
 기본적으로 AWS Glue는 작업을 실행하기 위해 사용자가 지정한 역할을 사용하여 생성되는 Amazon Redshift의 임시 보안 인증을 전달합니다. 이 보안 인증은 사용하지 않는 것이 좋습니다. 보안을 위해 이러한 보안 인증은 1시간 후에 만료됩니다.

**AWS Glue 작업의 역할 설정**  
AWS Glue 작업에는 Amazon S3 버킷에 액세스하기 위한 역할이 필요합니다. Amazon Redshift 클러스터에는 IAM 권한이 필요하지 않습니다. 액세스는 데이터베이스 보안 인증 및 Amazon VPC의 연결을 통해 제어됩니다.

### Amazon VPC 설정
<a name="aws-glue-programming-etl-redshift-config-vpc"></a>

**Amazon Redshift 데이터 스토어에 대한 액세스를 설정하려면**

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

1. 좌측 탐색 창에서 **클러스터**를 선택합니다.

1. AWS Glue로부터 액세스하고자 하는 클러스터 이름을 선택합니다.

1. **Cluster Properties(클러스터 속성)** 섹션에서 **VPC security groups(VPC 보안 그룹)**에서 보안 그룹을 선택하여 사용할 AWS Glue를 허용합니다. 미래 참조를 위해 선택하는 보안 그룹의 이름을 기록합니다. 보안 그룹을 선택하면 Amazon EC2 콘솔 [**보안 그룹(Security Groups)**] 목록을 엽니다.

1. 보안 그룹을 선택하여 [**Inbound(인바운드)**] 탭으로 수정하고 탐색합니다.

1. 자기 참조 규칙을 추가하여 AWS Glue 구성 요소를 허용하여 통신합니다. 특히, [**Type(유형)**] `All TCP` 의 규칙을 추가하고 확인합니다. [**Protocol(프로토콜)**]는 `TCP`이고 [**Port Range(포트 범위)**]는 모든 포트를 포함하고 포트의 [**Source(원본)**]은 [**Group ID(그룹 ID)**]이라는 동일한 보안 그룹입니다.

   인바운드 규칙은 다음과 비슷하게 보입니다.  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/glue/latest/dg/aws-glue-programming-etl-connect-redshift-home.html)

   예:  
![\[자기 참조 인바운드 규칙 예제\]](http://docs.aws.amazon.com/ko_kr/glue/latest/dg/images/SetupSecurityGroup-Start.png)

1. 아웃바운드 트래픽 규칙도 추가합니다. 예를 들어 아웃바운드 트래픽을 모든 포트로 엽니다.  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/glue/latest/dg/aws-glue-programming-etl-connect-redshift-home.html)

   또는 자기 참조 규칙을 생성합니다. 여기서 **Type(유형)** 은 `All TCP`이고 **Protocol(프로토콜)**은 `TCP`이고 **Port Range(포트 범위)**는 모든 포트를 포함하고 포트의 **Destination(대상)**은 **Group ID(그룹 ID)**와 동일한 보안 그룹 이름입니다. Amazon S3 VPC 엔드포인트를 사용할 경우 Amazon S3 액세스에 대한 HTTPS 규칙도 추가합니다. *s3-prefix-list-id*는 VPC에서 Amazon S3 VPC 엔드포인트로 트래픽을 허용하기 위해 보안 그룹에 필요합니다.

   예:  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/glue/latest/dg/aws-glue-programming-etl-connect-redshift-home.html)

### AWS Glue 설정
<a name="aws-glue-programming-etl-redshift-config-glue"></a>

Amazon VPC 연결 정보를 제공하는 AWS Glue 데이터 카탈로그 연결을 생성해야 합니다.

**콘솔에서 AWS Glue에 대한 Amazon Redshift Amazon VPC 연결을 구성하려면**

1. [AWS Glue 연결 추가](console-connections.md)의 단계에 따라 데이터 카탈로그 연결을 생성합니다. 연결을 생성한 후에는 다음 단계를 위해 연결 이름, *connectionName*을 유지합니다.
   + **연결 유형**을 선택할 때는 **Amazon Redshift**를 선택합니다.
   + **Redshift 클러스터**를 선택할 때는 이름을 기준으로 클러스터를 선택합니다.
   + 클러스터의 Amazon Redshift 사용자에 대한 기본 연결 정보를 제공합니다.
   + Amazon VPC 설정이 자동으로 구성됩니다.
**참고**  
AWS SDK를 통해 **Amazon Redshift** 연결을 생성할 때는 Amazon VPC에 대한 `PhysicalConnectionRequirements`를 수동으로 제공해야 합니다.

1. AWS Glue 작업 구성에서 **추가 네트워크 연결**로 *connectionName*을 제공합니다.

## 예제: Amazon Redshift 테이블에서 읽기
<a name="aws-glue-programming-etl-connect-redshift-read"></a>

 Amazon Redshift 클러스터와 Amazon Redshift 서버리스 환경에서 읽을 수 있습니다.

**필수 조건:** 읽으려는 Amazon Redshift 테이블. 임시 디렉터리로 Amazon S3 URI(*temp-s3-dir*) 및 IAM 역할(*role-account-id* 계정에 있는 *rs-role-name*)을 보유한 후에 이전 [Redshift 연결 구성](#aws-glue-programming-etl-connect-redshift-configure) 섹션의 단계를 수행합니다.

------
#### [ Using the Data Catalog ]

**추가 필수 조건:** 읽으려는 Amazon Redshift 테이블의 데이터 카탈로그 데이터베이스 및 테이블. 데이터 카탈로그에 대한 자세한 내용은 [AWS Glue에서 데이터 검색 및 카탈로그 작성](catalog-and-crawler.md) 섹션을 참조하세요. Amazon Redshift 테이블에 대한 항목을 생성한 후 *redshift-dc-database-name* 및 *redshift-table-name*으로 연결을 식별합니다.

**구성:** 함수 옵션에서 `database` 및 `table_name` 파라미터로 데이터 카탈로그 테이블을 식별합니다. Amazon S3 임시 디렉터리를 `redshift_tmp_dir`로 식별합니다. 또한 `additional_options` 파라미터의 `aws_iam_role` 키를 사용하여 *rs-role-name*도 제공합니다.

```
 glueContext.create_dynamic_frame.from_catalog(
    database = "redshift-dc-database-name", 
    table_name = "redshift-table-name", 
    redshift_tmp_dir = args["temp-s3-dir"], 
    additional_options = {"aws_iam_role": "arn:aws:iam::role-account-id:role/rs-role-name"})
```

------
#### [ Connecting directly ]

**추가 필수 조건:** *Amazon Redshift 테이블 이름(redshift-table-name*)이 필요합니다. 해당 테이블을 저장하는 Amazon Redshift 클러스터에 대한 JDBC 연결 정보가 필요합니다. *host*, *port*, *redshift-database-name*, *username*, *password*에서 연결 정보를 제공합니다.

Amazon Redshift 클러스터를 사용할 때 Amazon Redshift 콘솔에서 연결 정보를 검색할 수 있습니다. Amazon Redshift Serverless를 사용하는 경우 Amazon Redshift 설명서에서 [Amazon Redshift Serverless에 연결](https://docs.aws.amazon.com//redshift/latest/mgmt/serverless-connecting.html)을 참조하세요.

**구성:** 함수 옵션에서 `url`, `dbtable`, `user` 및 `password`로 연결 파라미터를 식별합니다. Amazon S3 임시 디렉터리를 `redshift_tmp_dir`로 식별합니다. `from_options`를 사용할 때 `aws_iam_role`을 사용하여 IAM 역할을 지정할 수 있습니다. 구문은 데이터 카탈로그를 통한 연결과 비슷하지만 `connection_options` 맵에 파라미터를 입력합니다.

암호를 AWS Glue 스크립트로 하드코딩하는 것은 좋지 않습니다. SDK for Python(Boto3)을 사용하여 AWS Secrets Manager에 암호를 저장하고 스크립트에서 검색하는 방법을 고려합니다.

```
my_conn_options = {  
    "url": "jdbc:redshift://host:port/redshift-database-name",
    "dbtable": "redshift-table-name",
    "user": "username",
    "password": "password",
    "redshiftTmpDir": args["temp-s3-dir"],
    "aws_iam_role": "arn:aws:iam::account id:role/rs-role-name"
}

df = glueContext.create_dynamic_frame.from_options("redshift", my_conn_options)
```

------

## 예제: Amazon Redshift 테이블에 쓰기
<a name="aws-glue-programming-etl-connect-redshift-write"></a>

 Amazon Redshift 클러스터와 Amazon Redshift 서버리스 환경에 쓸 수 있습니다.

**필수 조건:** Amazon Redshift 클러스터. 그리고 임시 디렉터리로 Amazon S3 URI(*temp-s3-dir*) 및 IAM 역할(*role-account-id* 계정에 있는 *rs-role-name*)을 보유한 후에 이전 [Redshift 연결 구성](#aws-glue-programming-etl-connect-redshift-configure) 섹션의 단계를 수행합니다. 또한 데이터베이스에 해당 콘텐츠를 쓰려는 `DynamicFrame`도 필요합니다.

------
#### [ Using the Data Catalog ]

**추가 필수 조건:** 쓰려는 Amazon Redshift 클러스터 및 테이블의 데이터 카탈로그 데이터베이스. 데이터 카탈로그에 대한 자세한 내용은 [AWS Glue에서 데이터 검색 및 카탈로그 작성](catalog-and-crawler.md) 섹션을 참조하세요. *redshift-dc-database-name*으로 연결을, *redshift-table-name*으로 대상 테이블을 식별합니다.

**구성:** 함수 옵션에서 `database` 파라미터로 데이터 카탈로그 데이터베이스를 식별하고 `table_name`에서 테이블을 제공합니다. Amazon S3 임시 디렉터리를 `redshift_tmp_dir`로 식별합니다. 또한 `additional_options` 파라미터의 `aws_iam_role` 키를 사용하여 *rs-role-name*도 제공합니다.

```
 glueContext.write_dynamic_frame.from_catalog(
    frame = input dynamic frame, 
    database = "redshift-dc-database-name", 
    table_name = "redshift-table-name", 
    redshift_tmp_dir = args["temp-s3-dir"], 
    additional_options = {"aws_iam_role": "arn:aws:iam::account-id:role/rs-role-name"})
```

------
#### [ Connecting through a AWS Glue connection ]

`write_dynamic_frame.from_options` 메서드를 사용하여 Amazon Redshift에 직접 연결할 수 있습니다. 하지만 스크립트에 연결 세부 정보를 직접 삽입하는 대신 `from_jdbc_conf` 메서드를 사용하여 데이터 카탈로그 연결에 저장된 연결 세부 정보를 참조할 수 있습니다. 데이터베이스의 데이터 카탈로그 테이블을 크롤링하거나 생성하지 않고도 이 작업을 수행할 수 있습니다. 데이터 카탈로그 연결에 대한 자세한 내용은 [데이터에 연결](glue-connections.md) 섹션을 참조하세요.

**추가 필수 조건:** 읽으려는 Amazon Redshift 테이블, 사용자 데이터베이스에 대한 데이터 카탈로그 연결.

**구성:** *dc-connection-name*으로 데이터 카탈로그 연결을 식별합니다. *redshift-table-name* 및 *redshift-database-name*으로 Amazon Redshift 데이터베이스 및 테이블을 식별합니다. `catalog_connection`으로 데이터 카탈로그 연결 정보를 제공하고 `dbtable` 및 `database`로 Amazon Redshift 정보를 제공합니다. 구문은 데이터 카탈로그를 통한 연결과 비슷하지만 `connection_options` 맵에 파라미터를 입력합니다.

```
my_conn_options = {
    "dbtable": "redshift-table-name",
    "database": "redshift-database-name",
    "aws_iam_role": "arn:aws:iam::role-account-id:role/rs-role-name"
}

glueContext.write_dynamic_frame.from_jdbc_conf(
    frame = input dynamic frame, 
    catalog_connection = "dc-connection-name", 
    connection_options = my_conn_options, 
    redshift_tmp_dir = args["temp-s3-dir"])
```

------

## Amazon Redshift 연결 옵션 참조
<a name="w2aac67c11c24b8c21c15"></a>

모든 AWS Glue JDBC 연결에서 `url`, `user` 및 `password`와 같은 정보를 설정하는 데 사용되는 기본 연결 옵션은 모든 JDBC 유형에서 일관됩니다. 표준 JDBC 클러스터 파라미터에 대한 자세한 내용은 [JDBC 연결 옵션 참조](aws-glue-programming-etl-connect-jdbc-home.md#aws-glue-programming-etl-connect-jdbc) 섹션을 참조하세요.

Amazon Redshift 연결 유형에는 다음과 같은 몇 가지 추가 연결 옵션이 있습니다.
+ `"redshiftTmpDir"`: (필수) 데이터베이스 외부에서 복사할 때 임시 데이터를 스테이징할 수 있는 Amazon S3 경로.
+ `"aws_iam_role"`: (선택 사항) IAM 역할의 ARN. AWS Glue 작업에서는 이 역할을 Amazon Redshift 클러스터로 전달하여 작업의 지침을 완료하는 데 필요한 권한을 클러스터에 부여합니다.

### AWS Glue 4.0 이상에서 사용할 수 있는 추가 연결 옵션
<a name="aws-glue-programming-etl-redshift-enhancements"></a>

AWS Glue 연결 옵션을 통해 새로운 Amazon Redshift 커넥터의 옵션을 전달할 수도 있습니다. 지원되는 커넥터 옵션의 전체 목록은 [Apache Spark용 Amazon Redshift 통합](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)의 *Spark SQL 파라미터* 섹션을 참조하세요.

편의를 위해 다음과 같은 새로운 특정 옵션을 다시 설명합니다.


| 이름 | 필수 | 기본값 | 설명 | 
| --- | --- | --- | --- | 
|  autopushdown  | 아니요 | TRUE |  SQL 작업에 대한 Spark 논리 계획을 캡처하고 분석하여 조건자 및 쿼리 푸시다운을 적용합니다. 작업은 SQL 쿼리로 변환된 다음 Amazon Redshift에서 실행되어 성능이 향상됩니다.  | 
|  autopushdown.s3\$1result\$1cache  | 아니요 | FALSE |  동일한 쿼리가 동일한 Spark 세션에서 다시 실행될 필요가 없도록 SQL 쿼리를 캐시하여 Amazon S3 경로 매핑 데이터를 메모리에서 언로드합니다. `autopushdown`이 활성화된 경우에만 지원됩니다.  | 
|  unload\$1s3\$1format  | 아니요 | PARQUET |  PARQUET - 쿼리 결과를 Parquet 형식으로 언로드합니다. TEXT - 쿼리 결과를 파이프로 구분된 텍스트 형식으로 언로드합니다.  | 
|  sse\$1kms\$1key  | 아니요 | 해당 사항 없음 |  AWS의 기본 암호화 대신 `UNLOAD` 작업 중에 암호화에 사용할 AWS SSE-KMS 키입니다.  | 
|  extracopyoptions  | 아니요 | 해당 사항 없음 |  데이터를 로드할 때 Amazon Redshift `COPY` 명령에 추가할 추가 옵션 목록(예: `TRUNCATECOLUMNS` 또는 `MAXERROR n`)입니다. 다른 옵션은 [COPY: 선택적 파라미터](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY.html#r_COPY-syntax-overview-optional-parameters)를 참조하세요. 이러한 옵션은 `COPY` 명령 끝에 추가되므로 명령 끝에 의미가 있는 옵션만 사용할 수 있습니다. 여기서는 가능한 대부분의 사용 사례를 다루어야 합니다.  | 
|  csvnullstring(실험용)  | 아니요 | NULL |  CSV `tempformat`을 사용할 때 null에 쓸 문자열 값입니다. 실제 데이터에 나타나지 않는 값이어야 합니다.  | 

이러한 새 파라미터는 다음과 같은 방법으로 사용할 수 있습니다.

**성능 개선을 위한 새로운 옵션**  
새 커넥터에는 몇 가지 새로운 성능 개선 옵션이 도입되었습니다.
+ `autopushdown`: 기본적으로 활성화됩니다.
+ `autopushdown.s3_result_cache`: 기본적으로 비활성화됩니다.
+ `unload_s3_format`: 기본적으로 `PARQUET`입니다.

이러한 옵션을 사용하는 방법에 대한 자세한 내용은 [Apache Spark용 Amazon Redshift 통합](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)을 참조하세요. 캐시된 결과에 오래된 정보가 포함될 수 있으므로 읽기 작업과 쓰기 작업이 혼합된 경우 ` autopushdown.s3_result_cache`를 켜지 않는 것이 좋습니다. 성능을 개선하고 스토리지 비용을 절감하기 위해 `UNLOAD` 명령의 `unload_s3_format` 옵션은 기본적으로 `PARQUET`로 설정됩니다. `UNLOAD` 명령 기본 동작을 사용하려면 옵션을 `TEXT`로 재설정합니다.

**읽기를 위한 새 암호화 옵션**  
Amazon Redshift 테이블에서 데이터를 읽을 때 AWS Glue가 사용하는 임시 폴더의 데이터는 기본값으로 `SSE-S3` 암호화를 사용하여 암호화됩니다. AWS Key Management Service(AWS KMS)의 고객 관리 키를 사용하여 데이터를 암호화하려면 AWS Glue 3.0 버전의 레거시 설정 옵션 `("sse_kms_key" → kmsKey)` 대신 ksmKey가 [AWS KMS의 키 ID](https://docs.aws.amazon.com/kms/latest/developerguide/find-cmk-id-arn.html)인 `("extraunloadoptions" → s"ENCRYPTED KMS_KEY_ID '$kmsKey'")`를 설정할 수 있습니다.

```
datasource0 = glueContext.create_dynamic_frame.from_catalog(
  database = "database-name", 
  table_name = "table-name", 
  redshift_tmp_dir = args["TempDir"],
  additional_options = {"sse_kms_key":"<KMS_KEY_ID>"}, 
  transformation_ctx = "datasource0"
)
```

**IAM 기반 JDBC URL 지원**  
새 커넥터는 IAM 기반 JDBC URL을 지원하므로 사용자 및 암호 또는 보안 암호를 전달할 필요가 없습니다. IAM 기반 JDBC URL을 사용하는 커넥터에서는 작업 런타임 역할을 사용하여 Amazon Redshift 데이터 소스에 액세스합니다.

1단계: 다음과 같은 최소 필수 정책을 AWS Glue 작업 런타임 역할에 연결합니다.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "redshift:GetClusterCredentials",
            "Resource": [
                "arn:aws:redshift:us-east-1:111122223333:dbgroup:<cluster name>/*",
                "arn:aws:redshift:*:111122223333:dbuser:*/*",
                "arn:aws:redshift:us-east-1:111122223333:dbname:<cluster name>/<database name>"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "redshift:DescribeClusters",
            "Resource": "*"
        }
    ]
}
```

------

2단계: IAM 기반 JDBC URL을 다음과 같이 사용합니다. 연결하려는 Amazon Redshift 사용자 이름을 사용하여 새 옵션 `DbUser`를 지정합니다.

```
conn_options = {
     // IAM-based JDBC URL
    "url": "jdbc:redshift:iam://<cluster name>:<region>/<database name>",
    "dbtable": dbtable,
    "redshiftTmpDir": redshiftTmpDir,
    "aws_iam_role": aws_iam_role,
    "DbUser": "<Redshift User name>" // required for IAM-based JDBC URL
    }

redshift_write = glueContext.write_dynamic_frame.from_options(
    frame=dyf,
    connection_type="redshift",
    connection_options=conn_options
)

redshift_read = glueContext.create_dynamic_frame.from_options(
    connection_type="redshift",
    connection_options=conn_options
)
```

**참고**  
`DynamicFrame`은 현재 `GlueContext.create_dynamic_frame.from_options` 워크플로에 ` DbUser`가 있는 IAM 기반 JDBC URL만 지원합니다.

## AWS Glue 3.0 버전에서 4.0 버전으로 마이그레이션
<a name="aws-glue-programming-etl-redshift-migrating"></a>

AWS Glue 4.0에서 ETL 작업은 다양한 옵션 및 구성을 통해 새로운 Amazon Redshift Spark 커넥터 및 새로운 JDBC 드라이버에 액세스할 수 있습니다. 새로운 Amazon Redshift 커넥터 및 드라이버는 성능을 염두에 두고 작성되었으며 데이터의 트랜잭션 일관성을 유지합니다. 이러한 제품은 Amazon Redshift 설명서에 문서화되어 있습니다. 자세한 내용은 다음을 참조하세요.
+ [Apache Spark용 Amazon Redshift 통합](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)
+ [Amazon Redshift JDBC 드라이버, 버전 2.1](https://docs.aws.amazon.com/redshift/latest/mgmt/jdbc20-download-driver.html)

**테이블/열 이름 및 식별자 제한**  
새로운 Amazon Redshift Spark 커넥터 및 드라이버에서는 Redshift 테이블 이름에 대한 요구 사항이 더 제한적입니다. 자세한 내용은 Amazon Redshift 테이블 이름을 정의하기 위한 [이름 및 식별자](https://docs.aws.amazon.com/redshift/latest/dg/r_names.html)를 참조하세요. 규칙을 따르지 않는 테이블 이름 및 특정 문자(예: 공백)에서는 작업 북마크 워크플로가 작동하지 않을 수 있습니다.

[이름 및 식별자](https://docs.aws.amazon.com/redshift/latest/dg/r_names.html) 규칙을 따르지 않는 이름을 가진 레거시 테이블이 있고 북마크에 문제가 있는 경우(이전 Amazon Redshift 테이블 데이터를 재처리하는 작업) 테이블 이름을 변경하는 것이 좋습니다. 자세한 내용은 [ALTER TABLE 예](https://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_TABLE_examples_basic.html)를 참조하세요.

**DataFrame의 기본 tempformat 변경**  
AWS Glue 3.0 버전 Spark 커넥터에서는 Amazon Redshift Redshift에 쓰는 동안 기본적으로 `tempformat`이 CSV로 지정됩니다. 일관성을 유지하기 위해 AWS Glue 3.0 버전에서는 ` DynamicFrame`의 기본 `tempformat`로 `CSV`를 계속 사용합니다. 이전에 Amazon Redshift Spark 커넥터에서 Spark Dataframe API를 직접 사용한 적이 있다면 `DataframeReader` 및 `Writer` 옵션에서 `tempformat`을 CSV로 명시적으로 설정할 수 있습니다. 그렇지 않으면 새 Spark 커넥터에서 `tempformat`이 기본적으로 `AVRO`로 설정됩니다.

**동작 변경: Amazon Redshift 데이터 형식 REAL을 DOUBLE 대신 Spark 데이터 형식 FLOAT에 매핑합니다.**  
AWS Glue 3.0 버전에서는 Amazon Redshift `REAL`이 Spark ` DOUBLE` 유형으로 변환됩니다. Amazon Redshift` REAL` 유형과 Spark `FLOAT` 유형 간에 상호 변환되도록 새로운 Amazon Redshift Spark 커넥터의 동작을 업데이트했습니다. 레거시 사용 사례에서 Amazon Redshift`REAL` 유형을 Spark`DOUBLE` 유형에 계속 매핑하려는 경우 다음 해결 방법을 사용할 수 있습니다.
+ `DynamicFrame`의 경우 `DynamicFrame.ApplyMapping`을 사용하여 `Float` 유형을 `Double` 유형에 매핑합니다. `Dataframe`의 경우 `cast`를 사용해야 합니다.

코드 예제:

```
dyf_cast = dyf.apply_mapping([('a', 'long', 'a', 'long'), ('b', 'float', 'b', 'double')])
```

**VARBYTE 데이터 형식 처리**  
AWS Glue 3.0 및 Amazon Redshift 데이터 형식으로 작업할 때, AWS Glue 3.0은 Amazon Redshift `VARBYTE`를 Spark `STRING` 형식으로 변환합니다. 그러나 최신 Amazon Redshift Spark 커넥터는 `VARBYTE` 데이터 형식을 지원하지 않습니다. 이 제한을 해결하려면 `VARBYTE` 열을 지원되는 데이터 형식으로 변환하는 [Redshift 뷰를 생성](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html)합니다. 그런 다음 새 커넥터를 사용하여 원래 테이블 대신 이 뷰에서 데이터를 로드하면 호환성을 보장하는 동시에 `VARBYTE` 데이터에 대한 액세스를 유지할 수 있습니다.

Redshift 쿼리의 예:

```
CREATE VIEW view_name AS SELECT FROM_VARBYTE(varbyte_column, 'hex') FROM table_name
```

# Kafka 연결
<a name="aws-glue-programming-etl-connect-kafka-home"></a>

Data Catalog 테이블에 저장된 정보를 사용하거나 데이터 스트림에 직접 액세스할 수 있는 정보를 제공하여 Kafka 연결을 통해 Kafka Data Streams에서 읽고 쓸 수 있습니다. 연결에서는 Kafka 클러스터 또는 Amazon Managed Streaming for Apache Kafka 클러스터를 지원합니다. Kafka의 정보를 Spark DataFrame으로 읽은 다음 AWS Glue DynamicFrame으로 변환할 수 있습니다. DynamicFrame을 JSON 형식으로 Kafka에 쓸 수 있습니다. 데이터 스트림에 직접 액세스하는 경우 이러한 옵션을 사용하여 데이터 스트림에 액세스하는 방법에 대한 정보를 제공합니다.

`getCatalogSource` 또는 `create_data_frame_from_catalog`를 사용하여 Kafka 스트리밍 소스에서 레코드를 소비하거나 `getCatalogSink` 또는 `write_dynamic_frame_from_catalog`를 사용하여 Kafka에 레코드를 쓰는 경우 작업에는 데이터 카탈로그 데이터베이스와 테이블 이름 정보가 있으며 이를 사용하여 Kafka 스트리밍 소스에서 읽기 위한 몇 가지 기본 파라미터를 얻을 수 있습니다. `getSource`, `getCatalogSink`, `getSourceWithFormat`, `getSinkWithFormat`, `createDataFrameFromOptions`, `create_data_frame_from_options` 또는 `write_dynamic_frame_from_catalog`를 사용하는 경우 여기에 설명된 연결 옵션을 통해 이러한 기본 파라미터를 지정해야 합니다.

`GlueContext` 클래스에 지정된 메서드에 대해 다음 인수를 사용하여 Kafka에 대한 연결 옵션을 지정할 수 있습니다.
+ Scala
  + `connectionOptions`: `getSource`, `createDataFrameFromOptions`, `getSink`와(과) 함께 사용 
  + `additionalOptions`: `getCatalogSource`, `getCatalogSink`와 함께 사용
  + `options`: `getSourceWithFormat`, `getSinkWithFormat`와 함께 사용
+ Python
  + `connection_options`: `create_data_frame_from_options`, `write_dynamic_frame_from_options`와 함께 사용
  + `additional_options`: `create_data_frame_from_catalog`, `write_dynamic_frame_from_catalog`와 함께 사용
  + `options`: `getSource`, `getSink`와 함께 사용

스트리밍 ETL 작업에 대한 참고 및 제한 사항은 [스트리밍 ETL 참고 사항 및 제한 사항](add-job-streaming.md#create-job-streaming-restrictions) 섹션을 참조하세요.

**Topics**
+ [

## Kafka 구성
](#aws-glue-programming-etl-connect-kafka-configure)
+ [

## 예제: Kafka 스트림에서 읽기
](#aws-glue-programming-etl-connect-kafka-read)
+ [

## 예: Kafka 스트림에 쓰기
](#aws-glue-programming-etl-connect-kafka-write)
+ [

## Kafka 연결 옵션 참조
](#aws-glue-programming-etl-connect-kafka)

## Kafka 구성
<a name="aws-glue-programming-etl-connect-kafka-configure"></a>

인터넷을 통해 사용할 수 있는 Kafka 스트림에 연결하기 위한 AWS의 필수 조건은 없습니다.

AWS Glue Kafka 연결을 생성하여 연결 보안 인증을 관리할 수 있습니다. 자세한 내용은 [Apache Kafka 데이터 스트림에 대한 AWS Glue 연결 생성](add-job-streaming.md#create-conn-streaming) 섹션을 참조하세요. AWS Glue 작업 구성에서 **추가 네트워크 연결**로 *connectionName*을 제공하고 메서드 직접 호출에서 `connectionName` 파라미터로 *ConnectionName*을 제공합니다.

경우에 따라 추가 필수 조건을 구성해야 합니다.
+ IAM 인증과 함께 Amazon Managed Streaming for Apache Kafka를 사용하는 경우 적절한 IAM 구성이 필요합니다.
+ Amazon VPC 내에서 Amazon Managed Streaming for Apache Kafka를 사용하는 경우 적절한 Amazon VPC 구성이 필요합니다. Amazon VPC 연결 정보를 제공하는 AWS Glue 연결을 생성해야 합니다. AWS Glue 연결을 **추가 네트워크 연결**로 포함하려면 작업 구성이 필요합니다.

스트리밍 ETL 작업 필수 조건에 대한 자세한 내용은 [AWS Glue에서 스트리밍 ETL 작업](add-job-streaming.md) 섹션을 참조하세요.

## 예제: Kafka 스트림에서 읽기
<a name="aws-glue-programming-etl-connect-kafka-read"></a>

[forEachBatch](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-forEachBatch)과(와) 함께 사용합니다.

Kafka 스트리밍 소스의 예:

```
kafka_options =
    { "connectionName": "ConfluentKafka", 
      "topicName": "kafka-auth-topic", 
      "startingOffsets": "earliest", 
      "inferSchema": "true", 
      "classification": "json" 
    }
data_frame_datasource0 = glueContext.create_data_frame.from_options(connection_type="kafka", connection_options=kafka_options)
```

## 예: Kafka 스트림에 쓰기
<a name="aws-glue-programming-etl-connect-kafka-write"></a>

Kafka에 쓰기의 예제:

`getSink` 메서드를 사용한 예제:

```
data_frame_datasource0 = 
glueContext.getSink(
	connectionType="kafka",
	connectionOptions={
		JsonOptions("""{
			"connectionName": "ConfluentKafka", 
			"classification": "json", 
			"topic": "kafka-auth-topic", 
			"typeOfData": "kafka"}
		""")}, 
	transformationContext="dataframe_ApacheKafka_node1711729173428")
	.getDataFrame()
```

`write_dynamic_frame.from_options` 메서드를 사용한 예제:

```
kafka_options =
    { "connectionName": "ConfluentKafka", 
      "topicName": "kafka-auth-topic", 
      "classification": "json" 
    }
data_frame_datasource0 = glueContext.write_dynamic_frame.from_options(connection_type="kafka", connection_options=kafka_options)
```

## Kafka 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-kafka"></a>

읽을 때는 `"connectionType": "kafka"`를 사용한 다음 연결 옵션을 사용합니다.
+ `"bootstrap.servers"` (필수) 부트스트랩 서버 URL의 목록입니다(예: `b-1.vpc-test-2.o4q88o.c6.kafka.us-east-1.amazonaws.com:9094`). 이 옵션은 API 호출에 지정하거나 데이터 카탈로그의 테이블 메타데이터에 정의해야 합니다.
+ `"security.protocol"` (필수) 브로커와 통신하는 데 사용되는 프로토콜입니다. 가능한 값은 `"SSL"` 또는 `"PLAINTEXT"`입니다.
+ `"topicName"`: (필수) 쉼표로 구분된 구독할 주제의 목록입니다. `"topicName"`, `"assign"` 또는 `"subscribePattern"` 중에서 하나만 지정해야 합니다.
+ `"assign"`: (필수) 사용할 특정 `TopicPartitions`을 지정하는 JSON 문자열입니다. `"topicName"`, `"assign"` 또는 `"subscribePattern"` 중에서 하나만 지정해야 합니다.

  예: '\$1"topicA":[0,1],"topicB":[2,4]\$1'
+ `"subscribePattern"`: (필수) 구독할 주제 목록을 식별하는 Java 정규식 문자열입니다. `"topicName"`, `"assign"` 또는 `"subscribePattern"` 중에서 하나만 지정해야 합니다.

  예: 'topic.\$1'
+ `"classification"`(필수) 레코드의 데이터에서 사용하는 파일 형식입니다. 데이터 카탈로그를 통해 제공되지 않는 한 필수입니다.
+ `"delimiter"`(선택 사항) `classification`이 CSV일 때 사용되는 값 구분 기호입니다. 기본값은 '`,`'입니다.
+ `"startingOffsets"`: (선택 사항) 데이터를 읽을 Kafka 주제의 시작 위치입니다. 가능한 값은 `"earliest"` 또는 `"latest"`입니다. 기본값은 `"latest"`입니다.
+ `"startingTimestamp"`: (선택 사항, AWS Glue 버전 4.0 이상에서만 지원됨) 데이터를 읽을 Kafka 주제에 있는 레코드의 타임스탬프입니다. 가능한 값은 `yyyy-mm-ddTHH:MM:SSZ` 패턴에서 UTC 형식의 타임스탬프 문자열입니다(여기서, `Z`는 UTC 시간대 오프셋(\$1/-)임, 예: '2023-04-04T08:00:00-04:00').

  참고: AWS Glue 스트리밍 스크립트의 연결 옵션 목록에는 'startingOffsets' 또는 'startingTimestamp' 중 하나만 존재할 수 있습니다. 이 두 속성을 모두 포함하면 작업에 실패합니다.
+ `"endingOffsets"`: (선택 사항) 일괄 쿼리가 종료되는 엔드포인트입니다. 가능한 값은 `"latest"` 또는 각 `TopicPartition`의 끝 오프셋을 지정하는 JSON 문자열입니다.

  JSON 문자열의 경우 포맷은 `{"topicA":{"0":23,"1":-1},"topicB":{"0":-1}}`입니다. 오프셋으로 값 `-1`은 `"latest"`를 나타냅니다.
+ `"pollTimeoutMs"`: (선택 사항) Spark 작업 실행기의 Kafka에서 데이터를 폴링하는 시간 제한(밀리초)입니다. 기본값은 `600000`입니다.
+ `"numRetries"`: (선택 사항) Kafka 오프셋 가져오기에 실패하기 전에 재시도할 횟수입니다. 기본값은 `3`입니다.
+ `"retryIntervalMs"`: (선택 사항) Kafka 오프셋을 가져오기를 다시 시도하기 전에 대기하는 시간(밀리초)입니다. 기본값은 `10`입니다.
+ `"maxOffsetsPerTrigger"`: (선택 사항) 트리거 간격당 처리되는 최대 오프셋 수에 대한 속도 제한입니다. 지정된 총 오프셋 수는 서로 다른 볼륨의 `topicPartitions`에 비례하여 분할됩니다. 기본값은 null입니다. 즉, 소비자가 알려진 최신 오프셋까지 모든 오프셋을 읽습니다.
+ `"minPartitions"`: (선택 사항) Kafka에서 읽을 원하는 최소 파티션 수입니다. 기본값은 null이며 이는 Spark 파티션의 수가 Kafka 파티션의 수와 동일함을 의미합니다.
+  `"includeHeaders"`: (선택 사항) Kafka 헤더를 포함할지 여부입니다. 옵션이 "true"로 설정되면 데이터 출력에는 유형이 `Array[Struct(key: String, value: String)]`인 "glue\$1streaming\$1kafka\$1headers"라는 추가 열이 포함됩니다. 기본값은 "false"입니다. 이 옵션은 AWS Glue 버전 3.0 이상에서만 사용할 수 있습니다.
+ `"schema"`: (InferSchema가 false로 설정된 경우 필수) 페이로드를 처리하는 데 사용할 스키마입니다. 분류가 `avro`인 경우 제공된 스키마는 Avro 스키마 형식이어야 합니다. 분류가 `avro`가 아닌 경우 제공된 스키마는 DDL 스키마 형식이어야 합니다.

  다음은 스키마의 예입니다.

------
#### [ Example in DDL schema format ]

  ```
  'column1' INT, 'column2' STRING , 'column3' FLOAT
  ```

------
#### [ Example in Avro schema format ]

  ```
  {
  "type":"array",
  "items":
  {
  "type":"record",
  "name":"test",
  "fields":
  [
    {
      "name":"_id",
      "type":"string"
    },
    {
      "name":"index",
      "type":
      [
        "int",
        "string",
        "float"
      ]
    }
  ]
  }
  }
  ```

------
+ `"inferSchema"`: (선택 사항) 기본값은 'false'입니다. 'true'로 설정하면 스키마가 런타임 시 `foreachbatch` 내의 페이로드에서 감지됩니다.
+ `"avroSchema"`: (더 이상 사용되지 않음) Avro 형식을 사용할 때 Avro 데이터의 스키마를 지정하는 데 사용되는 파라미터입니다. 이 파라미터는 이제 사용 중단되었습니다. `schema` 파라미터를 사용합니다.
+ `"addRecordTimestamp"`: (선택 사항) 이 옵션이 'true'로 설정되면 데이터 출력에는 이름이 '\$1\$1src\$1timestamp'라는 추가 열이 포함됩니다. 이 열은 주제에서 해당 레코드를 수신한 시간을 나타냅니다. 기본값은 'false'입니다. 이 옵션은 AWS Glue 버전 4.0 이상에서 지원됩니다.
+ `"emitConsumerLagMetrics"`: (선택 사항) 이 옵션을 'true'로 설정하면 각 배치에 대해 주제에서 수신한 가장 오래된 레코드와 AWS Glue에 도착한 시간 사이의 지표를 CloudWatch로 내보냅니다. 지표의 이름은 'glue.driver.streaming.maxConsumerLagInMs'입니다. 기본값은 'false'입니다. 이 옵션은 AWS Glue 버전 4.0 이상에서 지원됩니다.

쓸 때는 `"connectionType": "kafka"`를 사용한 다음 연결 옵션을 사용합니다.
+ `"connectionName"`(필수) Kafka 클러스터에 연결하는 데 사용되는 AWS Glue 연결의 이름(Kafka 소스와 유사).
+ `"topic"`(필수) 주제 열이 존재하는 경우 주제 구성 옵션이 설정되지 않은 한 Kafka에 지정된 행을 쓸 때 해당 값이 주제로 사용됩니다. 즉, `topic` 구성 옵션이 주제 열을 재정의합니다.
+ `"partition"`(선택 사항) 유효한 파티션 번호가 지정되면 레코드를 보낼 때 해당 `partition`이 사용됩니다.

  파티션을 지정하지 않았지만 `key`가 있는 경우 키의 해시를 사용하여 파티션이 선택됩니다.

  `key`와 `partition`이 모두 존재하지 않으면 파티션에 최소 batch.size 바이트가 생성될 때 변경 사항을 고정 파티셔닝하여 파티션이 선택됩니다.
+ `"key"`(선택 사항) `partition`이 null인 경우 파티셔닝에 사용됩니다.
+ `"classification"`(선택 사항) 레코드의 데이터에서 사용하는 파일 형식입니다. JSON, CSV, Avro만 지원합니다.

  Avro 형식을 사용하면 직렬화할 사용자 지정 avroSchema를 제공할 수 있지만 역직렬화를 위해서는 소스에서도 이를 제공해야 한다는 점에 유의하세요. 그렇지 않으면 기본적으로 직렬화를 위해 Apache AvroSchema를 사용합니다.

또한 필요에 따라 [Kafka 프로듀서 구성 파라미터](https://kafka.apache.org/documentation/#producerconfigs)를 업데이트하여 Kafka 싱크를 미세 튜닝할 수 있습니다. 연결 옵션에는 허용 목록이 없으며 모든 키-값 쌍은 싱크에 그대로 유지됩니다.

그러나 적용되지 않는 일부 거부 옵션의 목록이 있습니다. 자세한 내용은 [Kafka 특정 구성](https://spark.apache.org/docs/latest/structured-streaming-kafka-integration.html)을 참조하세요.

# Azure Cosmos DB 연결
<a name="aws-glue-programming-etl-connect-azurecosmos-home"></a>

AWS Glue for Spark를 이용하여 Azure Cosmos DB의 기존 컨테이너에서 읽고 쓸 수 있습니다. 이 때 AWS Glue 4.0 이상에서 NoSQL API를 이용합니다. SQL 쿼리를 사용하여 Azure Cosmos DB에서 읽을 내용을 정의할 수 있습니다. AWS Glue 연결을 통해 AWS Secrets Manager에 저장된 Azure Cosmos DB 키를 사용하여 Azure Cosmos DB에 연결합니다.

NoSQL용 Azure Cosmos DB에 대한 자세한 내용은 [Azure 설명서](https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/)를 참조하십시오.

## Azure Cosmos DB 연결 구성
<a name="aws-glue-programming-etl-connect-azurecosmos-configure"></a>

AWS Glue에서 Azure Cosmos DB에 연결하려면 Azure Cosmos DB 키를 만들어 AWS Secrets Manager 암호에 저장한 다음 해당 암호를 Azure Cosmos DB AWS Glue 연결에 연결해야 합니다.

**사전 조건 ** 
+ Azure에서는 AWS Glue `cosmosKey`에서 사용할 Azure Cosmos DB 키를 식별하거나 생성해야 합니다. 자세한 내용은 Azure 설명서의 [Azure Cosmos DB의 데이터에 대한 보안 액세스](https://learn.microsoft.com/en-us/azure/cosmos-db/secure-access-to-data?tabs=using-primary-key)를 참조하십시오.

**Azure Cosmos DB에 대한 연결 구성 방법:**

1. AWS Secrets Manager에서 Azure Cosmos DB 키를 사용하여 보안 암호를 생성합니다. Secrets Manager에서 보안 암호를 생성하려면 AWS Secrets Manager 설명서의 [Create an AWS Secrets Manager secret](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)에서 제공하는 자습서를 따릅니다. 보안 암호를 생성한 후에는 다음 단계를 위해 보안 암호 이름, *secretName*을 유지합니다.
   + **키/값 페어**를 선택하면 값 *cosmosKey*가 포함된 키 `spark.cosmos.accountKey`에 대한 페어를 생성합니다.

1. AWS Glue 콘솔에서 [AWS Glue 연결 추가](console-connections.md)의 단계에 따라 연결을 생성합니다. 연결을 생성한 후에는 AWS Glue에서 이용하기 위해 연결 이름 *connectionName*을 유지합니다.
   + **연결 유형**을 선택할 때는 Azure Cosmos DB를 선택합니다.
   + **AWS 보안 암호**를 선택할 때 *secretName*을 입력합니다.

AWS Glue Azure Cosmos DB 연결을 생성한 후에는 AWS Glue 작업을 실행하기 전에 다음 단계를 수행해야 합니다.
+ AWS Glue 작업과 연결된 IAM 역할에 *secretName*을 읽을 수 있는 권한을 부여합니다.
+ AWS Glue 작업 구성에서 **추가 네트워크 연결**로 *connectionName*을 제공합니다.

## NoSQL 컨테이너용 Azure Cosmos DB에서 읽기
<a name="aws-glue-programming-etl-connect-azurecosmos-read"></a>

**사전 조건 ** 
+ 읽으려는 NoSQL 컨테이너용 Azure Cosmos 데이터베이스. 컨테이너의 식별 정보가 필요합니다.

  NoSQL용 Azure Cosmos 컨테이너는 해당 데이터베이스 및 컨테이너로 식별됩니다. NoSQL API용 Azure Cosmos에 연결할 때 데이터베이스, *cosmosDBName*, 및 컨테이너너, *cosmosContainerName*, 이름을 제공해야 합니다.
+ 인증 및 네트워크 위치 정보를 제공하도록 구성된 AWS Glue Azure Cosmos DB 연결입니다. 이 정보를 얻으려면 앞 절차인 *Azure Cosmos DB에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예: 

```
azurecosmos_read = glueContext.create_dynamic_frame.from_options(
    connection_type="azurecosmos",
    connection_options={
    "connectionName": connectionName,
    "spark.cosmos.database": cosmosDBName,
    "spark.cosmos.container": cosmosContainerName,
    }
)
```

SELECT SQL 쿼리에 반환되는 결과를 필터링하는 쿼리를 제공할 수도 있습니다. `query`을 구성해야 합니다.

예:

```
azurecosmos_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="azurecosmos",
    connection_options={
        "connectionName": "connectionName",
        "spark.cosmos.database": cosmosDBName,
        "spark.cosmos.container": cosmosContainerName,
        "spark.cosmos.read.customQuery": "query"
    }
)
```

## NoSQL 컨테이너용 Azure Cosmos DB에 쓰기
<a name="aws-glue-programming-etl-connect-azurecosmos-write"></a>

이 예제에서는 기존 DynamicFrame, *dynamicFrame*의 정보를 Azure Cosmos DB에 씁니다. 컨테이너에 이미 정보가 있는 경우 AWS Glue는 DynamicFrame의 데이터를 추가합니다. 컨테이너의 정보가 작성한 정보와 다른 스키마를 사용하는 경우 오류가 발생합니다.

**사전 조건 ** 
+ 쓰려는 Azure Cosmos DB 테이블. 컨테이너의 식별 정보가 필요합니다. **연결 방법을 호출하기 전에 컨테이너를 만들어야 합니다.**

  NoSQL용 Azure Cosmos 컨테이너는 해당 데이터베이스 및 컨테이너로 식별됩니다. NoSQL API용 Azure Cosmos에 연결할 때 데이터베이스, *cosmosDBName*, 및 컨테이너너, *cosmosContainerName*, 이름을 제공해야 합니다.
+ 인증 및 네트워크 위치 정보를 제공하도록 구성된 AWS Glue Azure Cosmos DB 연결입니다. 이 정보를 얻으려면 앞 절차인 *Azure Cosmos DB에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예: 

```
azurecosmos_write = glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="azurecosmos",
    connection_options={
    "connectionName": connectionName,
    "spark.cosmos.database": cosmosDBName,
    "spark.cosmos.container": cosmosContainerName
)
```

## Azure Cosmos DB 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-azurecosmos-reference"></a>
+ `connectionName` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 연결 방법에 인증 및 네트워크 위치 정보를 제공하도록 구성된 AWS Glue Azure Cosmos DB 연결의 이름입니다.
+ `spark.cosmos.database` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 유효한 값: 데이터베이스 이름. NoSQL용 Azure Cosmos DB 데이터베이스 이름입니다.
+ `spark.cosmos.container` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 유효한 값: 컨테이너 이름. NoSQL용 Azure Cosmos DB 컨테이너 이름입니다.
+ `spark.cosmos.read.customQuery` — 읽기에 사용됩니다. 유효한 값: SQL 쿼리를 선택합니다. 읽을 문서를 선택하기 위한 사용자 지정 쿼리.

# Azure SQL 연결
<a name="aws-glue-programming-etl-connect-azuresql-home"></a>

AWS Glue for Spark를 사용하여 AWS Glue 4.0 이상 버전에서 Azure SQL Managed Instances의 테이블에서 읽고 쓸 수 있습니다. SQL 쿼리를 사용하여 Azure SQL에서 읽을 내용을 정의할 수 있습니다. AWS Glue 연결을 통해 AWS Secrets Manager에 저장된 사용자 이름 및 암호 보안 인증 정보를 사용하여 Azure SQL에 연결할 수 있습니다.

Azure SQL에 대한 자세한 내용은 [Azure SQL 설명서](https://azure.microsoft.com/en-us/products/azure-sql)를 참조하십시오.

## Azure SQL 연결 구성
<a name="aws-glue-programming-etl-connect-azuresql-configure"></a>

AWS Glue에서 Azure SQL에 연결하려면 Azure SQL 보안 인증 정보를 만들어 AWS Secrets Manager 암호에 저장한 다음 해당 암호를 Azure SQL AWS Glue 연결에 연결해야 합니다.

**Azure SQL에 대한 연결을 구성하는 방법:**

1. AWS Secrets Manager에서 Azure SQL 보안 인증을 사용하여 보안 암호를 생성합니다. Secrets Manager에서 보안 암호를 생성하려면 AWS Secrets Manager 설명서의 [Create an AWS Secrets Manager secret](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)에서 제공하는 자습서를 따릅니다. 보안 암호를 생성한 후에는 다음 단계를 위해 보안 암호 이름, *secretName*을 유지합니다.
   + **키/값 페어**를 선택하면 값 *azuresqlUsername*이 포함된 키 `user`에 대한 페어를 생성합니다.
   + **키/값 페어**를 선택하면 값 *azuresqlPassword*가 포함된 키 `password`에 대한 페어를 생성합니다.

1. AWS Glue 콘솔에서 [AWS Glue 연결 추가](console-connections.md)의 단계에 따라 연결을 생성합니다. 연결을 생성한 후에는 AWS Glue에서 이용하기 위해 연결 이름 *connectionName*을 유지합니다.
   + **연결 유형**을 선택할 때 Azure SQL를 선택합니다.
   + **Azure SQL URL을** 제공할 때는 JDBC 엔드포인트 URL을 제공하십시오.

      목록은 `jdbc:sqlserver://databaseServerName:databasePort;databaseName=azuresqlDBname;` 형식이어야 합니다.

     AWS Glue에는 다음과 같은 URL 속성이 필요합니다.
     + `databaseName` - 연결할 Azure SQL의 기본 데이터베이스입니다.

     Azure SQL 관리형 인스턴스용 JDBC URL에 대한 자세한 내용은 [Microsoft 설명서](https://learn.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=azuresqldb-mi-current)를 참조하십시오.
   + **AWS 보안 암호**를 선택할 때 *secretName*을 입력합니다.

AWS Glue Azure SQL 연결을 생성한 후에는 AWS Glue 작업을 실행하기 전에 다음 단계를 수행해야 합니다.
+ AWS Glue 작업과 연결된 IAM 역할에 *secretName*을 읽을 수 있는 권한을 부여합니다.
+ AWS Glue 작업 구성에서 **추가 네트워크 연결**로 *connectionName*을 제공합니다.

## Azure SQL 테이블에서 읽는 중
<a name="aws-glue-programming-etl-connect-azuresql-read"></a>

**사전 조건 ** 
+ 읽으려는 Azure SQL 테이블. 테이블, *databaseName*, *tableIdentifier*에 대한 식별 정보가 필요합니다.

  Azure SQL 테이블은 데이터베이스, 스키마 및 테이블 이름으로 식별됩니다. Azure SQL에 연결할 때 데이터베이스 이름과 테이블 이름을 제공해야 합니다. 스키마가 기본값인 "public"이 아닌 경우에도 스키마를 제공해야 합니다. 데이터베이스는 *connectionName*의 URL 속성을, `dbtable`을 통해 스키마 및 테이블 이름을 제공 받습니다.
+ 인증 정보를 제공하도록 구성된 AWS Glue Azure SQL 연결입니다. 인증 정보를 구성하려면 앞 절차인 *Azure SQL에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예: 

```
azuresql_read_table = glueContext.create_dynamic_frame.from_options(
    connection_type="azuresql",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableIdentifier"
    }
)
```

SELECT SQL 쿼리에 반환되는 결과를 필터링하는 쿼리를 제공할 수도 있습니다. `query`을 구성해야 합니다.

예:

```
azuresql_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="azuresql",
    connection_options={
        "connectionName": "connectionName",
        "query": "query"
    }
)
```

## Azure SQL 테이블에 쓰기
<a name="aws-glue-programming-etl-connect-azuresql-write"></a>

이 예제에서는 기존 DynamicFrame, *dynamicFrame*의 정보를 Azure SQL에 씁니다. 테이블에 이미 정보가 있는 경우 AWS Glue는 DynamicFrame의 데이터를 추가합니다.

**사전 조건 ** 
+ 쓰려는 Azure SQL 테이블. 테이블, *databaseName*, *tableIdentifier*에 대한 식별 정보가 필요합니다.

  Azure SQL 테이블은 데이터베이스, 스키마 및 테이블 이름으로 식별됩니다. Azure SQL에 연결할 때 데이터베이스 이름과 테이블 이름을 제공해야 합니다. 스키마가 기본값인 "public"이 아닌 경우에도 스키마를 제공해야 합니다. 데이터베이스는 *connectionName*의 URL 속성을, `dbtable`을 통해 스키마 및 테이블 이름을 제공 받습니다.
+ Azure SQL 인증 정보. 인증 정보를 구성하려면 앞 절차인 *Azure SQL에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예: 

```
azuresql_write = glueContext.write_dynamic_frame.from_options(
    connection_type="azuresql",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableIdentifier"
    }
)
```

## Azure SQL 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-azuresql-reference"></a>
+ `connectionName` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 연결 방법에 인증 정보를 제공하도록 구성된 AWS Glue Azure SQL 연결의 이름입니다.
+ `databaseName` - 읽기/쓰기에 사용됩니다. 유효한 값: Azure SQL 데이터베이스 이름. 연결할 Azure SQL 데이터베이스의 이름입니다.
+ `dbtable` - 쓰기 시 필수, `query`가 제공되지 않는 한 읽기 전용. 읽기 및 쓰기에 사용됩니다. 유효한 값: Azure SQL 테이블의 이름 또는 마침표로 구분된 스키마/테이블 이름 조합. 연결할 테이블을 식별하는 테이블과 스키마를 지정하는 데 사용됩니다. 기본 스키마는 "public"입니다. 테이블이 기본 스키마가 아닌 스키마를 사용하는 경우 이 정보를 양식 `schemaName.tableName`에 입력하십시오.
+ `query` — 읽기에 사용됩니다. Azure SQL에서 읽을 때 검색해야 하는 내용을 정의하는 Transact-SQL SELECT 쿼리입니다. 자세한 내용은 [Microsoft 설명서](https://learn.microsoft.com/en-us/sql/t-sql/queries/select-transact-sql?view=azuresqldb-mi-current)를 참조하십시오.

# BigQuery 연결
<a name="aws-glue-programming-etl-connect-bigquery-home"></a>

AWS Glue for Spark를 사용하여 AWS Glue 4.0 이상 버전에서 Google BigQuery의 테이블에서 읽고 쓸 수 있습니다. Google SQL 쿼리를 사용하여 BigQuery에서 읽을 수 있습니다. AWS Glue 연결을 통해 AWS Secrets Manager에 저장된 보안 인증 정보를 사용하여 BigQuery에 연결합니다.

Google BigQuery에 대한 자세한 내용은 [Google Cloud BigQuery 웹사이트](https://cloud.google.com/bigquery)를 참조하세요.

## BigQuery 연결 구성
<a name="aws-glue-programming-etl-connect-bigquery-configure"></a>

AWS Glue에서 Google BigQuery에 연결하려면 AWS Secrets Manager 보안 암호에서 Google Cloud Platform 보안 인증 정보를 생성하고 저장한 다음 해당 보안 암호를 Google BigQuery AWS Glue 연결에 연결해야 합니다.

**BigQuery에 대한 연결 구성하기:**

1. Google Cloud Platform에서 관련 리소스를 생성하고 식별합니다.
   + 연결하려는 BigQuery 테이블이 포함된 GCP 프로젝트를 생성하거나 식별합니다.
   + BigQuery API를 활성화합니다. 자세한 내용은 [BigQuery Storage Read API를 사용하여 테이블 데이터 읽기](https://cloud.google.com/bigquery/docs/reference/storage/#enabling_the_api)를 참조하세요.

1. Google Cloud Platform에서 서비스 계정 보안 인증 정보를 생성하고 내보냅니다.

   BigQuery 보안 인증 마법사를 사용하여 [보안 인증 정보 생성하기](https://console.cloud.google.com/apis/credentials/wizard?api=bigquery.googleapis.com) 단계를 신속하게 처리할 수 있습니다.

   GCP에서 서비스 계정을 생성하려면 [서비스 계정 생성하기](https://cloud.google.com/iam/docs/service-accounts-create)에서 제공되는 튜토리얼을 따르세요.
   + **프로젝트**를 선택할 때 BigQuery 테이블이 포함된 프로젝트를 선택합니다.
   + 서비스 계정의 GCP IAM 역할을 선택할 때 BigQuery 작업을 실행하여 BigQuery 테이블을 읽고, 쓰고, 생성할 수 있는 적절한 권한을 부여하는 역할을 추가하거나 생성하세요.

   서비스 계정의 보안 인증 정보를 생성하려면 [서비스 계정 키 생성하기](https://cloud.google.com/iam/docs/keys-create-delete#creating)에서 제공되는 튜토리얼을 따르세요.
   + 키 유형을 선택할 때 **JSON**을 선택합니다.

   이제 서비스 계정의 보안 인증 정보가 포함된 JSON 파일을 다운로드했어야 합니다. 예를 들면 다음과 같아야 합니다.

   ```
   {
     "type": "service_account",
     "project_id": "*****",
     "private_key_id": "*****",
     "private_key": "*****",
     "client_email": "*****",
     "client_id": "*****",
     "auth_uri": "https://accounts.google.com/o/oauth2/auth",
     "token_uri": "https://oauth2.googleapis.com/token",
     "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
     "client_x509_cert_url": "*****",
     "universe_domain": "googleapis.com"
   }
   ```

1. 보안 인증 JSON 파일을 적절하게 안전한 Amazon S3 위치에 업로드합니다. 향후 단계를 위해 파일 경로인 *s3secretpath*를 유지합니다.

1. AWS Secrets Manager에서 Google Cloud Platform 보안 인증 정보를 사용하여 보안 암호를 생성합니다. Secrets Manager에서 보안 암호를 생성하려면 AWS Secrets Manager 설명서의 [Create an AWS Secrets Manager secret](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)에서 제공하는 자습서를 따릅니다. 보안 암호를 생성한 후에는 다음 단계를 위해 보안 암호 이름, *secretName*을 유지합니다.

   키/값 페어를 생성할 때 키와 값을 다음과 같이 지정합니다.
   + `token_uri`, `client_x509_cert_url`, `private_key_id`, `project_id`, `universe_domain`, `auth_provider_x509_cert_url`, `auth_uri`, `client_email`, `private_key`, `type`, `client_id` 키의 경우 다운로드한 JSON 파일에서 해당되는 값을 지정합니다.
   + `spark.hadoop.google.cloud.auth.service.account.json.keyfile` 키의 경우 *s3secretpath*를 지정합니다.

1. AWS Glue 데이터 카탈로그에서 [AWS Glue 연결 추가](console-connections.md)의 단계에 따라 연결을 생성합니다. 연결을 생성한 후에는 다음 단계를 위해 연결 이름, *connectionName*을 유지합니다.
   + **연결 유형**을 선택할 때 Google BigQuery를 선택합니다.
   + **AWS 보안 암호**를 선택할 때 *secretName*을 입력합니다.

1. AWS Glue 작업과 연결된 IAM 역할에 *secretName*을 읽을 수 있는 권한을 부여합니다.

1. AWS Glue 작업 구성에서 **추가 네트워크 연결**로 *connectionName*을 제공합니다.

## BigQuery 테이블에서 읽기
<a name="aws-glue-programming-etl-connect-bigquery-read"></a>

**사전 조건 ** 
+ 읽으려는 BigQuery 테이블. 양식 `[dataset].[table]`에 있는 BigQuery 테이블 및 데이터 세트 이름이 필요합니다. 이 *tableName*이라고 부르겠습니다.
+ BigQuery 테이블의 청구 프로젝트. 프로젝트 이름인 *parentProject*가 필요합니다. 결제 상위 프로젝트가 없는 경우 테이블이 포함된 프로젝트를 사용합니다.
+ BigQuery 인증 정보. *AWS Glue로 연결 자격 증명 관리* 단계를 완료하여 인증 정보를 구성합니다. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예: 

```
bigquery_read = glueContext.create_dynamic_frame.from_options(
    connection_type="bigquery",
    connection_options={
        "connectionName": "connectionName",
        "parentProject": "parentProject",
        "sourceType": "table",
        "table": "tableName",
    }
```

DynamicFrame에 반환되는 결과를 필터링하는 쿼리를 제공할 수도 있습니다. `query`, `sourceType`, `viewsEnabled` 및 `materializationDataset`을(를) 구성해야 합니다.

예:

**추가 사전 조건:**

BigQuery가 쿼리에 대한 구체화된 뷰를 작성할 수 있는 BigQuery 데이터 세트인 *materializationDataset*를 생서하거나 식별해야 합니다.

*materializationDataset*에서 테이블을 생성하려면 서비스 계정에 적절한 GCP IAM 권한을 부여해야 합니다.

```
glueContext.create_dynamic_frame.from_options(
            connection_type="bigquery",
            connection_options={
                "connectionName": "connectionName",
                "materializationDataset": materializationDataset,
                "parentProject": "parentProject",
                "viewsEnabled": "true",
                "sourceType": "query",
                "query": "select * from bqtest.test"
            }
        )
```

## BigQuery 테이블에 쓰기
<a name="aws-glue-programming-etl-connect-bigquery-write"></a>

이 예시는 BigQuery 서비스에 직접 작성합니다. BigQuery는 '간접' 쓰기 메서드도 지원합니다. 간접 쓰기 구성에 대한 자세한 내용은 [Google BigQuery를 통한 간접 쓰기 사용](#aws-glue-programming-etl-connect-bigquery-indirect-write)을(를) 참조하세요.

**사전 조건 ** 
+ 쓰려는 BigQuery 테이블. 양식 `[dataset].[table]`에 있는 BigQuery 테이블 및 데이터 세트 이름이 필요합니다. 자동으로 생성되는 새 테이블 이름을 제공할 수도 있습니다. 이 *tableName*이라고 부르겠습니다.
+ BigQuery 테이블의 청구 프로젝트. 프로젝트 이름인 *parentProject*가 필요합니다. 결제 상위 프로젝트가 없는 경우 테이블이 포함된 프로젝트를 사용합니다.
+ BigQuery 인증 정보. *AWS Glue로 연결 자격 증명 관리* 단계를 완료하여 인증 정보를 구성합니다. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예: 

```
bigquery_write = glueContext.write_dynamic_frame.from_options(
    frame=frameToWrite,
    connection_type="bigquery",
    connection_options={
        "connectionName": "connectionName",
        "parentProject": "parentProject",
        "writeMethod": "direct",
        "table": "tableName",
    }
)
```

## BigQuery연결 옵션 참조
<a name="aws-glue-programming-etl-connect-bigquery-reference"></a>
+ `project`— 기본값: Google Cloud 서비스 계정 기본값. 읽기 및 쓰기에 사용됩니다. 테이블과 연결된 Google Cloud 프로젝트의 이름.
+ `table` -- (필수) 읽기 및 쓰기에 사용됩니다. `[[project:]dataset.]` 형식에 따른 BigQuery 테이블의 이름.
+ `dataset`— `table` 옵션을 통해 정의되지 않은 경우 필수입니다. 읽기 및 쓰기에 사용됩니다. BigQuery 테이블을 포함하는 데이터 세트의 이름.
+ `parentProject`— 기본값: Google Cloud 서비스 계정 기본값. 읽기 및 쓰기에 사용됩니다. 청구에 사용되는 `project`와(과) 연결된 Google Cloud 프로젝트의 이름.
+ `sourceType` — 읽기에 사용됩니다. 읽을 때 필요합니다. 유효한 값:`table`, `query`은(는) 테이블로 읽을 것인지 쿼리로 읽을 것인지 AWS Glue에 알립니다.
+ `materializationDataset` — 읽기에 사용됩니다. 유효한 값: 문자열. 보기의 구체화를 저장하는 데 사용되는 BigQuery 데이터 세트의 이름.
+ `viewsEnabled` — 읽기에 사용됩니다. 기본값: false. 유효한 값: 참, 거짓. BigQuery에서 보기를 사용할지 여부를 구성합니다.
+ `query` — 읽기에 사용됩니다. `viewsEnabled`이(가) 참일 때 사용됩니다. GoogleSQL DQL 쿼리.
+ `temporaryGcsBucket`— 쓰기에 사용됩니다. `writeMethod`이(가) 기본값(`indirect`)으로 설정된 경우에 필요합니다. BigQuery에 쓰는 동안 중간 형식의 데이터를 저장하는 데 사용되는 Google Cloud Storage 버킷의 이름.
+ `writeMethod` - 기본값: `indirect`. 유효한 값: `direct`, `indirect`. 쓰기에 사용됩니다. 데이터를 쓰는 데 사용되는 메서드를 지정합니다.
  + `direct`(으)로 설정하면 커넥터가 BigQuery Storage 쓰기 API를 사용하여 데이터를 작성합니다.
  + `indirect`(으)로 설정하면 커넥터가 Google Cloud Storage에 쓴 다음 로드 작업을 사용하여 BigQuery로 전송합니다. Google Cloud 서비스 계정에는 적절한 GCS 권한이 필요합니다.

## Google BigQuery를 통한 간접 쓰기 사용
<a name="aws-glue-programming-etl-connect-bigquery-indirect-write"></a>

이 예시에서는 Google Cloud Storage에 데이터를 쓰고 Google BigQuery에 데이터를 복사하는 간접 쓰기를 사용합니다.

**사전 조건 **

임시 Google Cloud Storage 버킷인 *temporaryBucket*이 필요합니다.

AWS Glue GCP 서비스 계정의 GCP IAM 역할에는 *temporaryBucket*에 액세스하는 적절한 GCS 권한이 필요합니다.

**추가 구성:**

**BigQuery를 사용하여 간접 쓰기 구성하기:**

1. [BigQuery 연결 구성](#aws-glue-programming-etl-connect-bigquery-configure)을(를) 평가하고, GCP 보안 인증 JSON 파일을 찾거나 다시 다운로드합니다. 작업에 사용되는 Google BigQuery AWS Glue 연결의 AWS Secrets Manager 보안 암호인 *secretName*을(를) 식별합니다.

1. 보안 인증 JSON 파일을 적절하게 안전한 Amazon S3 위치에 업로드합니다. 향후 단계를 위해 파일 경로인 *s3secretpath*를 유지합니다.

1. *secretName*을(를) 편집하고 `spark.hadoop.google.cloud.auth.service.account.json.keyfile` 키를 추가합니다. 값을 *s3secretpath*에 설정합니다.

1. AWSGlue 작업 Amazon S3 IAM에 *s3secretpath*에 액세스할 수 있는 권한을 부여합니다.

이제 쓰기 메서드에 임시 GCS 버킷 위치를 제공할 수 있습니다. `indirect`은(는) 이전에는 기본값이었기 때문에 `writeMethod`을(를) 제공하지 않아도 됩니다.

```
bigquery_write = glueContext.write_dynamic_frame.from_options(
    frame=frameToWrite,
    connection_type="bigquery",
    connection_options={
        "connectionName": "connectionName",
        "parentProject": "parentProject",
        "temporaryGcsBucket": "temporaryBucket",
        "table": "tableName",
    }
)
```

# JDBC 연결
<a name="aws-glue-programming-etl-connect-jdbc-home"></a>

 일반적으로 특정 관계형 데이터베이스 유형은 JDBC 표준을 통한 연결을 지원합니다. JDBC에 대한 자세한 내용은 [Java JDBC API](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) 설명서를 참조하세요. AWS Glue는 기본적으로 JDBC 커넥터를 통해 특정 데이터베이스 연결을 지원합니다. JDBC 라이브러리는 AWS Glue Spark 작업에서 제공됩니다. AWS Glue 라이브러리를 사용하여 이러한 데이터베이스 유형에 연결할 때 표준 옵션 세트에 액세스할 수 있습니다.

JDBC connectionType 값은 다음과 같습니다.
+ `"connectionType": "sqlserver"`: Microsoft SQL Server 데이터베이스에 연결을 지정합니다.
+ `"connectionType": "mysql"`: MySQL 데이터베이스에 대한 연결을 지정합니다.
+ `"connectionType": "oracle"`: Oracle Database에 연결을 지정합니다.
+ `"connectionType": "postgresql"`: PostgreSQL 데이터베이스에 대한 연결을 지정합니다.
+ `"connectionType": "redshift"`: Amazon Redshift 데이터베이스에 대한 연결을 지정합니다. 자세한 내용은 [Redshift 연결](aws-glue-programming-etl-connect-redshift-home.md) 섹션을 참조하세요.

다음 표에는 AWS Glue에서 지원하는 JDBC 드라이버 버전 목록이 있습니다.


| 제품 | Glue 5.1용 JDBC 드라이버 버전 | Glue 5.0용 JDBC 드라이버 버전 | Glue 4.0용 JDBC 드라이버 버전 | Glue 3.0용 JDBC 드라이버 버전 | Glue 0.9, 1.0, 2.0용 JDBC 드라이버 버전 | 
| --- | --- | --- | --- | --- | --- | 
| Microsoft SQL Server | 10.2.0 | 10.2.0 | 9.4.0 | 7.x | 6.x | 
| MySQL | 8.0.33 | 8.0.33 | 8.0.23 | 8.0.23 | 5.1 | 
| Oracle Database | 23.3.0.23.09 | 23.3.0.23.09 | 21.7 | 21.1 | 11.2 | 
| PostgreSQL | 42.7.3 | 42.7.3 | 42.3.6 | 42.2.18 | 42.1.x | 
| Amazon Redshift \$1 | redshift-jdbc42-2.1.0.29 | redshift-jdbc42-2.1.0.29 | redshift-jdbc42-2.1.0.16 | redshift-jdbc41-1.2.12.1017 | redshift-jdbc41-1.2.12.1017 | 

\$1 Amazon Redshift 연결 유형의 경우 형식 지정 옵션을 비롯하여 JDBC 연결에 대한 연결 옵션에 포함된 다른 모든 옵션 이름 및 값 페어는 기본 SparkSQL DataSource에 직접 전달됩니다. AWS Glue 4.0 이상 버전의 Spark 작업을 포함하는 AWS Glue에서 Amazon Redshift용 AWS Glue 네이티브 커넥터는 Apache Spark용 Amazon Redshift 통합을 사용합니다. 자세한 내용은 [Apache Spark용 Amazon Redshift 통합](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)을 참조하세요. 이전 버전인 경우 [Amazon Redshift data source for Spark](https://github.com/databricks/spark-redshift)를 참조하세요.

JDBC를 사용하여 Amazon RDS 데이터 스토어에 연결하도록 Amazon VPC를 구성하려면 [AWS Glue에서 Amazon RDS 데이터 스토어에 대해 JDBC를 연결하도록 Amazon VPC 설정](setup-vpc-for-glue-access.md) 섹션을 참조하세요.

**참고**  
AWS Glue 작업은 실행 중에 하나의 서브넷에만 연결됩니다. 이로 인해 동일한 작업을 통해 여러 데이터 소스에 연결하는 기능이 영향을 받을 수 있습니다. 이 동작은 JDBC 소스에만 국한되지 않습니다.

**Topics**
+ [

## JDBC 연결 옵션 참조
](#aws-glue-programming-etl-connect-jdbc)
+ [

## sampleQuery 사용
](#aws-glue-programming-etl-jdbc-samplequery)
+ [

## 사용자 지정 JDBC 드라이버 사용
](#aws-glue-programming-etl-jdbc-custom-driver)
+ [

# JDBC 테이블을 병렬로 읽기
](run-jdbc-parallel-read-job.md)
+ [

# AWS Glue에서 Amazon RDS 데이터 스토어에 대해 JDBC를 연결하도록 Amazon VPC 설정
](setup-vpc-for-glue-access.md)

## JDBC 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-jdbc"></a>

이미 JDBC AWS Glue 연결을 정의한 경우 URL, 사용자 및 암호와 같은 JDBC 연결에 정의된 구성 속성을 재사용할 수 있으므로 코드에서 연결 옵션으로 지정할 필요가 없습니다. 이 기능은 AWS Glue 3.0 이상 버전에서 사용할 수 있습니다. 이렇게 하려면 다음 연결 속성을 사용합니다.
+ `"useConnectionProperties"`: 연결에서 구성을 사용하려는 경우 이 값을 'true'로 설정합니다.
+ `"connectionName"`: 구성을 검색할 연결 이름을 입력합니다. 연결은 작업과 동일한 영역에 정의되어 있어야 합니다.

이 연결 옵션을 JDBC 연결에 사용하십시오.
+ `"url"`: (필수) 데이터베이스의 JDBC URL.
+ `"dbtable"`: (필수) 읽을 데이터베이스 테이블입니다. 데이터베이스 내의 스키마를 지원하는 JDBC 데이터 스토어의 경우 `schema.table-name`에 대해 지정합니다. 스키마가 제공되지 않으면 기본 "퍼블릭" 스키마가 사용됩니다.
+ `"user"`: (필수 사항) 연결할 때 사용할 사용자 이름입니다.
+ `"password"`: (필수) 연결할 때 사용할 암호.
+ (선택 사항) 다음 옵션을 사용하면 사용자 정의 JDBC 드라이버를 제공할 수 있습니다. AWS Glue에서 기본적으로 지원하지 않는 드라이버를 사용해야 한다면 이 옵션을 사용합니다.

  ETL 작업은 원본과 대상이 같은 데이터베이스 제품이어도 데이터 원본과 대상에 여러 JDBC 드라이버 버전을 사용할 수 있습니다. 따라서 버전이 다른 원본 데이터베이스와 대상 데이터베이스 간에 데이터를 마이그레이션할 수 있습니다. 이 옵션을 사용하려면 먼저 Amazon S3에 JDBC 드라이버의 JAR 파일을 업로드해야 합니다.
  + `"customJdbcDriverS3Path"`: 사용자 정의 JDBC 드라이버의 Amazon S3 경로입니다.
  + `"customJdbcDriverClassName"`: JDBC 드라이버의 클래스 이름입니다.
+ `"bulkSize"`: (선택 사항) JDBC 대상에 신속하게 대량 로드하기 위해 병렬 삽입을 구성하는 데 사용됩니다. 데이터를 쓰거나 삽입할 때 사용할 병렬 처리 수준의 정수 값을 지정합니다. 이 옵션은 Arch User Repository(AUR)와 같은 데이터베이스에 대한 쓰기 성능을 향상시키는 데 유용합니다.
+ `"hashfield"`(선택 사항) JDBC 테이블에서 병렬로 읽을 때 데이터를 파티션으로 구분하는 데 사용할 JDBC 테이블의 열 이름을 지정하기 위해 사용하는 문자열입니다. 'hashfield' 또는 'hashexpression'을 제공합니다. 자세한 내용은 [JDBC 테이블을 병렬로 읽기](run-jdbc-parallel-read-job.md) 섹션을 참조하세요.
+ `"hashexpression"`(선택 사항) 정수를 반환하는 SQL select 절입니다. JDBC 테이블에서 병렬로 읽을 때 JDBC 테이블의 데이터를 파티션으로 구분하는 데 사용됩니다. 'hashfield' 또는 'hashexpression'을 제공합니다. 자세한 내용은 [JDBC 테이블을 병렬로 읽기](run-jdbc-parallel-read-job.md) 섹션을 참조하세요.
+ `"hashpartitions"`(선택 사항) 양의 정수입니다. JDBC 테이블에서 병렬로 읽을 때 JDBC 테이블의 병렬 읽기 수를 지정하는 데 사용됩니다. 기본값: 7. 자세한 내용은 [JDBC 테이블을 병렬로 읽기](run-jdbc-parallel-read-job.md) 섹션을 참조하세요.
+ `"sampleQuery"`: (선택 사항) 사용자 지정 SQL 쿼리 문입니다. 테이블의 정보 하위 세트를 지정하여 테이블 콘텐츠의 샘플을 검색하는 데 사용됩니다. **데이터를 고려하지 않고 구성하면 DynamicFrame 메서드보다 효율성이 떨어져 시간 초과나 메모리 부족 오류가 발생할 수 있습니다.** 자세한 내용은 [sampleQuery 사용](#aws-glue-programming-etl-jdbc-samplequery) 섹션을 참조하세요.
+ `"enablePartitioningForSampleQuery"`: (선택 사항) 부울입니다. 기본값: false. `sampleQuery`를 지정할 때 JDBC 테이블에서 병렬 읽기를 활성화하는 데 사용됩니다. **true로 설정된 경우 AWS Glue에서 분할 조건을 추가하려면 `sampleQuery`가 'where' 또는 'and'로 끝나야 합니다.** 자세한 내용은 [sampleQuery 사용](#aws-glue-programming-etl-jdbc-samplequery) 섹션을 참조하세요.
+ `"sampleSize"`: (선택 사항) 양의 정수입니다. 샘플 쿼리에서 반환되는 행의 수를 제한합니다. `enablePartitioningForSampleQuery`가 true인 경우에만 작동합니다. 분할이 활성화되지 않은 경우 대신 `sampleQuery`에서 `"limit x"`를 직접 추가하여 크기를 제한해야 합니다. 자세한 내용은 [sampleQuery 사용](#aws-glue-programming-etl-jdbc-samplequery) 섹션을 참조하세요.

## sampleQuery 사용
<a name="aws-glue-programming-etl-jdbc-samplequery"></a>

이 섹션에서는 `sampleQuery`, `enablePartitioningForSampleQuery` 및 `sampleSize` 사용 방법을 설명합니다.

`sampleQuery`는 데이터 세트의 몇 개 행을 샘플링할 때 효율적입니다. 기본적으로 쿼리는 단일 실행기에 의해 실행됩니다. 데이터를 고려하지 않고 구성하면 DynamicFrame 메서드보다 효율성이 떨어져 시간 초과나 메모리 부족 오류가 발생할 수 있습니다. ETL 파이프라인의 일부로 기본 데이터베이스에서 SQL을 실행하는 방법은 일반적으로 성능 목적으로만 필요합니다. 데이터 세트의 몇 개 행을 미리 보려는 경우 [show](aws-glue-api-crawler-pyspark-extensions-dynamic-frame.md#aws-glue-api-crawler-pyspark-extensions-dynamic-frame-show) 사용을 고려합니다. SQL을 사용하여 데이터 세트를 변환하려는 경우 DataFrame 양식의 데이터에 대해 SparkSQL 변환을 정의하는 데 [toDF](aws-glue-api-crawler-pyspark-extensions-dynamic-frame.md#aws-glue-api-crawler-pyspark-extensions-dynamic-frame-toDF) 사용을 고려합니다.

쿼리가 다양한 테이블을 조작할 수 있지만 `dbtable`이 여전히 필요합니다.

**sampleQuery를 사용하여 테이블 샘플 검색**

기본 sampleQuery 동작을 사용하여 데이터 샘플을 검색할 때 AWS Glue는 뛰어난 처리량을 기대하지 않으므로 단일 실행기에서 쿼리를 실행합니다. 제공하는 데이터를 제한하고 성능 문제를 일으키지 않으려면 SQL에 `LIMIT` 절을 제공하는 것이 좋습니다.

**Example 분할 없이 SampleQuery 사용**  
다음 코드 예제에서는 분할 없이 `sampleQuery`를 사용하는 방법을 보여줍니다.  

```
//A full sql query statement.
val query = "select name from $tableName where age > 0 limit 1"
val connectionOptions = JsonOptions(Map(
    "url" -> url, 
    "dbtable" -> tableName, 
    "user" -> user, 
    "password" -> password, 
    "sampleQuery" -> query ))
val dyf = glueContext.getSource("mysql", connectionOptions)
          .getDynamicFrame()
```

**대규모 데이터 세트에서 sampleQuery 사용**

 대규모 데이터 세트를 읽는 경우 JDBC 분할을 활성화하여 테이블을 병렬로 쿼리해야 할 수 있습니다. 자세한 내용은 [JDBC 테이블을 병렬로 읽기](run-jdbc-parallel-read-job.md) 섹션을 참조하세요. JDBC 분할과 함께 `sampleQuery`를 사용하려면 `enablePartitioningForSampleQuery`를 true로 설정합니다. 이 기능을 활성화하려면 `sampleQuery`를 일부 변경해야 합니다.

`sampleQuery`와 함께 JDBC 분할을 사용하는 경우 AWS Glue에서 분할 조건을 추가하려면 쿼리가 'where' 또는 'and'로 끝나야 합니다.

 JDBC 테이블에서 병렬로 읽을 때 sampleQuery의 결과를 제한하려면 `LIMIT` 절을 지정하는 대신, `"sampleSize"` 파라미터를 설정합니다.

**Example JDBC 분할과 함께 sampleQuery 사용**  
다음 코드 예제는 JDBC 분할과 함께 `sampleQuery`를 사용하는 방법을 보여줍니다.  

```
//note that the query should end with "where" or "and" if use with JDBC partitioning.
val query = "select name from $tableName where age > 0 and"

//Enable JDBC partitioning by setting hashfield.
//to use sampleQuery with partitioning, set enablePartitioningForSampleQuery.
//use sampleSize to limit the size of returned data.
val connectionOptions = JsonOptions(Map(
    "url" -> url, 
    "dbtable" -> tableName, 
    "user" -> user, 
    "password" -> password, 
    "hashfield" -> primaryKey,
    "sampleQuery" -> query,
    "enablePartitioningForSampleQuery" -> true,
    "sampleSize" -> "1" ))
val dyf = glueContext.getSource("mysql", connectionOptions)
          .getDynamicFrame()
```

 **규칙 및 제한:** 

샘플 쿼리는 작업 북마크와 함께 사용할 수 없습니다. 두 가지 모두에 대한 구성이 제공되면 북마크 상태는 무시됩니다.

## 사용자 지정 JDBC 드라이버 사용
<a name="aws-glue-programming-etl-jdbc-custom-driver"></a>

다음 코드 예제에서는 사용자 지정 JDBC 드라이버로 JDBC 데이터베이스에서 읽고 쓰는 방법을 보여줍니다. 한 버전의 데이터베이스 제품에서 읽고 같은 제품의 나중 버전에 쓰는 작업을 볼 수 있습니다.

------
#### [ Python ]

```
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext, SparkConf
from awsglue.context import GlueContext
from awsglue.job import Job
import time
from pyspark.sql.types import StructType, StructField, IntegerType, StringType

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

# Construct JDBC connection options
connection_mysql5_options = {
    "url": "jdbc:mysql://<jdbc-host-name>:3306/db",
    "dbtable": "test",
    "user": "admin",
    "password": "pwd"}

connection_mysql8_options = {
    "url": "jdbc:mysql://<jdbc-host-name>:3306/db",
    "dbtable": "test",
    "user": "admin",
    "password": "pwd",
    "customJdbcDriverS3Path": "s3://amzn-s3-demo-bucket/mysql-connector-java-8.0.17.jar",
    "customJdbcDriverClassName": "com.mysql.cj.jdbc.Driver"}

connection_oracle11_options = {
    "url": "jdbc:oracle:thin:@//<jdbc-host-name>:1521/ORCL",
    "dbtable": "test",
    "user": "admin",
    "password": "pwd"}

connection_oracle18_options = {
    "url": "jdbc:oracle:thin:@//<jdbc-host-name>:1521/ORCL",
    "dbtable": "test",
    "user": "admin",
    "password": "pwd",
    "customJdbcDriverS3Path": "s3://amzn-s3-demo-bucket/ojdbc10.jar",
    "customJdbcDriverClassName": "oracle.jdbc.OracleDriver"}

# Read from JDBC databases with custom driver
df_mysql8 = glueContext.create_dynamic_frame.from_options(connection_type="mysql",
                                                          connection_options=connection_mysql8_options)

# Read DynamicFrame from MySQL 5 and write to MySQL 8
df_mysql5 = glueContext.create_dynamic_frame.from_options(connection_type="mysql",
                                                          connection_options=connection_mysql5_options)
glueContext.write_from_options(frame_or_dfc=df_mysql5, connection_type="mysql",
                               connection_options=connection_mysql8_options)

# Read DynamicFrame from Oracle 11 and write to Oracle 18
df_oracle11 = glueContext.create_dynamic_frame.from_options(connection_type="oracle",
                                                            connection_options=connection_oracle11_options)
glueContext.write_from_options(frame_or_dfc=df_oracle11, connection_type="oracle",
                               connection_options=connection_oracle18_options)
```

------
#### [ Scala ]

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.MappingSpec
import com.amazonaws.services.glue.errors.CallSite
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamicFrame
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._


object GlueApp {
  val MYSQL_5_URI: String = "jdbc:mysql://<jdbc-host-name>:3306/db"
  val MYSQL_8_URI: String = "jdbc:mysql://<jdbc-host-name>:3306/db"
  val ORACLE_11_URI: String = "jdbc:oracle:thin:@//<jdbc-host-name>:1521/ORCL"
  val ORACLE_18_URI: String = "jdbc:oracle:thin:@//<jdbc-host-name>:1521/ORCL"

  // Construct JDBC connection options
  lazy val mysql5JsonOption = jsonOptions(MYSQL_5_URI)
  lazy val mysql8JsonOption = customJDBCDriverJsonOptions(MYSQL_8_URI, "s3://amzn-s3-demo-bucket/mysql-connector-java-8.0.17.jar", "com.mysql.cj.jdbc.Driver")
  lazy val oracle11JsonOption = jsonOptions(ORACLE_11_URI)
  lazy val oracle18JsonOption = customJDBCDriverJsonOptions(ORACLE_18_URI, "s3://amzn-s3-demo-bucket/ojdbc10.jar", "oracle.jdbc.OracleDriver")

  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)

    // Read from JDBC database with custom driver
    val df_mysql8: DynamicFrame = glueContext.getSource("mysql", mysql8JsonOption).getDynamicFrame()

    // Read DynamicFrame from MySQL 5 and write to MySQL 8
    val df_mysql5: DynamicFrame = glueContext.getSource("mysql", mysql5JsonOption).getDynamicFrame()
    glueContext.getSink("mysql", mysql8JsonOption).writeDynamicFrame(df_mysql5)

    // Read DynamicFrame from Oracle 11 and write to Oracle 18
    val df_oracle11: DynamicFrame = glueContext.getSource("oracle", oracle11JsonOption).getDynamicFrame()
    glueContext.getSink("oracle", oracle18JsonOption).writeDynamicFrame(df_oracle11)

    Job.commit()
  }

  private def jsonOptions(url: String): JsonOptions = {
    new JsonOptions(
      s"""{"url": "${url}",
         |"dbtable":"test",
         |"user": "admin",
         |"password": "pwd"}""".stripMargin)
  }

  private def customJDBCDriverJsonOptions(url: String, customJdbcDriverS3Path: String, customJdbcDriverClassName: String): JsonOptions = {
    new JsonOptions(
      s"""{"url": "${url}",
         |"dbtable":"test",
         |"user": "admin",
         |"password": "pwd",
         |"customJdbcDriverS3Path": "${customJdbcDriverS3Path}",
         |"customJdbcDriverClassName" : "${customJdbcDriverClassName}"}""".stripMargin)
  }
}
```

------

# JDBC 테이블을 병렬로 읽기
<a name="run-jdbc-parallel-read-job"></a>

JDBC 테이블의 속성을 AWS Glue에서 분할된 데이터를 병렬로 읽도록 설정할 수 있습니다. 특정 속성을 설정할 때 AWS Glue에게 데이터의 논리적 파티션에 대해 병렬 SQL 쿼리를 실행하도록 지시합니다. 해시 필드 또는 해시 표현식을 설정하여 파티셔닝을 제어할 수 있습니다. 데이터에 액세스할 때 사용되는 병렬 읽기의 수도 제어할 수 있습니다.

JDBC 테이블에서 병렬로 읽는 것은 성능을 향상시킬 수 있는 최적화 기법입니다. 이 기법이 적절한 시기를 식별하는 프로세스에 대한 자세한 내용은 AWS 권장 가이드의 *Apache Spark용 AWS Glue 작업 성능 조정 모범 사례* 가이드에 있는 [데이터 스캔량 감소](https://docs.aws.amazon.com/prescriptive-guidance/latest/tuning-aws-glue-for-apache-spark/parallelize-tasks.html)를 참조하세요.

병렬 읽기를 활성화하려면 테이블 구조의 파라미터 필드에서 키 값 페어를 설정합니다. JSON 표기법을 사용하여 테이블 파라미터 필드 값을 설정합니다. 테이블 속성을 편집하는 방법에 대한 더 자세한 정보는 [테이블 세부 정보 보기 및 편집](tables-described.md#console-tables-details)를 참조하십시오. ETL(추출, 변환 및 로드) 방법 `create_dynamic_frame_from_options` 및 `create_dynamic_frame_from_catalog`을 호출할 때도 병렬 읽기를 활성화할 수 있습니다 이러한 방법에서 옵션을 지정하는 방법은 [from\$1options](aws-glue-api-crawler-pyspark-extensions-dynamic-frame-reader.md#aws-glue-api-crawler-pyspark-extensions-dynamic-frame-reader-from_options) 및 [from\$1catalog](aws-glue-api-crawler-pyspark-extensions-dynamic-frame-reader.md#aws-glue-api-crawler-pyspark-extensions-dynamic-frame-reader-from_catalog) 단원을 참조하십시오.

이 방법을 JDBC 테이블, 즉 베이스 데이터가 JDBC 데이터 스토어인 대부분의 테이블에 사용할 수 있습니다. Amazon Redshift 및 Amazon S3 테이블을 읽을 때 이러한 속성은 무시됩니다.

**hashfield**  
`hashfield`을 사용할 JDBC 테이블의 열 이름으로 설정하여 데이터를 파티션으로 분할합니다. 파티션 사이로 데이터를 분배할 값이 이 열에 고르게 분포하는 것이 가장 좋습니다. 이 열은 데이터 형식이 될 수 있습니다. AWS Glue는 이 열로 분할된 데이터를 읽기 위해 병렬로 실행되는 비-중첩 쿼리를 생성합니다. 예를 들어, 데이터가 월별로 고르게 분포할 경우 `month` 열을 사용하여 각 월의 데이터를 병렬로 읽을 수 있습니다.  

```
  'hashfield': 'month'
```
AWS Glue은 쿼리를 생성하여 필드 값을 파티션 번호로 해싱하고 전체 파티션의 질의를 병렬로 실행합니다. 사용자의 쿼리를 사용하여 테이블 읽기를 분할하려면 `hashfield` 대신 `hashexpression`를 제공합니다.

**hashexpression**  
`hashexpression`을 자연수를 반환하는 SQL 표현식(JDBC 데이터베이스 엔진 문법 준수)으로 설정합니다. 간단한 표현식은 테이블의 숫자 열 이름입니다. AWS Glue는 `WHERE` 절의 `hashexpression`를 사용하여 JDBC 데이터를 병렬로 읽어 데이터를 분할할 SQL 쿼리를 생성합니다.  
예를 들어, 숫자 열 `customerID`를 사용하여 고객 번호로 분할된 데이터를 읽습니다.  

```
  'hashexpression': 'customerID'
```
AWS Glue이 파티셔닝을 제어하게 하려면 `hashexpression` 대신 `hashfield`를 제공합니다.

**hashpartitions**  
`hashpartitions`을 JDBC 테이블 병렬 읽기 번호로 설정합니다. 이 속성을 설정하지 않을 경우 기본값은 7입니다.  
예를 들어, 병렬 읽기 번호를 `5`로 설정하면 AWS Glue는 쿼리가 5개(또는 이하)인 데이터를 읽습니다.  

```
  'hashpartitions': '5'
```

# AWS Glue에서 Amazon RDS 데이터 스토어에 대해 JDBC를 연결하도록 Amazon VPC 설정
<a name="setup-vpc-for-glue-access"></a>

 JDBC를 사용하여 Amazon RDS의 데이터베이스에 연결하는 경우 추가 설정을 수행해야 합니다. AWS Glue 구성 요소가 Amazon RDS와 통신할 수 있도록 하려면 Amazon VPC에서 Amazon RDS 데이터 스토어에 대한 액세스를 설정해야 합니다. AWS Glue가 구성 요소 간에 통신하려면 보안 그룹이 모든 TCP 포트에 자기 참조 인바운드 규칙을 지정해야 합니다. 자체 참조 규칙을 생성하면 소스를 VPC의 동일한 보안 그룹으로 제한할 수 있습니다. 자체 참조 규칙을 사용한다고 해서 VPC가 모든 네트워크에 개방되는 것은 아닙니다. VPC의 기본 보안 그룹은 ALL Traffic의 자기 참조 인바운드 액세스 규칙이 있습니다.

**AWS Glue 및 Amazon RDS 데이터 스토어 간에 액세스를 설정하려면**

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

1. Amazon RDS 콘솔에서 Amazon RDS 데이터베이스에 대한 액세스를 제어하는 데 사용되는 보안 그룹을 식별합니다.

   왼쪽 탐색 창에서 **데이터베이스**를 선택한 다음 기본 창의 목록에서 연결하려는 인스턴스를 선택합니다.

   데이터베이스 세부 정보 페이지의 **연결 및 보안** 탭에서 **VPC 보안 그룹**을 찾습니다.

1. 네트워크 아키텍처를 기반으로 AWS Glue 서비스에 대한 액세스를 허용하도록 수정하는 것이 가장 적합한 관련 보안 그룹을 식별합니다. 나중에 참조할 수 있도록 *database-security-group*이라는 이름을 저장하세요. 적절한 보안 그룹이 없는 경우 Amazon RDS 설명서의 [보안 그룹을 생성하여 VPC에서 DB 인스턴스에 대한 액세스 권한 제공](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_SettingUp.html) 지침을 따르세요.

1. AWS Management Console에 로그인하고 [https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/)에서 Amazon VPC 콘솔을 엽니다.

1. Amazon VPC 콘솔에서 *database-security-group*을 업데이트하는 방법을 확인합니다.

   왼쪽 탐색 창에서 **보안 그룹**을 선택한 다음 기본 창 목록에서 *database-security-group*을 선택합니다.

1. *database-security-group*, *database-sg-id*의 보안 그룹 ID를 식별합니다. 나중에 참조할 수 있도록 저장합니다.

   보안 그룹 세부 정보 페이지에서 **보안 그룹 ID**를 찾으세요.

1. *database-security-group*의 인바운드 규칙을 변경하고 AWS Glue 구성 요소가 통신할 수 있도록 자체 참조 규칙을 추가합니다. 구체적으로 **유형**이 `All TCP`, **프로토콜**이 `TCP`, **포트 범위**가 모든 포트를 포함하고 **소스**가 *database-sg-id*인 규칙을 추가하거나 있는지 확인합니다. **소스**에 입력한 보안 그룹이 편집 중인 보안 그룹과 동일한지 확인합니다.

   보안 그룹 세부 정보 페이지에서 **인바운드 규칙 편집**을 선택합니다.

   인바운드 규칙은 다음과 비슷하게 보입니다.  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/glue/latest/dg/setup-vpc-for-glue-access.html)

1. 아웃바운드 트래픽에 대한 규칙을 추가합니다.

   보안 그룹 세부 정보 페이지에서 **아웃바운드 규칙 편집**을 선택합니다.

   보안 그룹에서 모든 아웃바운드 트래픽을 허용하는 경우에는 별도의 규칙이 필요하지 않습니다. 예제:  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/glue/latest/dg/setup-vpc-for-glue-access.html)

   네트워크 아키텍처가 아웃바운드 트래픽을 제한하도록 설계된 경우 다음과 같은 아웃바운드 규칙을 생성하세요.

   **유형**은 `All TCP`, **프로토콜**은 `TCP`, **포트 범위**는 모든 포트를 포함하고 **대상**은 *database-sg-id*인 자체 참조 규칙을 생성합니다. **대상**에 입력한 보안 그룹이 편집 중인 보안 그룹과 동일한지 확인합니다.

    Amazon S3 VPC 엔드포인트를 사용하는 경우에는 HTTPS 규칙을 추가하여 VPC에서 Amazon S3로의 트래픽을 허용하세요. **유형**은 `HTTPS`, **프로토콜**은 `TCP`, **포트 범위**는 `443`이고 **대상**이 Amazon S3 게이트웨이 엔드포인트인 *s3-prefix-list-id*에 대한 관리형 접두사 목록의 ID인 규칙을 생성합니다. 접두사 목록 및 Amazon S3 게이트웨이 엔드포인트에 대한 자세한 내용은 Amazon VPC 설명서에서 [Amazon S3에 대한 게이트웨이 엔드포인트](https://docs.aws.amazon.com//vpc/latest/privatelink/vpc-endpoints-s3.html)를 참조하세요.

   예제:  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/glue/latest/dg/setup-vpc-for-glue-access.html)

# MongoDB 연결
<a name="aws-glue-programming-etl-connect-mongodb-home"></a>

AWS Glue for Spark를 사용하여 AWS Glue 4.0 이상 버전에서 MongoDB와 MongoDB Atlas의 테이블에서 읽고 쓸 수 있습니다. AWS Glue 연결을 통해 AWS Secrets Manager에 저장된 사용자 이름 및 암호 보안 인증 정보를 사용하여 MongoDB에 연결할 수 있습니다.

MongoDB 대한 자세한 내용은 [MongoDB 설명서](https://www.mongodb.com/docs/)를 참조하십시오.

## MongoDB 연결 구성
<a name="aws-glue-programming-etl-connect-mongodb-configure"></a>

AWS Glue에서 MongoDB에 연결하려면 MongoDB 보안 인증 정보와 *mongodbUser*, *mongodbPass*가 필요합니다.

AWS Glue에서 MongoDB에 연결하려면 몇 가지 전제 조건이 필요할 수 있습니다.
+ MongoDB 인스턴스가 Amazon VPC에 있는 경우, 퍼블릭 인터넷을 통과하는 트래픽 없이 AWS Glue 작업이 MongoDB 인스턴스와 통신할 수 있도록 Amazon VPC를 구성하십시오.

  Amazon VPC에서 AWS Glue가 작업을 실행하는 동안 사용할 **VPC**, **서브넷** 및 **보안 그룹**을 식별하거나 생성합니다. 또한 MongoDB 인스턴스와 이 위치 간의 네트워크 트래픽을 허용하도록 Amazon VPC를 구성해야 합니다. 네트워크 레이아웃에 따라 보안 그룹 규칙, 네트워크 ACL, NAT 게이트웨이 및 피어링 연결을 변경해야 할 수도 있습니다.

그런 다음 MongoDB와 함께 사용할 수 있도록 AWS Glue를 구성할 수 있습니다.

**MongoDB 연결 구성 방법:**

1. 대안으로 AWS Secrets Manager에서 MongoDB 보안 인증을 사용하여 보안 암호를 생성할 수 있습니다. Secrets Manager에서 보안 암호를 생성하려면 AWS Secrets Manager 설명서의 [Create an AWS Secrets Manager secret](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)에서 제공하는 자습서를 따릅니다. 보안 암호를 생성한 후에는 다음 단계를 위해 보안 암호 이름, *secretName*을 유지합니다.
   + **키/값 페어**를 선택하면 값 *mongodbUser*이 포함된 키 `username`에 대한 페어를 생성합니다.

     **키/값 페어**를 선택하면 값 *mongodbPass*가 포함된 키 `password`에 대한 페어를 생성합니다.

1. AWS Glue 콘솔에서 [AWS Glue 연결 추가](console-connections.md)의 단계에 따라 연결을 생성합니다. 연결을 생성한 후에는 AWS Glue에서 이용하기 위해 연결 이름 *connectionName*을 유지합니다.
   + **연결 유형**을 선택할 때에는 **MongoDB** 또는 **MongoDB Atlas**를 선택합니다.
   + **MongoDB URL** 또는 **MongoDB Atlas URL**을 선택할 때에는 MongoDB 인스턴스의 호스트 이름을 제공하십시오.

     MongoDB URL은 `mongodb://mongoHost:mongoPort/mongoDBname` 형식으로 제공됩니다.

     MongoDB Atlas URL은 `mongodb+srv://mongoHost/mongoDBname` 형식으로 제공됩니다.
   + Secrets Manager 암호를 생성하기로 선택한 경우 AWS Secrets Manager **보안 인증 정보 유형**을 선택합니다.

     그런 다음 **AWS 암호**에 *secretName*을 입력합니다.
   + **사용자 이름과 비밀번호**를 제공하기로 선택한 경우 *mongodbUser*와 *mongodbPass*를 제공하십시오.

1. 다음과 같은 상황에서는 추가 구성이 필요할 수도 있습니다.
   + 

     Amazon VPC에서 AWS에 호스팅된 MongoDB 인스턴스의 경우
     + MongoDB 보안 보안 인증 정보를 정의하는 AWS Glue 연결에 Amazon VPC 연결 정보를 제공해야 합니다. 연결을 만들거나 업데이트할 때 **네트워크 옵션**에서 **VPC**, **서브넷** 및 **보안 그룹**을 설정합니다.

AWS Glue MongoDB 연결을 생성한 후에는 연결 방법을 호출하기 전에 다음 조치를 수행해야 합니다.
+ Secrets Manager 암호을 생성하기로 선택한 경우, AWS Glue 작업과 연결된 IAM 역할에 *secretName*을 읽을 수 있는 권한을 부여하십시오.
+ AWS Glue 작업 구성에서 **추가 네트워크 연결**로 *connectionName*을 제공합니다.

AWS Glue for Spark에서 AWS Glue MongoDB 연결을 사용하려면 연결 방법 호출에서 `connectionName` 옵션을 제공하십시오. 또는, [ETL 작업의 MondoDB 연결 작업](integrate-with-mongo-db.md)의 단계에 따라 AWS Glue 데이터 카탈로그와 함께 연결을 사용할 수도 있습니다.

## Glue AWS 연결을 사용하여 MongoDB에서 읽기
<a name="aws-glue-programming-etl-connect-mongodb-read"></a>

**사전 조건**: 
+ 읽으려는 MongoDB 컬렉션. 컬렉션에 대한 식별 정보가 필요합니다.

  MongoDB 컬렉션은 데이터베이스 이름 *mongodbName* 및 컬렉션 이름 *mongodbCollection*으로 식별됩니다.
+ 인증 정보를 제공하도록 구성된 AWS Glue MongoDB 연결입니다. 인증 정보를 구성하려면 앞 절차인 *MongoDB에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예제: 

```
mongodb_read = glueContext.create_dynamic_frame.from_options(
    connection_type="mongodb",
    connection_options={
        "connectionName": "connectionName",
        "database": "mongodbName",
        "collection": "mongodbCollection",
        "partitioner": "com.mongodb.spark.sql.connector.read.partitioner.SinglePartitionPartitioner",
        "partitionerOptions.partitionSizeMB": "10",
        "partitionerOptions.partitionKey": "_id",
        "disableUpdateUri": "false",
    }
)
```

## MongoDB 테이블에 쓰기
<a name="aws-glue-programming-etl-connect-mongodb-write"></a>

이 예제에서는 기존 DynamicFrame, *dynamicFrame*의 정보를 MongoDB에 씁니다.

**사전 조건**: 
+ 쓰려는 MongoDB 컬렉션. 컬렉션에 대한 식별 정보가 필요합니다.

  MongoDB 컬렉션은 데이터베이스 이름 *mongodbName* 및 컬렉션 이름 *mongodbCollection*으로 식별됩니다.
+ 인증 정보를 제공하도록 구성된 AWS Glue MongoDB 연결입니다. 인증 정보를 구성하려면 앞 절차인 *MongoDB에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예제: 

```
glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="mongodb",
    connection_options={
        "connectionName": "connectionName",
        "database": "mongodbName",
        "collection": "mongodbCollection",
        "disableUpdateUri": "false",
        "retryWrites": "false", 
    },
)
```

## MongoDB에서 테이블에 쓰고 쓰는 중
<a name="aws-glue-programming-etl-connect-mongodb-read-write"></a>

이 예제에서는 기존 DynamicFrame, *dynamicFrame*의 정보를 MongoDB에 씁니다.

**사전 조건**: 
+ 읽으려는 MongoDB 컬렉션. 컬렉션에 대한 식별 정보가 필요합니다.

  쓰려는 MongoDB 컬렉션. 컬렉션에 대한 식별 정보가 필요합니다.

  MongoDB 컬렉션은 데이터베이스 이름 *mongodbName* 및 컬렉션 이름 *mongodbCollection*으로 식별됩니다.
+ MongoDB 인증 정보, *mongodbUser*, *mongodbPassword*.

예제: 

------
#### [ Python ]

```
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext, SparkConf
from awsglue.context import GlueContext
from awsglue.job import Job
import time

## @params: [JOB_NAME]
args = getResolvedOptions(sys.argv, ['JOB_NAME'])

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

job = Job(glueContext)
job.init(args['JOB_NAME'], args)

output_path = "s3://some_bucket/output/" + str(time.time()) + "/"
mongo_uri = "mongodb://<mongo-instanced-ip-address>:27017"
mongo_ssl_uri = "mongodb://<mongo-instanced-ip-address>:27017"
write_uri = "mongodb://<mongo-instanced-ip-address>:27017"

read_mongo_options = {
    "uri": mongo_uri,
    "database": "mongodbName",
    "collection": "mongodbCollection",
    "username": "mongodbUsername",
    "password": "mongodbPassword",
    "partitioner": "MongoSamplePartitioner",
    "partitionerOptions.partitionSizeMB": "10",
    "partitionerOptions.partitionKey": "_id"}

ssl_mongo_options = {
    "uri": mongo_ssl_uri,
    "database": "mongodbName",
    "collection": "mongodbCollection",
    "ssl": "true",
    "ssl.domain_match": "false"
}

write_mongo_options = {
    "uri": write_uri,
    "database": "mongodbName",
    "collection": "mongodbCollection",
    "username": "mongodbUsername",
    "password": "mongodbPassword",
}

# Get DynamicFrame from MongoDB
dynamic_frame = glueContext.create_dynamic_frame.from_options(connection_type="mongodb",
                                                              connection_options=read_mongo_options)

# Write DynamicFrame to MongoDB
glueContext.write_dynamic_frame.from_options(dynamicFrame, connection_type="mongodb", connection_options=write_mongo_options)

job.commit()
```

------
#### [ Scala ]

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.MappingSpec
import com.amazonaws.services.glue.errors.CallSite
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.DynamicFrame
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._

object GlueApp {
  val DEFAULT_URI: String = "mongodb://<mongo-instanced-ip-address>:27017"
  val WRITE_URI: String = "mongodb://<mongo-instanced-ip-address>:27017"
  lazy val defaultJsonOption = jsonOptions(DEFAULT_URI)
  lazy val writeJsonOption = jsonOptions(WRITE_URI)
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)

    // Get DynamicFrame from MongoDB
    val dynamicFrame: DynamicFrame = glueContext.getSource("mongodb", defaultJsonOption).getDynamicFrame()

    // Write DynamicFrame to MongoDB
    glueContext.getSink("mongodb", writeJsonOption).writeDynamicFrame(dynamicFrame)

    Job.commit()
  }

  private def jsonOptions(uri: String): JsonOptions = {
    new JsonOptions(
      s"""{"uri": "${uri}",
         |"database":"mongodbName",
         |"collection":"mongodbCollection",
         |"username": "mongodbUsername",
         |"password": "mongodbPassword",
         |"ssl":"true",
         |"ssl.domain_match":"false",
         |"partitioner": "MongoSamplePartitioner",
         |"partitionerOptions.partitionSizeMB": "10",
         |"partitionerOptions.partitionKey": "_id"}""".stripMargin)
  }
}
```

------

## MongoDB 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-mongodb"></a>

MongoDB에 대한 연결을 지정합니다. 연결 옵션은 소스 연결 및 싱크 연결에 따라 다릅니다.

다음과 같은 연결 속성은 소스 연결과 싱크 연결 간에 공유됩니다.
+ `connectionName` - 읽기/쓰기에 사용됩니다. 연결 방법에 인증 및 네트워킹 정보를 제공하도록 구성된 AWS Glue MongoDB 연결의 이름입니다. [MongoDB 연결 구성](#aws-glue-programming-etl-connect-mongodb-configure)에서 설명한 대로 AWS Glue 연결을 구성하면 `connectionName`을 제공했을 때`"uri"`, `"username"` 및 `"password"` 연결 옵션을 제공할 필요가 없어집니다.
+ `"uri"`: (필수 사항) 읽을 소스 MongoDB 호스트로, `mongodb://<host>:<port>` 형식입니다. AWS Glue 4.0 이전의 AWS Glue 버전에서 사용됩니다.
+ `"connection.uri"`: (필수 사항) 읽을 소스 MongoDB 호스트로, `mongodb://<host>:<port>` 형식입니다. AWS Glue 4.0 이상 버전에서 사용됩니다.
+ `"username"`: (필수 사항) MongoDB 사용자 이름입니다.
+ `"password"`: (필수 사항) MongoDB 암호입니다.
+ `"database"`: (필수 사항) 읽을 MongoDB 데이터베이스입니다. 이 옵션은 작업 스크립트에서 `glue_context.create_dynamic_frame_from_catalog`를 호출할 때 `additional_options`로 전달할 수도 있습니다.
+ `"collection"`: (필수 사항) 읽을 MongoDB 컬렉션입니다. 이 옵션은 작업 스크립트에서 `glue_context.create_dynamic_frame_from_catalog`를 호출할 때 `additional_options`로 전달할 수도 있습니다.

### 소스로서의 "connectionType": "mongodb"
<a name="etl-connect-mongodb-as-source"></a>

소스로서의 `"connectionType": "mongodb"`에는 다음 연결 옵션을 사용합니다.
+ `"ssl"`: (선택 사항) `true`이면 SSL 연결을 시작합니다. 기본값은 `false`입니다.
+ `"ssl.domain_match"`: (선택 사항) `true` 및 `ssl`이 `true`이면 도메인 일치 검사가 수행됩니다. 기본값은 `true`입니다.
+ `"batchSize"`: (선택 사항) 내부 배치의 커서 내에서 사용되는 배치당 반환할 문서 수입니다.
+ `"partitioner"`: (선택 사항) MongoDB에서 입력 데이터를 읽는 파티셔너의 클래스 이름입니다. 커넥터는 다음 파티셔너를 제공합니다.
  + `MongoDefaultPartitioner`(기본값)(AWS Glue 4.0에서는 지원되지 않음)
  + `MongoSamplePartitioner`(MongoDB 3.2 이상 필요)(AWS Glue 4.0에서는 지원되지 않음)
  + `MongoShardedPartitioner`(AWS Glue 4.0에서는 지원되지 않음)
  + `MongoSplitVectorPartitioner`(AWS Glue 4.0에서는 지원되지 않음)
  + `MongoPaginateByCountPartitioner`(AWS Glue 4.0에서는 지원되지 않음)
  + `MongoPaginateBySizePartitioner`(AWS Glue 4.0에서는 지원되지 않음)
  + `com.mongodb.spark.sql.connector.read.partitioner.SinglePartitionPartitioner`
  + `com.mongodb.spark.sql.connector.read.partitioner.ShardedPartitioner`
  + `com.mongodb.spark.sql.connector.read.partitioner.PaginateIntoPartitionsPartitioner`
+ `"partitionerOptions"`: (선택 사항) 지정된 파티셔너에 대한 옵션입니다. 각 파티셔너에 대해 다음 옵션이 지원됩니다.
  + `MongoSamplePartitioner`: `partitionKey`, `partitionSizeMB`, `samplesPerPartition`
  + `MongoShardedPartitioner`: `shardkey`
  + `MongoSplitVectorPartitioner`: `partitionKey`, `partitionSizeMB`
  + `MongoPaginateByCountPartitioner`: `partitionKey`, `numberOfPartitions`
  + `MongoPaginateBySizePartitioner`: `partitionKey`, `partitionSizeMB`

  이러한 옵션에 대한 자세한 내용은 MongoDB 설명서의 [파티셔너 구성](https://docs.mongodb.com/spark-connector/master/configuration/#partitioner-conf)을 참조하십시오.

### 싱크로서의 "connectionType": "mongodb"
<a name="etl-connect-mongodb-as-sink"></a>

싱크로서의 `"connectionType": "mongodb"`에는 다음 연결 옵션을 사용합니다.
+ `"ssl"`: (선택 사항) `true`이면 SSL 연결을 시작합니다. 기본값은 `false`입니다.
+ `"ssl.domain_match"`: (선택 사항) `true` 및 `ssl`이 `true`이면 도메인 일치 검사가 수행됩니다. 기본값은 `true`입니다.
+ `"extendedBsonTypes"`: (선택 사항) `true`이면 데이터를 MongoDB에 쓸 때 확장 BSON 유형을 허용합니다. 기본값은 `true`입니다.
+ `"replaceDocument"`: (선택 사항) `true`이면 `_id` 필드가 포함된 데이터 세트를 저장할 때 전체 문서를 대체합니다. `false`이면 데이터 세트의 필드와 일치하는 문서의 필드만 업데이트됩니다. 기본값은 `true`입니다.
+ `"maxBatchSize"`: (선택 사항) 데이터를 저장할 때 대량 작업의 최대 배치 크기입니다. 기본값은 512입니다.
+ `"retryWrites"`: (선택 사항): AWS Glue에서 네트워크 오류가 발생하는 경우 특정 쓰기 작업을 한 번 자동으로 재시도합니다.

# SAP HANA 커넥션
<a name="aws-glue-programming-etl-connect-saphana-home"></a>

AWS Glue for Spark를 사용하여 AWS Glue 4.0 이상 버전에서 SAP HANA의 테이블에서 읽고 쓸 수 있습니다. SQL 쿼리를 사용하여 SAP HANA에서 읽을 내용을 정의할 수 있습니다. AWS Glue SAP HANA 연결을 통해 AWS Secrets Manager에 저장된 JDBC 보안 인증 정보를 사용하여 SAP HANA에 연결합니다.

SAP HANA JDBC에 대한 자세한 내용은 [SAP HANA 설명서](https://help.sap.com/docs/SAP_HANA_PLATFORM/0eec0d68141541d1b07893a39944924e/ff15928cf5594d78b841fbbe649f04b4.html)를 참조하십시오.

## SAP HANA 연결 구성
<a name="aws-glue-programming-etl-connect-saphana-configure"></a>

AWS Glue에서 SAP HANA에 연결하려면 AWS Secrets Manager 보안 암호에서 SAP HANA 보안 인증 정보를 생성하고 저장한 다음 해당 보안 암호를 SAP HANA AWS 연결에 연결해야 합니다. SAP HANA 서비스와 AWS Glue 간의 네트워크 연결을 구성해야 합니다.

SAP HANA에 연결하려면 몇 가지 사전 요구 사항이 필요할 수 있습니다.
+ SAP HANA 서비스가 Amazon VPC에 있는 경우, 퍼블릭 인터넷을 통과하는 트래픽 없이 AWS Glue 작업이 SAP HANA 서비스와 통신할 수 있도록 Amazon VPC를 구성하십시오.

  Amazon VPC에서 AWS Glue가 작업을 실행하는 동안 사용할 **VPC**, **서브넷** 및 **보안 그룹**을 식별하거나 생성합니다. 또한 Amazon VPC가 SAP HANA 엔드포인트와 이 위치 간의 네트워크 트래픽을 허용하도록 구성되어 있는지 확인해야 합니다. 작업을 수행하려면 SAP HANA JDBC 포트와의 TCP 연결을 설정해야 합니다. SAP HANA 포트에 대한 자세한 내용은 [SAP HANA 설명서](https://help.sap.com/docs/HANA_SMART_DATA_INTEGRATION/7952ef28a6914997abc01745fef1b607/88e2e8bded9e4041ad3ad87dc46c7b55.html?locale=en-US)를 참조하십시오. 네트워크 레이아웃에 따라 보안 그룹 규칙, 네트워크 ACL, NAT 게이트웨이 및 피어링 연결을 변경해야 할 수도 있습니다.
+ SAP HANA 엔드포인트가 인터넷에 액세스할 수 있는 경우 추가 전제 조건은 없습니다.

**SAP HANA에 대한 연결 구성하는 방법:**

1. AWS Secrets Manager에서 SAP HANA 보안 인증을 사용하여 보안 암호를 생성합니다. Secrets Manager에서 보안 암호를 생성하려면 AWS Secrets Manager 설명서의 [Create an AWS Secrets Manager secret](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)에서 제공하는 자습서를 따릅니다. 보안 암호를 생성한 후에는 다음 단계를 위해 보안 암호 이름, *secretName*을 유지합니다.
   + **키/값 페어**를 선택하면 값 *saphanaUsername*이 포함된 키 `username/USERNAME`에 대한 페어를 생성합니다.
   + **키/값 페어**를 선택하면 값 *saphanaPassword*가 포함된 키 `password/PASSWORD`에 대한 페어를 생성합니다.

1. AWS Glue 콘솔에서 [AWS Glue 연결 추가](console-connections.md)의 단계에 따라 연결을 생성합니다. 연결을 생성한 후에는 AWS Glue에서 이용하기 위해 연결 이름 *connectionName*을 유지합니다.
   + **연결 유형**을 선택할 때 SAP HANA를 선택합니다.
   + **SAP HANA URL을** 제공할 때는 인스턴스의 URL을 제공하십시오.

     SAP HANA JDBC URL은 `jdbc:sap://saphanaHostname:saphanaPort/?databaseName=saphanaDBname,ParameterName=ParameterValue` 형식입니다

     AWS Glue에는 다음과 같은 JDBC URL 매개변수가 필요합니다.
     + `databaseName` - 연결할 SAP HANA의 기본 데이터베이스입니다.
   + **AWS 보안 암호**를 선택할 때 *secretName*을 입력합니다.

AWS Glue SAP HANA 연결을 생성한 후에는 AWS Glue 작업을 실행하기 전에 다음 단계를 수행해야 합니다.
+ AWS Glue 작업과 연결된 IAM 역할에 *secretName*을 읽을 수 있는 권한을 부여합니다.
+ AWS Glue 작업 구성에서 **추가 네트워크 연결**로 *connectionName*을 제공합니다.

## SAP HANA 테이블에서 읽는 중
<a name="aws-glue-programming-etl-connect-saphana-read"></a>

**사전 조건 ** 
+ 읽으려는 SAP HANA 테이블. 테이블에 대한 식별 정보가 필요합니다.

  SAP HANA 테이블 이름 및 스키마 이름을 `schemaName.tableName` 형식으로 테이블을 지정할 수 있습니다. 테이블이 기본 스키마 "public"에 있는 경우 스키마 이름과 "." 구분 기호는 필요하지 않습니다. 이것을 *tableIdentifier*라고 합니다. 데이터베이스는 `connectionName`에서 JDBC URL 매개변수로 제공된다는 점에 유의하십시오.
+ 인증 정보를 제공하도록 구성된 AWS Glue SAP HANA 연결입니다. 인증 정보를 구성하려면 앞 절차인 *SAP HANA에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예: 

```
saphana_read_table = glueContext.create_dynamic_frame.from_options(
    connection_type="saphana",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableIdentifier",
    }
)
```

SELECT SQL 쿼리에 반환되는 결과를 필터링하는 쿼리를 제공할 수도 있습니다. `query`을 구성해야 합니다.

예:

```
saphana_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="saphana",
    connection_options={
        "connectionName": "connectionName",
        "query": "query"
    }
)
```

## SAP HANA 테이블에 쓰기
<a name="aws-glue-programming-etl-connect-saphana-write"></a>

이 예제에서는 기존 DynamicFrame, *dynamicFrame*의 정보를 SAP HANA에 기록합니다. 테이블에 이미 정보가 있는 경우 AWS Glue에서 오류가 발생합니다.

**사전 조건 ** 
+ 쓰려고 하는 SAP HANA 테이블.

  SAP HANA 테이블 이름 및 스키마 이름을 `schemaName.tableName` 형식으로 테이블을 지정할 수 있습니다. 테이블이 기본 스키마 "public"에 있는 경우 스키마 이름과 "." 구분 기호는 필요하지 않습니다. 이것을 *tableIdentifier*라고 합니다. 데이터베이스는 `connectionName`에서 JDBC URL 매개변수로 제공된다는 점에 유의하십시오.
+ SAP HANA 인증 정보. 인증 정보를 구성하려면 앞 절차인 *SAP HANA에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예: 

```
options = {
    "connectionName": "connectionName",
    "dbtable": 'tableIdentifier'
}

    saphana_write = glueContext.write_dynamic_frame.from_options(
        frame=dynamicFrame,
        connection_type="saphana",
        connection_options=options
)
```

## SAP HANA 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-saphana-reference"></a>
+ `connectionName` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 연결 방법에 인증 및 네트워킹 정보를 제공하도록 구성된 AWS Glue SAP HANA 연결의 이름입니다.
+ `databaseName` - 읽기/쓰기에 사용됩니다. 유효한 값: SAP HANA의 데이터베이스 이름. 연결할 데이터베이스의 이름입니다.
+ `dbtable` - 쓰기 시 필수, `query`가 제공되지 않는 한 읽기 전용. 읽기 및 쓰기에 사용됩니다. 유효한 값: SAP HANA SQL FROM 절의 내용입니다. 연결할 SAP HANA의 테이블을 식별합니다. 테이블 이름 이외의 다른 SQL(예: 하위 쿼리)을 제공할 수도 있습니다. 자세한 내용은 SAP HANA 설명서의 [From 절](https://help.sap.com/docs/SAP_HANA_PLATFORM/4fe29514fd584807ac9f2a04f6754767/20fcf24075191014a89e9dc7b8408b26.html#loio20fcf24075191014a89e9dc7b8408b26__from_clause)을 참조하십시오.
+ `query` — 읽기에 사용됩니다. SAP HANA에서 읽을 때 검색해야 하는 내용을 정의하는 SAP HANA SQL SELECT 쿼리입니다.

# Snowflake 연결
<a name="aws-glue-programming-etl-connect-snowflake-home"></a>

AWS Glue for Spark를 사용하여 AWS Glue 4.0 이상 버전에서 Snowflake의 테이블에서 읽고 쓸 수 있습니다. SQL 쿼리를 사용하여 Snowflake에서 읽을 수 있습니다. 사용자와 암호를 사용하여 Snowflake에 연결할 수 있습니다. AWS Glue 데이터 카탈로그를 통해 AWS Secrets Manager에 저장된 Snowflake 보안 인증을 참조할 수 있습니다. AWS Glue for Spark용 데이터 카탈로그 Snowflake 보안 인증은 크롤러용 데이터 카탈로그 Snowflake 보안 인증과 별도로 저장됩니다. Snowflake에 연결하도록 구성된 `JDBC` 유형 연결이 아니라 `SNOWFLAKE` 유형 연결을 선택해야 합니다.

Snowball에 대한 자세한 내용은 [Snowflake 웹 사이트](https://www.snowflake.com/)를 참조하세요. AWS에서 Snowflake에 대한 자세한 내용은 [Snowflake Data Warehouse on Amazon Web Services](https://aws.amazon.com/financial-services/partner-solutions/snowflake/)를 참조하세요.

## Snowflake 연결 구성
<a name="aws-glue-programming-etl-connect-snowflake-configure"></a>

인터넷을 통해 사용할 수 있는 Snowflake 데이터베이스에 연결하기 위한 AWS의 필수 조건은 없습니다.

선택적으로 다음 구성을 수행하여 AWS Glue로 연결 보안 인증을 관리할 수 있습니다.

**AWS Glue로 연결 보안 인증을 관리하려면**

1. Snowflake에서 사용자, *snowflakeUser* 및 암호, *snowflakePassword*를 생성합니다.

1. AWS Secrets Manager에서 Snowflake 보안 인증을 사용하여 보안 암호를 생성합니다. Secrets Manager에서 보안 암호를 생성하려면 AWS Secrets Manager 설명서의 [Create an AWS Secrets Manager secret](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html#create_secret_cli)에서 제공하는 자습서를 따릅니다. 보안 암호를 생성한 후에는 다음 단계를 위해 보안 암호 이름, *secretName*을 유지합니다.
   + **키/값 페어**를 선택하면 키가 `USERNAME`인 *snowflakeUser*에 대한 페어를 생성합니다.
   + **키/값 페어**를 선택하면 키가 `PASSWORD`인 *snowflakePassword*에 대한 페어를 생성합니다.
   + **키/값 페어**를 선택하면 키가 `sfWarehouse`인 Snowflake 웨어하우스를 제공할 수 있습니다.
   + **키/값 페어**를 선택하는 경우 해당 Spark 속성 이름을 키로 사용하여 추가 Snowflake 연결 속성을 제공할 수 있습니다. 지원되는 속성으로 다음이 포함됩니다.
     + `sfDatabase` - Snowflake 데이터베이스 이름
     + `sfSchema` - Snowflake 스키마 이름
     + `sfRole` - Snowflake 역할 이름
     + `pem_private_key` - 키 페어 인증에 대한 프라이빗 키

1. AWS Glue Data Catalog에서 **연결**과 **연결 생성**을 차례로 선택하여 연결을 생성합니다. 다음과 같이 연결 마법사의 단계에 따라 프로세스를 완료합니다.
   + **데이터 소스**를 선택할 때 Snowflake를 선택하고 **다음**을 선택합니다.
   + 호스트, 포트와 같은 연결 세부정보를 입력합니다. 호스트 **Snowflake URL**을 입력을 때 Snowflake 인스턴스의 URL을 제공합니다. URL은 일반적으로 `account_identifier.snowflakecomputing.com` 양식의 호스트 이름을 사용합니다. 그러나 Snowflake 계정 유형(예: AWS, Azure 또는 Snowflake 호스팅)에 따라 URL 형식이 다를 수 있습니다.
   + IAM 서비스 역할을 선택할 때에는 드롭다운 메뉴에서 선택합니다. 이것은 VPC가 지정된 경우 AWS Secrets Manager에 액세스하고 IP를 할당하는 데 사용되는 계정의 IAM 역할입니다.
   + **AWS 보안 암호**를 선택할 때 *secretName*을 입력합니다.

1. 마법사의 다음 단계에서 Snowflake 연결에 대한 속성을 설정합니다.

1. 마법사의 마지막 단계에서 설정을 검토한 후 프로세스를 완료하여 연결을 생성합니다.

다음과 같은 상황에서 다음이 필요할 수 있습니다.
+ 

  Amazon VPC에서 AWS에 호스팅된 Snowflake의 경우
  + Snowflake에 적합한 Amazon VPC 구성이 필요합니다. Amazon VPC를 구성하는 방법에 대한 자세한 내용은 Snowflake 설명서의 [AWS PrivateLink & Snowflake](https://docs.snowflake.com/en/user-guide/admin-security-privatelink)를 참조하세요.
  + AWS Glue에 적합한 Amazon VPC 구성이 필요합니다. [AWS Glue에 대한 인터페이스 VPC 엔드포인트(AWS PrivateLink) 구성(AWS PrivateLink)](vpc-interface-endpoints.md).
  + Snowflake 보안 인증을 정의하는 AWS Secrets Manager 보안 암호의 ID 외에도 Amazon VPC 연결 정보를 제공하는 AWS Glue Data Catalog 연결을 생성해야 합니다. 이전 항목에 링크된 Snowflake 설명서에 설명된 대로 AWS PrivateLink 사용 시 URL이 변경됩니다.
  + 데이터 카탈로그 연결을 **추가 네트워크 연결**로 포함하는 작업 구성이 필요합니다.

## Snowflake 테이블에서 읽기
<a name="aws-glue-programming-etl-connect-snowflake-read"></a>

**사전 조건:** 읽으려는 Snowflake 테이블. Snowflake 테이블 이름, *tableName*이 필요합니다. Snowflake URL *snowflakeUrl*, 사용자 이름 *snowflakeUser* 및 암호 *snowflakePassword*가 필요합니다. Snowflake 사용자에게 기본 네임스페이스가 설정되어 있지 않은 경우 Snowflake 데이터베이스 이름, *databaseName* 및 스키마 이름, *schemaName*이 필요합니다. 또한 Snowflake 사용자에게 기본 웨어하우스가 설정되어 있지 않은 경우 웨어하우스 이름, *warehouseName*이 필요합니다.

예:

**추가 사전 조건:** *AWS Glue로 연결을 관리하려면* 단계를 수행하여 *snowflakeUrl*, *snowflakeUsername* 및 *snowflakePassword*를 구성합니다. 이 단계를 검토하려면 이전 [Snowflake 연결 구성](#aws-glue-programming-etl-connect-snowflake-configure) 섹션을 참조하세요. 연결할 **추가 네트워크 연결**을 선택하기 위해 `connectionName` 파라미터를 사용합니다.

```
snowflake_read = glueContext.create_dynamic_frame.from_options(
  connection_type="snowflake",
  connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableName",
        "sfDatabase": "databaseName",
        "sfSchema": "schemaName",
        "sfWarehouse": "warehouseName",
    }
)
```

 또한 `autopushdown` 및 `query` 파라미터를 사용하여 Snowflake 테이블의 일부를 읽을 수 있습니다. 이 방법은 결과를 Spark에 로드한 후 필터링하는 것보다 훨씬 더 효율적일 수 있습니다. 모든 판매가 동일한 테이블에 저장되지만 연휴에 특정 매장의 매출만 분석하려는 예제를 살펴봅니다. 해당 정보가 테이블에 저장된 경우 다음과 같이 조건자 푸시다운을 사용하여 결과를 가져올 수 있습니다.

```
snowflake_node = glueContext.create_dynamic_frame.from_options(
    connection_type="snowflake",
    connection_options={
        "autopushdown": "on",
        "query": "select * from sales where store='1' and IsHoliday='TRUE'",
        "connectionName": "snowflake-glue-conn",
        "sfDatabase": "databaseName",
        "sfSchema": "schemaName",
        "sfWarehouse": "warehouseName",
    }
)
```

## Snowflake 테이블에 쓰기
<a name="aws-glue-programming-etl-connect-snowflake-write"></a>

**사전 조건:** 쓰려는 Snowflake 데이터베이스. 현재 또는 원하는 테이블 이름, *TableName*이 필요합니다. Snowflake URL *snowflakeUrl*, 사용자 이름 *snowflakeUser* 및 암호 *snowflakePassword*가 필요합니다. Snowflake 사용자에게 기본 네임스페이스가 설정되어 있지 않은 경우 Snowflake 데이터베이스 이름, *databaseName* 및 스키마 이름, *schemaName*이 필요합니다. 또한 Snowflake 사용자에게 기본 웨어하우스가 설정되어 있지 않은 경우 웨어하우스 이름, *warehouseName*이 필요합니다.

예:

**추가 사전 조건:** *AWS Glue로 연결을 관리하려면* 단계를 수행하여 *snowflakeUrl*, *snowflakeUsername* 및 *snowflakePassword*를 구성합니다. 이 단계를 검토하려면 이전 [Snowflake 연결 구성](#aws-glue-programming-etl-connect-snowflake-configure) 섹션을 참조하세요. 연결할 **추가 네트워크 연결**을 선택하기 위해 `connectionName` 파라미터를 사용합니다.

```
glueContext.write_dynamic_frame.from_options(
    connection_type="snowflake",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableName",
        "sfDatabase": "databaseName",
        "sfSchema": "schemaName",
        "sfWarehouse": "warehouseName",
    },
)
```

## Snowflake 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-snowflake-reference"></a>

Snowflake 연결 유형에서는 다음과 같은 연결 옵션을 사용합니다.

이 섹션의 일부 파라미터는 데이터 카탈로그 연결(`sfUrl`, `sfUser`, `sfPassword`)에서 검색할 수 있으며, 이 경우 사용자가 해당 파라미터를 제공하지 않아도 됩니다. `connectionName` 파라미터를 제공하여 이 작업을 수행할 수 있습니다.

`secretId` 파라미터를 사용하여 AWS Secrets Manager 보안 암호에서 연결 파라미터를 검색할 수 있습니다. Secrets Manager를 사용하는 경우 보안 암호에 다음 Spark 속성이 존재하면 이를 자동으로 검색할 수 있습니다.
+ `sfUser`(키 `USERNAME` 또는 `sfUser` 사용)
+ `sfPassword`(키 `PASSWORD` 또는 `sfPassword` 사용)
+ `sfWarehouse`(키 `sfWarehouse` 사용)
+ `sfDatabase`(키 `sfDatabase` 사용)
+ `sfSchema`(키 `sfSchema` 사용)
+ `sfRole`(키 `sfRole` 사용)
+ `pem_private_key`(키 `pem_private_key` 사용)

**속성 우선순위:** 동일한 속성이 여러 위치에 지정되는 경우 AWS Glue는 다음 우선순위(최고에서 최저 순서)를 사용합니다.

1. 작업 코드에 명시적으로 제공된 연결 옵션

1. Data Catalog 연결 속성

1. AWS Secrets Manager 보안 암호 값(`secretId`가 지정된 경우)

1. Snowflake 사용자 기본값

다음 파라미터는 보통 Snowflake에 연결할 때 사용됩니다.
+ `sfDatabase` - Snowflake에 사용자 기본값이 설정되어 있지 않은 경우 필요합니다. 읽기 및 쓰기에 사용됩니다. 연결 후 세션에 사용할 데이터베이스입니다.
+ `sfSchema` - Snowflake에 사용자 기본값이 설정되어 있지 않은 경우 필요합니다. 읽기 및 쓰기에 사용됩니다. 연결 후 세션에 사용할 스키마입니다.
+ `sfWarehouse` - Snowflake에 사용자 기본값이 설정되어 있지 않은 경우 필요합니다. 읽기 및 쓰기에 사용됩니다. 연결 후 세션에 사용할 기본 가상 웨어하우스입니다.
+ `sfRole` - Snowflake에 사용자 기본값이 설정되어 있지 않은 경우 필요합니다. 읽기 및 쓰기에 사용됩니다. 연결 후 세션에 사용할 기본 보안 암호 역할입니다.
+ `sfUrl` -- (필수) 읽기 및 쓰기에 사용됩니다. 다음 `account_identifier.snowflakecomputing.com` 형식으로 계정의 호스트 이름을 지정합니다. 계정 식별자에 대한 자세한 내용은 Snowflake 설명서의 [Account Identifiers](https://docs.snowflake.com/en/user-guide/admin-account-identifier)를 참조하세요.
+ `sfUser` -- (필수) 읽기 및 쓰기에 사용됩니다. Snowflake 사용자의 로그인 이름입니다.
+ `sfPassword` - (`pem_private_key`가 제공되지 않은 경우 필수) 읽기/쓰기에 사용됩니다. Snowflake 사용자의 암호입니다.
+ `dbtable` - 전체 테이블에 대한 작업을 수행할 때 필요합니다. 읽기 및 쓰기에 사용됩니다. 읽을 테이블 또는 데이터를 쓸 테이블의 이름입니다. 읽을 때 모든 열과 레코드가 검색됩니다.
+ `pem_private_key` - 읽기/쓰기에 사용됩니다. 암호화되지 않은 b64 인코딩된 프라이빗 키 문자열입니다. Snowflake 사용자의 프라이빗 키입니다. 일반적으로 이를 PEM 파일에서 복사합니다. 자세한 내용은 Snowflake 설명서의 [키 페어 인증 & 키 페어 순환](https://docs.snowflake.com/en/user-guide/key-pair-auth)을 참조하세요.
+ `query` - 쿼리로 읽을 때 필요합니다. 읽기에 사용됩니다. 실행할 정확한 쿼리(`SELECT` 문)입니다.

다음 옵션은 Snowflake에 연결하는 과정에서 특정 동작을 구성하는 데 사용됩니다.
+ `preactions` - 읽기/쓰기에 사용됩니다. 유효한 값: 세미콜론으로 구분된 SQL 문 목록(문자열). SQL 문은 AWS Glue와 Snowflake 사이에서 데이터가 전송되기 전에 실행됩니다. 명령문에 `%s`가 포함된 경우 `%s`는 작업에서 참조하는 테이블 이름으로 바뀝니다.
+ `postactions` - 읽기/쓰기에 사용됩니다. SQL 문은 AWS Glue와 Snowflake 사이에서 데이터가 전송된 후에 실행됩니다. 명령문에 `%s`가 포함된 경우 `%s`는 작업에서 참조하는 테이블 이름으로 바뀝니다.
+ `autopushdown` - 기본값: `"on"`. 유효한 값: `"on"`, `"off"`. 이 파라미터는 자동 쿼리 푸시다운의 활성화 여부를 제어합니다. 푸시다운이 활성화된 경우 Spark에서 쿼리를 실행할 때 쿼리의 일부를 Snowflake 서버로 '푸시다운'할 수 있으면 해당 쿼리가 푸시다운됩니다. 이렇게 하면 일부 쿼리의 성능이 향상됩니다. 쿼리의 푸시다운 여부에 대한 자세한 내용은 Snowflake 설명서의 [Pushdown](https://docs.snowflake.com/en/user-guide/spark-connector-use#pushdown)을 참조하세요.

또한 Snowflake Spark 커넥터에서 사용할 수 있는 일부 옵션이 AWS Glue에서 지원될 수도 있습니다. Snowflake Spark 커넥터에서 사용할 수 있는 옵션에 대한 자세한 내용은 Snowflake 설명서의 [Setting Configuration Options for the Connector](https://docs.snowflake.com/en/user-guide/spark-connector-use#setting-configuration-options-for-the-connector)를 참조하세요.

## Snowflake 인증 방법
<a name="aws-glue-programming-etl-connect-snowflake-authentication"></a>

AWS Glue는 Snowflake에 연결하기 위해 다음과 같은 인증 방법을 지원합니다.
+ **사용자 이름 및 암호 인증:** `sfUser` 및 `sfPassword` 파라미터를 제공합니다.
+ **키 페어 인증:** `sfUser` 및 `pem_private_key` 파라미터를 제공합니다. 키 페어 인증을 사용하는 경우 `sfPassword` 파라미터가 필요하지 않습니다.

두 인증 방법 모두 완벽하게 지원되며 연결 옵션, Data Catalog 연결 또는 AWS Secrets Manager 보안 암호의 조합을 사용하여 구성할 수 있습니다.

## Snowflake 커넥터 제한
<a name="aws-glue-programming-etl-connect-snowflake-limitations"></a>

AWS Glue for Spark를 사용하여 Snowflake에 연결하는 경우 다음과 같은 제한 사항이 적용됩니다.
+ 이 커넥터는 작업 북마크를 지원하지 않습니다. 작업 북마크에 대한 자세한 내용을 알아보려면 [처리된 데이터를 작업 북마크로 추적](monitor-continuations.md)을(를) 참조하세요.
+ 이 커넥터는 `create_dynamic_frame.from_catalog` 및 `write_dynamic_frame.from_catalog` 메서드를 사용하여 AWS Glue 데이터 카탈로그의 테이블을 통한 Snowflake 읽기 및 쓰기를 지원하지 않습니다.
+ 이 커넥터는 사용자 이름/암호 인증 및 키 페어 인증을 지원합니다. 현재 다른 인증 방법(예: OAuth 또는 SAML)은 지원되지 않습니다.
+ 이 커넥터는 스트리밍 작업 내에서 지원되지 않습니다.
+ 이 커넥터는 정보를 검색할 때(예: `query` 파라미터 사용) `SELECT` 문 기반 쿼리를 지원합니다. 다른 종류의 쿼리(예: `SHOW`, `DESC` 또는 DML 문)는 지원되지 않습니다.
+ Snowflake는 Snowflake 클라이언트를 통해 제출되는 쿼리 텍스트(즉, SQL 문)의 크기를 명령문당 1MB로 제한합니다. 자세한 내용은 [Limits on Query Text Size](https://docs.snowflake.com/en/user-guide/query-size-limits)를 참조하세요.

# Teradata Vantage 연결
<a name="aws-glue-programming-etl-connect-teradata-home"></a>

AWS Glue for Spark를 이용하여 AWS Glue 4.0 이상 버전에서 Teradata Vantage의 테이블에서 읽고 쓸 수 있습니다. SQL 쿼리를 사용하여 Teradata에서 읽을 내용을 정의할 수 있습니다. AWS Glue 연결을 통해 AWS Secrets Manager에 저장된 사용자 이름 및 암호 보안 인증 정보를 사용하여 Teradata에 연결할 수 있습니다.

Teradata에 대한 자세한 내용은 [Teradata 설명서](https://docs.teradata.com/)를 참조하십시오.

## Teradata 연결 구성
<a name="aws-glue-programming-etl-connect-teradata-configure"></a>

AWS Glue에서 Teradata에 연결하려면 Teradata 보안 인증 정보를 생성하여 AWS Secrets Manager 암호에 저장한 다음 해당 암호를 AWS Glue Teradata 연결에 연결해야 합니다. Teradata 인스턴스가 Amazon VPC에 있는 경우 AWS Glue Teradata 연결에 네트워킹 옵션도 제공해야 합니다.

AWS Glue에서 Teradata에 연결하려면 몇 가지 전제 조건이 필요할 수 있습니다.
+ Amazon VPC를 통해 Teradata 환경에 액세스하는 경우, AWS Glue 작업이 Teradata 환경과 통신할 수 있도록 Amazon VPC를 구성하십시오. 퍼블릭 인터넷을 통해 Teradata 환경에 액세스하는 것은 권장하지 않습니다.

  Amazon VPC에서 AWS Glue가 작업을 실행하는 동안 사용할 **VPC**, **서브넷** 및 **보안 그룹**을 식별하거나 생성합니다. 또한 Amazon VPC가 Teradata 인스턴스와 이 위치 간의 네트워크 트래픽을 허용하도록 구성되어 있는지 확인해야 합니다. 작업을 수행하려면 Teradata 클라이언트 포트와 TCP 연결을 설정해야 합니다. Teradata 포트에 대한 자세한 내용은 [Teradata 설명서](https://docs.teradata.com/r/Teradata-VantageTM-on-AWS-DIY-Installation-and-Administration-Guide/April-2020/Before-Deploying-Vantage-on-AWS-DIY/Security-Groups-and-Ports)를 참조하십시오.

  네트워크 레이아웃에 따라 보안 VPC 연결에는 Amazon VPC 및 기타 네트워킹 서비스를 변경해야 할 수 있습니다. AWS 연결에 대한 자세한 내용은 Teradata 설명서의 [AWS연결 옵션](https://docs.teradata.com/r/Teradata-VantageCloud-Enterprise/Get-Started/Connecting-Your-Environment/AWS-Connectivity-Options)을 참조하십시오.

**AWS Glue Teradata 연결을 구성하는 방법:**

1. Teradata 구성에서 AWS Glue가 *teradataUser* 및 *teradataPassword*와 연결할 사용자 및 암호를 식별하거나 생성합니다. 자세한 내용은 Teradata 설명서의 [Vantage 보안 개요](https://docs.teradata.com/r/Configuring-Teradata-VantageTM-After-Installation/January-2021/Security-Overview/Vantage-Security-Overview)를 참조하십시오.

1. AWS Secrets Manager에서 Teradata 보안 인증 정보를 사용하여 보안 암호를 생성합니다. Secrets Manager에서 보안 암호를 생성하려면 AWS Secrets Manager 설명서의 [Create an AWS Secrets Manager secret](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)에서 제공하는 자습서를 따릅니다. 보안 암호를 생성한 후에는 다음 단계를 위해 보안 암호 이름, *secretName*을 유지합니다.
   + **키/값 페어**를 선택하면 값 *teradataUsername*이 포함된 키 `user`에 대한 페어를 생성합니다.
   + **키/값 페어**를 선택하면 값 *teradataPassword*가 포함된 키 `password`에 대한 페어를 생성합니다.

1. AWS Glue 콘솔에서 [AWS Glue 연결 추가](console-connections.md)의 단계에 따라 연결을 생성합니다. 연결을 생성한 후에는 다음 단계를 위해 연결 이름, *connectionName*을 유지합니다.
   + **연결 유형**을 선택할 때 Teradata를 선택합니다.
   + **JDBC URL**을 제공할 때는 인스턴스의 URL을 제공하십시오. 또한 JDBC URL에 쉼표로 구분된 특정 연결 매개변수를 하드코딩할 수 있습니다. URL의 형식: `jdbc:teradata://teradataHostname/ParameterName=ParameterValue,ParameterName=ParameterValue`

     지원되는 URL 파라미터는 다음과 같습니다.
     + `DATABASE` - 기본으로 액세스하는 호스트의 데이터베이스 이름입니다.
     + `DBS_PORT` - 비표준 포트에서 실행할 때 사용되는 데이터베이스 포트입니다.
   + **보안 인증 정보 유형**을 선택할 때에는 **AWS Secrets Manager**을 선택한 다음 **AWS보안 암호**를 *secretName*으로 설정합니다.

1. 다음과 같은 상황에서는 추가 구성이 필요할 수도 있습니다.
   + 

     Amazon VPC에서 AWS에 호스팅된 Teradata 인스턴스의 경우
     + Teradata 보안 보안 인증 정보를 정의하는 AWS Glue 연결에 Amazon VPC 연결 정보를 제공해야 합니다. 연결을 만들거나 업데이트할 때 **네트워크 옵션**에서 **VPC**, **서브넷** 및 **보안 그룹**을 설정합니다.

AWS Glue Teradata 연결을 생성한 후에는 연결 방법을 호출하기 전에 다음 단계를 수행해야 합니다.
+ AWS Glue 작업과 연결된 IAM 역할에 *secretName*을 읽을 수 있는 권한을 부여합니다.
+ AWS Glue 작업 구성에서 **추가 네트워크 연결**로 *connectionName*을 제공합니다.

## Teradata에서 읽는 중
<a name="aws-glue-programming-etl-connect-teradata-read"></a>

**사전 조건 **
+ 읽으려는 Teradata 테이블. 테이블 이름, *tableName*이 필요합니다.
+ 인증 정보를 제공하도록 구성된 AWS Glue Teradata 연결입니다. 인증 정보를 구성하려면 *Teradata에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

예: 

```
teradata_read_table = glueContext.create_dynamic_frame.from_options(
    connection_type="teradata",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableName"
    }
)
```

SELECT SQL 쿼리에 반환되는 결과를 필터링하는 쿼리를 제공할 수도 있습니다. `query`을 구성해야 합니다.

예:

```
teradata_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="teradata",
    connection_options={
        "connectionName": "connectionName",
        "query": "query"
    }
)
```

## Teradata 테이블에 쓰기
<a name="aws-glue-programming-etl-connect-teradata-write"></a>

**전제 조건:** 쓰고 싶은 Teradata 테이블, *tableName*. **연결 방법을 호출하기 전에 테이블을 생성해야 합니다.**

예:

```
teradata_write = glueContext.write_dynamic_frame.from_options(
    connection_type="teradata",
    connection_options={
        "connectionName": "connectionName", 
        "dbtable": "tableName"
    }
)
```

## Teradata 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-teradata-reference"></a>
+ `connectionName` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 연결 방법에 인증 및 네트워킹 정보를 제공하도록 구성된 AWS Glue Teradata 연결의 이름입니다.
+ `dbtable` - 쓰기 시 필수, `query`가 제공되지 않는 한 읽기 전용. 읽기 및 쓰기에 사용됩니다. 연결 방법이 상호 작용할 테이블의 이름.
+ `query` — 읽기에 사용됩니다. Teradata에서 읽을 때 검색해야 하는 내용을 정의하는 SELECT SQL 쿼리입니다.

# Teradata Vantage NOS 연결
<a name="connecting-to-data-teradata-nos"></a>

 Teradata NOS(네이티브 객체 스토어) 연결은 Teradata WRITE\$1NOS 쿼리를 활용하여 기존 테이블에서 읽고 READ\$1NOS 쿼리를 활용하여 테이블에 쓰는 Teradata Vantage에 대한 새로운 연결입니다. 이 쿼리는 Amazon S3을 스테이징 디렉터리로 사용하므로 특히 대량의 데이터를 처리할 때 Teradata NOS 커넥터가 기존 Teradata 커넥터(JDBC 기반)보다 빠릅니다.

 AWS Glue for Spark에서 Teradata NOS 연결을 이용하여 AWS Glue 5.0 이상 버전에서 Teradata Vantage의 테이블에서 읽고 쓸 수 있습니다. SQL 쿼리를 사용하여 Teradata에서 읽을 내용을 정의할 수 있습니다. AWS Glue 연결을 통해 AWS Secrets Manager에 저장된 사용자 이름 및 암호 자격 증명을 사용하여 Teradata에 연결할 수 있습니다.

 Teradata에 대한 자세한 내용은 [Teradata 설명서](https://docs.teradata.com/)를 참조하세요.

**Topics**
+ [

## Teradata NOS 연결 생성
](#creating-teradata-nos-connection)
+ [

## Teradata 테이블에서 읽기
](#reading-from-teradata-nos-tables)
+ [

## Teradata 테이블에 쓰기
](#writing-to-teradata-nos-tables)
+ [

## Teradata 연결 옵션 참조
](#teradata-nos-connection-option-reference)
+ [

## AWS Glue 시각적 ETL UI에서 옵션 제공
](#teradata-nos-connection-option-visual-etl-ui)

## Teradata NOS 연결 생성
<a name="creating-teradata-nos-connection"></a>

AWS Glue에서 Teradata NOS에 연결하려면 Teradata 자격 증명을 생성하여 AWS Secrets Manager 암호에 저장한 다음 해당 암호를 AWS Glue Teradata NOS 연결에 연결해야 합니다. Teradata 인스턴스가 Amazon VPC에 있는 경우 AWS Glue Teradata NOS 연결에 네트워킹 옵션도 제공해야 합니다.

 **사전 조건**: 
+  Amazon VPC를 통해 Teradata 환경에 액세스하는 경우, AWS Glue 작업이 Teradata 환경과 통신할 수 있도록 Amazon VPC를 구성하십시오. 퍼블릭 인터넷을 통해 Teradata 환경에 액세스하는 것은 권장하지 않습니다.
+  Amazon VPC에서 작업을 실행하는 동안 AWS Glue가 사용할 VPC, 서브넷 및 보안 그룹을 식별하거나 생성합니다. 또한 Amazon VPC가 Teradata 인스턴스와 이 위치 간의 네트워크 트래픽을 허용하도록 구성되어 있는지 확인해야 합니다. 작업을 수행하려면 Teradata 클라이언트 포트와 TCP 연결을 설정해야 합니다. Teradata 포트에 대한 자세한 내용은 [ Security Groups for Teradata Vantage](https://docs.teradata.com/r/Teradata-VantageTM-on-AWS-DIY-Installation-and-Administration-Guide/April-2020/Before-Deploying-Vantage-on-AWS-DIY/Security-Groups-and-Ports)을 참조하세요.
+  네트워크 레이아웃에 따라 보안 VPC 연결에는 Amazon VPC 및 기타 네트워킹 서비스를 변경해야 할 수 있습니다. AWS 연결에 대한 자세한 내용은 Teradata 설명서의 [AWS 연결 옵션](https://docs.teradata.com/r/Teradata-VantageCloud-Enterprise/Get-Started/Connecting-Your-Environment/AWS-Connectivity-Options)을 참조하세요.

### AWS Glue Teradata NOS 연결을 구성하는 방법:
<a name="creating-teradata-nos-connection-procedure"></a>

1.  Teradata 구성에서 AWS Glue가 연결할 *teradataUsername* 및 *teradataPassword*를 식별하거나 생성합니다. 자세한 내용은 Teradata 설명서의 [Vantage 보안 개요](https://docs.teradata.com/r/Configuring-Teradata-VantageTM-After-Installation/January-2021/Security-Overview/Vantage-Security-Overview)를 참조하세요.

1.  AWS Secrets Manager에서 Teradata 보안 인증 정보를 사용하여 보안 암호를 생성합니다. AWS Secrets Manager에서 보안 암호를 생성하려면 [AWS Secrets Manager 설명서의 AWS Secrets Manager 보안 암호 생성](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html)에서 제공하는 자습서를 따릅니다. 보안 암호를 생성한 후에는 다음 단계를 위해 보안 암호 이름, *secretName*을 유지합니다.
   +  키/값 페어를 선택하면 값 *teradataUsername*이 포함된 키 사용자 이름에 대한 페어를 생성합니다.
   +  키/값 페어를 선택하면 값 *teradataPassword*가 포함된 키 암호에 대한 페어를 생성합니다.

1.  AWS Glue 콘솔에서 [AWS Glue 연결 추가](https://docs.aws.amazon.com/glue/latest/dg/console-connections.html)의 단계에 따라 연결을 생성합니다. 연결을 생성한 후에는 다음 단계를 위해 연결 이름, *connectionName*을 유지합니다.
   +  **연결 유형**을 선택할 때 Teradata Vantage NOS를 선택합니다.
   +  JDBC URL을 제공할 때는 인스턴스의 URL을 제공하십시오. 또한 JDBC URL에 쉼표로 구분된 특정 연결 매개변수를 하드코딩할 수 있습니다. URL은 다음 형식을 준수해야 합니다. ` jdbc:teradata://teradataHostname/ParameterName=ParameterValue,ParameterName=ParameterValue ` 
   +  지원되는 URL 파라미터는 다음과 같습니다.
     +  `DATABASE` - 기본으로 액세스하는 호스트의 데이터베이스 이름입니다.
     +  `DBS_PORT` - 비표준 포트에서 실행할 때 사용되는 데이터베이스 포트입니다.
   +  **자격 증명 유형**을 선택할 때에는 AWS Secrets Manager을 선택한 다음 **AWS 보안 암호**를 *secretName*으로 설정합니다.

1.  다음과 같은 상황에서는 추가 구성이 필요할 수도 있습니다.
   +  Amazon VPC의 AWS에 호스팅된 Teradata 인스턴스의 경우 Teradata 보안 자격 증명을 정의하는 AWS Glue 연결에 Amazon VPC 연결 정보를 제공해야 합니다. 연결을 만들거나 업데이트할 때 **네트워크 옵션**에서 **VPC**, **서브넷**, **보안 그룹**을 설정합니다.

 AWS Glue Teradata Vantage NOS 연결을 생성한 후에는 연결 방법을 호출하기 전에 다음 단계를 수행해야 합니다.

1.  AWS Glue 작업 권한과 연결된 IAM 역할에 *secretName*을 읽을 수 있는 권한을 부여합니다.

1.  AWS Glue 작업 구성에서 **연결**의 **추가 네트워크 연결**로 *connectionName*을 제공합니다.

## Teradata 테이블에서 읽기
<a name="reading-from-teradata-nos-tables"></a>

### 사전 조건:
<a name="w2aac67c11c24b8c41c17b3"></a>
+  읽으려는 Teradata 테이블. 테이블 이름, *tableName*이 필요합니다.
+  Teradata 환경에는 `staging_fs_url` 옵션인 *stagingFsUrl*에서 지정한 Amazon S3 경로에 대한 쓰기 액세스 권한이 있습니다.
+  AWS Glue 작업과 연결된 IAM 역할은 `staging_fs_url` 옵션에서 지정한 Amazon S3 위치에 대한 쓰기 액세스 권한이 있습니다.
+  인증 정보를 제공하도록 구성된 AWS Glue Teradata NOS 연결입니다. 인증 정보를 구성하는 [AWS Glue Teradata NOS 연결을 구성하는 방법:](#creating-teradata-nos-connection-procedure) 단계를 완료합니다. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

 예제: 

```
teradata_read_table = glueContext.create_dynamic_frame.from_options(
    connection_type= "teradatanos",
    connection_options={
        "connectionName": "connectionName",
        "dbtable": "tableName",
        "staging_fs_url": "stagingFsUrl"
    }
)
```

 SELECT SQL 쿼리에 반환되는 결과를 필터링하는 쿼리를 제공할 수도 있습니다. 쿼리를 구성해야 합니다. dbTable과 쿼리를 모두 구성하면 커넥터가 데이터를 읽지 못합니다. 예제: 

```
teradata_read_query = glueContext.create_dynamic_frame.from_options(
    connection_type="teradatanos",
    connection_options={
        "connectionName": "connectionName",
        "query": "query",
        "staging_fs_url": "stagingFsUrl"
    }
)
```

 또한 Spark DataFrame API를 사용하여 Teradata 테이블에서 읽을 수 있습니다. 예제: 

```
options = {
    "url": "JDBC_URL",
    "dbtable": "tableName",
    "user": "teradataUsername", # or use "username" as key here
    "password": "teradataPassword",
    "staging_fs_url": "stagingFsUrl"
}
teradata_read_table = spark.read.format("teradatanos").option(**options).load()
```

## Teradata 테이블에 쓰기
<a name="writing-to-teradata-nos-tables"></a>

### 사전 조건
<a name="writing-to-teradata-nos-tables-prerequisites"></a>
+  쓰고 싶은 Teradata 테이블인 *tableName*입니다.
+  Teradata 환경에는 `staging_fs_url` 옵션인 *stagingFsUrl*에 의해 지정된 Amazon S3 위치에 대한 읽기 액세스 권한이 있습니다.
+  AWS Glue 작업과 연결된 IAM 역할은 `staging_fs_url` 옵션에서 지정한 Amazon S3 위치에 대한 쓰기 액세스 권한이 있습니다.
+  인증 정보를 제공하도록 구성된 AWS Glue Teradata 연결입니다. [AWS Glue Teradata NOS 연결을 구성하는 방법:](#creating-teradata-nos-connection-procedure)의 단계를 완료하여 인증 정보를 구성합니다. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.

   예제: 

  ```
  teradata_write = glueContext.write_dynamic_frame.from_options(
      frame=dynamicFrame,
      connection_type= "teradatanos",
      connection_options={
          "connectionName": "connectionName", 
          "dbtable": "tableName",
          "staging_fs_url": "stagingFsUrl"
      }
  )
  ```

## Teradata 연결 옵션 참조
<a name="teradata-nos-connection-option-reference"></a>

 **연결 및 작업 옵션:** 
+  `connectionName` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 연결 방법에 인증 및 네트워킹 정보를 제공하도록 구성된 AWS Glue Teradata 연결의 이름입니다.
+  `staging_fs_url` - 필수입니다. 읽기 및 쓰기에 사용됩니다. Amazon S3의 쓰기 가능한 위치로, Teradata에서 읽을 때 언로드된 데이터에 사용되며 Teradata에 쓸 때 Parquet 데이터를 Redshift에 로드하는 데 사용됩니다. S3 버킷이 AWS Glue 작업과 동일한 리전에 있어야 합니다.
+  `dbtable` - 쓰기 시 필수, `query`가 제공되지 않는 한 읽기 전용. 읽기 및 쓰기에 사용됩니다. 연결 방법이 상호 작용할 테이블의 이름.
+  `query` — 읽기에 사용됩니다. Teradata에서 읽을 때 검색해야 하는 내용을 정의하는 SELECT SQL 쿼리입니다. `dbtable` 옵션이 제공된 경우 전달할 수 없습니다.
+  `clean_staging_s3_dir`-선택 사항입니다. 읽기 및 쓰기에 사용됩니다. true인 경우 읽기 또는 쓰기 후 스테이징 Amazon S3 객체를 정리합니다. 기본값은 true입니다.
+  `pre_actions`-선택 사항입니다. 쓰기에 사용됩니다. Spark와 Teradata Vantage 간에 데이터가 전송되기 전에 실행되는 세미콜론으로 구분된 SQL 명령 목록입니다.
+  `post_actions`-선택 사항입니다. 쓰기에 사용됩니다. Spark와 Teradata Vantage 간에 데이터가 전송된 후에 실행되는 세미콜론으로 구분된 SQL 명령 목록입니다.
+  `truncate`-선택 사항입니다. 쓰기에 사용됩니다. true인 경우 커넥터는 덮어쓰기 모드로 쓸 때 테이블을 잘라냅니다. false인 경우 커넥터는 덮어쓰기 모드로 쓸 때 테이블을 삭제합니다. 기본값은 false입니다.
+  `create_table_script`-선택 사항입니다. 쓰기에 사용됩니다. Teradata Vantage에 쓸 때 테이블을 생성하는 SQL 문입니다. 사용자 지정 메타데이터(예: CREATE MULTISET 또는 SET 테이블 또는 기본 인덱스 변경)가 있는 테이블을 생성하려는 경우에 유용합니다. 테이블 스크립트 생성에 사용되는 테이블 이름은 `dbtable` 옵션에 지정된 테이블 이름과 일치해야 합니다.
+  `partition_size_in_mb`-선택 사항입니다. 읽기에 사용됩니다. 스테이징 Amazon S3 객체를 읽는 동안 Spark 파티션의 최대 크기(MB)입니다. 기본값은 128입니다.

 Teradata 노드를 생성할 때 고급 옵션을 제공할 수 있습니다. 이 옵션은 Spark 스크립트에 대한 AWS Glue를 프로그래밍할 때 사용할 수 있는 옵션과 동일합니다.

 [Teradata Vantage 연결](aws-glue-programming-etl-connect-teradata-home.md)을(를) 참조하세요.

 **권한 부여 옵션:** 

 다음은 커넥터가 스테이징 Amazon S3 버킷에 액세스하는 데 사용하는 AWS 계정 자격 증명을 제공하는 데 사용되는 옵션입니다. (1) 권한 부여 옵션을 전혀 제공하지 않고 AWS Glue 실행 역할에서 생성된 임시 자격 증명을 사용하는 옵션, (2) 생성한 권한 부여 객체 `auth_object`를 제공하는 옵션, (3) 장기 자격 증명을 사용하는 `aws_access_key_id and aws_secret_access_key`를 제공하거나, 임시 자격 증명을 사용하는 경우 `aws_access_key`, `aws_secret_access_key`, `aws_session_token`을 제공하는 옵션 중에서 선택할 수 있습니다.
+  `auth_object` – 선택 사항입니다. 스테이징 Amazon S3 버킷에 액세스하는 데 사용됩니다. Teradata 인스턴스에서 생성된 권한 부여 객체 문자열입니다. 제공된 경우 커넥터는 이 권한 부여 객체를 사용하여 스테이징 Amazon S3 버킷에 액세스합니다. 제공되지 않은 경우 `aws_access_key_id` 및 `aws_secret_access_key`도 제공되지 않았으면 커넥터가 AWS Glue 실행 역할에서 임시 자격 증명이 검색하여 사용합니다. 이 권한 부여 객체와 연결된 AWS 계정은 AWS Glue 작업 및 스테이징 Amazon S3 버킷과 동일한 리전에 있거나 교차 계정 신뢰로 구성되어야 합니다.
+  `aws_access_key_id` – 선택 사항입니다. 스테이징 Amazon S3 버킷에 액세스하는 데 사용됩니다. AWS 계정 보안 자격 증명의 일부입니다. `auth_object`가 제공되지 않고 `aws_access_key_id`가 `aws_secret_access_key`와 함께 제공되는 경우 커넥터는 이들을 사용하여 스테이징 Amazon S3 버킷에 액세스합니다. 이 액세스 키와 연결된 AWS 계정은 AWS Glue 작업 및 스테이징 Amazon S3 버킷과 동일한 리전에 있거나 교차 계정 신뢰로 구성되어야 합니다.
+  `aws_secret_access_key` – 선택 사항입니다. 스테이징 Amazon S3 버킷에 액세스하는 데 사용됩니다. AWS 계정 보안 자격 증명의 일부입니다. `auth_object`가 제공되지 않고 `aws_secret_access_key`가 `aws_access_key_id`와 함께 제공되는 경우 커넥터는 이들을 사용하여 스테이징 Amazon S3 버킷에 액세스합니다. 이 비밀 키와 연결된 AWS 계정은 AWS Glue 작업 및 스테이징 Amazon S3 버킷과 동일한 리전에 있거나 교차 계정 신뢰로 구성되어야 합니다.
+  `aws_session_token` – 선택 사항입니다. 스테이징 Amazon S3 버킷에 액세스하는 데 사용됩니다. 임시 AWS 계정 보안 자격 증명의 일부입니다. `aws_access_key_id` 및 `aws_secret_access_key`와 함께 제공되어야 합니다.

## AWS Glue 시각적 ETL UI에서 옵션 제공
<a name="teradata-nos-connection-option-visual-etl-ui"></a>

 시각적 ETL 작업 UI에서 위의 옵션을 모두 제공할 수 있습니다. connectionName 옵션의 경우 Teradata Vantage NOS 연결 드롭다운 목록에서 선택해야 합니다. 다른 모든 옵션의 경우 사용자 지정 Teradata Vantage NOS 속성을 통해 키/값 페어로 제공해야 합니다.

![\[창에 선택된 Teradata NOS Vantage 연결이 표시됩니다.\]](http://docs.aws.amazon.com/ko_kr/glue/latest/dg/images/teradata-nos-vantage-connection-options.png)


# 수직 연결
<a name="aws-glue-programming-etl-connect-vertica-home"></a>

AWS Glue for Spark를 사용하여 AWS Glue 4.0 이상 버전에서 Vertica의 테이블에서 읽고 쓸 수 있습니다. SQL 쿼리를 사용하여 Vertica에서 읽을 내용을 정의할 수 있습니다. AWS Glue 연결을 통해 AWS Secrets Manager에 저장된 사용자 이름 및 암호 보안 인증 정보를 사용하여 Vertica에 연결할 수 있습니다.

Vertica에 대한 자세한 내용은 [Vertica 설명서](https://www.vertica.com/docs/9.3.x/HTML/Content/Authoring/UsingVerticaOnAWS/UsingVerticaOnAWS.htm)를 참조하십시오.

## Vertica 연결 구성
<a name="aws-glue-programming-etl-connect-vertica-configure"></a>

AWS Glue에서 Vertica에 연결하려면 AWS Secrets Manager 보안 암호에서 Vertica 보안 인증 정보를 생성하고 저장한 다음 해당 보안 암호를 Vertica AWS Glue 연결에 연결해야 합니다. Vertica 인스턴스가 Amazon VPC에 있는 경우 AWS Glue Vertica 연결에 네트워킹 옵션도 제공해야 합니다. 데이터베이스에서 읽고 쓸 때 임시 스토리지로 이용할 Amazon S3 버킷이나 폴더가 필요합니다.

AWS Glue에서 Vertica에 연결하려면 몇 가지 필수 조건이 필요합니다.
+ *tempS3Path*에서 참조하여 데이터베이스에서 읽고 쓸 때 임시 스토리지로 사용하는 Amazon S3 버킷 또는 폴더.
**참고**  
AWS Glue 작업 데이터 미리 보기의 Vertica를 사용하는 경우 임시 파일은 *tempS3Path*에서 자동으로 제거되지 않을 수 있습니다. 임시 파일을 제거하려면 **데이터 미리 보기** 창에서 **세션 종료**를 선택하여 데이터 미리 보기 세션을 바로 종료합니다.  
데이터 미리 보기 세션이 바로 종료되도록 보장할 수 없는 경우 이전 데이터를 제거하도록 Amazon S3 수명 주기 구성을 설정하는 것이 좋습니다. 최대 작업 런타임에 여백을 더한 기준으로 49시간이 지난 데이터는 제거하는 것이 좋습니다. Amazon S3 수명 주기 구성에 대한 자세한 내용은 Amazon S3 설명서에서 [스토리지 수명 주기 관리](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html)를 참조하십시오.
+ Amazon S3 경로에 대한 적절한 권한이 있는 IAM 정책을 AWS Glue 작업 역할과 연결할 수 있습니다.
+ Vertica 인스턴스가 Amazon VPC에 있는 경우, 퍼블릭 인터넷을 통과하는 트래픽 없이 AWS Glue 작업이 Vertica 인스턴스와 통신할 수 있도록 Amazon VPC를 구성하십시오.

  Amazon VPC에서 AWS Glue가 작업을 실행하는 동안 사용할 **VPC**, **서브넷**, **보안 그룹**을 식별하거나 생성합니다. 또한 Vertica 인스턴스와 이 위치 간의 네트워크 트래픽을 허용하도록 Amazon VPC를 구성해야 합니다. 작업을 수행하려면 Vertica 클라이언트 포트(기본값 5433)와의 TCP 연결을 설정해야 합니다. 네트워크 레이아웃에 따라 보안 그룹 규칙, 네트워크 ACL, NAT 게이트웨이 및 피어링 연결을 변경해야 할 수도 있습니다.

그런 다음 Vertica와 함께 사용할 AWS Glue를 구성할 수 있습니다.

**Vertica에 대한 연결 구성하는 방법:**

1. AWS Secrets Manager에서 Vertica 보안 인증 정보, *verticaUsername*, *verticaPassword*을 사용하여 암호를 생성합니다. Secrets Manager에서 보안 암호를 생성하려면 AWS Secrets Manager 설명서의 [Create an AWS Secrets Manager secret](https://docs.aws.amazon.com//secretsmanager/latest/userguide/create_secret.html)에서 제공하는 자습서를 따릅니다. 보안 암호를 생성한 후에는 다음 단계를 위해 보안 암호 이름, *secretName*을 유지합니다.
   + **키/값 페어**를 선택하면 값 *verticaUsername*이 포함된 키 `user`에 대한 페어를 생성합니다.
   + **키/값 페어**를 선택하면 값 *verticaPassword*이 포함된 키 `password`에 대한 페어를 생성합니다.

1. AWS Glue 콘솔에서 [AWS Glue 연결 추가](console-connections.md)의 단계에 따라 연결을 생성합니다. 연결을 생성한 후에는 다음 단계를 위해 연결 이름, *connectionName*을 유지합니다.
   + **연결 유형**을 선택할 때 Vertica를 선택합니다.
   + **Vertica 호스트**를 선택할 때 Vertica 설치의 호스트 이름을 제공합니다.
   + **Vertica 포트**를 선택하면 해당 포트를 통해 Vertica 설치를 사용할 수 있습니다.
   + **AWS 보안 암호**를 선택할 때 *secretName*을 입력합니다.

1. 다음과 같은 상황에서는 추가 구성이 필요할 수도 있습니다.
   + 

     Amazon VPC에서 AWS에 호스팅된 Vertica 인스턴스의 경우
     + Vertica 보안 보안 인증 정보를 정의하는 Amazon VPC 연결 정보를 AWS Glue 연결에 제공하십시오. 연결을 만들거나 업데이트할 때 **네트워크 옵션**에서 **VPC**, **서브넷** 및 **보안 그룹**을 설정합니다.

AWS Glue Vertica 연결을 생성한 후에는 연결 방법을 호출하기 전에 다음 단계를 수행해야 합니다.
+ AWS Glue 작업과 권한과 연결된 IAM 역할을 *tempS3Path*에 부여합니다.
+ AWS Glue 작업과 연결된 IAM 역할에 *secretName*을 읽을 수 있는 권한을 부여합니다.
+ AWS Glue 작업 구성에서 **추가 네트워크 연결**로 *connectionName*을 제공합니다.

## Vertica에서 읽는 중
<a name="aws-glue-programming-etl-connect-vertica-read"></a>

**사전 조건 ** 
+ 읽으려는 Vertica 테이블. Vertica 데이터베이스 이름인 *dbName*과 테이블 이름인 *tableName*이 필요합니다.
+ 인증 정보를 제공하도록 구성된 AWS Glue Vertica 연결. 인증 정보를 구성하려면 앞 절차인 *Vertica에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.
+ 앞서 언급한 임시 스토리지로 사용할 Amazon S3 버킷 또는 폴더. *tempS3Path*라는 이름이 필요합니다. `s3a` 프로토콜을 사용하여 이 위치에 연결해야 합니다.

예: 

```
dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="vertica",
    connection_options={
        "connectionName": "connectionName",
        "staging_fs_url": "s3a://tempS3Path",
        "db": "dbName",
        "table": "tableName",
    }
)
```

SELECT SQL 쿼리를 제공하여 DynamicFrame에 반환되는 결과를 필터링할 수도 있고 여러 테이블의 데이터 세트에 액세스할 수도 있습니다.

예:

```
dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="vertica",
    connection_options={
        "connectionName": "connectionName",
        "staging_fs_url": "s3a://tempS3Path",
        "db": "dbName",
        "query": "select * FROM tableName",
    },
)
```

## Vertica 테이블에 쓰기
<a name="aws-glue-programming-etl-connect-vertica-write"></a>

이 예제에서는 기존 DynamicFrame, *dynamicFrame*의 정보를 Vertica에 씁니다. 테이블에 이미 정보가 있는 경우 AWS Glue는 DynamicFrame의 데이터를 추가합니다.

**사전 조건 ** 
+ 쓰려는 현재 또는 원하는 테이블 이름, *tableName*. 또한 해당하는 Vertica 데이터베이스 이름인 *dbName*도 필요합니다.
+ 인증 정보를 제공하도록 구성된 AWS Glue Vertica 연결. 인증 정보를 구성하려면 앞 절차인 *Vertica에 대한 연결을 구성하는 방법*의 단계를 완료하십시오. AWS Glue 연결의 이름인 *connectionName*이 필요합니다.
+ 앞서 언급한 임시 스토리지로 사용할 Amazon S3 버킷 또는 폴더. *tempS3Path*라는 이름이 필요합니다. `s3a` 프로토콜을 사용하여 이 위치에 연결해야 합니다.

예: 

```
glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="vertica",
    connection_options={
        "connectionName": "connectionName",
        "staging_fs_url": "s3a://tempS3Path",
        "db": "dbName",
        "table": "tableName",
    }
)
```

## Vertica 연결 옵션 참조
<a name="aws-glue-programming-etl-connect-vertica-reference"></a>
+ `connectionName` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 연결 방법에 인증 및 네트워킹 정보를 제공하도록 구성된 AWS Glue Vertica 연결의 이름입니다.
+ `db` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 연결 방법이 상호 작용하는 Vertica의 데이터베이스 이름.
+ `dbSchema` - 테이블을 식별하는 데 필요한 경우 필요합니다. 읽기 및 쓰기에 사용됩니다. 기본값: `public`. 연결 방법이 상호 작용할 스키마의 이름.
+ `table` - 쓰기 시 필수, `query`가 제공되지 않는 한 읽기 전용. 읽기 및 쓰기에 사용됩니다. 연결 방법이 상호 작용할 테이블의 이름.
+ `query` — 읽기에 사용됩니다. Teradata에서 읽을 때 검색해야 하는 내용을 정의하는 SELECT SQL 쿼리입니다.
+ `staging_fs_url` - 필수입니다. 읽기 및 쓰기에 사용됩니다. 유효한 값: `s3a` URL. 임시 스토리지로 사용할 Amazon S3 버킷 또는 폴더의 URL입니다.

## Spark용 AWS Glue 5.0의 ETL에 대한 DataFrame 옵션
<a name="aws-glue-programming-etl-connect-dataframe"></a>

DataFrame은 이름이 지정된 열로 구성되는 데이터세트이며, 테이블과 비슷한 기능적 스타일(맵/줄임/필터 등) 작업과 SQL 작업(선택, 계획, 집계)을 지원합니다.

Glue에서 지원하는 데이터 소스에 대한 DataFrame을 생성하려면 다음이 필요합니다.
+ 데이터 소스 커넥터 `ClassName`
+ 데이터 소스 연결 `Options`

마찬가지로 Glue에서 지원하는 데이터 싱크에 DataFrame을 작성하려면 동일한 작업이 필요합니다.
+ 데이터 싱크 커넥터 `ClassName`
+ 데이터 싱크 연결 `Options`

작업 북마크와 같은 AWS Glue 기능 및 `connectionName`과 같은 DynamicFrame 옵션은 DataFrame에서 지원되지 않습니다. DataFrame 및 지원되는 작업에 대한 자세한 내용은 [DataFrame](https://spark.apache.org/docs/3.5.2/api/python/reference/pyspark.sql/dataframe.html)용 Spark 설명서를 참조하세요.

### 커넥터 ClassName 지정
<a name="aws-glue-programming-etl-connect-dataframe-classname"></a>

데이터 소스/싱크의 `ClassName`을 지정하려면 `.format` 옵션을 사용하여 데이터 소스/싱크를 정의하는 해당 커넥터 `ClassName`을 제공합니다.

**JDBC 커넥터**  
JDBC 커넥터의 경우 `.format` 옵션의 값으로 `jdbc`를 지정하고 `driver` 옵션에 JDBC 드라이버 `ClassName`을 제공합니다.

```
df = spark.read.format("jdbc").option("driver", "<DATA SOURCE JDBC DRIVER CLASSNAME>")...

df.write.format("jdbc").option("driver", "<DATA SINK JDBC DRIVER CLASSNAME>")...
```

다음 표에는 DataFrames용 AWS Glue에서 지원되는 데이터 소스의 JDBC 드라이버 `ClassName`이 나열되어 있습니다.

| 데이터 소스 | Driver ClassName | 
| --- |--- |
| PostgreSQL | org.postgresql.Driver | 
| Oracle | oracle.jdbc.driver.OracleDriver | 
| SQLServer | com.microsoft.sqlserver.jdbc.SQLServerDriver | 
| MySQL | com.mysql.jdbc.Driver | 
| SAPHana | com.sap.db.jdbc.Driver | 
| Teradata | com.teradata.jdbc.TeraDriver | 

**Spark 커넥터**  
Spark 커넥터의 경우 커넥터의 `ClassName`을 `.format` 옵션 값으로 지정합니다.

```
df = spark.read.format("<DATA SOURCE CONNECTOR CLASSNAME>")...

df.write.format("<DATA SINK CONNECTOR CLASSNAME>")...
```

다음 표에는 DataFrames용 AWS Glue에서 지원되는 데이터 소스의 Spark 커넥터 `ClassName`이 나열되어 있습니다.

| 데이터 소스 | ClassName | 
| --- |--- |
| MongoDB/DocumentDB | glue.spark.mongodb | 
| Redshift | io.github.spark\$1redshift\$1community.spark.redshift | 
| AzureCosmos | cosmos.oltp | 
| AzureSQL | com.microsoft.sqlserver.jdbc.spark | 
| BigQuery | com.google.cloud.spark.bigquery | 
| OpenSearch | org.opensearch.spark.sql | 
| Snowflake | net.snowflake.spark.snowflake | 
| Vertica | com.vertica.spark.datasource.VerticaSource | 

### 연결 옵션 지정
<a name="aws-glue-programming-etl-connect-dataframe-connection-options"></a>

데이터 소스/싱크에 대한 연결의 `Options`를 지정하려면 `.option(<KEY>, <VALUE>)`을 사용하여 개별 옵션을 제공하거나 `.options(<MAP>)`를 사용하여 여러 옵션을 키-값 맵으로 제공합니다.

각 데이터 소스/싱크는 자체 연결 `Options` 세트를 지원합니다. 사용 가능한 `Options`에 대한 자세한 내용은 다음 표에 나열된 특정 데이터 소스/싱크 Spark 커넥터의 퍼블릭 설명서를 참조하세요.
+ [JDBC](https://spark.apache.org/docs/3.5.2/sql-data-sources-jdbc.html)
+ [MongoDB/DocumentDB](https://www.mongodb.com/docs/spark-connector/v10.4/)
+ [Redshift](https://docs.aws.amazon.com/redshift/latest/mgmt/spark-redshift-connector.html)
+ [AzureCosmos](https://github.com/Azure/azure-cosmosdb-spark)
+ [AzureSQL](https://learn.microsoft.com/en-us/sql/connect/spark/connector?view=sql-server-ver16)
+ [BigQuery](https://cloud.google.com/dataproc/docs/tutorials/bigquery-connector-spark-example)
+ [OpenSearch](https://github.com/opensearch-project/opensearch-hadoop/blob/main/USER_GUIDE.md#apache-spark)
+ [Snowflake](https://docs.snowflake.com/en/user-guide/spark-connector-use#setting-configuration-options-for-the-connector)
+ [Vertica](https://github.com/vertica/spark-connector)

### 예제
<a name="aws-glue-programming-etl-connect-dataframe-examples"></a>

다음 예에서는 PostgreSQL에서 읽고 SnowFlake에 씁니다.

**Python**  
예제:

```
from awsglue.context import GlueContext
from pyspark.sql import SparkSession

spark = SparkSession.builder.getOrCreate()

dataSourceClassName = "jdbc"
dataSourceOptions = {
  "driver": "org.postgresql.Driver",
  "url": "<url>",
  "user": "<user>",
  "password": "<password>",
  "dbtable": "<dbtable>",
}

dataframe = spark.read.format(className).options(**options).load()

dataSinkClassName = "net.snowflake.spark.snowflake"
dataSinkOptions = {
  "sfUrl": "<url>",
  "sfUsername": "<username>",
  "sfPassword": "<password>",
  "sfDatabase" -> "<database>",                              
  "sfSchema" -> "<schema>",                       
  "sfWarehouse" -> "<warehouse>"  
}

dataframe.write.format(dataSinkClassName).options(**dataSinkOptions).save()
```

**Scala**  
예제:

```
import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder().getOrCreate()

val dataSourceClassName = "jdbc"
val dataSourceOptions = Map(
  "driver" -> "org.postgresql.Driver",
  "url" -> "<url>",
  "user" -> "<user>",
  "password" -> "<password>",
  "dbtable" -> "<dbtable>"
)

val dataframe = spark.read.format(dataSourceClassName).options(dataSourceOptions).load()

val dataSinkClassName = "net.snowflake.spark.snowflake"
val dataSinkOptions = Map(
  "sfUrl" -> "<url>",
  "sfUsername" -> "<username>",
  "sfPassword" -> "<password>",
  "sfDatabase" -> "<database>",
  "sfSchema" -> "<schema>",
  "sfWarehouse" -> "<warehouse>"
)

dataframe.write.format(dataSinkClassName).options(dataSinkOptions).save()
```

## 사용자 정의 및 AWS Marketplace 연결 유형 값
<a name="aws-glue-programming-etl-connect-market"></a>

여기에는 다음이 포함됩니다.
+ `"connectionType": "marketplace.athena"`: Amazon Athena 데이터 스토어에 대한 연결을 지정합니다. 연결은 AWS Marketplace의 커넥터를 사용합니다.
+ `"connectionType": "marketplace.spark"`: Apache Spark 데이터 스토어에 대한 연결을 지정합니다. 연결은 AWS Marketplace의 커넥터를 사용합니다.
+ `"connectionType": "marketplace.jdbc"`: JDBC 데이터 스토어에 대한 연결을 지정합니다. 연결은 AWS Marketplace의 커넥터를 사용합니다.
+ `"connectionType": "custom.athena"`: Amazon Athena 데이터 스토어에 대한 연결을 지정합니다. 연결은 AWS Glue Studio에 업로드하는 사용자 지정 커넥터를 사용합니다.
+ `"connectionType": "custom.spark"`: Apache Spark 데이터 스토어에 대한 연결을 지정합니다. 연결은 AWS Glue Studio에 업로드하는 사용자 지정 커넥터를 사용합니다.
+ `"connectionType": "custom.jdbc"`: JDBC 데이터 스토어에 대한 연결을 지정합니다. 연결은 AWS Glue Studio에 업로드하는 사용자 지정 커넥터를 사용합니다.

### custom.jdbc 또는 marketplace.jdbc 유형에 대한 연결 옵션
<a name="marketplace-jdbc-connect-options"></a>
+ `className` - 문자열, 필수, 드라이버 클래스 이름입니다.
+ `connectionName` - 문자열, 필수, 커넥터와 연결된 연결 이름입니다.
+ `url`- 문자열, 필수, 데이터 원본에 대한 연결을 구축하는 데 사용되는 자리 표시자(`${}`)가 있는 JDBC URL입니다. 자리 표시자 `${secretKey}`는 AWS Secrets Manager에서 같은 이름의 보안 암호로 대체됩니다. URL 구성에 대한 자세한 내용은 데이터 스토어 설명서를 참조하세요.
+ `secretId` 또는 `user/password` – 문자열, 필수, URL에 대한 자격 증명을 검색하는 데 사용됩니다.
+ `dbTable` 또는 `query` - 문자열, 필수, 데이터를 가져올 테이블 또는 SQL 쿼리입니다. `dbTable` 또는 `query`을 지정할 수 있지만 둘 다 함께 지정할 수는 없습니다.
+ `partitionColumn`- 문자열, 선택 사항, 파티셔닝에 사용되는 정수 열의 이름입니다. 이 옵션은 `lowerBound`, `upperBound` 및 `numPartitions`에 포함되는 경우에만 작동합니다. 이 옵션은 Spark SQL JDBC 리더에서와 같은 방식으로 작동합니다. 자세한 내용은 *Apache Spark SQL, DataFrames and Datasets Guide*의 [JDBC To Other Databases](https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html)를 참조하세요.

  `lowerBound` 및 `upperBound` 값은 테이블의 행을 필터링하는 것이 아니라 파티션 스트라이드를 결정하는 데 사용됩니다. 테이블의 모든 행이 분할되어 반환됩니다.
**참고**  
테이블 이름 대신 쿼리를 사용하는 경우 쿼리가 지정된 분할 조건에서 작동하는지 확인해야 합니다. 예:   
쿼리 포맷이 `"SELECT col1 FROM table1"`이면 파티션 열을 사용하는 쿼리 끝에 `WHERE` 절을 추가하여 쿼리를 테스트합니다.
쿼리 포맷이 "`SELECT col1 FROM table1 WHERE col2=val"`이면 `AND`와 파티션 열을 사용하는 표현식으로 `WHERE` 절을 확장하여 쿼리를 테스트합니다.
+ `lowerBound` - 정수, 선택 사항, 파티션 스트라이드를 결정하는 데 사용되는 `partitionColumn`의 최소값입니다.
+ `upperBound` - 정수, 선택 사항, 파티션 스트라이드를 결정하는 데 사용되는 `partitionColumn`의 최대값입니다.
+ `numPartitions`- 정수, 선택 사항, 파티션 수입니다. 이 값은 `lowerBound`(포함) 및 `upperBound`(배타)와 함께 `partitionColumn`을 분할하는 데 사용되는 생성된 `WHERE` 절 표현에 대한 파티션 스트라이드를 형성합니다.
**중요**  
파티션이 너무 많으면 외부 데이터베이스 시스템에 문제가 발생할 수 있으므로 파티션 수에 주의합니다.
+ `filterPredicate` - 문자열, 선택 사항, 소스에서 데이터를 필터링하기 위한 추가 조건 절입니다. 예: 

  ```
  BillingCity='Mountain View'
  ```

  *테이블* 이름 대신 *쿼리*를 사용하는 경우 쿼리가 지정된 `filterPredicate`에서 작동하는지 검증해야 합니다. 예: 
  + 쿼리 포맷이 `"SELECT col1 FROM table1"`이면 필터 조건자를 사용하는 쿼리 끝에 `WHERE` 절을 추가하여 쿼리를 테스트합니다.
  + 쿼리 포맷이 `"SELECT col1 FROM table1 WHERE col2=val"`이면 `AND`로 `WHERE` 절을 확장하고 필터 조건자를 사용하는 표현식을 사용하여 쿼리를 테스트합니다.
+ `dataTypeMapping` – 딕셔너리, 선택 사항, **JDBC** 데이터 유형에서 **Glue** 데이터 유형으로의 매핑을 구축하는 사용자 정의 데이터 유형 매핑입니다. 예를 들어 `"dataTypeMapping":{"FLOAT":"STRING"}` 옵션은 드라이버의 `ResultSet.getString()` 메서드를 호출하여 JDBC 유형 `FLOAT`의 데이터 필드를 Java `String` 유형으로 매핑하고 이를 AWS Glue 레코드를 구축하는 데 사용합니다. `ResultSet` 객체는 각 드라이버에 의해 구현되므로 동작은 사용하는 드라이버에 따라 다릅니다. 드라이버가 변환을 수행하는 방법을 이해하려면 JDBC 드라이버에 대한 설명서를 참조하세요.
+ 현재 지원되는 AWS Glue 데이터 유형은 다음과 같습니다.
  + DATE
  + STRING
  + TIMESTAMP
  + INT
  + FLOAT
  + LONG
  + BIGDECIMAL
  + BYTE
  + SHORT
  + DOUBLE

   지원되는 JDBC 데이터 유형은 [Java8 java.sql.types](https://docs.oracle.com/javase/8/docs/api/java/sql/Types.html)입니다.

  기본 데이터 유형 매핑(JDBC에서 AWS Glue로)은 다음과 같습니다.
  +  DATE -> DATE
  +  VARCHAR -> STRING
  +  CHAR -> STRING
  +  LONGNVARCHAR -> STRING
  +  TIMESTAMP -> TIMESTAMP
  +  INTEGER -> INT
  +  FLOAT -> FLOAT
  +  REAL -> FLOAT
  +  BIT -> BOOLEAN
  +  BOOLEAN -> BOOLEAN
  +  BIGINT -> LONG
  +  DECIMAL -> BIGDECIMAL
  +  NUMERIC -> BIGDECIMAL
  +  TINYINT -> SHORT
  +  SMALLINT -> SHORT
  +  DOUBLE -> DOUBLE

  옵션 `dataTypeMapping`과 함께 사용자 정의 데이터 유형 매핑을 사용하는 경우 기본 데이터 유형 매핑을 재정의할 수 있습니다. `dataTypeMapping` 옵션에 나열된 JDBC 데이터 유형만 영향을 받습니다. 기본 매핑은 다른 모든 JDBC 데이터 유형에 사용됩니다. 필요한 경우 추가 JDBC 데이터 유형에 대한 매핑을 추가할 수 있습니다. JDBC 데이터 유형이 기본 매핑이나 사용자 지정 매핑에 포함되지 않은 경우 데이터 유형은 기본값으로 AWS Glue `STRING` 데이터 유형으로 변환됩니다.

다음 Python 코드 예제는 AWS Marketplace JDBC 드라이버를 사용하여 JDBC 데이터베이스에서 읽는 방법을 보여줍니다. 데이터베이스에서 읽고 S3 위치에 쓰는 방법을 보여줍니다.

```
    import sys
    from awsglue.transforms import *
    from awsglue.utils import getResolvedOptions
    from pyspark.context import SparkContext
    from awsglue.context import GlueContext
    from awsglue.job import Job
     
    ## @params: [JOB_NAME]
    args = getResolvedOptions(sys.argv, ['JOB_NAME'])
     
    sc = SparkContext()
    glueContext = GlueContext(sc)
    spark = glueContext.spark_session
    job = Job(glueContext)
    job.init(args['JOB_NAME'], args)
    ## @type: DataSource
    ## @args: [connection_type = "marketplace.jdbc", connection_options = 
     {"dataTypeMapping":{"INTEGER":"STRING"},"upperBound":"200","query":"select id, 
       name, department from department where id < 200","numPartitions":"4",
       "partitionColumn":"id","lowerBound":"0","connectionName":"test-connection-jdbc"},
        transformation_ctx = "DataSource0"]
    ## @return: DataSource0
    ## @inputs: []
    DataSource0 = glueContext.create_dynamic_frame.from_options(connection_type = 
      "marketplace.jdbc", connection_options = {"dataTypeMapping":{"INTEGER":"STRING"},
      "upperBound":"200","query":"select id, name, department from department where 
       id < 200","numPartitions":"4","partitionColumn":"id","lowerBound":"0",
       "connectionName":"test-connection-jdbc"}, transformation_ctx = "DataSource0")
    ## @type: ApplyMapping
    ## @args: [mappings = [("department", "string", "department", "string"), ("name", "string",
      "name", "string"), ("id", "int", "id", "int")], transformation_ctx = "Transform0"]
    ## @return: Transform0
    ## @inputs: [frame = DataSource0]
    Transform0 = ApplyMapping.apply(frame = DataSource0, mappings = [("department", "string",
      "department", "string"), ("name", "string", "name", "string"), ("id", "int", "id", "int")], 
       transformation_ctx = "Transform0")
    ## @type: DataSink
    ## @args: [connection_type = "s3", format = "json", connection_options = {"path": 
     "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0"]
    ## @return: DataSink0
    ## @inputs: [frame = Transform0]
    DataSink0 = glueContext.write_dynamic_frame.from_options(frame = Transform0, 
      connection_type = "s3", format = "json", connection_options = {"path": 
      "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0")
    job.commit()
```

### custom.athena 또는 marketplace.athena 유형에 대한 연결 옵션
<a name="marketplace-athena-connect-options"></a>
+ `className` - 문자열, 필수, 드라이버 클래스 이름입니다. Athena-CloudWatch 커넥터를 사용하는 경우 이 파라미터 값은 클래스 이름의 접두사(예: `"com.amazonaws.athena.connectors"`)입니다. Athena-CloudWatch 커넥터는 메타데이터 핸들러와 레코드 핸들러의 두 가지 클래스로 구성됩니다. 여기에 공통 접두사를 제공하면 API가 해당 접두사를 기반으로 올바른 클래스를 로드합니다.
+ `tableName` - 문자열, 필수, 읽을 CloudWatch 로그 스트림의 이름입니다. 이 코드 조각은 특수 보기 이름 `all_log_streams`을 사용합니다. 즉, 반환된 동적 데이터 프레임에는 로그 그룹의 모든 로그 스트림 데이터가 포함됩니다.
+ `schemaName` - 문자열, 필수, 읽을 CloudWatch 로그 그룹의 이름입니다. 예를 들어 `/aws-glue/jobs/output`입니다.
+ `connectionName` - 문자열, 필수, 커넥터와 연결된 연결 이름입니다.

이 커넥터에 대한 추가 옵션은 GitHub의 [Amazon Athena CloudWatch 커넥터 README](https://github.com/awslabs/aws-athena-query-federation/tree/master/athena-cloudwatch)를 참조하세요.

다음 Python 코드 예제는 AWS Marketplace 커넥터를 사용하여 Athena 데이터 스토어에서 읽는 방법을 보여줍니다. Athena에서 읽고 S3 위치에 쓰는 방법을 보여줍니다.

```
    import sys
    from awsglue.transforms import *
    from awsglue.utils import getResolvedOptions
    from pyspark.context import SparkContext
    from awsglue.context import GlueContext
    from awsglue.job import Job
     
    ## @params: [JOB_NAME]
    args = getResolvedOptions(sys.argv, ['JOB_NAME'])
     
    sc = SparkContext()
    glueContext = GlueContext(sc)
    spark = glueContext.spark_session
    job = Job(glueContext)
    job.init(args['JOB_NAME'], args)
    ## @type: DataSource
    ## @args: [connection_type = "marketplace.athena", connection_options = 
     {"tableName":"all_log_streams","schemaName":"/aws-glue/jobs/output",
      "connectionName":"test-connection-athena"}, transformation_ctx = "DataSource0"]
    ## @return: DataSource0
    ## @inputs: []
    DataSource0 = glueContext.create_dynamic_frame.from_options(connection_type = 
      "marketplace.athena", connection_options = {"tableName":"all_log_streams",,
      "schemaName":"/aws-glue/jobs/output","connectionName":
      "test-connection-athena"}, transformation_ctx = "DataSource0")
    ## @type: ApplyMapping
    ## @args: [mappings = [("department", "string", "department", "string"), ("name", "string",
      "name", "string"), ("id", "int", "id", "int")], transformation_ctx = "Transform0"]
    ## @return: Transform0
    ## @inputs: [frame = DataSource0]
    Transform0 = ApplyMapping.apply(frame = DataSource0, mappings = [("department", "string",
      "department", "string"), ("name", "string", "name", "string"), ("id", "int", "id", "int")], 
       transformation_ctx = "Transform0")
    ## @type: DataSink
    ## @args: [connection_type = "s3", format = "json", connection_options = {"path": 
     "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0"]
    ## @return: DataSink0
    ## @inputs: [frame = Transform0]
    DataSink0 = glueContext.write_dynamic_frame.from_options(frame = Transform0, 
      connection_type = "s3", format = "json", connection_options = {"path": 
      "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0")
    job.commit()
```

### custom.spark 또는 marketplace.spark 유형에 대한 연결 옵션
<a name="marketplace-spark-connect-options"></a>
+ `className` - 문자열, 필수, 커넥터 클래스 이름입니다.
+ `secretId` - 문자열, 선택 사항, 커넥터 연결에 대한 자격 증명을 검색하는 데 사용됩니다.
+ `connectionName` - 문자열, 필수, 커넥터와 연결된 연결 이름입니다.
+ 다른 옵션은 데이터 스토어에 따라 다릅니다. 예를 들어 OpenSearch 구성 옵션은 [Apache Hadoop용 Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/hadoop/current/configuration.html) 설명서에 설명된 대로 접두사 `es`로 시작합니다. Snowflake에 대한 Spark 연결은 *Connecting to Snowflake* 가이드의 [Using the Spark Connector](https://docs.snowflake.com/en/user-guide/spark-connector-use.html)에 설명된 대로 `sfUser` 및 `sfPassword`와 같은 옵션을 사용합니다.

다음 Python 코드 예제는 `marketplace.spark` 연결을 사용하여 OpenSearch 데이터 스토어에서 읽는 방법을 보여줍니다.

```
    import sys
    from awsglue.transforms import *
    from awsglue.utils import getResolvedOptions
    from pyspark.context import SparkContext
    from awsglue.context import GlueContext
    from awsglue.job import Job
     
    ## @params: [JOB_NAME]
    args = getResolvedOptions(sys.argv, ['JOB_NAME'])
     
    sc = SparkContext()
    glueContext = GlueContext(sc)
    spark = glueContext.spark_session
    job = Job(glueContext)
    job.init(args['JOB_NAME'], args)
    ## @type: DataSource
    ## @args: [connection_type = "marketplace.spark", connection_options = {"path":"test",
      "es.nodes.wan.only":"true","es.nodes":"https://<AWS endpoint>",
      "connectionName":"test-spark-es","es.port":"443"}, transformation_ctx = "DataSource0"]
    ## @return: DataSource0
    ## @inputs: []
    DataSource0 = glueContext.create_dynamic_frame.from_options(connection_type = 
      "marketplace.spark", connection_options = {"path":"test","es.nodes.wan.only":
      "true","es.nodes":"https://<AWS endpoint>","connectionName":
      "test-spark-es","es.port":"443"}, transformation_ctx = "DataSource0")
    ## @type: DataSink
    ## @args: [connection_type = "s3", format = "json", connection_options = {"path": 
         "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0"]
    ## @return: DataSink0
    ## @inputs: [frame = DataSource0]
    DataSink0 = glueContext.write_dynamic_frame.from_options(frame = DataSource0, 
       connection_type = "s3", format = "json", connection_options = {"path": 
       "s3://<S3 path>/", "partitionKeys": []}, transformation_ctx = "DataSink0")
    job.commit()
```

## 일반 옵션
<a name="aws-glue-programming-etl-connect-general-options"></a>

이 섹션의 옵션은 `connection_options`로 제공되지만 특별히 하나의 커넥터에만 적용되지는 않습니다.

다음 파라미터는 보통 북마크를 구성할 때 사용됩니다. Amazon S3 또는 JDBC 워크플로에 적용될 수도 있습니다. 자세한 내용은 [작업 북마크 사용](programming-etl-connect-bookmarks.md) 섹션을 참조하세요.
+ `jobBookmarkKeys` - 열 이름의 배열입니다.
+ `jobBookmarkKeysSortOrder` - 정렬 순서에 따라 값을 비교하는 방법을 정의하는 문자열입니다. 유효한 값: `"asc"`, `"desc"`.
+ `useS3ListImplementation` - Amazon S3 버킷 콘텐츠를 나열할 때 메모리 성능을 관리하는 데 사용됩니다. 자세한 내용은 [Optimize memory management in AWS Glue](https://aws.amazon.com/blogs/big-data/optimize-memory-management-in-aws-glue/)를 참조하세요.

# AWS Glue for Spark에서 입력 및 출력의 데이터 형식 옵션
<a name="aws-glue-programming-etl-format"></a>

이 페이지는 AWS Glue for Spark에서 지원하는 데이터 형식에 대한 기능 지원 및 구성 파라미터에 대한 정보를 제공합니다. 이 정보의 사용 및 적용 가능성에 대한 설명은 다음을 참조하세요.

## AWS Glue의 데이터 형식 전반에 걸친 기능 지원
<a name="aws-glue-programming-etl-format-features"></a>

 각 데이터 형식은 다른 AWS Glue 기능을 지원할 수 있습니다. 다음 공통 기능은 해당 형식 유형에 따라 지원되거나 지원되지 않을 수 있습니다. 요구 사항을 충족하기 위해 기능을 활용하는 방법을 이해하려면 데이터 형식에 대한 설명서를 참조하세요.


|  |  | 
| --- |--- |
| 읽기 | AWS Glue는 커넥터와 같은 추가 리소스 없이 이 데이터 형식을 인식하고 해석할 수 있습니다. | 
| 쓰기 | AWS Glue는 추가 리소스 없이 이 형식으로 데이터를 쓸 수 있습니다. 다른 Spark 환경에서와 같이 작업에 타사 라이브러리를 포함하고 표준 Apache Spark 기능을 사용하여 데이터를 작성할 수 있습니다. 라이브러리를 포함한 자세한 내용은 [AWS Glue와 함께 Python 라이브러리 사용](aws-glue-programming-python-libraries.md) 단원을 참조하세요. | 
| 스트리밍 읽기 | AWS Glue는 Apache Kafka, Amazon Managed Streaming for Apache Kafka 또는 Amazon Kinesis 메시지 스트림에서 이 데이터 형식을 인식하고 해석할 수 있습니다. 스트림이 일관된 형식으로 데이터를 표시할 것으로 예상하므로 DataFrames로 읽습니다. | 
| 작은 파일 그룹화 | AWS Glue는 AWS Glue 변환을 수행할 때 각 노드로 전송되는 일괄 작업으로 파일을 그룹화할 수 있습니다. 이렇게 하면 많은 양의 작은 파일이 포함된 워크로드의 성능이 크게 향상될 수 있습니다. 자세한 내용은 [입력 파일을 더 큰 그룹에서 읽기](grouping-input-files.md) 섹션을 참조하세요. | 
| 작업 북마크 | AWS Glue는 작업 북마크를 사용하여 작업 실행 전반에 걸쳐 동일한 데이터 세트에서 동일한 작업을 수행하는 변환의 진행 상황을 추적할 수 있습니다. 이렇게 하면 마지막 작업 실행 이후 새 데이터에 대해서만 작업을 수행해야 하는 데이터 세트와 관련된 워크로드의 성능을 향상시킬 수 있습니다. 자세한 내용은 [처리된 데이터를 작업 북마크로 추적](monitor-continuations.md) 섹션을 참조하세요. | 

## AWS Glue의 데이터 형식과 상호 작용하는 데 사용되는 파라미터
<a name="aws-glue-programming-etl-format-parameters"></a>

특정 AWS Glue 연결 유형은 여러 `format` 유형을 지원하므로 `GlueContext.write_dynamic_frame.from_options`와 같은 방법을 사용할 때 `format_options` 객체로 데이터 형식에 대한 정보를 지정해야 합니다.
+ `s3` - 자세한 내용은 AWS Glue: [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)의 ETL 연결 유형 및 옵션을 참조하세요. 이 연결 유형(Python에서 [create\$1dynamic\$1frame\$1from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 및 [write\$1dynamic\$1frame\$1from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options), 그에 해당하는 스칼라 메서드 [def getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 및 [def getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat))을 지원하는 메서드에 대한 문서도 볼 수 있습니다.

  
+ `kinesis` - 자세한 내용은 AWS Glue: [Kinesis 연결 파라미터](aws-glue-programming-etl-connect-kinesis-home.md#aws-glue-programming-etl-connect-kinesis)의 ETL 연결 유형 및 옵션을 참조하세요. 이 연결 유형([create\$1data\$1frame\$1from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create-dataframe-from-options) 및 그에 해당하는 스칼라 메서드 [def createDataFrameFromOptions](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-createDataFrameFromOptions))을 지원하는 메서드에 대한 문서도 볼 수 있습니다.
+ `kafka` - 자세한 내용은 AWS Glue: [Kafka 연결 파라미터](aws-glue-programming-etl-connect-kafka-home.md#aws-glue-programming-etl-connect-kafka)의 ETL 연결 유형 및 옵션을 참조하세요. 이 연결 유형([create\$1data\$1frame\$1from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create-dataframe-from-options) 및 그에 해당하는 스칼라 메서드 [def createDataFrameFromOptions](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-createDataFrameFromOptions))을 지원하는 메서드에 대한 문서도 볼 수 있습니다.

일부 연결 유형은 `format_options`가 필요하지 않습니다. 예를 들어 일반적인 사용 과정에서 관계형 데이터베이스에 대한 JDBC 연결은 일관된 테이블형 데이터 형식으로 데이터를 검색하므로 JDBC 연결에서 읽을 때 `format_options`가 필요하지 않습니다.

Glue에서 데이터를 읽고 쓰는 일부 방법은 `format_options`가 필요하지 않습니다. 예를 들어, Glue 크롤러에서 `GlueContext.create_dynamic_frame.from_catalog` 및 AWS를 사용하는 경우. 크롤러는 데이터의 형태를 결정합니다. 크롤러를 사용할 때 AWS Glue 분류기는 데이터를 검사하여 데이터 형식을 표현하는 방법에 대한 현명한 결정을 내립니다. 그런 다음 AWS Glue ETL 스크립트 내에서 `GlueContext.create_dynamic_frame.from_catalog` 메서드로 데이터를 검색하는 데 사용할 수 있는 AWS Glue 데이터 카탈로그에 데이터 표현을 저장합니다. 크롤러를 사용하면 데이터 형식에 대한 정보를 수동으로 지정할 필요가 없습니다.

AWS Lake Formation 관리형 테이블에 액세스하는 작업의 경우 AWS Glue는 Lake Formation 관리형 테이블에서 지원되는 모든 포맷을 읽고 쓸 수 있도록 지원합니다. AWS Lake Formation 관리형 테이블에서 현재 지원되는 포맷 목록은 [AWS Lake Formation 개발자 가이드](https://docs.aws.amazon.com/lake-formation/latest/dg/governed-table-restrictions.html)의 *관리형 테이블에 대한 참고 사항 및 제한 사항*을 참조하세요.

**참고**  
Apache Parquet 쓰기의 경우 AWS Glue ETL은 Dynamic Frames에 최적화된 사용자 지정 Parquet 라이터 유형에 대한 옵션을 지정하여 관리형 테이블에 쓰는 기능만을 지원합니다. `parquet` 포맷을 사용하는 관리형 테이블에 쓰는 경우 테이블 파라미터의 `true` 값과 함께 `useGlueParquetWriter` 키를 추가해야 합니다.

**Topics**
+ [

## AWS Glue의 데이터 형식 전반에 걸친 기능 지원
](#aws-glue-programming-etl-format-features)
+ [

## AWS Glue의 데이터 형식과 상호 작용하는 데 사용되는 파라미터
](#aws-glue-programming-etl-format-parameters)
+ [

# AWS Glue에서 CSV 형식 사용
](aws-glue-programming-etl-format-csv-home.md)
+ [

# AWS Glue에서 Parquet 형식 사용
](aws-glue-programming-etl-format-parquet-home.md)
+ [

# AWS Glue에서 XML 형식 사용
](aws-glue-programming-etl-format-xml-home.md)
+ [

# AWS Glue에서 Avro 형식 사용
](aws-glue-programming-etl-format-avro-home.md)
+ [

# AWS Glue에서 grokLog 형식 사용
](aws-glue-programming-etl-format-grokLog-home.md)
+ [

# AWS Glue에서 Ion 형식 사용
](aws-glue-programming-etl-format-ion-home.md)
+ [

# AWS Glue에서 JSON 형식 사용
](aws-glue-programming-etl-format-json-home.md)
+ [

# AWS Glue에서 ORC 형식 사용
](aws-glue-programming-etl-format-orc-home.md)
+ [

# AWS Glue ETL 작업에서 데이터 레이크 프레임워크 사용
](aws-glue-programming-etl-datalake-native-frameworks.md)
+ [

## 공유 구성 참조
](#aws-glue-programming-etl-format-shared-reference)

# AWS Glue에서 CSV 형식 사용
<a name="aws-glue-programming-etl-format-csv-home"></a>

AWS Glue는 소스에서 데이터를 검색하고 다양한 데이터 형식으로 저장 및 전송되는 대상에 데이터를 씁니다. 데이터가 CSV 데이터 형식으로 저장 또는 전송되는 경우 이 문서에서는 AWS Glue에서 데이터를 사용하는 데 사용할 수 있는 기능을 소개합니다.

 AWS Glue는 CSV(쉼표로 분리된 값) 형식 사용만 지원합니다. 이 형식은 최소 행 기반 데이터 형식입니다. CSV는 표준을 엄격하게 준수하지 않는 경우가 많지만 [RFC 4180](https://tools.ietf.org/html/rfc4180)과 [RFC 7111](https://tools.ietf.org/html/rfc7111)에서 자세한 정보를 참조할 수 있습니다.

AWS Glue를 사용하여 Amazon S3와 스트리밍 소스에서 CSV를 읽을 수 있을 뿐만 아니라 Amazon S3에 CSV를 쓸 수 있습니다. S3에서 CSV 파일이 포함된 `bzip` 및 `gzip` 아카이브를 읽고 쓸 수 있습니다. 이 페이지에서 설명하는 구성 대신 [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)에서 압축 동작을 구성할 수 있습니다.

다음 표에서는 CSV 형식 옵션을 지원하는 일반적인 AWS Glue 기능을 보여줍니다.


| 읽기 | 쓰기 | 스트리밍 읽기 | 작은 파일 그룹화 | 작업 북마크 | 
| --- | --- | --- | --- | --- | 
| 지원됨 | 지원됨 | 지원됨 | 지원됨 | 지원됨 | 

## 예: S3에서 CSV 파일 또는 폴더 읽기
<a name="aws-glue-programming-etl-format-csv-read"></a>

 **사전 조건:** 읽고자 하는 CSV 파일 또는 폴더에 대한 S3 경로(`s3path`)가 필요합니다.

 **구성:** 함수 옵션에서 `format="csv"`를 지정합니다. `connection_options`에서 `paths` 키를 사용하여 `s3path`를 지정합니다. `connection_options`에서 리더와 S3가 상호 작용하는 방식을 구성할 수 있습니다. 자세한 내용은 AWS Glue에서 ETL 관련 연결 유형 및 옵션 참조: [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 리더에서 `format_options`의 CSV 파일을 해석하는 방법을 구성할 수 있습니다. 자세한 내용은 [CSV 구성 참조](#aws-glue-programming-etl-format-csv-reference)를 참조하십시오.

다음 AWS Glue ETL 스크립트는 S3에서 CSV 파일 또는 폴더를 읽는 프로세스를 보여줍니다.

 `optimizePerformance` 구성 키를 통해 사용자 지정 CSV 리더에 일반적인 워크플로우에 대한 성능 최적화가 제공됩니다. 이 리더가 워크로드에 적합한지 확인하려면 [벡터화된 SIMD CSV 리더로 읽기 성능 최적화](#aws-glue-programming-etl-format-simd-csv-reader) 단원을 참조하십시오.

------
#### [ Python ]

이 예에서는 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 메서드를 사용합니다.

```
# Example: Read CSV from S3
# For show, we handle a CSV with a header row.  Set the withHeader option.
# Consider whether optimizePerformance is right for your workflow.

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="csv",
    format_options={
        "withHeader": True,
        # "optimizePerformance": True,
    },
)
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
dataFrame = spark.read\
    .format("csv")\
    .option("header", "true")\
    .load("s3://s3path")
```

------
#### [ Scala ]

이 예에서는 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 작업을 사용합니다.

```
// Example: Read CSV from S3
// For show, we handle a CSV with a header row.  Set the withHeader option.
// Consider whether optimizePerformance is right for your workflow.

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    
    val dynamicFrame = glueContext.getSourceWithFormat(
      formatOptions=JsonOptions("""{"withHeader": true}"""),
      connectionType="s3",
      format="csv",
      options=JsonOptions("""{"paths": ["s3://s3path"], "recurse": true}""")
    ).getDynamicFrame()
  }
}
```

또한 스크립트(`org.apache.spark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
val dataFrame = spark.read
  .option("header","true")
  .format("csv")
  .load("s3://s3path“)
```

------

## 예: S3에 CSV 파일 및 폴더 쓰기
<a name="aws-glue-programming-etl-format-csv-write"></a>

 **사전 조건:** 초기화된 DataFrame(`dataFrame`) 또는 DynamicFrame(`dynamicFrame`)이 필요합니다. 예상되는 S3 출력 경로(`s3path`)도 필요합니다.

 **구성:** 함수 옵션에서 `format="csv"`를 지정합니다. `connection_options`에서 `paths` 키를 사용하여 `s3path`를 지정합니다. `connection_options`에서 라이터와 S3가 상호 작용하는 방식을 구성할 수 있습니다. 자세한 내용은 AWS Glue에서 ETL 관련 연결 유형 및 옵션 참조: [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 작업에서 `format_options`에 있는 파일의 내용을 쓰는 방법을 구성할 수 있습니다. 자세한 내용은 [CSV 구성 참조](#aws-glue-programming-etl-format-csv-reference)를 참조하십시오. 다음 AWS Glue ETL 스크립트는 S3로 CSV 파일 및 폴더를 쓰는 프로세스를 보여줍니다.

------
#### [ Python ]

이 예에서는 [write\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options) 메서드를 사용합니다.

```
# Example: Write CSV to S3
# For show, customize how we write string type values.  Set quoteChar to -1 so our values are not quoted.

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="s3",
    connection_options={"path": "s3://s3path"},
    format="csv",
    format_options={
        "quoteChar": -1,
    },
)
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
dataFrame.write\
    .format("csv")\
    .option("quote", None)\
    .mode("append")\
    .save("s3://s3path")
```

------
#### [ Scala ]

이 예에서는 [getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat) 메서드를 사용합니다.

```
// Example: Write CSV to S3
// For show, customize how we write string type values. Set quoteChar to -1 so our values are not quoted.

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    
    glueContext.getSinkWithFormat(
        connectionType="s3",
        options=JsonOptions("""{"path": "s3://s3path"}"""),
        format="csv"
    ).writeDynamicFrame(dynamicFrame)
  }
}
```

또한 스크립트(`org.apache.spark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
dataFrame.write
    .format("csv")
    .option("quote", null)
    .mode("Append")
    .save("s3://s3path")
```

------

## CSV 구성 참조
<a name="aws-glue-programming-etl-format-csv-reference"></a>

AWS Glue 라이브러리가 `format="csv"`를 지정한 곳이라면 어디에서든 다음 `format_options`을 사용할 수 있습니다.
+ `separator` - 구분 기호 문자열을 지정합니다. 기본값은 쉼표(,)이지만, 다른 문자도 지정할 수 있습니다.
  + **유형:** 텍스트, **기본값:** `","`
+ `escaper` - 이스케이프 처리에 사용할 문자를 지정합니다. 이 옵션은 CSV 파일을 읽을 때만 사용되며 쓸 때는 사용되지 않습니다. 활성화된 경우 바로 다음에 나오는 문자가 잘 알려진 이스케이프 세트(`\n`, `\r`, `\t` 및 `\0`)를 제외하고는 있는 그대로 사용됩니다.
  + **유형:** 텍스트, **기본값:** 없음
+ `quoteChar` - 인용에 사용할 문자를 지정합니다. 기본값은 큰 따옴표(")입니다. 전체 인용을 해제하려면 이 값을 `-1`로 설정합니다.
  + **유형:** 텍스트, **기본값:** `'"'`
+ `multiLine` - 단일 기록이 다양한 라인을 포괄할 수 있는지 여부를 지정합니다. 필드가 인용된 새로운 라인 문자를 포함할 때 발생합니다. 이 옵션을 `True`로 설정해야 기록이 여러 라인을 포괄할 수 있습니다. `multiLine`을 활성화하면 구문 분석하는 동안 더 신중한 파일 분할이 필요하므로 성능이 저하될 수 있습니다.
  + **유형:** 부울, **기본값:** `false`
+ `withHeader` - 첫 번째 라인을 헤더로 취급할지 여부를 지정합니다. 이 옵션은 `DynamicFrameReader` 클래스에서 사용할 수 있습니다.
  + **유형:** 부울, **기본값:** `false`
+ `writeHeader` - 헤더를 작성하여 출력할지 여부를 지정합니다. 이 옵션은 `DynamicFrameWriter` 클래스에서 사용할 수 있습니다.
  + **유형:** 부울, **기본값:** `true`
+ `skipFirst`- 첫 번째 데이터 라인을 건너뛸지 여부를 지정합니다.
  + **유형:** 부울, **기본값:** `false`
+ `optimizePerformance` - Apache Arrow 기반 열 포맷 메모리 포맷과 함께 고급 SIMD CSV 리더를 사용할지 여부를 지정합니다. AWS Glue 3.0 이상에서만 사용 가능합니다.
  + **유형:** 부울, **기본값:** `false`
+ `strictCheckForQuoting` - CSV를 쓸 때 Glue는 문자열로 해석되는 값에 따옴표를 추가할 수 있습니다. 이는 기록된 내용이 모호하지 않도록 하기 위해서입니다. 기록할 내용을 결정할 때 시간을 절약하기 위해 Glue는 따옴표가 필요하지 않은 특정 상황에서 인용할 수 있습니다. 엄격한 검사를 활성화하면 보다 컴퓨팅 집약적인 작업을 수행하고 필요한 경우에만 인용합니다. AWS Glue 3.0 이상에서만 사용 가능합니다.
  + **유형:** 부울, **기본값:** `false`

## 벡터화된 SIMD CSV 리더로 읽기 성능 최적화
<a name="aws-glue-programming-etl-format-simd-csv-reader"></a>

AWS Glue 버전 3.0에는 행 기반 CSV 리더에 비해 전반적인 작업 속도를 크게 높일 수 있는 최적화된 CSV 리더가 추가되었습니다.

 최적화된 리더:
+ CPU SIMD 명령을 사용하여 디스크에서 읽기
+ 레코드를 열 기반 형식으로 메모리에 즉시 쓰기(Apache Arrow) 
+ 레코드를 배치로 분할

이렇게 하면 나중에 레코드가 일괄 처리되거나 열 기반 형식으로 변환될 때 처리 시간이 절약됩니다. 스키마를 변경하거나 열별로 데이터를 검색하는 경우를 예로 들 수 있습니다.

최적화된 리더를 사용하려면 `format_options` 또는 테이블 속성에서 `"optimizePerformance"`를 `true`로 설정합니다.

```
glueContext.create_dynamic_frame.from_options(
    frame = datasource1,
    connection_type = "s3", 
    connection_options = {"paths": ["s3://s3path"]}, 
    format = "csv", 
    format_options={
        "optimizePerformance": True, 
        "separator": ","
        }, 
    transformation_ctx = "datasink2")
```

**벡터화된 CSV 리더에 대한 제한 사항**  
벡터화된 CSV 리더의 제한 사항:
+ `multiLine` 및 `escaper` 포맷 옵션은 지원되지 않습니다. 큰따옴표 문자(`'"'`)의 기본값 `escaper`가 사용됩니다. 이러한 옵션을 설정하면 AWS Glue는 행 기반 CSV 리더를 사용하는 상태로 자동으로 돌아갑니다.
+ [ChoiceType](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-crawler-pyspark-extensions-types.html#aws-glue-api-crawler-pyspark-extensions-types-awsglue-choicetype)으로 DynamicFrame 생성이 지원되지 않습니다.
+ [오류 레코드](https://docs.aws.amazon.com/glue/latest/dg/glue-etl-scala-apis-glue-dynamicframe-class.html#glue-etl-scala-apis-glue-dynamicframe-class-defs-errorsAsDynamicFrame)로 DynamicFrame 생성이 지원되지 않습니다.
+ 일본어 또는 중국어와 같은 멀티바이트 문자가 포함된 CSV 파일 읽기가 지원되지 않습니다.

# AWS Glue에서 Parquet 형식 사용
<a name="aws-glue-programming-etl-format-parquet-home"></a>

AWS Glue는 소스에서 데이터를 검색하고 다양한 데이터 형식으로 저장 및 전송되는 대상에 데이터를 씁니다. 데이터가 Parquet 데이터 형식으로 저장 또는 전송되는 경우 이 문서에서는 AWS Glue에서 데이터를 사용하는 데 사용할 수 있는 기능을 소개합니다.

AWS Glue는 Parquet 형식 사용을 지원합니다. 이 형식은 성능 중심의 열 기반 데이터 형식입니다. 표준 기관의 형식에 대한 소개는 [Apache Parquet 설명서 개요](https://parquet.apache.org/docs/overview/)를 참조하세요.

AWS Glue를 사용하여 Amazon S3와 스트리밍 소스에서 Parquet 파일을 읽을 수 있을 뿐만 아니라 Amazon S3에 Parquet 파일을 쓸 수 있습니다. S3에서 Parquet 파일이 포함된 `bzip` 및 `gzip` 아카이브를 읽고 쓸 수 있습니다. 이 페이지에서 설명하는 구성 대신 [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)에서 압축 동작을 구성할 수 있습니다.

다음 표에서는 Parquet 형식 옵션을 지원하는 일반적인 AWS Glue 기능을 보여줍니다.


| 읽기 | 쓰기 | 스트리밍 읽기 | 작은 파일 그룹화 | 작업 북마크 | 
| --- | --- | --- | --- | --- | 
| 지원됨 | 지원됨 | 지원됨 | 지원되지 않음 | 지원\$1 | 

\$1 AWS Glue 버전 1.0 이상에서 지원

## 예: S3에서 Parquet 파일 또는 폴더 읽기
<a name="aws-glue-programming-etl-format-parquet-read"></a>

**사전 조건:** 읽고자 하는 Parquet 파일 또는 폴더에 대한 S3 경로(`s3path`)가 필요합니다.

 **구성:** 함수 옵션에서 `format="parquet"`를 지정합니다. `connection_options`에서 `paths` 키를 사용하여 `s3path`를 지정합니다.

`connection_options`에서 리더와 S3가 상호 작용하는 방식을 구성할 수 있습니다. 자세한 내용은 AWS Glue에서 ETL 관련 연결 유형 및 옵션 참조: [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)

 리더에서 `format_options`의 Parquet 파일을 해석하는 방법을 구성할 수 있습니다. 자세한 내용은 [Parquet 구성 참조](#aws-glue-programming-etl-format-parquet-reference)를 참조하십시오.

다음 AWS Glue ETL 스크립트는 S3에서 Parquet 파일 또는 폴더를 읽는 프로세스를 보여줍니다.

------
#### [ Python ]

이 예에서는 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 메서드를 사용합니다.

```
# Example: Read Parquet from S3

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type = "s3", 
    connection_options = {"paths": ["s3://s3path/"]}, 
    format = "parquet"
)
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
dataFrame = spark.read.parquet("s3://s3path/")
```

------
#### [ Scala ]

이 예에서는 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 메서드를 사용합니다.

```
// Example: Read Parquet from S3

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    
    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType="s3",
      format="parquet",
      options=JsonOptions("""{"paths": ["s3://s3path"]}""")
    ).getDynamicFrame()
  }
}
```

또한 스크립트(`org.apache.spark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
spark.read.parquet("s3://s3path/")
```

------

## 예: S3에 Parquet 파일 및 폴더 쓰기
<a name="aws-glue-programming-etl-format-parquet-write"></a>

**사전 조건:** 초기화된 DataFrame(`dataFrame`) 또는 DynamicFrame(`dynamicFrame`)이 필요합니다. 예상되는 S3 출력 경로(`s3path`)도 필요합니다.

 **구성:** 함수 옵션에서 `format="parquet"`를 지정합니다. `connection_options`에서 `paths` 키를 사용하여 `s3path`를 지정합니다.

`connection_options`에서 라이터가 S3와 상호 작용하는 방식을 추가로 변경할 수 있습니다. 자세한 내용은 AWS Glue에서 ETL 관련 연결 유형 및 옵션 참조: [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 작업에서 `format_options`에 있는 파일의 내용을 쓰는 방법을 구성할 수 있습니다. 자세한 내용은 [Parquet 구성 참조](#aws-glue-programming-etl-format-parquet-reference)를 참조하십시오.

다음 AWS Glue ETL 스크립트는 S3로 Parquet 파일 및 폴더를 쓰는 프로세스를 보여줍니다.

`useGlueParquetWriter` 구성 키를 통해 사용자 지정 Parquet 라이터에 DynamicFrame에 대한 성능 최적화가 제공됩니다. 이 라이터가 워크로드에 적합한지 확인하려면 [Glue Parquet 라이터](#aws-glue-programming-etl-format-glue-parquet-writer)를 참조하세요.

------
#### [ Python ]

이 예에서는 [write\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options) 메서드를 사용합니다.

```
# Example: Write Parquet to S3
# Consider whether useGlueParquetWriter is right for your workflow.

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="s3",
    format="parquet",
    connection_options={
        "path": "s3://s3path",
    },
    format_options={
        # "useGlueParquetWriter": True,
    },
)
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
df.write.parquet("s3://s3path/")
```

------
#### [ Scala ]

이 예에서는 [getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat) 메서드를 사용합니다.

```
// Example: Write Parquet to S3
// Consider whether useGlueParquetWriter is right for your workflow.

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    
    glueContext.getSinkWithFormat(
        connectionType="s3",
        options=JsonOptions("""{"path": "s3://s3path"}"""),
        format="parquet"
    ).writeDynamicFrame(dynamicFrame)
  }
}
```

또한 스크립트(`org.apache.spark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
df.write.parquet("s3://s3path/")
```

------

## Parquet 구성 참조
<a name="aws-glue-programming-etl-format-parquet-reference"></a>

AWS Glue 라이브러리가 `format="parquet"`을 지정한 어디에서나 다음 `format_options`를 사용할 수 있습니다.
+ `useGlueParquetWriter` - DynamicFrame 워크플로에 대한 성능 최적화가 포함된 사용자 지정 Parquet 라이터의 사용을 지정합니다. 자세한 내용은 [Glue Parquet 라이터](#aws-glue-programming-etl-format-glue-parquet-writer)를 참조하세요.
  + **유형:** 부울, **기본값:**`false`
+ `compression` - 사용되는 압축 코덱을 지정합니다. 값은 `org.apache.parquet.hadoop.metadata.CompressionCodecName`과 완벽하게 호환됩니다.
  + **유형:** 열거 텍스트, **기본값:** `"snappy"`
  + 값: `"uncompressed"`, `"snappy"`, `"gzip"` 및 `"lzo"`
+ `blockSize` - 메모리에 버퍼링되는 행 그룹의 크기(바이트 단위)를 지정합니다. 성능 튜닝에 사용합니다. 크기는 정확히 메가바이트 수로 나눠야 합니다.
  + **유형:** 숫자, **기본값:**`134217728`
  + 기본값은 128MB입니다.
+ `pageSize` - 페이지의 크기를 바이트 단위로 지정합니다. 성능 튜닝에 사용합니다. 페이지는 단일 레코드에 액세스하기 위해 완전하게 읽어야 하는 가장 작은 단위입니다.
  + **유형:** 숫자, **기본값:**`1048576`
  + 기본값은 1MB입니다.

**참고**  
또한 SparkSQL 기초 코드에 의해 수락된 옵션은 `connection_options` 맵 파라미터를 거쳐 SparkSQL 기초 코드로 넘겨질 수 있습니다. 예를 들어 AWS Glue Spark 리더에 대해 [mergeSchema](https://spark.apache.org/docs/latest/sql-data-sources-parquet.html#schema-merging)와 같은 Spark 구성을 설정하여 모든 파일의 스키마를 병합할 수 있습니다.

## AWS Glue Parquet 라이터를 사용한 쓰기 성능 최적화
<a name="aws-glue-programming-etl-format-glue-parquet-writer"></a>

**참고**  
 AWS Glue Parquet 라이터는 예전에 `glueparquet` 형식 유형을 통해 액세스되었습니다. 이 액세스 패턴은 더 이상 지원되지 않습니다. 대신 `useGlueParquetWriter`이 활성화된 `parquet` 유형을 사용합니다.

AWS Glue Parquet 라이터는 더 빠른 Parquet 파일 쓰기가 가능하도록 성능이 향상되었습니다. 기존 라이터는 쓰기 전에 스키마를 컴퓨팅합니다. Parquet 형식은 빠르게 검색할 수 있는 방식으로 스키마를 저장하지 않으므로 시간이 걸릴 수 있습니다. AWS Glue Parquet 라이터를 사용하는 경우 사전 컴퓨팅된 스키마가 필요하지 않습니다. 데이터가 들어오면 라이터는 스키마를 동적으로 컴퓨팅 및 수정합니다.

`useGlueParquetWriter`를 지정하는 경우 다음 제한에 유의하세요.
+ 라이터는 열 추가 또는 제거와 같은 스키마 개선만 지원하고 `ResolveChoice`와 같은 열 유형 변경은 지원하지 않습니다.
+ 작성기는 빈 DataFrames 작성(예: 스키마 전용 파일 작성)을 지원하지 않습니다. `enableUpdateCatalog=True`를 설정하여 AWS Glue 데이터 카탈로그와 통합할 때 빈 DataFrame을 작성하려고 해도 데이터 카탈로그가 업데이트되지 않습니다. 그러면 스키마 없이 데이터 카탈로그에 테이블이 생성됩니다.

변형에 이러한 제한이 필요하지 않은 경우 AWS Glue Parquet 라이터를 켜면 성능이 향상됩니다.

# AWS Glue에서 XML 형식 사용
<a name="aws-glue-programming-etl-format-xml-home"></a>

AWS Glue는 소스에서 데이터를 검색하고 다양한 데이터 형식으로 저장 및 전송되는 대상에 데이터를 씁니다. 데이터가 XML 데이터 형식으로 저장 또는 전송되는 경우 이 문서에서는 AWS Glue에서 데이터를 사용하는 데 사용할 수 있는 기능을 소개합니다.

AWS Glue는 XML 형식 사용을 지원합니다. 이 형식은 행이나 열을 기반으로 하지 않는 고도로 구성 가능하고 엄격하게 정의된 데이터 구조를 나타냅니다. XML은 고도로 표준화되어 있습니다. 표준 기관의 형식에 대한 소개는 [XML 필수 사항](https://www.w3.org/standards/xml/core)을 참조하십시오.

AWS Glue를 사용하여 Amazon S3는 물론 XML 파일이 포함된 `bzip` 및 `gzip` 아카이브에서 XML 파일을 읽을 수 있습니다. 이 페이지에서 설명하는 구성 대신 [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)에서 압축 동작을 구성할 수 있습니다.

다음 표에서는 XML 형식 옵션을 지원하는 일반적인 AWS Glue 기능을 보여줍니다.


| 읽기 | 쓰기 | 스트리밍 읽기 | 작은 파일 그룹화 | 작업 북마크 | 
| --- | --- | --- | --- | --- | 
| 지원 | 지원되지 않음 | 지원되지 않음 | 지원 | 지원 | 

## 예: S3에서 XML 읽기
<a name="aws-glue-programming-etl-format-xml-read"></a>

 XML 리더는 XML 태그 이름을 사용합니다. 입력 내에 해당 태그가 있는 요소를 검사하여 스키마를 추론하고 DynamicFrame을 해당 값으로 채웁니다. AWS Glue XML 기능은 [Apache Spark용 XML 데이터 소스](https://github.com/databricks/spark-xml)와 비슷하게 작동합니다. 이 리더를 해당 프로젝트의 문서와 비교하면 기본 동작에 대한 통찰력을 얻을 수 있습니다.

**사전 조건:** 읽고자 하는 CSV 파일 또는 폴더에 대한 S3 경로(`s3path`), 그리고 XML 파일에 관한 약간의 정보가 필요합니다. 읽으려는 XML 요소에 대한 태그(`xmlTag`)도 필요합니다.

 **구성:** 함수 옵션에서 `format="xml"`를 지정합니다. `connection_options`에서 `paths` 키를 사용하여 `s3path`를 지정합니다. `connection_options`에서 리더와 S3가 상호 작용하는 방식을 추가로 구성할 수 있습니다. 자세한 내용은 AWS Glue에서 ETL 관련 연결 유형 및 옵션 참조: [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) `format_options`에서 `rowTag` 키를 사용하여 `xmlTag`를 지정합니다. 리더에서 `format_options`의 XML 파일을 해석하는 방법을 추가로 구성할 수 있습니다. 자세한 내용은 [XML 구성 참조](#aws-glue-programming-etl-format-xml-reference)를 참조하십시오.

다음 AWS Glue ETL 스크립트는 S3에서 XML 파일 또는 폴더를 읽는 프로세스를 보여줍니다.

------
#### [ Python ]

이 예에서는 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 메서드를 사용합니다.

```
# Example: Read XML from S3
# Set the rowTag option to configure the reader.

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="xml",
    format_options={"rowTag": "xmlTag"},
)
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
dataFrame = spark.read\
    .format("xml")\
    .option("rowTag", "xmlTag")\
    .load("s3://s3path")
```

------
#### [ Scala ]

이 예에서는 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 작업을 사용합니다.

```
// Example: Read XML from S3
// Set the rowTag option to configure the reader.

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.GlueContext
import org.apache.spark.sql.SparkSession

val glueContext = new GlueContext(SparkContext.getOrCreate())
val sparkSession: SparkSession = glueContext.getSparkSession

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val dynamicFrame = glueContext.getSourceWithFormat(
      formatOptions=JsonOptions("""{"rowTag": "xmlTag"}"""), 
      connectionType="s3", 
      format="xml", 
      options=JsonOptions("""{"paths": ["s3://s3path"], "recurse": true}""")
    ).getDynamicFrame()
}
```

또한 스크립트(`org.apache.spark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
val dataFrame = spark.read
  .option("rowTag", "xmlTag")
  .format("xml")
  .load("s3://s3path“)
```

------

## XML 구성 참조
<a name="aws-glue-programming-etl-format-xml-reference"></a>

AWS Glue 라이브러리가 `format="xml"`를 지정한 곳이라면 어디에서든 다음 `format_options`을 사용할 수 있습니다.
+ `rowTag` - 파일의 XML 태그를 지정하여 태그를 열로 취급합니다. 열 태그는 자기 복제를 할 수 없습니다.
  + **유형:** 텍스트, **필수**
+ `encoding` - 문자 인코딩을 지정합니다. 런타임 환경에서 지원하는 [Charset](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html)의 이름 또는 별칭이 될 수 있습니다. 인코딩 지원에 대해 구체적으로 보장하지는 않지만 주요 인코딩은 작동할 것입니다.
  + **유형:** 텍스트, **기본값:** `"UTF-8"`
+ `excludeAttribute` - 요소에서 속성을 제외할지 여부를 지정합니다.
  + **유형:** 부울, **기본값:** `false`
+ `treatEmptyValuesAsNulls` - 공백을 null 값으로 취급할지 여부를 지정합니다.
  + **유형:** 부울, **기본값:** `false`
+ `attributePrefix` - 하위 요소 텍스트와 구별하기 위한 속성용 접두사. 이 접두사는 필드 이름으로 사용됩니다.
  + **유형:** 텍스트, **기본값:** `"_"`
+ `valueTag` - 하위 요소가 없는 요소에 속성이 있는 값에 사용되는 태그.
  + **유형:** 텍스트, **기본값:** `"_VALUE"`
+ `ignoreSurroundingSpaces` - 값을 둘러싸는 공백을 무시할지 여부를 지정합니다.
  + **유형:** 부울, **기본값:** `false`
+ `withSchema` - 추론된 스키마를 재정의하려는 상황에서 예상되는 스키마를 포함합니다. 이 옵션을 사용하지 않으면 AWS Glue는 XML 데이터에서 스키마를 유추합니다.
  + **유형:** 텍스트, **기본값:** 해당 사항 없음
  + 값은 `StructType`을 나타내는 JSON 객체여야 합니다.

## XML 스키마를 수동으로 지정
<a name="aws-glue-programming-etl-format-xml-withschema"></a>

**수동 XML 스키마 예**

`withSchema` 포맷 옵션을 사용하여 XML 데이터에 대한 스키마를 지정하는 예입니다.

```
from awsglue.gluetypes import *

schema = StructType([ 
  Field("id", IntegerType()),
  Field("name", StringType()),
  Field("nested", StructType([
    Field("x", IntegerType()),
    Field("y", StringType()),
    Field("z", ChoiceType([IntegerType(), StringType()]))
  ]))
])

datasource0 = create_dynamic_frame_from_options(
    connection_type, 
    connection_options={"paths": ["s3://xml_bucket/someprefix"]},
    format="xml", 
    format_options={"withSchema": json.dumps(schema.jsonValue())},
    transformation_ctx = ""
)
```

# AWS Glue에서 Avro 형식 사용
<a name="aws-glue-programming-etl-format-avro-home"></a>

AWS Glue는 소스에서 데이터를 검색하고 다양한 데이터 형식으로 저장 및 전송되는 대상에 데이터를 씁니다. 데이터가 Avro 데이터 형식으로 저장 또는 전송되는 경우 이 문서에서는 AWS Glue에서 데이터를 사용하는 데 사용할 수 있는 기능을 소개합니다.

AWS Glue는 Avro 형식 사용을 지원합니다. 이 형식은 성능 중심의 행 기반 데이터 형식입니다. 표준 기관의 형식에 대한 소개는 [Apache Avro 1.8.2 설명서 개요](https://avro.apache.org/docs/1.8.2/)를 참조하세요.

AWS Glue를 사용하여 Amazon S3와 스트리밍 소스에서 Avro 파일을 읽을 수 있을 뿐만 아니라 Amazon S3에 Avro 파일을 쓸 수 있습니다. S3에서 Avro 파일이 포함된 `bzip2` 및 `gzip` 아카이브를 읽고 쓸 수 있습니다. 또한 Avro 파일이 포함된 `deflate`, `snappy`, `xz` 아카이브를 쓸 수 있습니다. 이 페이지에서 설명하는 구성 대신 [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)에서 압축 동작을 구성할 수 있습니다.

다음 표에서는 Avro 형식 옵션을 지원하는 일반적인 AWS Glue 기능을 보여 줍니다.


| 읽기 | 쓰기 | 스트리밍 읽기 | 작은 파일 그룹화 | 작업 북마크 | 
| --- | --- | --- | --- | --- | 
| 지원 | 지원 | 지원\$1 | 지원되지 않음 | 지원 | 

\$1제한적으로 지원됩니다. 자세한 내용은 [Avro 스트리밍 소스에 대한 참고 사항 및 제한 사항](add-job-streaming.md#streaming-avro-notes) 섹션을 참조하세요.

## 예: S3에서 Avro 파일 또는 폴더 읽기
<a name="aws-glue-programming-etl-format-avro-read"></a>

** 사전 조건:** 읽으려는 Avro 파일 또는 폴더에 대한 S3 경로(`s3path`)가 필요합니다.

**구성:** 함수 옵션에서 `format="avro"`를 지정합니다. `connection_options`에서 `paths` 키를 사용하여 `s3path`를 지정합니다. `connection_options`에서 리더와 S3가 상호 작용하는 방식을 구성할 수 있습니다. 자세한 내용은 AWS Glue: [Amazon S3 연결 옵션 참조](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)의 ETL 입력 및 출력에 대한 데이터 형식 옵션을 참조하세요. 리더에서 `format_options`의 Avro 파일을 해석하는 방법을 구성할 수 있습니다. 자세한 내용은 [Avro 구성 참조](#aws-glue-programming-etl-format-avro-reference)를 참조하세요.

다음 AWS Glue ETL 스크립트는 S3에서 Avro 파일 또는 폴더를 읽는 프로세스를 보여 줍니다.

------
#### [ Python ]

이 예에서는 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 메서드를 사용합니다.

```
from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="avro"
)
```

------
#### [ Scala ]

이 예에서는 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 작업을 사용합니다.

```
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.GlueContext
import org.apache.spark.sql.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType="s3",
      format="avro",
      options=JsonOptions("""{"paths": ["s3://s3path"]}""")
    ).getDynamicFrame()
  }
```

------

## 예: S3에 Avro 파일 및 폴더 쓰기
<a name="aws-glue-programming-etl-format-avro-write"></a>

**사전 조건:** 초기화된 DataFrame(`dataFrame`) 또는 DynamicFrame(`dynamicFrame`)이 필요합니다. 예상되는 S3 출력 경로(`s3path`)도 필요합니다.

**구성:** 함수 옵션에서 `format="avro"`를 지정합니다. `connection_options`에서 `paths` 키를 사용하여 `s3path`를 지정합니다. `connection_options`에서 라이터가 S3와 상호 작용하는 방식을 추가로 변경할 수 있습니다. 자세한 내용은 AWS Glue: [Amazon S3 연결 옵션 참조](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)의 ETL 입력 및 출력에 대한 데이터 형식 옵션을 참조하세요. 작가가 `format_options`에서 Avro 파일을 해석하는 방식을 변경할 수 있습니다. 자세한 내용은 [Avro 구성 참조](#aws-glue-programming-etl-format-avro-reference)를 참조하세요.

다음 AWS Glue ETL 스크립트는 S3로 Avro 파일 및 폴더를 쓰는 프로세스를 보여줍니다.

------
#### [ Python ]

이 예에서는 [write\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options) 메서드를 사용합니다.

```
from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="s3",
    format="avro",
    connection_options={
        "path": "s3://s3path"
    }
)
```

------
#### [ Scala ]

이 예에서는 [getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat) 메서드를 사용합니다.

```
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    glueContext.getSinkWithFormat(
      connectionType="s3",
      options=JsonOptions("""{"path": "s3://s3path"}"""),
      format="avro"
    ).writeDynamicFrame(dynamicFrame)
  }
}
```

------

## Avro 구성 참조
<a name="aws-glue-programming-etl-format-avro-reference"></a>

AWS Glue 라이브러리가 `format="avro"`를 지정한 곳이라면 어디에서든 다음 `format_options` 값을 사용할 수 있습니다.
+ `version` - 지원하는 Apache Avro 리더/라이터 포맷의 버전을 지정합니다. 기본값은 "1.7"입니다. `format_options={"version": “1.8”}`를 지정해 Avro 논리적 유형 읽기 및 쓰기를 활성화할 수 있습니다. 자세한 내용은 [Apache Avro 1.7.7 사양](https://avro.apache.org/docs/1.7.7/spec.html) 및 [Apache Avro 1.8.2 사양](https://avro.apache.org/docs/1.8.2/spec.html)을 참조하십시오.

  Apache Avro 1.8 커넥터는 다음과 같은 논리적 유형 변환을 지원합니다.

리더의 경우: 다음 테이블은 Avro 리더 1.7 및 1.8을 위한 Avro 데이터 유형(논리적 유형, Avro 기본 유형)과 AWS Glue `DynamicFrame` 데이터 유형 간 변환을 보여줍니다.


| Avro 데이터 형식: 논리적 유형 | Avro 데이터 형식: Avro 기본 유형 | GlueDynamicFrame 데이터 유형:Avro 리더 1.7 | GlueDynamicFrame 데이터 유형: Avro 리더 1.8 | 
| --- | --- | --- | --- | 
| 10진수 | bytes | BINARY | 10진수 | 
| 10진수 | 고정 | BINARY | 10진수 | 
| 날짜 | int | INT | 날짜 | 
| 시간(밀리초) | int | INT | INT | 
| 시간(마이크로초) | long | LONG | LONG | 
| 타임스탬프(밀리초) | long | LONG | Timestamp | 
| 타임스탬프(마이크로초) | long | LONG | LONG | 
| 기간(논리적 유형 아님) | 고정(12) | BINARY | BINARY | 

라이터의 경우: 다음 테이블은 Avro 라이터 1.7 및 1.8을 위한 AWS Glue `DynamicFrame` 데이터 유형과 Avro 데이터 유형 간 변환을 보여줍니다.


| AWS Glue `DynamicFrame` 데이터 유형 | Avro 데이터 형식:Avro 라이터 1.7 | Avro 데이터 형식:Avro 라이터 1.8 | 
| --- | --- | --- | 
| 10진수 | String | decimal | 
| 날짜 | String | date | 
| Timestamp | String | timestamp-micros | 

## Avro Spark DataFrame 지원
<a name="aws-glueprogramming-etl-format-avro-dataframe-support"></a>

Spark DataFrame API에서 Avro를 사용하려면 해당 Spark 버전에 대한 Spark Avro 플러그인을 설치해야 합니다. 작업에서 사용할 수 있는 Spark 버전은 AWS Glue 버전에 따라 결정됩니다. Spark 버전에 대한 자세한 내용은 [AWS Glue 버전](release-notes.md) 섹션을 참조하세요. 이 플러그인은 Apache에서 유지 관리하며 구체적인 지원을 보장하지는 않습니다.

AWS Glue 2.0에서 - Spark Avro 플러그인의 버전 2.4.3을 사용하세요. 이 JAR는 Maven Central에서 찾을 수 있습니다. [org.apache.spark:spark-avro\$12.12:2.4.3](https://search.maven.org/artifact/org.apache.spark/spark-avro_2.12/3.1.1/jar)을 참조하세요.

AWS Glue 3.0에서 - Spark Avro 플러그인의 버전 3.1.1을 사용하세요. 이 JAR는 Maven Central에서 찾을 수 있습니다. [org.apache.spark:spark-avro\$12.12:3.1.1](https://search.maven.org/artifact/org.apache.spark/spark-avro_2.12/3.1.1/jar)을 참조하세요.

추가 JAR을 AWS Glue ETL 작업에 포함하려면 `--extra-jars` 작업 파라미터를 사용하세요. 작업 파라미터에 대한 자세한 내용을 알아보려면 [AWS Glue 작업에서 작업 파라미터 사용](aws-glue-programming-etl-glue-arguments.md) 섹션을 참조하세요. AWS Management Console에서 이 매개 변수를 구성할 수도 있습니다.

# AWS Glue에서 grokLog 형식 사용
<a name="aws-glue-programming-etl-format-grokLog-home"></a>

AWS Glue는 소스에서 데이터를 검색하고 다양한 데이터 형식으로 저장 및 전송되는 대상에 데이터를 씁니다. 데이터가 느슨하게 구조화된 일반 텍스트 형식으로 저장되거나 전송되는 경우 이 문서에서는 Grok 패턴을 통해 AWS Glue에서 데이터를 사용하는 데 사용할 수 있는 기능을 소개합니다.

AWS Glue는 Grok 패턴 사용을 지원합니다. Grok 패턴은 정규 표현식 캡처 그룹과 유사합니다. 이들은 일반 텍스트 파일에서 문자 시퀀스의 패턴을 인식하여 유형과 목적을 부여합니다. AWS Glue에서 주요 목적은 로그를 읽는 것입니다. 저자의 Grok에 대한 소개는 [Logstash 참조: Grok 필터 플러그인](https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html)을 참조하세요.


| 읽기 | 쓰기 | 스트리밍 읽기 | 작은 파일 그룹화 | 작업 북마크 | 
| --- | --- | --- | --- | --- | 
| 지원 | 해당 사항 없음 | 지원 | 지원 | 지원되지 않음 | 

## grokLog 구성 참조
<a name="aws-glue-programming-etl-format-groklog-reference"></a>

`format="grokLog"`으로 다음 `format_options` 값을 사용할 수 있습니다.
+ `logFormat` - 로그 포맷과 일치하는 Grok 패턴을 지정합니다.
+ `customPatterns` - 여기서 사용된 Grok 패턴을 지정합니다.
+ `MISSING` - 누락된 값을 식별하는 데 사용된 신호를 지정합니다. 기본값은 `'-'`입니다.
+ `LineCount` - 각 로그 기록의 라인 수를 지정합니다. 기본값은 `'1'`이며 현재 단일 라인 기록만 지원합니다.
+ `StrictMode` - 제한 모드를 설정할지 여부를 지정하는 부울 값. 제한 모드에서 리더는 자동적으로 유형을 전환하거나 복구하지 않습니다. 기본값은 `"false"`입니다.

# AWS Glue에서 Ion 형식 사용
<a name="aws-glue-programming-etl-format-ion-home"></a>

AWS Glue는 소스에서 데이터를 검색하고 다양한 데이터 형식으로 저장 및 전송되는 대상에 데이터를 씁니다. 데이터가 Ion 데이터 형식으로 저장 또는 전송되는 경우 이 문서에서는 AWS Glue에서 데이터를 사용하는 데 사용할 수 있는 기능을 소개합니다.

AWS Glue는 Ion 형식 사용을 지원합니다. 이 형식은 교환 가능한 이진 및 일반 텍스트 표현으로 데이터 구조(행 또는 열 기반이 아님)를 나타냅니다. 저자의 형식에 대한 소개는 [Amazon Ion](https://amzn.github.io/ion-docs/)을 참조하세요. (자세한 내용은 [Amazon Ion 상세 정보](https://amzn.github.io/ion-docs/spec.html)를 참조하십시오.)

AWS Glue를 사용하여 Amazon S3에서 Ion 파일을 읽을 수 있습니다. S3에서 Ion 파일이 포함된 `bzip` 및 `gzip` 아카이브를 읽을 수 있습니다. 이 페이지에서 설명하는 구성 대신 [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)에서 압축 동작을 구성할 수 있습니다.

다음 표에서는 Ion 형식 옵션을 지원하는 일반적인 AWS Glue 기능을 보여 줍니다.


| 읽기 | 쓰기 | 스트리밍 읽기 | 작은 파일 그룹화 | 작업 북마크 | 
| --- | --- | --- | --- | --- | 
| 지원 | 지원되지 않음 | 지원되지 않음 | 지원 | 지원되지 않음 | 

## 예: S3에서 Ion 파일 및 폴더 읽기
<a name="aws-glue-programming-etl-format-ion-read"></a>

** 사전 조건:** 읽으려는 Ion 파일 또는 폴더에 대한 S3 경로(`s3path`)가 필요합니다.

**구성:** 함수 옵션에서 `format="json"`를 지정합니다. `connection_options`에서 `paths` 키를 사용하여 `s3path`를 지정합니다. `connection_options`에서 리더와 S3가 상호 작용하는 방식을 구성할 수 있습니다. 자세한 내용은 AWS Glue에서 ETL 관련 연결 유형 및 옵션 참조: [Amazon S3 연결 옵션 참조](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3) 

다음 AWS Glue ETL 스크립트는 S3에서 Ion 파일 또는 폴더를 읽는 프로세스를 보여 줍니다.

------
#### [ Python ]

이 예에서는 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 메서드를 사용합니다.

```
# Example: Read ION from S3

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="ion"
)
```

------
#### [ Scala ]

이 예에서는 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 작업을 사용합니다.

```
// Example: Read ION from S3

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.GlueContext
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType="s3",
      format="ion",
      options=JsonOptions("""{"paths": ["s3://s3path"], "recurse": true}""")
    ).getDynamicFrame()
  }
}
```

------

## Ion 구성 참조
<a name="aws-glue-programming-etl-format-ion-reference"></a>

`format="ion"`을 위한 `format_options` 값은 없습니다.

# AWS Glue에서 JSON 형식 사용
<a name="aws-glue-programming-etl-format-json-home"></a>

AWS Glue는 소스에서 데이터를 검색하고 다양한 데이터 형식으로 저장 및 전송되는 대상에 데이터를 씁니다. 데이터가 JSON 데이터 형식으로 저장 또는 전송되는 경우 이 문서에서는 AWS Glue에서 데이터를 사용하는 데 사용할 수 있는 기능을 소개합니다.

AWS Glue는 JSON 형식 사용을 지원합니다. 이 형식은 행이나 열을 기반으로 하지 않는 일관된 모양이지만 유연한 내용의 데이터 구조를 나타냅니다. JSON은 여러 기관에서 발행한 병렬 표준으로 정의되며 그 중 하나는 ECMA-404입니다. 일반적으로 참조되는 소스의 형식에 대한 소개는 [JSON 소개](https://www.json.org/)를 참조하세요.

AWS Glue를 사용하여 Amazon S3에서 JSON 파일과 `bzip` 및 `gzip` 압축된 JSON 파일을 읽을 수 있습니다. 이 페이지에서 설명하는 구성 대신 [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)에서 압축 동작을 구성할 수 있습니다.


| 읽기 | 쓰기 | 스트리밍 읽기 | 작은 파일 그룹화 | 작업 북마크 | 
| --- | --- | --- | --- | --- | 
| 지원 | 지원 | 지원 | 지원 | 지원 | 

## 예: S3에서 JSON 파일 또는 폴더 읽기
<a name="aws-glue-programming-etl-format-json-read"></a>

** 사전 조건:** 읽으려는 JSON 파일 또는 폴더에 대한 S3 경로(`s3path`)가 필요합니다.

**구성:** 함수 옵션에서 `format="json"`를 지정합니다. `connection_options`에서 `paths` 키를 사용하여 `s3path`를 지정합니다. 연결 옵션에서 읽기 작업이 s3를 통과하는 방법을 추가로 변경할 수 있습니다. 자세한 내용은 [Amazon S3 연결 옵션 참조](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)를 참조하세요. 리더에서 `format_options`의 JSON 파일을 해석하는 방법을 구성할 수 있습니다. 자세한 내용은 [JSON 구성 참조](#aws-glue-programming-etl-format-json-reference)를 참조하세요.

 다음 AWS Glue ETL 스크립트는 S3에서 JSON 파일 또는 폴더를 읽는 프로세스를 보여 줍니다.

------
#### [ Python ]

이 예에서는 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 메서드를 사용합니다.

```
# Example: Read JSON from S3
# For show, we handle a nested JSON file that we can limit with the JsonPath parameter
# For show, we also handle a JSON where a single entry spans multiple lines
# Consider whether optimizePerformance is right for your workflow.

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)
spark = glueContext.spark_session

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="json",
    format_options={
        "jsonPath": "$.id",
        "multiline": True,
        # "optimizePerformance": True, -> not compatible with jsonPath, multiline
    }
)
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
dataFrame = spark.read\
    .option("multiline", "true")\
    .json("s3://s3path")
```

------
#### [ Scala ]

이 예에서는 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 작업을 사용합니다.

```
// Example: Read JSON from S3
// For show, we handle a nested JSON file that we can limit with the JsonPath parameter
// For show, we also handle a JSON where a single entry spans multiple lines
// Consider whether optimizePerformance is right for your workflow.

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    val dynamicFrame = glueContext.getSourceWithFormat(
      formatOptions=JsonOptions("""{"jsonPath": "$.id", "multiline": true, "optimizePerformance":false}"""),
      connectionType="s3",
      format="json",
      options=JsonOptions("""{"paths": ["s3://s3path"], "recurse": true}""")
    ).getDynamicFrame()
  }
}
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
val dataFrame = spark.read
    .option("multiline", "true")
    .json("s3://s3path")
```

------

## 예: S3에 JSON 파일 및 폴더 쓰기
<a name="aws-glue-programming-etl-format-json-write"></a>

** 사전 조건:** 초기화된 DataFrame(`dataFrame`) 또는 DynamicFrame(`dynamicFrame`)이 필요합니다. 예상되는 S3 출력 경로(`s3path`)도 필요합니다.

**구성:** 함수 옵션에서 `format="json"`를 지정합니다. `connection_options`에서 `paths` 키를 사용하여 `s3path`를 지정합니다. `connection_options`에서 라이터가 S3와 상호 작용하는 방식을 추가로 변경할 수 있습니다. 자세한 내용은 AWS Glue: [Amazon S3 연결 옵션 참조](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)의 ETL 입력 및 출력에 대한 데이터 형식 옵션을 참조하세요. 작성기에서 `format_options`의 JSON 파일을 해석하는 방법을 구성할 수 있습니다. 자세한 내용은 [JSON 구성 참조](#aws-glue-programming-etl-format-json-reference)를 참조하세요.

다음 AWS Glue ETL 스크립트는 S3에서 JSON 파일 또는 폴더를 쓰는 프로세스를 보여 줍니다.

------
#### [ Python ]

이 예에서는 [write\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options) 메서드를 사용합니다.

```
# Example: Write JSON to S3

from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="s3",
    connection_options={"path": "s3://s3path"},
    format="json"
)
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
df.write.json("s3://s3path/")
```

------
#### [ Scala ]

이 예에서는 [getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat) 메서드를 사용합니다.

```
// Example: Write JSON to S3

import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    glueContext.getSinkWithFormat(
        connectionType="s3",
        options=JsonOptions("""{"path": "s3://s3path"}"""),
        format="json"
    ).writeDynamicFrame(dynamicFrame)
  }
}
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
df.write.json("s3://s3path")
```

------

## JSON 구성 참조
<a name="aws-glue-programming-etl-format-json-reference"></a>

`format="json"`으로 다음 `format_options` 값을 사용할 수 있습니다.
+ `jsonPath` - 레코드로 읽을 객체를 식별하는 [JsonPath](https://github.com/json-path/JsonPath) 표현식. 이것은 외부 배열 안에 중첩된 레코드가 파일에 있을 때 특히 유용합니다. 예를 들어, 다음 JsonPath 표현식은 JSON 객체의 `id` 필드를 대상으로 합니다.

  ```
  format="json", format_options={"jsonPath": "$.id"}
  ```
+ `multiline` - 단일 기록이 다양한 라인을 포괄할 수 있는지 여부를 지정하는 부울 값. 필드가 인용된 새로운 라인 문자를 포함할 때 발생합니다. 이 옵션을 `"true"`로 설정해야 기록이 여러 라인을 포괄할 수 있습니다. 기본값은 `"false"`이라서 파싱 동안 더 많은 공격적 파일 쪼개기가 가능합니다.
+ `optimizePerformance` - Apache Arrow 기반 열 포맷 메모리 포맷과 함께 고급 SIMD JSON 리더를 사용할지 여부를 지정하는 부울 값입니다. AWS Glue 3.0에서만 사용 가능합니다. `multiline` 또는 `jsonPath`와 호환되지 않습니다. 이러한 옵션 중 하나를 제공하면 AWS Glue에서 표준 리더로 돌아갑니다.
+ `withSchema` - [XML 스키마를 수동으로 지정](aws-glue-programming-etl-format-xml-home.md#aws-glue-programming-etl-format-xml-withschema)에 설명된 형식으로 테이블 스키마를 지정하는 문자열 값입니다. 비카탈로그 연결에서 읽을 때 `optimizePerformance`에만 사용됩니다.

## Apache Arrow 열 포맷으로 벡터화된 SIMD JSON 리더 사용
<a name="aws-glue-programming-etl-format-simd-json-reader"></a>

AWS Glue 버전 3.0은 JSON 데이터에 대한 벡터화된 리더를 추가합니다. 이 리더는 특정 조건에서 표준 리더에 비해 2배 더 빠른 성능을 발휘합니다. 이 리더에는 사용하기 전에 사용자가 알아야 할 특정 제한 사항이 있습니다(이 섹션에 설명되어 있음).

최적화된 리더를 사용하려면 `format_options` 또는 테이블 속성에서 `"optimizePerformance"`를 True로 설정합니다. 또한 카탈로그에서 읽지 않는 한 `withSchema`를 제공해야 합니다. `withSchema`는 [XML 스키마를 수동으로 지정](aws-glue-programming-etl-format-xml-home.md#aws-glue-programming-etl-format-xml-withschema)에 설명된 대로 입력을 기대합니다.

```
// Read from S3 data source        
glueContext.create_dynamic_frame.from_options(
    connection_type = "s3", 
    connection_options = {"paths": ["s3://s3path"]}, 
    format = "json", 
    format_options={
        "optimizePerformance": True,
        "withSchema": SchemaString
        })    
 
// Read from catalog table
glueContext.create_dynamic_frame.from_catalog(
    database = database, 
    table_name = table, 
    additional_options = {
    // The vectorized reader for JSON can read your schema from a catalog table property.
        "optimizePerformance": True,
        })
```

AWS Glue 라이브러리에서 *SchemaString* 구축에 대한 자세한 내용은 [PySpark 확장 유형](aws-glue-api-crawler-pyspark-extensions-types.md) 섹션을 참조하세요.

**벡터화된 CSV 리더에 대한 제한 사항**  
다음과 같은 제한 사항이 있습니다.
+ 중첩된 객체 또는 배열 값이 있는 JSON 요소는 지원되지 않습니다. 제공 시 AWS Glue는 표준 리더로 돌아갑니다.
+ 카탈로그에서 또는 `withSchema`를 사용하여 스키마를 제공해야 합니다.
+ `multiline` 또는 `jsonPath`와 호환되지 않습니다. 이러한 옵션 중 하나를 제공하면 AWS Glue에서 표준 리더로 돌아갑니다.
+ 입력 스키마와 일치하지 않는 입력 레코드를 제공하면 리더가 실패할 수 있습니다.
+ [오류 레코드](https://docs.aws.amazon.com/glue/latest/dg/glue-etl-scala-apis-glue-dynamicframe-class.html#glue-etl-scala-apis-glue-dynamicframe-class-defs-errorsAsDynamicFrame)는 생성되지 않습니다.
+ 일본어 또는 중국어와 같은 멀티바이트 문자가 포함된 JSON 파일은 지원되지 않습니다.

# AWS Glue에서 ORC 형식 사용
<a name="aws-glue-programming-etl-format-orc-home"></a>

AWS Glue는 소스에서 데이터를 검색하고 다양한 데이터 형식으로 저장 및 전송되는 대상에 데이터를 씁니다. 데이터가 ORC 데이터 형식으로 저장 또는 전송되는 경우 이 문서에서는 AWS Glue에서 데이터를 사용하는 데 사용할 수 있는 기능을 소개합니다.

AWS Glue는 ORC 형식 사용을 지원합니다. 이 형식은 성능 중심의 열 기반 데이터 형식입니다. 표준 기관의 형식에 대한 소개는 [Apache Orc](https://orc.apache.org/docs/)를 참조하세요.

AWS Glue를 사용하여 Amazon S3와 스트리밍 소스에서 ORC 파일을 읽을 수 있을 뿐만 아니라 Amazon S3에 ORC 파일을 쓸 수 있습니다. S3에서 ORC 파일이 포함된 `bzip` 및 `gzip` 아카이브를 읽고 쓸 수 있습니다. 이 페이지에서 설명하는 구성 대신 [S3 연결 파라미터](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)에서 압축 동작을 구성할 수 있습니다.

다음 표에서는 ORC 형식 옵션을 지원하는 일반적인 AWS Glue 기능을 보여 줍니다.


| 읽기 | 쓰기 | 스트리밍 읽기 | 작은 파일 그룹화 | 작업 북마크 | 
| --- | --- | --- | --- | --- | 
| 지원 | 지원 | 지원 | 지원되지 않음 | 지원\$1 | 

\$1 AWS Glue 버전 1.0 이상에서 지원

## 예: S3에서 ORC 파일 또는 폴더 읽기
<a name="aws-glue-programming-etl-format-orc-read"></a>

** 사전 조건:** 읽으려는 ORC 파일 또는 폴더에 대한 S3 경로(`s3path`)가 필요합니다.

**구성:** 함수 옵션에서 `format="orc"`를 지정합니다. `connection_options`에서 `paths` 키를 사용하여 `s3path`를 지정합니다. `connection_options`에서 리더와 S3가 상호 작용하는 방식을 구성할 수 있습니다. 자세한 내용은 AWS Glue에서 ETL 관련 연결 유형 및 옵션 참조: [Amazon S3 연결 옵션 참조](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)

 다음 AWS Glue ETL 스크립트는 S3에서 ORC 파일 또는 폴더를 읽는 프로세스를 보여 줍니다.

------
#### [ Python ]

이 예에서는 [create\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create_dynamic_frame_from_options) 메서드를 사용합니다.

```
from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

dynamicFrame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": ["s3://s3path"]},
    format="orc"
)
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
dataFrame = spark.read\
    .orc("s3://s3path")
```

------
#### [ Scala ]

이 예에서는 [getSourceWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSourceWithFormat) 작업을 사용합니다.

```
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.GlueContext
import org.apache.spark.sql.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    val dynamicFrame = glueContext.getSourceWithFormat(
      connectionType="s3",
      format="orc",
      options=JsonOptions("""{"paths": ["s3://s3path"]}""")
    ).getDynamicFrame()
  }
}
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
val dataFrame = spark.read
    .orc("s3://s3path")
```

------

## 예: S3에 ORC 파일 및 폴더 쓰기
<a name="aws-glue-programming-etl-format-orc-write"></a>

**사전 조건:** 초기화된 DataFrame(`dataFrame`) 또는 DynamicFrame(`dynamicFrame`)이 필요합니다. 예상되는 S3 출력 경로(`s3path`)도 필요합니다.

**구성:** 함수 옵션에서 `format="orc"`를 지정합니다. 연결 옵션에서 `paths` 키를 사용하여 `s3path`를 지정합니다. `connection_options`에서 라이터가 S3와 상호 작용하는 방식을 추가로 변경할 수 있습니다. 자세한 내용은 AWS Glue: [Amazon S3 연결 옵션 참조](aws-glue-programming-etl-connect-s3-home.md#aws-glue-programming-etl-connect-s3)의 ETL 입력 및 출력에 대한 데이터 형식 옵션을 참조하세요. 다음 코드 예제는 프로세스를 보여 줍니다.

------
#### [ Python ]

이 예에서는 [write\$1dynamic\$1frame.from\$1options](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_dynamic_frame_from_options) 메서드를 사용합니다.

```
from pyspark.context import SparkContext
from awsglue.context import GlueContext

sc = SparkContext.getOrCreate()
glueContext = GlueContext(sc)

glueContext.write_dynamic_frame.from_options(
    frame=dynamicFrame,
    connection_type="s3",
    format="orc",
    connection_options={
        "path": "s3://s3path"
    }
)
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
df.write.orc("s3://s3path/")
```

------
#### [ Scala ]

이 예에서는 [getSinkWithFormat](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getSinkWithFormat) 메서드를 사용합니다.

```
import com.amazonaws.services.glue.util.JsonOptions
import com.amazonaws.services.glue.{DynamicFrame, GlueContext}
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)

    glueContext.getSinkWithFormat(
      connectionType="s3",
      options=JsonOptions("""{"path": "s3://s3path"}"""),
      format="orc"
    ).writeDynamicFrame(dynamicFrame)
  }
}
```

또한 스크립트(`pyspark.sql.DataFrame`)에서 DataFrame을 사용합니다.

```
df.write.orc("s3://s3path/")
```

------

## XML 구성 참조
<a name="aws-glue-programming-etl-format-orc-reference"></a>

`format="orc"`을 위한 `format_options` 값은 없습니다. 그러나 SparkSQL 기초 코드에 의해 수락된 옵션은 `connection_options` 맵 파라미터를 거쳐 SparkSQL 기초 코드로 넘겨질 수 있습니다.

# AWS Glue ETL 작업에서 데이터 레이크 프레임워크 사용
<a name="aws-glue-programming-etl-datalake-native-frameworks"></a>

오픈 소스 데이터 레이크 프레임워크는 Amazon S3에 빌드된 데이터 레이크에 저장된 파일의 증분 데이터 처리를 간소화합니다. AWS Glue 3.0 이상에서는 다음과 같은 오픈 소스 데이터 레이크 프레임워크를 지원합니다.
+ Apache Hudi
+ Linux Foundation Delta Lake
+ Apache Iceberg

Amazon S3에 저장된 데이터를 트랜잭션적으로 일관된 방식으로 읽고 쓸 수 있도록 이러한 프레임워크에 대한 기본 지원을 제공합니다. AWS Glue ETL 작업에 이러한 프레임워크를 사용하기 위해 별도의 커넥터를 설치하거나 추가 구성 단계를 완료할 필요가 없습니다.

AWS Glue Data Catalog를 통해 데이터 세트를 관리하는 경우 Spark DataFrames에서 AWS Glue 메서드를 사용하여 데이터 레이크 테이블을 읽고 쓸 수 있습니다. Spark DataFrame API를 사용하여 Amazon S3 데이터를 읽고 쓸 수도 있습니다.

이 비디오에서는 Apache Hudi, Apache Iceberg 및 Delta Lake work의 작동 방식에 대한 기본 사항을 살펴봅니다. 데이터 레이크에서 데이터를 삽입, 업데이트 및 삭제하는 방법과 각 프레임워크의 작동 방식을 확인할 수 있습니다.

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/fryfx0Zg7KA/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/fryfx0Zg7KA)


**Topics**
+ [

# 제한 사항
](aws-glue-programming-etl-datalake-native-frameworks-limitations.md)
+ [

# AWS Glue에서 Hudi 프레임워크 사용
](aws-glue-programming-etl-format-hudi.md)
+ [

# AWS Glue에서 Delta Lake 프레임워크 사용
](aws-glue-programming-etl-format-delta-lake.md)
+ [

# AWS Glue에서 Iceberg 프레임워크 사용
](aws-glue-programming-etl-format-iceberg.md)

# 제한 사항
<a name="aws-glue-programming-etl-datalake-native-frameworks-limitations"></a>

AWS Glue에서 데이터 레이크 프레임워크를 사용하기 전에 다음 제한 사항을 고려하세요.
+ 다음 DynamicFrame의 AWS Glue `GlueContext` 방법은 데이터 레이크 프레임워크 테이블의 읽기 및 쓰기를 지원하지 않습니다. 대신 DataFrame 또는 Spark DataFrame API용 `GlueContext` 방법을 사용하십시오.
  + `create_dynamic_frame.from_catalog`
  + `write_dynamic_frame.from_catalog`
  + `getDynamicFrame`
  + `writeDynamicFrame`
+ Lake Formation 권한 제어에서는 다음과 같은 DataFrame `GlueContext` 방법이 지원됩니다.
  + `create_data_frame.from_catalog`
  + `write_data_frame.from_catalog`
  + `getDataFrame`
  + `writeDataFrame`
+ [작은 파일 그룹화](grouping-input-files.md)는 지원되지 않습니다.
+ [작업 북마크](monitor-continuations.md)는 지원되지 않습니다.
+ Apache Hudi 0.10.1 for AWS Glue 3.0은 Hudi 읽을 때 병합(MoR) 테이블을 지원하지 않습니다.
+ `ALTER TABLE … RENAME TO`는 Apache Iceberg 0.13.1 for AWS Glue 3.0에서 사용할 수 없습니다.

## Lake Formation 권한으로 관리되는 데이터 레이크 형식 테이블에 대한 제한
<a name="w2aac67c11c24c11c31c17b7"></a>

데이터 레이크 형식은 Lake Formation 권한을 통해 AWS Glue ETL과 통합됩니다. `create_dynamic_frame`를 사용하여 DynamicFrame을 생성하는 것은 지원되지 않습니다. 자세한 내용은 다음 예를 참조하세요.
+ [예: Lake Formation 권한 제어가 포함된 Iceberg 테이블 읽기 및 쓰기](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-format-iceberg.html#aws-glue-programming-etl-format-iceberg-read-write-lake-formation-tables)
+ [예: Lake Formation 권한 제어를 사용하여 Hudi 테이블 읽기 및 쓰기](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-format-hudi.html#aws-glue-programming-etl-format-hudi-read-write-lake-formation-tables)
+ [예: Lake Formation 권한 제어가 포함된 Delta Lake 테이블 읽기 및 쓰기](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-format-delta-lake.html#aws-glue-programming-etl-format-delta-lake-read-write-lake-formation-tables)

**참고**  
Apache Hudi, Apache Iceberg, Delta Lake에 대한 Lake Formation 권한을 통한 AWS Glue ETL과의 통합은 AWS Glue 버전 4.0에서만 지원됩니다.

Apache Iceberg는 Lake Formation 권한을 통해 AWS Glue ETL과 가장 잘 통합됩니다. 거의 모든 작업을 지원하며 SQL 지원을 포함합니다.

Hudi는 관리 작업을 제외한 대부분의 기본 작업을 지원합니다. 이러한 옵션은 일반적으로 데이터 프레임 작성을 통해 수행되고 `additional_options`를 통해 지정되기 때문입니다. SparkSQL은 지원되지 않으므로 AWS Glue API를 사용하여 작업을 위한 DataFrames을 생성해야 합니다.

Delta Lake는 테이블 데이터의 읽기, 추가, 덮어쓰기만 지원합니다. Delta Lake에서는 업데이트와 같은 다양한 작업을 수행하려면 자체 라이브러리를 사용해야 합니다.

Lake Formation 권한으로 관리되는 Iceberg 테이블에는 다음 기능을 사용할 수 없습니다.
+ AWS Glue ETL을 사용한 압축
+ AWS Glue ETL을 통한 Spark SQL 지원

Lake Formation 권한으로 관리되는 Hudi 테이블의 제한 사항은 다음과 같습니다.
+ 분리된 파일 제거

Lake Formation 권한으로 관리되는 Delta Lake 테이블의 제한 사항은 다음과 같습니다.
+ Delta Lake 테이블에서 삽입 및 읽기 이외의 모든 기능.

# AWS Glue에서 Hudi 프레임워크 사용
<a name="aws-glue-programming-etl-format-hudi"></a>

AWS Glue 3.0 이상에서는 데이터 레이크에 대한 Apache Hudi 프레임워크를 지원합니다. Hudi는 증분 데이터 처리 및 데이터 파이프라인 개발을 간소화하는 오픈 소스 데이터 레이크 스토리지 프레임워크입니다. 이 항목에서는 Hudi 테이블에서 데이터를 전송하거나 저장할 때 AWS Glue에서 데이터를 사용하는 데 사용할 수 있는 기능에 대해 설명합니다. Hudi에 대한 자세한 내용은 공식 [Apache Hudi 설명서](https://hudi.apache.org/docs/overview/)를 참조하세요.

AWS Glue를 사용하여 Amazon S3의 Hudi 테이블에서 읽기 및 쓰기 작업을 수행하거나 AWS Glue 데이터 카탈로그를 사용하여 Hudi 테이블로 작업할 수 있습니다. 삽입, 업데이트, 모든 [Apache Spark 작업](https://hudi.apache.org/docs/quick-start-guide/)을 포함한 추가 작업도 지원됩니다.

**참고**  
AWS Glue 5.0의 Apache Hudi 0.15.0 구현은 [HUDI-7001](https://github.com/apache/hudi/pull/9936)을 내부적으로 되돌립니다. 레코드 키가 단일 필드로 구성된 경우 복합 키 생성과 관련된 회귀를 나타내지 않습니다. 그러나 이 동작은 OSS Apache Hudi 0.15.0과 다릅니다.  
Apache Hudi 0.10.1 for AWS Glue 3.0은 Hudi 읽을 때 병합(MoR) 테이블을 지원하지 않습니다.

다음 표에는 각 AWS Glue 버전에 포함된 Hudi 버전이 나와 있습니다.


****  

| AWS Glue 버전 | 지원되는 Hudi 버전 | 
| --- | --- | 
| 5.1 | 1.0.2 | 
| 5.0 | 0.15.0 | 
| 4.0 | 0.12.1 | 
| 3.0 | 0.10.1 | 

AWS Glue가 지원하는 데이터 레이크 프레임워크에 대한 자세한 내용은 [AWS Glue ETL 작업에서 데이터 레이크 프레임워크 사용](aws-glue-programming-etl-datalake-native-frameworks.md) 섹션을 참조하세요.

## Hudi 활성화
<a name="aws-glue-programming-etl-format-hudi-enable"></a>

Hudi for AWS Glue를 활성화하려면 다음 작업을 완료합니다.
+ `hudi`를 `--datalake-formats` 작업 파라미터의 값으로 지정합니다. 자세한 내용은 [AWS Glue 작업에서 작업 파라미터 사용](aws-glue-programming-etl-glue-arguments.md) 섹션을 참조하세요.
+ AWS Glue 작업에 대한 `--conf` 키를 생성하고 다음 값으로 설정합니다. 또는 스크립트에서 `SparkConf`를 사용하여 다음 구성을 설정할 수 있습니다. 이러한 설정은 Apache Spark에서 Hudi 테이블을 올바르게 처리하는 데 도움이 됩니다.

  ```
  spark.serializer=org.apache.spark.serializer.KryoSerializer
  ```
+ Hudi에 대한 Lake Formation 권한 지원은 AWS Glue 4.0에서 기본으로 활성화되어 있습니다. Lake Formation에 등록된 Hudi 테이블을 읽고 쓰는 데 추가 구성이 필요하지 않습니다. 등록된 Hudi 테이블을 읽으려면 AWS Glue 작업 IAM 역할에 SELECT 권한이 있어야 합니다. 등록된 Hudi 테이블에 글을 쓰려면 AWS Glue 작업 IAM 역할에 SUPER 권한이 있어야 합니다. Lake Formation 권한 관리에 대해 자세히 알아보려면 [Data Catalog 리소스에 대한 권한 부여 및 취소](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-catalog-permissions.html)를 참조하십시오.

**다른 Hudi 버전 사용**

AWS Glue에서 지원하지 않는 Hudi 버전을 사용하려면 `--extra-jars` 작업 파라미터를 사용하여 고유한 Hudi JAR 파일을 지정하세요. `--datalake-formats` 작업 파라미터의 값으로 `hudi`를 포함하지 마세요. AWS Glue 5.0 이상을 사용하는 경우, `--user-jars-first true` 작업 파라미터를 설정해야 합니다.

## 예: Amazon S3에 Hudi 테이블을 작성하고 AWS Glue 데이터 카탈로그에 등록
<a name="aws-glue-programming-etl-format-hudi-write"></a>

이 예제 스크립트는 Amazon S3에 Hudi 테이블을 작성하고 AWS Glue 데이터 카탈로그에 테이블을 등록하는 방법을 보여줍니다. 이 예제에서는 Hudi [Hive Sync 도구](https://hudi.apache.org/docs/syncing_metastore/)를 사용하여 테이블을 등록합니다.

**참고**  
이 예에서는 AWS Glue 데이터 카탈로그를 Apache Spark Hive 메타스토어로 사용하기 위해 `--enable-glue-datacatalog` 작업 파라미터를 설정해야 합니다. 자세한 내용은 [AWS Glue 작업에서 작업 파라미터 사용](aws-glue-programming-etl-glue-arguments.md)를 참조하세요.

------
#### [ Python ]

```
# Example: Create a Hudi table from a DataFrame 
# and register the table to Glue Data Catalog

additional_options={
    "hoodie.table.name": "<your_table_name>",
    "hoodie.database.name": "<your_database_name>",
    "hoodie.datasource.write.storage.type": "COPY_ON_WRITE",
    "hoodie.datasource.write.operation": "upsert",
    "hoodie.datasource.write.recordkey.field": "<your_recordkey_field>",
    "hoodie.datasource.write.precombine.field": "<your_precombine_field>",
    "hoodie.datasource.write.partitionpath.field": "<your_partitionkey_field>",
    "hoodie.datasource.write.hive_style_partitioning": "true",
    "hoodie.datasource.hive_sync.enable": "true",
    "hoodie.datasource.hive_sync.database": "<your_database_name>",
    "hoodie.datasource.hive_sync.table": "<your_table_name>",
    "hoodie.datasource.hive_sync.partition_fields": "<your_partitionkey_field>",
    "hoodie.datasource.hive_sync.partition_extractor_class": "org.apache.hudi.hive.MultiPartKeysValueExtractor",
    "hoodie.datasource.hive_sync.use_jdbc": "false",
    "hoodie.datasource.hive_sync.mode": "hms",
    "path": "s3://<s3Path/>"
}

dataFrame.write.format("hudi") \
    .options(**additional_options) \
    .mode("overwrite") \
    .save()
```

------
#### [ Scala ]

```
// Example: Example: Create a Hudi table from a DataFrame
// and register the table to Glue Data Catalog

val additionalOptions = Map(
  "hoodie.table.name" -> "<your_table_name>",
  "hoodie.database.name" -> "<your_database_name>",
  "hoodie.datasource.write.storage.type" -> "COPY_ON_WRITE",
  "hoodie.datasource.write.operation" -> "upsert",
  "hoodie.datasource.write.recordkey.field" -> "<your_recordkey_field>",
  "hoodie.datasource.write.precombine.field" -> "<your_precombine_field>",
  "hoodie.datasource.write.partitionpath.field" -> "<your_partitionkey_field>",
  "hoodie.datasource.write.hive_style_partitioning" -> "true",
  "hoodie.datasource.hive_sync.enable" -> "true",
  "hoodie.datasource.hive_sync.database" -> "<your_database_name>",
  "hoodie.datasource.hive_sync.table" -> "<your_table_name>",
  "hoodie.datasource.hive_sync.partition_fields" -> "<your_partitionkey_field>",
  "hoodie.datasource.hive_sync.partition_extractor_class" -> "org.apache.hudi.hive.MultiPartKeysValueExtractor",
  "hoodie.datasource.hive_sync.use_jdbc" -> "false",
  "hoodie.datasource.hive_sync.mode" -> "hms",
  "path" -> "s3://<s3Path/>")

dataFrame.write.format("hudi")
  .options(additionalOptions)
  .mode("append")
  .save()
```

------

## 예: AWS Glue 데이터 카탈로그를 사용하여 Amazon S3에서 Hudi 테이블 읽기
<a name="aws-glue-programming-etl-format-hudi-read"></a>

이 예에서는 Amazon S3의 [예: Amazon S3에 Hudi 테이블을 작성하고 AWS Glue 데이터 카탈로그에 등록](#aws-glue-programming-etl-format-hudi-write)에서 생성한 Hudi 테이블을 읽습니다.

**참고**  
이 예에서는 AWS Glue 데이터 카탈로그를 Apache Spark Hive 메타스토어로 사용하기 위해 `--enable-glue-datacatalog` 작업 파라미터를 설정해야 합니다. 자세한 내용은 [AWS Glue 작업에서 작업 파라미터 사용](aws-glue-programming-etl-glue-arguments.md)를 참조하세요.

------
#### [ Python ]

이 예에서는 `GlueContext.create\$1data\$1frame.from\$1catalog()` 메서드를 사용합니다.

```
# Example: Read a Hudi table from Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

dataFrame = glueContext.create_data_frame.from_catalog(
    database = "<your_database_name>",
    table_name = "<your_table_name>"
)
```

------
#### [ Scala ]

이 예에서는 [getCatalogSource](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSource) 메서드를 사용합니다.

```
// Example: Read a Hudi table from Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import org.apache.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    
    val dataFrame = glueContext.getCatalogSource(
      database = "<your_database_name>",
      tableName = "<your_table_name>"
    ).getDataFrame()
  }
}
```

------

## 예: Amazon S3의 Hudi 테이블에서 `DataFrame` 업데이트 및 삽입
<a name="aws-glue-programming-etl-format-hudi-update-insert"></a>

이 예제에서는 AWS Glue 데이터 카탈로그를 사용하여 [예: Amazon S3에 Hudi 테이블을 작성하고 AWS Glue 데이터 카탈로그에 등록](#aws-glue-programming-etl-format-hudi-write)에서 생성한 Hudi 테이블에 DataFrame을 삽입합니다.

**참고**  
이 예에서는 AWS Glue 데이터 카탈로그를 Apache Spark Hive 메타스토어로 사용하기 위해 `--enable-glue-datacatalog` 작업 파라미터를 설정해야 합니다. 자세한 내용은 [AWS Glue 작업에서 작업 파라미터 사용](aws-glue-programming-etl-glue-arguments.md)를 참조하세요.

------
#### [ Python ]

이 예에서는 `GlueContext.write\$1data\$1frame.from\$1catalog()` 메서드를 사용합니다.

```
# Example: Upsert a Hudi table from Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

glueContext.write_data_frame.from_catalog(
    frame = dataFrame,
    database = "<your_database_name>",
    table_name = "<your_table_name>",
    additional_options={
        "hoodie.table.name": "<your_table_name>",
        "hoodie.database.name": "<your_database_name>",
        "hoodie.datasource.write.storage.type": "COPY_ON_WRITE",
        "hoodie.datasource.write.operation": "upsert",
        "hoodie.datasource.write.recordkey.field": "<your_recordkey_field>",
        "hoodie.datasource.write.precombine.field": "<your_precombine_field>",
        "hoodie.datasource.write.partitionpath.field": "<your_partitionkey_field>",
        "hoodie.datasource.write.hive_style_partitioning": "true",
        "hoodie.datasource.hive_sync.enable": "true",
        "hoodie.datasource.hive_sync.database": "<your_database_name>",
        "hoodie.datasource.hive_sync.table": "<your_table_name>",
        "hoodie.datasource.hive_sync.partition_fields": "<your_partitionkey_field>",
        "hoodie.datasource.hive_sync.partition_extractor_class": "org.apache.hudi.hive.MultiPartKeysValueExtractor",
        "hoodie.datasource.hive_sync.use_jdbc": "false",
        "hoodie.datasource.hive_sync.mode": "hms"
    }
)
```

------
#### [ Scala ]

이 예에서는 [getCatalogSink](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSink) 메서드를 사용합니다.

```
// Example: Upsert a Hudi table from Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.util.JsonOptions
import org.apacke.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    glueContext.getCatalogSink("<your_database_name>", "<your_table_name>",
      additionalOptions = JsonOptions(Map(
        "hoodie.table.name" -> "<your_table_name>",
        "hoodie.database.name" -> "<your_database_name>",
        "hoodie.datasource.write.storage.type" -> "COPY_ON_WRITE",
        "hoodie.datasource.write.operation" -> "upsert",
        "hoodie.datasource.write.recordkey.field" -> "<your_recordkey_field>",
        "hoodie.datasource.write.precombine.field" -> "<your_precombine_field>",
        "hoodie.datasource.write.partitionpath.field" -> "<your_partitionkey_field>",
        "hoodie.datasource.write.hive_style_partitioning" -> "true",
        "hoodie.datasource.hive_sync.enable" -> "true",
        "hoodie.datasource.hive_sync.database" -> "<your_database_name>",
        "hoodie.datasource.hive_sync.table" -> "<your_table_name>",
        "hoodie.datasource.hive_sync.partition_fields" -> "<your_partitionkey_field>",
        "hoodie.datasource.hive_sync.partition_extractor_class" -> "org.apache.hudi.hive.MultiPartKeysValueExtractor",
        "hoodie.datasource.hive_sync.use_jdbc" -> "false",
        "hoodie.datasource.hive_sync.mode" -> "hms"
      )))
      .writeDataFrame(dataFrame, glueContext)
  }
}
```

------

## 예: Spark를 사용하여 Amazon S3에서 Hudi 테이블 읽기
<a name="aws-glue-programming-etl-format-hudi-read-spark"></a>

이 예에서는 Spark DataFrame API를 사용하여 Amazon S3에서 Hudi 테이블을 읽습니다.

------
#### [ Python ]

```
# Example: Read a Hudi table from S3 using a Spark DataFrame

dataFrame = spark.read.format("hudi").load("s3://<s3path/>")
```

------
#### [ Scala ]

```
// Example: Read a Hudi table from S3 using a Spark DataFrame

val dataFrame = spark.read.format("hudi").load("s3://<s3path/>")
```

------

## 예: Spark를 사용하여 Amazon S3에 Hudi 테이블 쓰기
<a name="aws-glue-programming-etl-format-hudi-write-spark"></a>

이 예에서는 Spark를 사용하여 Amazon S3에 Hudi 테이블을 씁니다.

------
#### [ Python ]

```
# Example: Write a Hudi table to S3 using a Spark DataFrame

dataFrame.write.format("hudi") \
    .options(**additional_options) \
    .mode("overwrite") \
    .save("s3://<s3Path/>)
```

------
#### [ Scala ]

```
// Example: Write a Hudi table to S3 using a Spark DataFrame

dataFrame.write.format("hudi")
  .options(additionalOptions)
  .mode("overwrite")
  .save("s3://<s3path/>")
```

------

## 예: Lake Formation 권한 제어를 사용하여 Hudi 테이블 읽기 및 쓰기
<a name="aws-glue-programming-etl-format-hudi-read-write-lake-formation-tables"></a>

이 예제에서는 Lake Formation 권한 제어가 있는 Hudi 테이블을 읽고 씁니다.

1. Hudi 테이블을 생성하여 Lake Formation에 등록합니다.

   1. Lake Formation 권한 제어를 활성화하려면 먼저 Lake Formation에 Amazon S3 경로를 등록해야 합니다. 자세한 내용을 알아보려면 [Registering an Amazon S3 location](https://docs.aws.amazon.com/lake-formation/latest/dg/register-location.html)(Amazon S3 위치 등록)을 참조하세요. Lake Formation 콘솔에서 등록하거나 AWS CLI를 사용하여 등록할 수 있습니다.

      ```
      aws lakeformation register-resource --resource-arn arn:aws:s3:::<s3-bucket>/<s3-folder> --use-service-linked-role --region <REGION>
      ```

      Amazon S3 위치를 등록하면 해당 위치(또는 하위 위치)를 가리키는 AWS Glue 테이블이 `GetTable` 호출 시 `IsRegisteredWithLakeFormation` 파라미터 값을 true로 반환합니다.

   1. Spark 데이터프레임 API를 통해 등록된 Amazon S3 경로를 가리키는 Hudi 테이블을 생성합니다.

      ```
      hudi_options = {
          'hoodie.table.name': table_name,
          'hoodie.database.name': database_name,
          'hoodie.datasource.write.storage.type': 'COPY_ON_WRITE',
          'hoodie.datasource.write.recordkey.field': 'product_id',
          'hoodie.datasource.write.table.name': table_name,
          'hoodie.datasource.write.operation': 'upsert',
          'hoodie.datasource.write.precombine.field': 'updated_at',
          'hoodie.datasource.write.hive_style_partitioning': 'true',
          'hoodie.upsert.shuffle.parallelism': 2,
          'hoodie.insert.shuffle.parallelism': 2,
          'path': <S3_TABLE_LOCATION>,
          'hoodie.datasource.hive_sync.enable': 'true',
          'hoodie.datasource.hive_sync.database': database_name,
          'hoodie.datasource.hive_sync.table': table_name,
          'hoodie.datasource.hive_sync.use_jdbc': 'false',
          'hoodie.datasource.hive_sync.mode': 'hms'
      }
      
      df_products.write.format("hudi")  \
          .options(**hudi_options)  \
          .mode("overwrite")  \
          .save()
      ```

1. AWSGlue 작업 IAM 역할에 Lake Formation 권한을 부여하십시오. Lake Formation 콘솔에서 권한을 부여하거나 AWS CLI를 사용하여 권한을 부여할 수 있습니다. 자세한 내용을 알아보려면 [Lake Formation 콘솔 및 명명된 리소스 방법을 사용하여 데이터베이스 권한 부여](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-table-permissions.html)를 참조하십시오

1.  Lake Formation에 등록된 Hudi 테이블을 읽어보십시오. 코드는 등록되지 않은 Hudi 테이블을 읽는 것과 같습니다. 읽기에 성공하려면 AWS Glue 작업 IAM 역할에 SELECT 권한이 있어야 한다는 점에 유의하십시오.

   ```
    val dataFrame = glueContext.getCatalogSource(
         database = "<your_database_name>",
         tableName = "<your_table_name>"
       ).getDataFrame()
   ```

1. Lake Formation에 등록된 Hudi 테이블에 글을 작성하십시오. 코드는 등록되지 않은 Hudi 테이블에 쓰는 것과 같습니다. 참고로 AWS Glue 작업 IAM 역할에 SUPER 권한이 있어야 쓰기가 성공합니다.

   ```
   glueContext.getCatalogSink("<your_database_name>", "<your_table_name>",
         additionalOptions = JsonOptions(Map(
           "hoodie.table.name" -> "<your_table_name>",
           "hoodie.database.name" -> "<your_database_name>",
           "hoodie.datasource.write.storage.type" -> "COPY_ON_WRITE",
           "hoodie.datasource.write.operation" -> "<write_operation>",
           "hoodie.datasource.write.recordkey.field" -> "<your_recordkey_field>",
           "hoodie.datasource.write.precombine.field" -> "<your_precombine_field>",
           "hoodie.datasource.write.partitionpath.field" -> "<your_partitionkey_field>",
           "hoodie.datasource.write.hive_style_partitioning" -> "true",
           "hoodie.datasource.hive_sync.enable" -> "true",
           "hoodie.datasource.hive_sync.database" -> "<your_database_name>",
           "hoodie.datasource.hive_sync.table" -> "<your_table_name>",
           "hoodie.datasource.hive_sync.partition_fields" -> "<your_partitionkey_field>",
           "hoodie.datasource.hive_sync.partition_extractor_class" -> "org.apache.hudi.hive.MultiPartKeysValueExtractor",
           "hoodie.datasource.hive_sync.use_jdbc" -> "false",
           "hoodie.datasource.hive_sync.mode" -> "hms"
         )))
         .writeDataFrame(dataFrame, glueContext)
   ```

# AWS Glue에서 Delta Lake 프레임워크 사용
<a name="aws-glue-programming-etl-format-delta-lake"></a>

AWS Glue 3.0 이상은 Linux Foundation Delta Lake 프레임워크를 지원합니다. Delta Lake는 ACID 트랜잭션을 수행하고, 메타데이터 처리를 확장하고, 스트리밍 및 배치 데이터 처리를 통합하는 데 도움이 되는 오픈 소스 데이터 레이크 스토리지 프레임워크입니다. 이 항목에서는 Delta Lake 테이블에서 데이터를 전송하거나 저장할 때 AWS Glue에서 데이터를 사용하는 데 사용할 수 있는 기능에 대해 설명합니다. Delta Lake에 대한 자세한 내용은 공식 [Delta Lake 설명서](https://docs.delta.io/latest/delta-intro.html)를 참조하세요.

AWS Glue를 사용하여 Amazon S3의 Delta Lake 테이블에서 읽기 및 쓰기 작업을 수행하거나 AWS Glue 데이터 카탈로그를 사용하여 Delta Lake 테이블로 작업할 수 있습니다. 삽입, 업데이트, [테이블 배치 읽기 및 쓰기](https://docs.delta.io/0.7.0/api/python/index.html)와 같은 추가 작업도 지원됩니다. Delta Lake 테이블을 사용할 경우 Delta Lake Python 라이브러리(예: `DeltaTable.forPath`)의 메서드를 사용할 수도 있습니다. Delta Lake Python 라이브러리에 대한 자세한 내용은 Delta Lake의 Python 설명서를 참조하세요.

다음 표에는 각 AWS Glue 버전에 포함된 Delta Lake의 버전이 나와 있습니다.


****  

| AWS Glue 버전 | 지원되는 Delta Lake 버전 | 
| --- | --- | 
| 5.1 | 3.3.2 | 
| 5.0 | 3.3.0 | 
| 4.0 | 2.1.0 | 
| 3.0 | 1.0.0 | 

AWS Glue가 지원하는 데이터 레이크 프레임워크에 대한 자세한 내용은 [AWS Glue ETL 작업에서 데이터 레이크 프레임워크 사용](aws-glue-programming-etl-datalake-native-frameworks.md) 섹션을 참조하세요.

## Delta Lake for AWS Glue 활성화
<a name="aws-glue-programming-etl-format-delta-lake-enable"></a>

Delta Lake for AWS Glue를 활성화하려면 다음 작업을 완료합니다.
+ `delta`를 `--datalake-formats` 작업 파라미터의 값으로 지정합니다. 자세한 내용은 [AWS Glue 작업에서 작업 파라미터 사용](aws-glue-programming-etl-glue-arguments.md) 섹션을 참조하세요.
+ AWS Glue 작업에 대한 `--conf` 키를 생성하고 다음 값으로 설정합니다. 또는 스크립트에서 `SparkConf`를 사용하여 다음 구성을 설정할 수 있습니다. 이러한 설정은 Apache Spark에서 Delta Lake 테이블을 올바르게 처리하는 데 도움이 됩니다.

  ```
  spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension --conf spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog --conf spark.delta.logStore.class=org.apache.spark.sql.delta.storage.S3SingleDriverLogStore
  ```
+ Delta 테이블에 대한 Lake Formation 권한 지원은 AWS Glue 4.0에서 기본적으로 활성화되어 있습니다. Lake Formation에 등록된 Delta 테이블을 읽고 쓰는 데 추가 구성이 필요하지 않습니다. 등록된 Delta 테이블을 읽으려면 AWS Glue 작업 IAM 역할에 SELECT 권한이 있어야 합니다. 등록된 Delta 테이블에 쓰려면 AWS Glue 작업 IAM 역할에 SUPER 권한이 있어야 합니다. Lake Formation 권한 관리에 대해 자세히 알아보려면 [Data Catalog 리소스에 대한 권한 부여 및 취소](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-catalog-permissions.html)를 참조하십시오.

**다른 Delta Lake 버전 사용**

AWS Glue에서 지원하지 않는 Delta Lake 버전을 사용하려면 `--extra-jars` 작업 파라미터를 사용하여 고유한 Delta Lake JAR 파일을 지정하세요. `--datalake-formats` 작업 파라미터의 값으로 `delta`를 포함하지 마세요. AWS Glue 5.0 이상을 사용하는 경우, `--user-jars-first true` 작업 파라미터를 설정해야 합니다. 이 경우에 Delta Lake Python 라이브러리를 사용하려면 `--extra-py-files` 작업 파라미터를 사용하여 라이브러리 JAR 파일을 지정해야 합니다. Python 라이브러리는 Delta Lake JAR 파일에 패키징되어 제공됩니다.

## 예: Amazon S3에 Delta Lake 테이블을 작성하고 AWS Glue 데이터 카탈로그에 등록
<a name="aws-glue-programming-etl-format-delta-lake-write"></a>

다음 AWS Glue ETL 스크립트는 Amazon S3에 Delta Lake 테이블을 작성하고 AWS Glue 데이터 카탈로그에 테이블을 등록하는 방법을 보여줍니다.

------
#### [ Python ]

```
# Example: Create a Delta Lake table from a DataFrame 
# and register the table to Glue Data Catalog

additional_options = {
    "path": "s3://<s3Path>"
}
dataFrame.write \
    .format("delta") \
    .options(**additional_options) \
    .mode("append") \
    .partitionBy("<your_partitionkey_field>") \
    .saveAsTable("<your_database_name>.<your_table_name>")
```

------
#### [ Scala ]

```
// Example: Example: Create a Delta Lake table from a DataFrame
// and register the table to Glue Data Catalog

val additional_options = Map(
  "path" -> "s3://<s3Path>"
)
dataFrame.write.format("delta")
  .options(additional_options)
  .mode("append")
  .partitionBy("<your_partitionkey_field>")
  .saveAsTable("<your_database_name>.<your_table_name>")
```

------

## 예: AWS Glue 데이터 카탈로그를 사용하여 Amazon S3에서 Delta Lake 테이블 읽기
<a name="aws-glue-programming-etl-format-delta-lake-read"></a>

다음 AWS Glue ETL 스크립트는 [예: Amazon S3에 Delta Lake 테이블을 작성하고 AWS Glue 데이터 카탈로그에 등록](#aws-glue-programming-etl-format-delta-lake-write)에서 생성한 Delta Lake 테이블을 읽습니다.

------
#### [ Python ]

이 예에서는 [create\$1data\$1frame.from\$1catalog](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-create-dataframe-from-catalog) 메서드를 사용합니다.

```
# Example: Read a Delta Lake table from Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

df = glueContext.create_data_frame.from_catalog(
    database="<your_database_name>",
    table_name="<your_table_name>",
    additional_options=additional_options
)
```

------
#### [ Scala ]

이 예에서는 [getCatalogSource](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSource) 메서드를 사용합니다.

```
// Example: Read a Delta Lake table from Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import org.apacke.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val df = glueContext.getCatalogSource("<your_database_name>", "<your_table_name>",
      additionalOptions = additionalOptions)
      .getDataFrame()
  }
}
```

------

## 예: AWS Glue 데이터 카탈로그를 사용하여 Amazon S3에서 Delta Lake 테이블에 `DataFrame` 삽입
<a name="aws-glue-programming-etl-format-delta-lake-insert"></a>

이 예에서는 [예: Amazon S3에 Delta Lake 테이블을 작성하고 AWS Glue 데이터 카탈로그에 등록](#aws-glue-programming-etl-format-delta-lake-write)에서 생성한 Delta Lake 테이블에 데이터를 삽입합니다.

**참고**  
이 예에서는 AWS Glue 데이터 카탈로그를 Apache Spark Hive 메타스토어로 사용하기 위해 `--enable-glue-datacatalog` 작업 파라미터를 설정해야 합니다. 자세한 내용은 [AWS Glue 작업에서 작업 파라미터 사용](aws-glue-programming-etl-glue-arguments.md)를 참조하세요.

------
#### [ Python ]

이 예에서는 [write\$1data\$1frame.from\$1catalog](aws-glue-api-crawler-pyspark-extensions-glue-context.md#aws-glue-api-crawler-pyspark-extensions-glue-context-write_data_frame_from_catalog) 메서드를 사용합니다.

```
# Example: Insert into a Delta Lake table in S3 using Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

glueContext.write_data_frame.from_catalog(
    frame=dataFrame,
    database="<your_database_name>",
    table_name="<your_table_name>",
    additional_options=additional_options
)
```

------
#### [ Scala ]

이 예에서는 [getCatalogSink](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSink) 메서드를 사용합니다.

```
// Example: Insert into a Delta Lake table in S3 using Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import org.apacke.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    glueContext.getCatalogSink("<your_database_name>", "<your_table_name>",
      additionalOptions = additionalOptions)
      .writeDataFrame(dataFrame, glueContext)
  }
}
```

------

## 예: Spark API를 사용하여 Amazon S3에서 Delta Lake 테이블 읽기
<a name="aws-glue-programming-etl-format-delta_lake-read-spark"></a>

이 예에서는 Spark API를 사용하여 Amazon S3에서 Delta Lake 테이블을 읽습니다.

------
#### [ Python ]

```
# Example: Read a Delta Lake table from S3 using a Spark DataFrame

dataFrame = spark.read.format("delta").load("s3://<s3path/>")
```

------
#### [ Scala ]

```
// Example: Read a Delta Lake table from S3 using a Spark DataFrame

val dataFrame = spark.read.format("delta").load("s3://<s3path/>")
```

------

## 예: Spark를 사용하여 Amazon S3에 Delta Lake 테이블 쓰기
<a name="aws-glue-programming-etl-format-delta_lake-write-spark"></a>

이 예에서는 Spark를 사용하여 Amazon S3에 Delta Lake 테이블을 씁니다.

------
#### [ Python ]

```
# Example: Write a Delta Lake table to S3 using a Spark DataFrame

dataFrame.write.format("delta") \
    .options(**additional_options) \
    .mode("overwrite") \
    .partitionBy("<your_partitionkey_field>")
    .save("s3://<s3Path>")
```

------
#### [ Scala ]

```
// Example: Write a Delta Lake table to S3 using a Spark DataFrame

dataFrame.write.format("delta")
  .options(additionalOptions)
  .mode("overwrite")
  .partitionBy("<your_partitionkey_field>")
  .save("s3://<s3path/>")
```

------

## 예: Lake Formation 권한 제어가 포함된 Delta Lake 테이블 읽기 및 쓰기
<a name="aws-glue-programming-etl-format-delta-lake-read-write-lake-formation-tables"></a>

이 예제에서는 Lake Formation 권한 제어를 사용하여 Delta Lake 테이블을 읽고 씁니다.

1. Delta 테이블을 생성하여 Lake Formation에 등록하기

   1. Lake Formation 권한 제어를 활성화하려면 먼저 Lake Formation에 Amazon S3 경로를 등록해야 합니다. 자세한 내용을 알아보려면 [Registering an Amazon S3 location](https://docs.aws.amazon.com/lake-formation/latest/dg/register-location.html)(Amazon S3 위치 등록)을 참조하세요. Lake Formation 콘솔에서 등록하거나 AWS CLI를 사용하여 등록할 수 있습니다.

      ```
      aws lakeformation register-resource --resource-arn arn:aws:s3:::<s3-bucket>/<s3-folder> --use-service-linked-role --region <REGION>
      ```

      Amazon S3 위치를 등록하면 해당 위치(또는 하위 위치)를 가리키는 AWS Glue 테이블이 `GetTable` 호출 시 `IsRegisteredWithLakeFormation` 파라미터 값을 true로 반환합니다.

   1. Spark를 통해 등록된 Amazon S3 경로를 가리키는 Delta 테이블을 생성합니다.
**참고**  
Python의 예를 들면 다음과 같습니다.

      ```
      dataFrame.write \
      	.format("delta") \
      	.mode("overwrite") \
      	.partitionBy("<your_partitionkey_field>") \
      	.save("s3://<the_s3_path>")
      ```

      Amazon S3에 데이터를 기록한 후 AWS Glue 크롤러를 사용하여 새 Delta 카탈로그 테이블을 생성합니다. 자세한 내용은 [AWSGlue 크롤러를 통한 네이티브 Delta Lake 테이블 지원 소개](https://aws.amazon.com/blogs/big-data/introducing-native-delta-lake-table-support-with-aws-glue-crawlers/)를 참조하십시오.

      AWSGlue `CreateTable` API를 통해 테이블을 수동으로 생성할 수도 있습니다.

1. AWSGlue 작업 IAM 역할에 Lake Formation 권한을 부여하십시오. Lake Formation 콘솔에서 권한을 부여하거나 AWS CLI를 사용하여 권한을 부여할 수 있습니다. 자세한 내용을 알아보려면 [Lake Formation 콘솔 및 명명된 리소스 방법을 사용하여 데이터베이스 권한 부여](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-table-permissions.html)를 참조하십시오

1.  Lake Formation에 등록된 Delta 테이블을 읽어보십시오. 코드는 등록되지 않은 Delta 테이블을 읽는 것과 같습니다. 읽기에 성공하려면 AWS Glue 작업 IAM 역할에 SELECT 권한이 있어야 한다는 점에 유의하십시오.

   ```
   # Example: Read a Delta Lake table from Glue Data Catalog
   
   df = glueContext.create_data_frame.from_catalog(
       database="<your_database_name>",
       table_name="<your_table_name>",
       additional_options=additional_options
   )
   ```

1. Lake Formation에 등록된 Delta 테이블에 글을 씁니다. 코드는 등록되지 않은 Delta 테이블에 쓰는 것과 같습니다. 참고로 AWS Glue 작업 IAM 역할에 SUPER 권한이 있어야 쓰기가 성공합니다.

   기본 설정상 AWS Glue는 `Append`를 saveMode로 사용합니다. `additional_options`에서 saveMode 옵션을 설정하여 변경할 수 있습니다. Delta 테이블의 saveMode 지원에 대한 자세한 내용은 [테이블에 쓰기](https://docs.delta.io/latest/delta-batch.html#write-to-a-table)를 참조하십시오.

   ```
   glueContext.write_data_frame.from_catalog(
       frame=dataFrame,
       database="<your_database_name>",
       table_name="<your_table_name>",
       additional_options=additional_options
   )
   ```

# AWS Glue에서 Iceberg 프레임워크 사용
<a name="aws-glue-programming-etl-format-iceberg"></a>

AWS Glue 3.0 이상에서는 데이터 레이크에 대한 Apache Iceberg 프레임워크를 지원합니다. Iceberg는 SQL 테이블처럼 작동하는 고성능 테이블 형식을 제공합니다. 이 항목에서는 Iceberg 테이블에서 데이터를 전송하거나 저장할 때 AWS Glue에서 데이터를 사용하는 데 사용할 수 있는 기능에 대해 설명합니다. Iceberg에 대한 자세한 내용은 공식 [Apache Iceberg 설명서](https://iceberg.apache.org/docs/latest/)를 참조하세요.

AWS Glue를 사용하여 Amazon S3의 Iceberg 테이블에서 읽기 및 쓰기 작업을 수행하거나 AWS Glue 데이터 카탈로그를 사용하여 Iceberg 테이블로 작업할 수 있습니다. 삽입 및 모든 [Spark 쿼리](https://iceberg.apache.org/docs/latest/spark-queries/) [Spark 쓰기](https://iceberg.apache.org/docs/latest/spark-writes/)를 포함한 추가 작업도 지원됩니다. Iceberg 테이블에 대한 업데이트는 지원되지 않습니다.

**참고**  
`ALTER TABLE … RENAME TO`는 Apache Iceberg 0.13.1 for AWS Glue 3.0에서 사용할 수 없습니다.

다음 표에는 각 AWS Glue 버전에 포함된 Iceberg의 버전이 나와 있습니다.


****  

| AWS Glue 버전 | 지원되는 Iceberg 버전 | 
| --- | --- | 
| 5.1 | 1.10.0 | 
| 5.0 | 1.7.1 | 
| 4.0 | 1.0.0 | 
| 3.0 | 0.13.1 | 

AWS Glue가 지원하는 데이터 레이크 프레임워크에 대한 자세한 내용은 [AWS Glue ETL 작업에서 데이터 레이크 프레임워크 사용](aws-glue-programming-etl-datalake-native-frameworks.md) 섹션을 참조하세요.

## Iceberg 프레임워크 활성화
<a name="aws-glue-programming-etl-format-iceberg-enable"></a>

Iceberg for AWS Glue를 활성화하려면 다음 작업을 완료합니다.
+ `iceberg`를 `--datalake-formats` 작업 파라미터의 값으로 지정합니다. 자세한 내용은 [AWS Glue 작업에서 작업 파라미터 사용](aws-glue-programming-etl-glue-arguments.md) 섹션을 참조하세요.
+ AWS Glue 작업에 대한 `--conf` 키를 생성하고 다음 값으로 설정합니다. 또는 스크립트에서 `SparkConf`를 사용하여 다음 구성을 설정할 수 있습니다. 이러한 설정은 Apache Spark에서 Iceberg 테이블을 올바르게 처리하는 데 도움이 됩니다.

  ```
  spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions 
  --conf spark.sql.catalog.glue_catalog=org.apache.iceberg.spark.SparkCatalog 
  --conf spark.sql.catalog.glue_catalog.warehouse=s3://<your-warehouse-dir>/ 
  --conf spark.sql.catalog.glue_catalog.catalog-impl=org.apache.iceberg.aws.glue.GlueCatalog 
  --conf spark.sql.catalog.glue_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO
  ```

  Lake Formation에 등록된 Iceberg 테이블을 읽거나 쓰는 경우 AWS Glue 5.0 이상 [세분화된 액세스 제어를 위해 AWS Lake Formation과 함께 AWS Glue 사용](security-lf-enable.md)에서의 지침을 따르세요. AWS Glue 4.0에서 다음 구성을 추가하여 Lake Formation 지원을 활성화합니다.

  ```
  --conf spark.sql.catalog.glue_catalog.glue.lakeformation-enabled=true
  --conf spark.sql.catalog.glue_catalog.glue.id=<table-catalog-id>
  ```

  AWS Glue 3.0을 Iceberg 0.13.1과 함께 사용하는 경우 Amazon DynamoDB 잠금 관리자를 사용하여 원자성 트랜잭션을 보장하려면 다음과 같은 추가 구성을 설정해야 합니다. AWS Glue 4.0 이상은 기본적으로 낙관적 잠금을 사용합니다. 자세한 내용은 공식 Apache Iceberg 설명서의 [Iceberg AWS 통합](https://iceberg.apache.org/docs/latest/aws/#dynamodb-lock-manager)을 참조하세요.

  ```
  --conf spark.sql.catalog.glue_catalog.lock-impl=org.apache.iceberg.aws.glue.DynamoLockManager 
  --conf spark.sql.catalog.glue_catalog.lock.table=<your-dynamodb-table-name>
  ```

**다른 Iceberg 버전 사용**

AWS Glue에서 지원하지 않는 Iceberg 버전을 사용하려면 `--extra-jars` 작업 파라미터를 사용하여 고유한 Iceberg JAR 파일을 지정하세요. `--datalake-formats` 파라미터의 값으로 `iceberg`를 포함하지 마세요. AWS Glue 5.0 이상을 사용하는 경우, `--user-jars-first true` 작업 파라미터를 설정해야 합니다.

**Iceberg 테이블에 대한 암호화 활성화**

**참고**  
Iceberg 테이블에는 서버 측 암호화를 활성화하는 자체 메커니즘이 있습니다. AWS Glue의 보안 구성 외에도 이 구성을 활성화해야 합니다.

Iceberg 테이블에서 서버 측 암호화를 활성화하려면 [Iceberg 설명서](https://iceberg.apache.org/docs/latest/aws/#s3-server-side-encryption)의 지침을 검토하세요.

**Iceberg 교차 리전에 대한 Spark 구성 추가**

AWS Glue Data Catalog 및 AWS Lake Formation을 사용하여 Iceberg 교차 리전 테이블 액세스에 대한 스파크 구성을 추가하려면 아래 단계를 따르세요.

1. [다중 리전 액세스 포인트](https://docs.aws.amazon.com/AmazonS3/latest/userguide/multi-region-access-point-create-examples.html)를 생성합니다.

1. 다음 Spark 속성을 설정합니다.

   ```
   -----
       --conf spark.sql.catalog.my_catalog.s3.use-arn-region-enabled=true \
       --conf spark.sql.catalog.{CATALOG}.s3.access-points.bucket1", "arn:aws:s3::<account-id>:accesspoint/<mrap-id>.mrap \
       --conf spark.sql.catalog.{CATALOG}.s3.access-points.bucket2", "arn:aws:s3::<account-id>:accesspoint/<mrap-id>.mrap
   -----
   ```

## 예: Amazon S3에 Iceberg 테이블을 작성하고 AWS Glue 데이터 카탈로그에 등록
<a name="aws-glue-programming-etl-format-iceberg-write"></a>

이 예제 스크립트는 Amazon S3에 Iceberg 테이블을 쓰는 방법을 보여줍니다. 이 예제에서는 [Iceberg AWS 통합](https://iceberg.apache.org/docs/latest/aws/)을 사용하여 테이블을 AWS Glue 데이터 카탈로그에 등록합니다.

------
#### [ Python ]

```
# Example: Create an Iceberg table from a DataFrame 
# and register the table to Glue Data Catalog

dataFrame.createOrReplaceTempView("tmp_<your_table_name>")

query = f"""
CREATE TABLE glue_catalog.<your_database_name>.<your_table_name>
USING iceberg
TBLPROPERTIES ("format-version"="2")
AS SELECT * FROM tmp_<your_table_name>
"""
spark.sql(query)
```

------
#### [ Scala ]

```
// Example: Example: Create an Iceberg table from a DataFrame
// and register the table to Glue Data Catalog

dataFrame.createOrReplaceTempView("tmp_<your_table_name>")

val query = """CREATE TABLE glue_catalog.<your_database_name>.<your_table_name>
USING iceberg
TBLPROPERTIES ("format-version"="2")
AS SELECT * FROM tmp_<your_table_name>
"""
spark.sql(query)
```

------

대신에 Spark 메서드를 사용하여 Amazon S3 및 데이터 카탈로그에 Iceberg 테이블을 작성할 수 있습니다.

사전 조건: Iceberg 라이브러리에서 사용할 카탈로그를 프로비저닝해야 합니다. AWS Glue 데이터 카탈로그를 사용할 때 AWS Glue를 사용하면 이 작업을 간편하게 수행할 수 있습니다. AWS Glue 데이터 카탈로그는 Spark 라이브러리에서 `glue_catalog`로 사용하도록 미리 구성되어 있습니다. 데이터 카탈로그 테이블은 *databaseName* 및 *tableName*으로 식별됩니다. AWS Glue 데이터 카탈로그에 대한 자세한 내용은 [AWS Glue에서 데이터 검색 및 카탈로그 작성](catalog-and-crawler.md) 섹션을 참조하세요.

AWS Glue 데이터 카탈로그를 사용하지 않는 경우 Spark API를 통해 카탈로그를 프로비저닝해야 합니다. 자세한 내용은 Iceberg 설명서의 [Spark Configuration](https://iceberg.apache.org/docs/latest/spark-configuration/)을 참조하세요.

이 예시에서는 Spark를 사용하여 데이터 카탈로그에서 Amazon S3의 Iceberg 테이블을 작성합니다.

------
#### [ Python ]

```
# Example: Write an Iceberg table to S3 on the Glue Data Catalog

# Create (equivalent to CREATE TABLE AS SELECT)
dataFrame.writeTo("glue_catalog.databaseName.tableName") \
    .tableProperty("format-version", "2") \
    .create()

# Append (equivalent to INSERT INTO)
dataFrame.writeTo("glue_catalog.databaseName.tableName") \
    .tableProperty("format-version", "2") \
    .append()
```

------
#### [ Scala ]

```
// Example: Write an Iceberg table to S3 on the Glue Data Catalog

// Create (equivalent to CREATE TABLE AS SELECT)
dataFrame.writeTo("glue_catalog.databaseName.tableName")
    .tableProperty("format-version", "2")
    .create()

// Append (equivalent to INSERT INTO)
dataFrame.writeTo("glue_catalog.databaseName.tableName")
    .tableProperty("format-version", "2")
    .append()
```

------

## 예: AWS Glue 데이터 카탈로그를 사용하여 Amazon S3에서 Iceberg 테이블 읽기
<a name="aws-glue-programming-etl-format-iceberg-read"></a>

이 예제에서는 [예: Amazon S3에 Iceberg 테이블을 작성하고 AWS Glue 데이터 카탈로그에 등록](#aws-glue-programming-etl-format-iceberg-write)에서 생성한 Iceberg 테이블을 읽습니다.

------
#### [ Python ]

이 예에서는 `GlueContext.create\$1data\$1frame.from\$1catalog()` 메서드를 사용합니다.

```
# Example: Read an Iceberg table from Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

df = glueContext.create_data_frame.from_catalog(
    database="<your_database_name>",
    table_name="<your_table_name>",
    additional_options=additional_options
)
```

------
#### [ Scala ]

이 예에서는 [getCatalogSource](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSource) 메서드를 사용합니다.

```
// Example: Read an Iceberg table from Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import org.apacke.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val df = glueContext.getCatalogSource("<your_database_name>", "<your_table_name>",
      additionalOptions = additionalOptions)
      .getDataFrame()
  }
}
```

------

## 예: AWS Glue 데이터 카탈로그를 사용하여 Amazon S3에서 Iceberg 테이블에 `DataFrame` 삽입
<a name="aws-glue-programming-etl-format-iceberg-insert"></a>

이 예에서는 [예: Amazon S3에 Iceberg 테이블을 작성하고 AWS Glue 데이터 카탈로그에 등록](#aws-glue-programming-etl-format-iceberg-write)에서 생성한 Iceberg 테이블에 데이터를 삽입합니다.

**참고**  
이 예에서는 AWS Glue 데이터 카탈로그를 Apache Spark Hive 메타스토어로 사용하기 위해 `--enable-glue-datacatalog` 작업 파라미터를 설정해야 합니다. 자세한 내용은 [AWS Glue 작업에서 작업 파라미터 사용](aws-glue-programming-etl-glue-arguments.md)를 참조하세요.

------
#### [ Python ]

이 예에서는 `GlueContext.write\$1data\$1frame.from\$1catalog()` 메서드를 사용합니다.

```
# Example: Insert into an Iceberg table from Glue Data Catalog

from awsglue.context import GlueContext
from pyspark.context import SparkContext

sc = SparkContext()
glueContext = GlueContext(sc)

glueContext.write_data_frame.from_catalog(
    frame=dataFrame,
    database="<your_database_name>",
    table_name="<your_table_name>",
    additional_options=additional_options
)
```

------
#### [ Scala ]

이 예에서는 [getCatalogSink](glue-etl-scala-apis-glue-gluecontext.md#glue-etl-scala-apis-glue-gluecontext-defs-getCatalogSink) 메서드를 사용합니다.

```
// Example: Insert into an Iceberg table from Glue Data Catalog

import com.amazonaws.services.glue.GlueContext
import org.apacke.spark.SparkContext

object GlueApp {
  def main(sysArgs: Array[String]): Unit = {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    glueContext.getCatalogSink("<your_database_name>", "<your_table_name>",
      additionalOptions = additionalOptions)
      .writeDataFrame(dataFrame, glueContext)
  }
}
```

------

## 예: Spark를 사용하여 Amazon S3에서 Iceberg 테이블 읽기
<a name="aws-glue-programming-etl-format-iceberg-read-spark"></a>

사전 조건: Iceberg 라이브러리에서 사용할 카탈로그를 프로비저닝해야 합니다. AWS Glue 데이터 카탈로그를 사용할 때 AWS Glue를 사용하면 이 작업을 간편하게 수행할 수 있습니다. AWS Glue 데이터 카탈로그는 Spark 라이브러리에서 `glue_catalog`로 사용하도록 미리 구성되어 있습니다. 데이터 카탈로그 테이블은 *databaseName* 및 *tableName*으로 식별됩니다. AWS Glue 데이터 카탈로그에 대한 자세한 내용은 [AWS Glue에서 데이터 검색 및 카탈로그 작성](catalog-and-crawler.md) 섹션을 참조하세요.

AWS Glue 데이터 카탈로그를 사용하지 않는 경우 Spark API를 통해 카탈로그를 프로비저닝해야 합니다. 자세한 내용은 Iceberg 설명서의 [Spark Configuration](https://iceberg.apache.org/docs/latest/spark-configuration/)을 참조하세요.

이 예제에서는 Spark를 사용하여 데이터 카탈로그에서 Amazon S3의 Iceberg 테이블을 읽습니다.

------
#### [ Python ]

```
# Example: Read an Iceberg table on S3 as a DataFrame from the Glue Data Catalog

dataFrame = spark.read.format("iceberg").load("glue_catalog.databaseName.tableName")
```

------
#### [ Scala ]

```
// Example: Read an Iceberg table on S3 as a DataFrame from the Glue Data Catalog

val dataFrame = spark.read.format("iceberg").load("glue_catalog.databaseName.tableName")
```

------

## 예: Lake Formation 권한 제어가 포함된 Iceberg 테이블 읽기 및 쓰기
<a name="aws-glue-programming-etl-format-iceberg-read-write-lake-formation-tables"></a>

이 예제에서는 Lake Formation 권한 제어를 사용하여 Iceberg 테이블을 읽고 씁니다.

**참고**  
이 예제는 AWS Glue 4.0에서만 작동합니다. AWS Glue 5.0 이상에서는 [세분화된 액세스 제어를 위해 AWS Lake Formation과 함께 AWS Glue 사용](security-lf-enable.md)의 지침을 따릅니다.

1. Iceberg 테이블을 만들고 Lake Formation에 등록하십시오.

   1. Lake Formation 권한 제어를 활성화하려면 먼저 Lake Formation에 Amazon S3 경로를 등록해야 합니다. 자세한 내용을 알아보려면 [Registering an Amazon S3 location](https://docs.aws.amazon.com/lake-formation/latest/dg/register-location.html)(Amazon S3 위치 등록)을 참조하세요. Lake Formation 콘솔에서 등록하거나 AWS CLI를 사용하여 등록할 수 있습니다.

      ```
      aws lakeformation register-resource --resource-arn arn:aws:s3:::<s3-bucket>/<s3-folder> --use-service-linked-role --region <REGION>
      ```

      Amazon S3 위치를 등록하면 해당 위치(또는 하위 위치)를 가리키는 AWS Glue 테이블이 `GetTable` 호출 시 `IsRegisteredWithLakeFormation` 파라미터 값을 true로 반환합니다.

   1. Spark SQL을 통해 등록된 경로를 가리키는 Iceberg 테이블을 생성하십시오.
**참고**  
Python의 예를 들면 다음과 같습니다.

      ```
      dataFrame.createOrReplaceTempView("tmp_<your_table_name>")
      
      query = f"""
      CREATE TABLE glue_catalog.<your_database_name>.<your_table_name>
      USING iceberg
      AS SELECT * FROM tmp_<your_table_name>
      """
      spark.sql(query)
      ```

      AWS Glue `CreateTable` API를 통해 테이블을 수동으로 생성할 수도 있습니다. 자세한 내용은 [Apache Iceberg 테이블 생성](https://docs.aws.amazon.com/lake-formation/latest/dg/creating-iceberg-tables.html)을 참조하십시오.
**참고**  
현재 `UpdateTable` API는 작업에 대한 입력으로 Iceberg 테이블 형식을 지원하지 않습니다.

1. 작업 IAM 역할에 Lake Formation 권한을 부여하십시오. Lake Formation 콘솔에서 권한을 부여하거나 AWS CLI를 사용하여 권한을 부여할 수 있습니다. 자세한 내용은 https://docs.aws.amazon.com/lake-formation/latest/dg/granting-table-permissions.html 단원을 참조하십시오.

1. Lake Formation에 등록된 Iceberg 테이블을 참조하십시오. 코드는 등록되지 않은 Iceberg 테이블을 읽는 것과 같습니다. 읽기에 성공하려면 AWS Glue Job IAM 역할에 SELECT 권한이 있어야 한다는 점에 유의하십시오.

   ```
   # Example: Read an Iceberg table from the AWS Glue Data Catalog
   from awsglue.context import GlueContextfrom pyspark.context import SparkContext
   
   sc = SparkContext()
   glueContext = GlueContext(sc)
   
   df = glueContext.create_data_frame.from_catalog(
       database="<your_database_name>",
       table_name="<your_table_name>",
       additional_options=additional_options
   )
   ```

1. Lake Formation에 등록된 Iceberg 테이블에 씁니다. 코드는 등록되지 않은 Iceberg 테이블에 쓰는 것과 같습니다. 글쓰기가 성공하려면 AWS Glue 작업 IAM 역할에 SUPER 권한이 있어야 한다는 점을 참고하십시오.

   ```
   glueContext.write_data_frame.from_catalog(
       frame=dataFrame,
       database="<your_database_name>",
       table_name="<your_table_name>",
       additional_options=additional_options
   )
   ```

## 공유 구성 참조
<a name="aws-glue-programming-etl-format-shared-reference"></a>

 모든 형식 유형의 다음과 같은 `format_options` 값을 사용할 수 있습니다.
+ `attachFilename` - 열 이름으로 사용할 적절한 형식의 문자열입니다. 이 옵션을 제공하면 레코드의 소스 파일 이름이 레코드에 추가됩니다. 파라미터 값이 열 이름으로 사용됩니다.
+ `attachTimestamp` - 열 이름으로 사용할 적절한 형식의 문자열입니다. 이 옵션을 제공하면 레코드의 소스 파일 수정 시간이 레코드에 추가됩니다. 파라미터 값이 열 이름으로 사용됩니다.

# Spark SQL 작업에 대해 AWS Glue Data Catalog 지원
<a name="aws-glue-programming-etl-glue-data-catalog-hive"></a>

AWS Glue Data Catalog는 Apache Hive 메타스토어와 호환되는 카탈로그입니다. Data Catalog를 외부 Apache Hive 메타스토어로 사용하도록 AWS Glue 작업과 개발 엔드포인트를 구성할 수 있습니다. 그런 다음, Data Catalog에 저장된 테이블에 대해 Apache Spark SQL 쿼리를 직접 실행할 수 있습니다. AWS Glue 동적 프레임은 기본값으로 Data Catalog와 통합됩니다. 한편, Spark SQL 작업은 이 기능을 통해 외부 Hive 메타스토어로 Data Catalog를 사용하기 시작할 수 있습니다.

이 기능을 사용하려면 AWS Glue API 엔드포인트에 대한 네트워크 액세스가 필요합니다. 프라이빗 서브넷에 있는 연결을 사용하는 AWS Glue 작업의 경우 네트워크 액세스를 제공하도록 VPC 엔드포인트 또는 NAT 게이트웨이를 구성해야 합니다. VPC 엔드포인트 구성 방법에 대한 자세한 내용은 [데이터 스토어에 대한 네트워크 액세스 설정](start-connecting.md) 섹션을 참조하세요. NAT 게이트웨이를 생성하려면 *Amazon VPC 사용 설명서*의 [NAT 게이트웨이](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html)를 참조하세요.

작업 인수 및 개발 엔드포인트 인수에 각각 `"--enable-glue-datacatalog": ""`를 추가하여 AWS Glue 작업 및 개발 엔드포인트를 구성할 수 있습니다. 이 인수를 전달하면 외부 Hive 메타스토어로 Data Catalog에 액세스 할 수 있도록 Spark에서 특정 구성이 설정됩니다. 또한 AWS Glue 작업 또는 개발 엔드포인트에서 생성된 `SparkSession` 객체에서 [Hive 지원을 사용](https://spark.apache.org/docs/latest/api/java/org/apache/spark/sql/SparkSession.Builder.html#enableHiveSupport--)합니다.

Data Catalog 액세스를 사용하려면 콘솔의 **작업 추가(Add job)** 또는 **엔드포인트 추가(Add endpoint)** 페이지에 있는 **카탈로그 옵션(Catalog options)** 그룹에서 **AWS Glue Data Catalog를 Hive 메타스토어로 사용(Use Glue Data Catalog as the Hive metastore)** 확인란을 선택합니다. 작업 또는 개발 엔드포인트에 사용되는 IAM 역할은 `glue:CreateDatabase` 권한을 가져야 합니다. "`default`"라는 데이터베이스가 없는 경우에 Data Catalog에서 생성됩니다.

Spark SQL 작업에서 이 기능을 사용할 수 있는 방법의 예제를 살펴보십시오. 다음 예에서는 `s3://awsglue-datasets/examples/us-legislators`에서 사용 가능한 미국 법률 기관의 데이터 세트를 크롤링했다고 가정합니다.

AWS Glue Data Catalog에 정의된 테이블에서 데이터를 직렬화/역직렬화하려면 Spark 작업의 클래스 경로의 AWS Glue Data Catalog에 정의된 포맷을 위한 [Hive SerDe](https://cwiki.apache.org/confluence/display/Hive/SerDe) 클래스가 Spark SQL에 있어야 합니다.

특정 공통 형식을 위한 SerDe는 AWS Glue에 의해 배포됩니다. 다음은 이들에 대한 Amazon S3 링크입니다.
+ [JSON](https://s3.us-west-2.amazonaws.com/crawler-public/json/serde/json-serde.jar)
+ [XML](https://s3.us-west-2.amazonaws.com/crawler-public/xml/serde/hivexmlserde-1.0.5.3.jar)
+ [Grok](https://s3.us-west-2.amazonaws.com/crawler-public/grok/serde/AWSGlueHiveGrokSerDe-1.0-super.jar)

[개발 엔드포인트에 대한 외부 JAR](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-dev-endpoint.html#aws-glue-api-dev-endpoint-DevEndpointCustomLibraries)로서 JSON SerDe를 추가합니다. 작업 시, 인수 필드의 `--extra-jars` 인수를 사용하여 SerDe를 추가할 수 있습니다. 자세한 내용은 [AWS Glue 작업에서 작업 파라미터 사용](aws-glue-programming-etl-glue-arguments.md) 섹션을 참조하세요.

다음은 Spark SQL에서 Data Catalog를 사용할 수 있도록 설정된 개발 엔드포인트를 생성하기 위한 입력 JSON의 예입니다.

```
{
    "EndpointName": "Name",
    "RoleArn": "role_ARN",
    "PublicKey": "public_key_contents",
    "NumberOfNodes": 2,
    "Arguments": {
      "--enable-glue-datacatalog": ""
    },
    "ExtraJarsS3Path": "s3://crawler-public/json/serde/json-serde.jar"
}
```

이제 Spark SQL을 사용하여 미국 법률 기관 데이터 세트에서 생성된 테이블을 쿼리합니다.

```
>>> spark.sql("use legislators")
DataFrame[]
>>> spark.sql("show tables").show()
+-----------+------------------+-----------+
|   database|         tableName|isTemporary|
+-----------+------------------+-----------+
|legislators|        areas_json|      false|
|legislators|    countries_json|      false|
|legislators|       events_json|      false|
|legislators|  memberships_json|      false|
|legislators|organizations_json|      false|
|legislators|      persons_json|      false|
+-----------+------------------+-----------+
>>> spark.sql("describe memberships_json").show()
+--------------------+---------+-----------------+
|            col_name|data_type|          comment|
+--------------------+---------+-----------------+
|             area_id|   string|from deserializer|
|     on_behalf_of_id|   string|from deserializer|
|     organization_id|   string|from deserializer|
|                role|   string|from deserializer|
|           person_id|   string|from deserializer|
|legislative_perio...|   string|from deserializer|
|          start_date|   string|from deserializer|
|            end_date|   string|from deserializer|
+--------------------+---------+-----------------+
```

이 형식에 대한 SerDe 클래스를 작업의 클래스 경로에서 사용할 수 없는 경우에는 아래와 비슷한 오류가 나타납니다.

```
>>> spark.sql("describe memberships_json").show()

Caused by: MetaException(message:java.lang.ClassNotFoundException Class org.openx.data.jsonserde.JsonSerDe not found)
    at org.apache.hadoop.hive.metastore.MetaStoreUtils.getDeserializer(MetaStoreUtils.java:399)
    at org.apache.hadoop.hive.ql.metadata.Table.getDeserializerFromMetaStore(Table.java:276)
    ... 64 more
```

`memberships` 테이블에서 별도의 `organization_id`만 보려면 다음 SQL 쿼리를 실행합니다.

```
>>> spark.sql("select distinct organization_id from memberships_json").show()
+--------------------+
|     organization_id|
+--------------------+
|d56acebe-8fdc-47b...|
|8fa6c3d2-71dc-478...|
+--------------------+
```

동적 프레임에서 똑같이 하려면 다음을 실행합니다.

```
>>> memberships = glueContext.create_dynamic_frame.from_catalog(database="legislators", table_name="memberships_json")
>>> memberships.toDF().createOrReplaceTempView("memberships")
>>> spark.sql("select distinct organization_id from memberships").show()
+--------------------+
|     organization_id|
+--------------------+
|d56acebe-8fdc-47b...|
|8fa6c3d2-71dc-478...|
+--------------------+
```

DynamicFrame이 ETL 작업에 최적화된 상태에서 Spark SQL이 Data Catalog에 액세스할 수 있도록 하면 손쉽게 복잡한 SQL 문을 실행하거나 기존 애플리케이션을 포팅할 수 있습니다.

# 작업 북마크 사용
<a name="programming-etl-connect-bookmarks"></a>

AWS Glue for Spark는 작업 북마크를 사용하여 이미 진행된 데이터를 추적합니다. 작업 북마크 기능에 대한 요약 및 지원 내용은 [처리된 데이터를 작업 북마크로 추적](monitor-continuations.md) 섹션을 참조하세요. 북마크를 사용해 AWS Glue 작업을 프로그래밍하면 시각적 작업에서 얻을 수 없었던 유연성을 활용할 수 있습니다.
+  JDBC에서 읽을 때 AWS Glue 스크립트에서 북마크 키로 사용할 열을 지정할 수 있습니다.
+  각 메서드의 직접 호출에 적용할 `transformation_ctx`를 선택할 수 있습니다.

*스크립트 시작 부분에서는 항상 `job.init`를 호출하고 스크립트 끝 부분에서는 적절하게 구성된 파라미터를 사용하여 `job.commit`을 호출하세요.* 이 두 함수는 북마크 서비스를 초기화하고 서비스에 대한 상태 변경을 업데이트합니다. 북마크는 호출하지 않으면 작동하지 않습니다.

## 북마크 키 지정
<a name="programming-etl-connect-bookmarks-columns"></a>

JDBC 워크플로의 경우 북마크는 키 필드의 값을 북마크된 값과 비교하여 작업에서 읽은 행을 추적합니다. 이는 Amazon S3 워크플로에 필요하지 않거나 적용될 수 없습니다. 시각적 편집기 없이 AWS Glue 스크립트를 작성할 때 북마크로 추적할 열을 지정할 수 있습니다. 열을 여러 개 지정할 수도 있습니다. 사용자 정의 북마크 키를 지정할 때는 값 순서에 간격을 둘 수 있습니다.

**주의**  
사용자 정의 북마크 키를 사용하는 경우 각각 엄격하게 단순 증가 또는 감소해야 합니다. 복합 키에 대해 추가 필드를 선택할 때 '마이너 버전' 또는 '개정 번호'와 같은 개념에 대한 필드는 해당 값이 데이터 세트 전체에서 재사용되므로 이 기준을 충족하지 않습니다.

다음과 같은 방법으로 `jobBookmarkKeys` 및 `jobBookmarkKeysSortOrder`를 지정할 수 있습니다.
+ `create_dynamic_frame.from_catalog` - `additional_options`를 사용합니다.
+ `create_dynamic_frame.from_options` - `connection_options`를 사용합니다.

## 변환 컨텍스트
<a name="monitor-continuations-implement-context"></a>

대부분의 AWS Glue PySpark 동적 프레임 메서드에는 ETL 연산자 인스턴스의 고유한 식별자인 조건부 파라미터 `transformation_ctx`가 들어 있습니다. `transformation_ctx` 파라미터는 작업 북마크 내에서 지정된 연산자의 상태 정보를 식별하는 데 사용됩니다. 특히 AWS Glue는 `transformation_ctx`를 사용해 북마크 상태에 키를 인덱싱합니다.

**주의**  
이 `transformation_ctx`는 스크립트에서 특정 소스에 대한 책갈피 상태를 검색하는 키 역할을 합니다. 북마크가 제대로 작동하려면 항상 소스와 관련 `transformation_ctx`를 일치시켜야 합니다. 소스 속성이나 `transformation_ctx`의 이름을 변경하면 이전 북마크를 유효하지 않게 만들 수 있으며 타임스탬프 기반 필터링으로 인해 올바른 결과가 나오지 않을 수 있습니다.

작업 북마크가 제대로 작동하려면 작업 북마크 파라미터를 활성화하고 `transformation_ctx` 파라미터를 설정해야 합니다. `transformation_ctx` 파라미터를 전달하지 않으면 메서드에서 사용하는 테이블이나 동적 프레임에 대해 작업 북마크가 활성화되지 않습니다. 예를 들어, ETL 작업이 2개의 Amazon S3 소스를 읽고 조인하면 `transformation_ctx` 파라미터를 사용하고자 하는 북마크의 방법에만 전달할 수도 있습니다. 작업의 작업 북마크를 재설정하면 어떤 `transformation_ctx`를 사용하든 간에 해당 작업과 연관된 모든 변환이 재설정됩니다.

`DynamicFrameReader` 클래스에 대한 자세한 내용은 [DynamicFrameReader 클래스](aws-glue-api-crawler-pyspark-extensions-dynamic-frame-reader.md)를 참조하십시오. PySpark 확장에 대한 자세한 내용은 [AWS Glue PySpark 확장 참조](aws-glue-programming-python-extensions.md) 단원을 참조하십시오.

## 예시
<a name="monitor-continuations-implement-examples"></a>

**Example**  
다음은 Amazon S3 데이터 원본에 대해 생성된 스크립트의 예입니다. 작업 북마크를 사용하는 데 필요한 스크립트 부분은 기울임꼴로 표시됩니다. 이러한 요소에 대한 자세한 내용은 [GlueContext 클래스](aws-glue-api-crawler-pyspark-extensions-glue-context.md) API 및 [DynamicFrameWriter 클래스](aws-glue-api-crawler-pyspark-extensions-dynamic-frame-writer.md) API를 참조하세요.  

```
# Sample Script
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job

args = getResolvedOptions(sys.argv, ['JOB_NAME'])
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

datasource0 = glueContext.create_dynamic_frame.from_catalog(
    database = "database",
    table_name = "relatedqueries_csv",
    transformation_ctx = "datasource0"
)

applymapping1 = ApplyMapping.apply(
    frame = datasource0,
    mappings = [("col0", "string", "name", "string"), ("col1", "string", "number", "string")],
    transformation_ctx = "applymapping1"
)

datasink2 = glueContext.write_dynamic_frame.from_options(
    frame = applymapping1,
    connection_type = "s3",
    connection_options = {"path": "s3://input_path"},
    format = "json",
    transformation_ctx = "datasink2"
)


job.commit()
```

**Example**  
다음은 JDBC 소스에 대해 생성된 스크립트의 예입니다. 소스 테이블은 기본 키로 `empno` 열이 있는 직원 테이블입니다. 북마크 키가 지정되지 않은 경우 작업은 기본적으로 순차 기본 키를 북마크 키로 사용하지만 `empno`는 반드시 순차적이지 않기 때문에(값에 공백이 있을 수 있음) 기본 북마크 키로 적합하지 않습니다. 따라서 스크립트는 `empno`를 북마크 키로 명시적으로 지정합니다. 코드의 해당 부분은 기울임꼴로 표시됩니다.  

```
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job

args = getResolvedOptions(sys.argv, ['JOB_NAME'])

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

datasource0 = glueContext.create_dynamic_frame.from_catalog(
    database = "hr",
    table_name = "emp",
    transformation_ctx = "datasource0",
    additional_options = {"jobBookmarkKeys":["empno"],"jobBookmarkKeysSortOrder":"asc"}
)

applymapping1 = ApplyMapping.apply(
    frame = datasource0,
    mappings = [("ename", "string", "ename", "string"), ("hrly_rate", "decimal(38,0)", "hrly_rate", "decimal(38,0)"), ("comm", "decimal(7,2)", "comm", "decimal(7,2)"), ("hiredate", "timestamp", "hiredate", "timestamp"), ("empno", "decimal(5,0)", "empno", "decimal(5,0)"), ("mgr", "decimal(5,0)", "mgr", "decimal(5,0)"), ("photo", "string", "photo", "string"), ("job", "string", "job", "string"), ("deptno", "decimal(3,0)", "deptno", "decimal(3,0)"), ("ssn", "decimal(9,0)", "ssn", "decimal(9,0)"), ("sal", "decimal(7,2)", "sal", "decimal(7,2)")],
    transformation_ctx = "applymapping1"
)

datasink2 = glueContext.write_dynamic_frame.from_options(
    frame = applymapping1,
    connection_type = "s3",
    connection_options = {"path": "s3://hr/employees"},
    format = "csv",
    transformation_ctx = "datasink2"
)

job.commit()
```

# AWS Glue Studio 외부에서 민감한 데이터 감지 사용
<a name="aws-glue-api-sensitive-data-example"></a>

 AWS Glue Studio는 민감한 데이터 감지를 허용하지만 AWS Glue Studio 외부에서 민감한 데이터 감지 기능을 사용할 수도 있습니다.

 민감한 관리형 데이터 형식의 목록은 [관리형 데이터 형식](https://docs.aws.amazon.com/glue/latest/dg/sensitive-data-managed-data-types.html)을 참조하세요.

## AWS 관리형 PII 유형을 사용한 민감한 데이터 감지 탐지
<a name="sensitive-data-managed-pii-types"></a>

 AWS Glue에서는 AWS Glue ETL 작업에서 2개의 API를 제공합니다. 이러한 항목은 `detect()` 및 `classifyColumns()`입니다.

```
  detect(frame: DynamicFrame, 
      entityTypesToDetect: Seq[String], 
      outputColumnName: String = "DetectedEntities",
      detectionSensitivity: String = "LOW"): DynamicFrame

 detect(frame: DynamicFrame, 
      detectionParameters: JsonOptions,
      outputColumnName: String = "DetectedEntities",
      detectionSensitivity: String = "LOW"): DynamicFrame
      
  classifyColumns(frame: DynamicFrame, 
      entityTypesToDetect: Seq[String], 
      sampleFraction: Double = 0.1, 
      thresholdFraction: Double = 0.1,
      detectionSensitivity: String = "LOW")
```

 `detect()` API를 사용하여 AWS 관리형 PII 유형 및 사용자 지정 엔터티 유형을 식별할 수 있습니다. 새로운 열이 감지 결과와 함께 자동 생성됩니다. `classifyColumns()` API는 키가 열 이름이고 값이 감지된 엔터티 유형 목록인 맵을 반환합니다. `SampleFraction`은 PII 엔터티를 검색할 때 샘플링할 데이터의 비율을 나타내는 반면, `ThresholdFraction`은 열이 PII 데이터로 식별되기 위해 충족되어야 하는 데이터의 비율을 나타냅니다.

### 행 수준 탐지
<a name="w2aac67c11c24c19b9c11"></a>

 이 예제에서는 작업이 `detect()` 및`classifyColumns()` API를 사용하여 다음 작업을 수행합니다.
+  Amazon S3 버킷에서 데이터를 읽고 이를 DynamicFrame으로 변환 
+  DynamicFrame에서 '이메일' 및 '신용 카드' 인스턴스 검색 
+  원래 값과 각 행에 대한 감지 결과를 포함하는 하나의 열이 포함된 DynamicFrame 반환 
+  반환된 DynamicFrame을 다른 Amazon S3 경로에 쓰기 

```
  import com.amazonaws.services.glue.GlueContext
  import com.amazonaws.services.glue.MappingSpec
  import com.amazonaws.services.glue.errors.CallSite
  import com.amazonaws.services.glue.util.GlueArgParser
  import com.amazonaws.services.glue.util.Job
  import com.amazonaws.services.glue.util.JsonOptions
  import org.apache.spark.SparkContext
  import scala.collection.JavaConverters._
  import com.amazonaws.services.glue.ml.EntityDetector
  
  object GlueApp {
    def main(sysArgs: Array[String]) {
      val spark: SparkContext = new SparkContext()
      val glueContext: GlueContext = new GlueContext(spark)
      val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
      Job.init(args("JOB_NAME"), glueContext, args.asJava)
      val frame= glueContext.getSourceWithFormat(formatOptions=JsonOptions("""{"quoteChar": "\"", "withHeader": true, "separator": ","}"""), connectionType="s3", format="csv", options=JsonOptions("""{"paths": ["s3://pathToSource"], "recurse": true}"""), transformationContext="AmazonS3_node1650160158526").getDynamicFrame()
  
      val frameWithDetectedPII = EntityDetector.detect(frame, Seq("EMAIL", "CREDIT_CARD"))
  
      glueContext.getSinkWithFormat(connectionType="s3", options=JsonOptions("""{"path": "s3://pathToOutput/", "partitionKeys": []}"""), transformationContext="someCtx", format="json").writeDynamicFrame(frameWithDetectedPII)
  
      Job.commit()
    }
  }
```

### 세분화된 동작을 통한 행 수준 탐지
<a name="w2aac67c11c24c19b9c15"></a>

 이 예제에서는 작업이 `detect()` API를 사용하여 다음 작업을 수행합니다.
+  Amazon S3 버킷에서 데이터를 읽고 이를 dynamicFrame으로 변환 
+  dynamicFrame에서 “USA\$1PTIN”, “ BANK\$1ACCOUNT”, “USA\$1SSN”, “USA\$1PASSPORT\$1NUMBER”, “PHONE\$1NUMBER”에 대한 민감한 데이터 유형 탐지 
+  수정된 마스크 값과 각 행에 대한 감지 결과를 포함하는 하나의 열이 포함된 dynamicFrame 반환 
+  반환된 dynamicFrame을 다른 Amazon S3 경로에 쓰기 

 위의 `detect()` API와 달리 이 API에서는 개체 유형이 탐지할 수 있도록 세분화된 동작을 사용합니다. 자세한 내용은 [`detect()` 사용을 위한 탐지 파라미터](#sensitive-data-detect-parameters-fine-grained-actions) 섹션을 참조하세요.

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.MappingSpec
import com.amazonaws.services.glue.errors.CallSite
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._
import com.amazonaws.services.glue.ml.EntityDetector

object GlueApp {
  def main(sysArgs: Array[String]) {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    val frame = glueContext.getSourceWithFormat(formatOptions=JsonOptions("""{"quoteChar": "\"", "withHeader": true, "separator": ","}"""), connectionType="s3", format="csv", options=JsonOptions("""{"paths": ["s3://pathToSource"], "recurse": true}"""), transformationContext="AmazonS3_node_source").getDynamicFrame()

    val detectionParameters = JsonOptions(
      """
        {
          "USA_DRIVING_LICENSE": [{
            "action": "PARTIAL_REDACT",
            "sourceColumns": ["Driving License"],
            "actionOptions": {
              "matchPattern": "[0-9]",
              "redactChar": "*"
            }
          }],
          "BANK_ACCOUNT": [{
            "action": "DETECT",
            "sourceColumns": ["*"]
          }],
          "USA_SSN": [{
            "action": "SHA256_HASH",
            "sourceColumns": ["SSN"]
          }],
          "IP_ADDRESS": [{
            "action": "REDACT",
            "sourceColumns": ["IP Address"],
            "actionOptions": {"redactText": "*****"}
          }],
          "PHONE_NUMBER": [{
            "action": "PARTIAL_REDACT",
            "sourceColumns": ["Phone Number"],
            "actionOptions": {
              "numLeftCharsToExclude": 1,
              "numRightCharsToExclude": 0,
              "redactChar": "*"
            }
          }]
        }
      """
    )

    val frameWithDetectedPII = EntityDetector.detect(frame, detectionParameters, "DetectedEntities", "HIGH")

    glueContext.getSinkWithFormat(connectionType="s3", options=JsonOptions("""{"path": "s3://pathToOutput/", "partitionKeys": []}"""), transformationContext="AmazonS3_node_target", format="json").writeDynamicFrame(frameWithDetectedPII)

    Job.commit()
  }
}
```

### 열 수준 탐지
<a name="w2aac67c11c24c19b9c19"></a>

 이 예제에서는 작업이 `classifyColumns()` API를 사용하여 다음 작업을 수행합니다.
+  Amazon S3 버킷에서 데이터를 읽고 이를 dynamicFrame으로 변환 
+  DynamicFrame에서 '이메일' 및 '신용 카드' 인스턴스 검색 
+  열을 100% 샘플링하고, 셀의 10% 에 존재하며, 민감도가 “LOW”이면 개체를 탐지된 것으로 표시하도록 파라미터를 설정합니다 
+  키가 열 이름이고 값이 탐지된 개체 유형 목록인 맵을 반환합니다 
+  반환된 dynamicFrame을 다른 Amazon S3 경로에 쓰기 

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.MappingSpec
import com.amazonaws.services.glue.errors.CallSite
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._
import com.amazonaws.services.glue.DynamicFrame
import com.amazonaws.services.glue.ml.EntityDetector

object GlueApp {
  def main(sysArgs: Array[String]) {
    val spark: SparkContext = new SparkContext()
    val glueContext: GlueContext = new GlueContext(spark)
    val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
    Job.init(args("JOB_NAME"), glueContext, args.asJava)
    val frame = glueContext.getSourceWithFormat(formatOptions=JsonOptions("""{"quoteChar": "\"", "withHeader": true, "separator": ",", "optimizePerformance": false}"""), connectionType="s3", format="csv", options=JsonOptions("""{"paths": ["s3://pathToSource"], "recurse": true}"""), transformationContext="frame").getDynamicFrame()
    
    import glueContext.sparkSession.implicits._

    val detectedDataFrame = EntityDetector.classifyColumns(
        frame, 
        entityTypesToDetect = Seq("CREDIT_CARD", "PHONE_NUMBER"), 
        sampleFraction = 1.0, 
        thresholdFraction = 0.1,
        detectionSensitivity = "LOW"
    )
    val detectedDF = (detectedDataFrame).toSeq.toDF("columnName", "entityTypes")
    val DetectSensitiveData_node = DynamicFrame(detectedDF, glueContext)

    glueContext.getSinkWithFormat(connectionType="s3", options=JsonOptions("""{"path": "s3://pathToOutput", "partitionKeys": []}"""), transformationContext="someCtx", format="json").writeDynamicFrame(DetectSensitiveData_node)

    Job.commit()
  }
}
```

## AWS CustomEntityType PII 유형을 사용한 민감한 데이터 감지 탐지
<a name="sensitive-data-custom-entity-PII-types"></a>

 AWS Studio를 통해 사용자 지정 엔터티를 정의할 수 있습니다. 하지만 AWS Studio에서 이 기능을 사용하기 위해서는 먼저 사용자 지정 엔터티 유형을 정의한 다음 정의된 사용자 지정 엔터티 유형을 `entityTypesToDetect` 목록에 추가해야 합니다.

 데이터에 특정 민감한 데이터 유형(예: '직원 ID')이 있는 경우에는 `CreateCustomEntityType()` API를 호출하여 사용자 지정 엔터티를 만들 수 있습니다. 다음 예제에서는 요청 파라미터를 사용하여 `CreateCustomEntityType()` API에 사용자 지정 엔터티 유형 'EMPLOYE\$1ID'를 정의합니다.

```
  { 
      "name": "EMPLOYEE_ID",
      "regexString": "\d{4}-\d{3}",
      "contextWords": ["employee"]
  }
```

 그리고 나서 `EntityDetector()` API에 사용자 지정 엔터티 유형(EMPLOYEE\$1ID)을 추가하여 새로운 사용자 지정 민감한 데이터 유형을 사용하도록 작업을 수정합니다.

```
  import com.amazonaws.services.glue.GlueContext
  import com.amazonaws.services.glue.MappingSpec
  import com.amazonaws.services.glue.errors.CallSite
  import com.amazonaws.services.glue.util.GlueArgParser
  import com.amazonaws.services.glue.util.Job
  import com.amazonaws.services.glue.util.JsonOptions
  import org.apache.spark.SparkContext
  import scala.collection.JavaConverters._
  import com.amazonaws.services.glue.ml.EntityDetector
  
  object GlueApp {
    def main(sysArgs: Array[String]) {
      val spark: SparkContext = new SparkContext()
      val glueContext: GlueContext = new GlueContext(spark)
      val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
      Job.init(args("JOB_NAME"), glueContext, args.asJava)
      val frame= glueContext.getSourceWithFormat(formatOptions=JsonOptions("""{"quoteChar": "\"", "withHeader": true, "separator": ","}"""), connectionType="s3", format="csv", options=JsonOptions("""{"paths": ["s3://pathToSource"], "recurse": true}"""), transformationContext="AmazonS3_node1650160158526").getDynamicFrame()
  
      val frameWithDetectedPII = EntityDetector.detect(frame, Seq("EMAIL", "CREDIT_CARD", "EMPLOYEE_ID"))
  
      glueContext.getSinkWithFormat(connectionType="s3", options=JsonOptions("""{"path": "s3://pathToOutput/", "partitionKeys": []}"""), transformationContext="someCtx", format="json").writeDynamicFrame(frameWithDetectedPII)
  
      Job.commit()
    }
  }
```

**참고**  
 사용자 지정 민감한 데이터 유형이 기존 관리형 엔터티 유형과 동일한 이름을 사용하여 정의된 경우 사용자 지정 민감한 데이터 유형이 우선 적용되고 관리형 엔터티 유형의 논리를 덮어씁니다.

## `detect()` 사용을 위한 탐지 파라미터
<a name="sensitive-data-detect-parameters-fine-grained-actions"></a>

 이 방법은 DynamicFrame에서 개체를 감지하는 데 사용됩니다. 원래 값과 PII 탐지 메타데이터가 있는 outputColumnName이라는 추가 열이 포함된 새 DataFrame을 반환합니다. 이 DynamicFrame이 AWS Glue 스크립트 내에서 반환된 후에 사용자 지정 마스킹을 수행하거나 세분화된 작업이 포함된 detect() API를 대신 사용할 수 있습니다.

```
detect(frame: DynamicFrame, 
       entityTypesToDetect: Seq[String], 
       outputColumnName: String = "DetectedEntities",
       detectionSensitivity: String = "LOW"): DynamicFrame
```

 파라미터: 
+  **frame** - (유형:`DynamicFrame`) 처리할 데이터가 포함된 입력 DynamicFrame입니다.
+  **entityTypesToDetect** - (type:`[Seq[String]`) 탐지할 개체 유형 목록입니다. 관리 개체 유형 또는 사용자 지정 개체 유형일 수 있습니다.
+  **outputColumnName** - (유형: `String`, 기본값: "DetectedEntities") 탐지된 개체를 저장할 열의 이름입니다. 지정하지 않은 경우 기본 열 이름은 "DetectedEntities"입니다.
+  **detectionSensitivity** - (유형: `String`, 옵션: "LOW" or "HIGH", 기본: "LOW") 탐지 프로세스의 민감도를 지정합니다. 유효한 옵션은 "LOW" 또는 "HIGH"입니다. 제공되지 않은 경우 기본 민감도는 "LOW"으로 설정됩니다.

 `outputColumnName` 설정: 

 탐지될 열 이름입니다. 지정하지 않은 경우 기본 열 이름은 "DetectedEntities"입니다. 출력 열의 각 행에 대해 보조 열에는 탐지된 개체 메타데이터에 대한 열 이름 맵이 다음과 같은 키-값 쌍과 함께 포함됩니다.
+  **entityType** - 탐지된 엔티티 유형입니다.
+  **start** - 원본 데이터에서 탐지된 개체의 시작 위치입니다.
+  **end** - 원본 데이터에서 탐지된 개체의 끝 위치입니다.
+  **actionUsed** - 탐지된 개체에 대해 수행된 작업 (예: "DETECT," "REDACT," "PARTIAL\$1REDACT," "SHA256\$1HASH").

 예제: 

```
{
   "DetectedEntities":{
      "SSN Col":[
         {
            "entityType":"USA_SSN",
            "actionUsed":"DETECT",
            "start":4,
            "end":15
         }
      ],
      "Random Data col":[
         {
            "entityType":"BANK_ACCOUNT",
            "actionUsed":"PARTIAL_REDACT",
            "start":4,
            "end":13
         },
         {
            "entityType":"IP_ADDRESS",
            "actionUsed":"REDACT",
            "start":4,
            "end":13
         }
      ]
   }
}
```

 **세분화된 동작이 포함된 `detect()`의 탐지 파라미터** 

 이 방법은 지정된 매개 변수를 사용하여 DynamicFrame에서 개체를 감지하는 데 사용됩니다. 원래 값이 마스킹된 민감한 데이터로 대체되고 PII 탐지 메타데이터가 있는 추가 `outputColumnName` 열이 포함된 새 DataFrame을 반환합니다.

```
detect(frame: DynamicFrame, 
       detectionParameters: JsonOptions,
       outputColumnName: String = "DetectedEntities",
       detectionSensitivity: String = "LOW"): DynamicFrame
```

 파라미터: 
+  **frame** - (유형: `DynamicFrame`): 처리할 데이터가 포함된 입력 DynamicFrame입니다.
+  **detectionParameters** - (유형: `JsonOptions`): 탐지 프로세스의 매개 변수를 지정하는 JSON 옵션입니다.
+  **outputColumnName** - (유형: `String`, 기본값: "DetectedEntities"): 탐지된 개체를 저장할 열의 이름입니다. 지정하지 않은 경우 기본 열 이름은 "DetectedEntities"입니다.
+  **detectionSensitivity** - (유형: `String`, 옵션: "LOW" or "HIGH", 기본: "LOW"): 탐지 프로세스의 민감도를 지정합니다. 유효한 옵션은 "LOW" 또는 "HIGH"입니다. 제공되지 않은 경우 기본 민감도는 "LOW"으로 설정됩니다.

<a name="detection-parameters-settings"></a> `detectionParameters` 설정 

 설정이 포함되지 않은 경우 기본값이 사용됩니다.
+  **action** - (유형: `String`, 옵션: "DETECT", "REDACT", "PARTIAL\$1REDACT", "SHA256\$1HASH") 엔티티에 대해 수행할 작업을 지정합니다. 필수 사항입니다. 마스킹을 수행하는 작업 ("DETECT"을 제외한 모든 작업) 은 열당 하나의 작업만 수행할 수 있다는 점에 유의하십시오. 이는 합쳐진 개체를 마스킹하기 위한 예방 조치입니다.
+  **sourceColumns** - (유형: `List[String]`, 기본값: [“\$1”]) 개체에 대해 탐지를 수행할 소스 열 이름 목록입니다. 없는 경우 기본값은 [“\$1”]입니다. 잘못된 열 이름을 사용하면 `IllegalArgumentException`이 발생합니다.
+  **sourceColumnsToExclude** - (유형: `List[String]`) 엔티티에 대한 탐지를 수행할 소스 열 이름 목록입니다. `sourceColumns` 또는 `sourceColumnsToExclude`를 사용합니다. 잘못된 열 이름을 사용하면 `IllegalArgumentException`이 발생합니다.
+  **actionOptions** - 지정된 작업에 따른 추가 옵션: 
  +  "DETECT"와 "SHA256\$1HASH"는 옵션이 불가합니다.
  +  "REDACT"의 경우: 
    + **redactText** - (유형: `String`, 기본값: "\$1\$1\$1\$1\$1") 탐지된 개체를 대체할 텍스트입니다.
  +  "PARTIAL\$1REDACT"의 경우: 
    +  **redactChar** -(유형: `String`, 기본값: "\$1") 개체에서 감지된 각 문자를 대체할 문자입니다.
    +  **matchPattern** - (유형: `String`) 부분 수정을 위한 정규식 패턴입니다. numLeftCharsToExclude 또는 `numRightCharsToExclude`과 결합할 수 없습니다.
    +  **numLeftCharsToExclude** - (유형: `String, integer`) 제외할 왼쪽 문자 수입니다. matchPattern과 함께 사용할 수는 없지만 `numRightCharsToExclude`와 함께 사용할 수는 있습니다.
    +  **numRightCharsToExclude**- (유형: `String, integer`) 제외할 오른쪽 문자 수입니다. matchPattern과 함께 사용할 수는 없지만 `numRightCharsToExclude`와 함께 사용할 수는 있습니다.

 `outputColumnName` 설정 

 [outputColumnName 설정을 참조하십시오](#sensitive-data-detect-parameters-fine-grained-actions) 

## `classifyColumns()`의 탐지 파라미터
<a name="detection-parameters-classifycolumns"></a>

 이 방법은 DynamicFrame에서 개체를 감지하는 데 사용됩니다. 키가 열 이름이고 값이 탐지된 개체 유형 목록인 맵을 반환합니다. 사용자 지정 마스킹은 AWS Glue 스크립트 내에서 반환된 후에 수행할 수 있습니다.

```
classifyColumns(frame: DynamicFrame, 
                entityTypesToDetect: Seq[String], 
                sampleFraction: Double = 0.1, 
                thresholdFraction: Double = 0.1,
                detectionSensitivity: String = "LOW")
```

 파라미터: 
+  **frame** - (유형:`DynamicFrame`) 처리할 데이터가 포함된 입력 DynamicFrame입니다.
+  **entityTypesToDetect** - (type:`Seq[String]`) 탐지할 개체 유형 목록입니다. 관리 개체 유형 또는 사용자 지정 개체 유형일 수 있습니다.
+  **sampleFraction** - (유형: `Double`, 기본값: 10%) PII 엔터티를 스캔할 때 샘플링할 데이터의 이름입니다.
+  **thresholdFraction**- (유형: `Double`, 기본값: 10%): 열을 PII 데이터로 식별하기 위해 충족되어야 하는 데이터의 비율입니다.
+  **detectionSensitivity** - (유형: `String`, 옵션: "LOW" or "HIGH", 기본: "LOW") 탐지 프로세스의 민감도를 지정합니다. 유효한 옵션은 "LOW" 또는 "HIGH"입니다. 제공되지 않은 경우 기본 민감도는 "LOW"으로 설정됩니다.

# 관리형 민감한 데이터 유형
<a name="sensitive-data-managed-data-types"></a>

 **글로벌 엔티티** 


| 데이터 형식 | 범주 | 설명 | 
| --- | --- | --- | 
| PERSON\$1NAME | 일반 |  사람의 이름.  | 
| EMAIL | 개인 |  이메일 주소.  | 
| IP\$1ADDRESS | 컴퓨터 |  IP 주소   | 
| MAC\$1ADDRESS | 개인 |  MAC 주소.  | 



 **미국 데이터 유형** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| BANK\$1ACCOUNT |  은행 계좌 번호. 특정 국가나 지역에 국한되지 않으나 미국 및 캐나다 계정 형식만 검색됩니다.  | 
| CREDIT\$1CARD |  신용카드 번호.  | 
| PHONE\$1NUMBER |   전화번호 특정 국가나 지역에 국한되지 않으나 현재 미국 및 캐나다 전화번호만 검색됩니다.  | 
| USA\$1ATIN |  미국 국세청에서 발급한 미국 Adoption Taxpayer Identification Number(ATIN).  | 
| USA\$1CPT\$1CODE |  CPT 코드(미국만 해당).  | 
| USA\$1DEA\$1NUMBER |  DEA 번호(미국만 해당).  | 
| USA\$1DRIVING\$1LICENSE |  운전면허증 번호(미국만 해당).  | 
| USA\$1HCPCS\$1CODE |  HCPCS 코드(미국만 해당).  | 
| USA\$1HEALTH\$1INSURANCE\$1CLAIM\$1NUMBER |  건강 보험 청구 번호(미국만 해당).  | 
| USA\$1ITIN |  ITIN(미국 개인 또는 법인의 경우).  | 
| USA\$1MEDICARE\$1BENEFICIARY\$1IDENTIFIER |  메디케어 수혜자 식별자(미국만 해당).  | 
| USA\$1NATIONAL\$1DRUG\$1CODE |  NDC 코드(미국만 해당).  | 
| USA\$1NATIONAL\$1PROVIDER\$1IDENTIFIER |  국가 공급자 식별 번호(미국만 해당).  | 
| USA\$1PASSPORT\$1NUMBER |  여권 번호(미국인의 경우).  | 
| USA\$1PTIN |  미국 국세청에서 발급한 미국 Preparer Tax Identification Number(PTIN).  | 
| USA\$1SSN |  사회보장번호(미국인의 경우).  | 



 **아르헨티나 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| ARGENTINA\$1TAX\$1IDENTIFICATION\$1NUMBER |   아르헨티나 세금 식별 번호. CUIT 또는 CUIL이라고도 합니다.  | 

 **오스트레일리아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| AUSTRALIA\$1BUSINESS\$1NUMBER |   호주 사업자 번호(ABN). 정부 및 지역 사회가 기업을 식별하기 위해 호주 사업자 등록부(ABN)에서 발급하는 고유 식별자.  | 
| AUSTRALIA\$1COMPANY\$1NUMBER |   호주 회사 번호(ACN). 호주 증권투자위원회에서 발행한 고유 식별자.  | 
| AUSTRALIA\$1DRIVING\$1LICENSE |  호주의 운전면허증 번호.  | 
| AUSTRALIA\$1MEDICARE\$1NUMBER |  호주 메디케어 번호. 호주 건강보험위원회에서 발급한 개인 식별자.  | 
| AUSTRALIA\$1PASSPORT\$1NUMBER |  호주 여권 번호.  | 
| AUSTRALIA\$1TAX\$1FILE\$1NUMBER |   호주 납세자 번호(TFN). 세금 납부를 위해 호주 국세청(ATO)에서 납세자(개인, 회사 등)에게 발급하는 번호.  | 

 **오스트리아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| AUSTRIA\$1DRIVING\$1LICENSE |  운전면허증 번호(오스트리아만 해당).  | 
| AUSTRIA\$1PASSPORT\$1NUMBER |  여권 번호(오스트리아만 해당).  | 
| AUSTRIA\$1SSN |  사회보장번호(호주인의 경우).  | 
| AUSTRIA\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(오스트리아만 해당).  | 
| AUSTRIA\$1VALUE\$1ADDED\$1TAX |  부가가치세(오스트리아만 해당).  | 

 **발칸 반도 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| BOSNIA\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  보스니아-헤르체고비나 시민의 고유 마스터 시민 번호(JMBG).  | 
| KOSOVO\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  코소보의 고유 마스터 시민 번호(JMBG).  | 
| MACEDONIA\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  마케도니아의 고유 마스터 시민 번호.  | 
| MONTENEGRO\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  몬테네그로의 고유 마스터 시민 번호(JMBG).  | 
| SERBIA\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  세르비아의 고유 마스터 시민 번호(JMBG).  | 
| SERBIA\$1VALUE\$1ADDED\$1TAX |  부가가치세(세르비아만 해당).  | 
| VOJVODINA\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  보이보디나의 고유 마스터 시민 번호(JMBG).  | 

 **벨기에 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| BELGIUM\$1DRIVING\$1LICENSE |  운전면허증 번호(벨기에만 해당).  | 
| BELGIUM\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  벨기에 국가 번호(BNN).  | 
| BELGIUM\$1PASSPORT\$1NUMBER |  여권 번호(벨기에만 해당).  | 
| BELGIUM\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(벨기에만 해당).  | 
| BELGIUM\$1VALUE\$1ADDED\$1TAX |  부가가치세(벨기에만 해당).  | 

 **브라질 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| BRAZIL\$1BANK\$1ACCOUNT | 은행 계좌 번호(브라질만 해당). | 
| BRAZIL\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자(브라질만 해당).  | 
| BRAZIL\$1NATIONAL\$1REGISTRY\$1OF\$1LEGAL\$1ENTITIES\$1NUMBER |  회사에 발급되는 식별 번호(CNPJ라고도 함, 브라질만 해당).  | 
| BRAZIL\$1NATURAL\$1PERSON\$1REGISTRY\$1NUMBER |  자연인 등록 번호(CPF라고도 함).  | 

 **불가리아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| BULGARIA\$1DRIVING\$1LICENSE |  운전면허증 번호(불가리아만 해당).  | 
| BULGARIA\$1UNIFORM\$1CIVIL\$1NUMBER |  국가 식별 번호 역할을 하는 통합 시민 번호(EGN).  | 
| BULGARIA\$1VALUE\$1ADDED\$1TAX |  부가가치세(불가리아만 해당).  | 

 **캐나다 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| CANADA\$1DRIVING\$1LICENSE |  운전면허증 번호(캐나다만 해당).  | 
| CANADA\$1GOVERNMENT\$1IDENTIFICATION\$1CARD\$1NUMBER |  국가 식별자(캐나다만 해당).  | 
| CANADA\$1PASSPORT\$1NUMBER |  여권 번호(캐나다만 해당).  | 
| CANADA\$1PERMANENT\$1RESIDENCE\$1NUMBER |  영주권 번호(PR 카드 번호).  | 
| CANADA\$1PERSONAL\$1HEALTH\$1NUMBER |  의료용 고유 식별자(PHN 번호).  | 
| CANADA\$1SOCIAL\$1INSURANCE\$1NUMBER |  캐나다의 사회보험 번호(SIN).  | 

 **칠레 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| CHILE\$1DRIVING\$1LICENSE |  운전면허증 번호(칠레만 해당).  | 
| CHILE\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  칠레 국가 식별자(RUT 또는 RUN이라고도 함).  | 

 **중국, 홍콩, 마카오, 대만 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| CHINA\$1IDENTIFICATION |  중국 식별자.  | 
| CHINA\$1LICENSE\$1PLATE\$1NUMBER |  운전면허증 번호(중국만 해당).  | 
| CHINA\$1MAINLAND\$1TRAVEL\$1PERMIT\$1ID\$1HONG\$1KONG\$1MACAU |  홍콩 및 마카오 거주자를 위한 본토 여행 허가증.  | 
| CHINA\$1MAINLAND\$1TRAVEL\$1PERMIT\$1ID\$1TAIWAN |  중화인민공화국 정부(PRC)에서 발급한 대만 거주자를 위한 본토 여행 허가증.  | 
| CHINA\$1PASSPORT\$1NUMBER |  여권 번호(중국만 해당).  | 
| CHINA\$1PHONE\$1NUMBER |  전화번호(캐나다만 해당).  | 
| HONG\$1KONG\$1IDENTITY\$1CARD |  홍콩 이민국에서 발급한 공식 신분증.  | 
| MACAU\$1RESIDENT\$1IDENTITY\$1CARD |  마카오 거주자 신분증 또는 BIR은 마카오 신원확인국에서 발급하는 공식 신분증.  | 
| TAIWAN\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자(대만만 해당).  | 
| TAIWAN\$1PASSPORT\$1NUMBER |  여권 번호(대만만 해당).  | 

 **콜롬비아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| COLOMBIA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  콜롬비아 출생 시 부여되는 고유 식별자.  | 
| COLOMBIA\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(콜롬비아만 해당).  | 

 **크로아티아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| CROATIA\$1DRIVING\$1LICENSE |  운전면허증 번호(크로아티아만 해당).  | 
| CROATIA\$1IDENTITY\$1NUMBER |  국가 식별자(크로아티아에만 해당).  | 
| CROATIA\$1PASSPORT\$1NUMBER |  여권 번호(크로아티아만 해당).  | 
| CROATIA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  개인 식별 번호(OIB).  | 

 **키프로스 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| CYPRUS\$1DRIVING\$1LICENSE |  운전면허증 번호(키프로스만 해당).  | 
| CYPRUS\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  키프로스 신분증.  | 
| CYPRUS\$1PASSPORT\$1NUMBER |  여권 번호(키프로스만 해당).  | 
| CYPRUS\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(키프로스만 해당).  | 
| CYPRUS\$1VALUE\$1ADDED\$1TAX |  부가가치세(키프로스만 해당).  | 

 **체코 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| CZECHIA\$1DRIVING\$1LICENSE |  운전면허증 번호(체코만 해당).  | 
| CZECHIA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  개인 식별자 번호(체코만 해당).  | 
| CZECHIA\$1VALUE\$1ADDED\$1TAX |  부가가치세(체코만 해당).  | 

 **덴마크 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| DENMARK\$1DRIVING\$1LICENSE |  운전면허증 번호(덴마크만 해당).  | 
| DENMARK\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  개인 식별자 번호(덴마크만 해당).  | 
| DENMARK\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(덴마크만 해당).  | 
| DENMARK\$1VALUE\$1ADDED\$1TAX |  부가가치세(덴마크만 해당).  | 

 **에스토니아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| ESTONIA\$1DRIVING\$1LICENSE |  운전면허증 번호(에스토니아만 해당).  | 
| ESTONIA\$1PASSPORT\$1NUMBER |  여권 번호(에스토니아만 해당).  | 
| ESTONIA\$1PERSONAL\$1IDENTIFICATION\$1CODE |  개인 식별자 번호(에스토니아만 해당).  | 
| ESTONIA\$1VALUE\$1ADDED\$1TAX |  부가가치세(에스토니아만 해당).  | 

 **핀란드 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| FINLAND\$1DRIVING\$1LICENSE |  운전면허증 번호(핀란드만 해당).  | 
| FINLAND\$1HEALTH\$1INSURANCE\$1NUMBER |  건강 보험 번호(핀란드만 해당).  | 
| FINLAND\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자 번호(핀란드만 해당).  | 
| FINLAND\$1PASSPORT\$1NUMBER |  여권 번호(핀란드만 해당).  | 
| FINLAND\$1VALUE\$1ADDED\$1TAX |  부가가치세(핀란드만 해당).  | 

 **프랑스 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| FRANCE\$1BANK\$1ACCOUNT |  은행 계좌 번호(프랑스만 해당).  | 
| FRANCE\$1DRIVING\$1LICENSE |  운전면허증 번호(프랑스만 해당).  | 
| FRANCE\$1HEALTH\$1INSURANCE\$1NUMBER |  프랑스 건강보험 번호.  | 
| FRANCE\$1INSEE\$1CODE |  프랑스 사회보장번호, SSN 번호 또는 NIR 번호.  | 
| FRANCE\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  프랑스 국가 식별자 번호(CNI).  | 
| FRANCE\$1PASSPORT\$1NUMBER |  여권 번호(프랑스만 해당).  | 
| FRANCE\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(프랑스만 해당).  | 
| FRANCE\$1VALUE\$1ADDED\$1TAX |  부가가치세(프랑스만 해당).  | 

 **독일 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| GERMANY\$1BANK\$1ACCOUNT |  은행 계좌 번호(독일만 해당).  | 
| GERMANY\$1DRIVING\$1LICENSE |  운전면허증 번호(독일만 해당).  | 
| GERMANY\$1PASSPORT\$1NUMBER |  여권 번호(독일만 해당).  | 
| GERMANY\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  개인 식별 번호(독일만 해당).  | 
| GERMANY\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(독일만 해당).  | 
| GERMANY\$1VALUE\$1ADDED\$1TAX |  부가가치세(독일만 해당).  | 

 **그리스 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| GREECE\$1DRIVING\$1LICENSE |  운전면허증 번호(그리스만 해당).  | 
| GREECE\$1PASSPORT\$1NUMBER |  여권 번호(그리스만 해당).  | 
| GREECE\$1SSN |  사회보장번호(그리스인의 경우).  | 
| GREECE\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(그리스만 해당).  | 
| GREECE\$1VALUE\$1ADDED\$1TAX |  부가가치세(그리스만 해당).  | 

 **헝가리 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| HUNGARY\$1DRIVING\$1LICENSE |  운전면허증 번호(헝가리만 해당).  | 
| HUNGARY\$1PASSPORT\$1NUMBER |  여권 번호(헝가리만 해당).  | 
| HUNGARY\$1SSN |  사회보장번호(헝가리인의 경우).  | 
| HUNGARY\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(헝가리만 해당).  | 
| HUNGARY\$1VALUE\$1ADDED\$1TAX |  부가가치세(헝가리만 해당).  | 

 **아이슬란드 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| ICELAND\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자(아이슬란드만 해당).  | 
| ICELAND\$1PASSPORT\$1NUMBER |  여권 번호(아이슬란드만 해당).  | 
| ICELAND\$1VALUE\$1ADDED\$1TAX |  부가가치세(아이슬란드만 해당).  | 

 **인도 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| INDIA\$1AADHAAR\$1NUMBER |  인도 Unique Identification Authority에서 발급한 아드하르 식별 번호.  | 
| INDIA\$1PERMANENT\$1ACCOUNT\$1NUMBER |  인도의 소득세 번호(PAN).  | 

 **인도네시아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| INDONESIA\$1IDENTITY\$1CARD\$1NUMBER |  국가 식별자(인도네시아만 해당).  | 

 **아일랜드 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| IRELAND\$1DRIVING\$1LICENSE |  운전면허증 번호(아일랜드만 해당).  | 
| IRELAND\$1PASSPORT\$1NUMBER |  여권 번호(아일랜드만 해당).  | 
| IRELAND\$1PERSONAL\$1PUBLIC\$1SERVICE\$1NUMBER |  아일랜드 개인 공공 서비스 번호(PPS).  | 
| IRELAND\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(아일랜드만 해당).  | 
| IRELAND\$1VALUE\$1ADDED\$1TAX |  부가가치세(아일랜드만 해당).  | 

 **이스라엘 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| ISRAEL\$1IDENTIFICATION\$1NUMBER |  국가 식별자(이스라엘만 해당).  | 

 **이탈리아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| ITALY\$1BANK\$1ACCOUNT |  은행 계좌 번호(이탈리아만 해당).  | 
| ITALY\$1DRIVING\$1LICENSE |  운전면허증 번호(이탈리아만 해당).  | 
| ITALY\$1FISCAL\$1CODE |  식별자 번호(이탈리아 코디체 피스칼레(Codice Fiscale)라고도 함).  | 
| ITALY\$1PASSPORT\$1NUMBER |  여권 번호(이탈리아만 해당).  | 
| ITALY\$1VALUE\$1ADDED\$1TAX |  부가가치세(이탈리아만 해당).  | 

 **일본 데이터 유형** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| JAPAN\$1BANK\$1ACCOUNT |  일본 은행 계좌.  | 
| JAPAN\$1DRIVING\$1LICENSE |  일본의 운전면허증 번호.  | 
| JAPAN\$1MY\$1NUMBER |  조세 행정, 사회 보장 행정 및 재해 대응을 위해 사용하는 일본 시민 또는 법인의 고유 식별자   | 
| JAPAN\$1PASSPORT\$1NUMBER |  일본 여권 번호.  | 

 **한국 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| KOREA\$1PASSPORT\$1NUMBER |  여권 번호(한국만 해당).  | 
| KOREA\$1RESIDENCE\$1REGISTRATION\$1NUMBER\$1FOR\$1CITIZENS |  한국 주민등록번호.  | 
| KOREA\$1RESIDENCE\$1REGISTRATION\$1NUMBER\$1FOR\$1FOREIGNERS |  외국인을 위한 한국의 외국인 등록 번호.  | 

 **라트비아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| LATVIA\$1DRIVING\$1LICENSE |  운전면허증 번호(라트비아만 해당).  | 
| LATVIA\$1PASSPORT\$1NUMBER |  여권 번호(라트비아만 해당).  | 
| LATVIA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  개인 식별자 번호(라트비아만 해당).  | 
| LATVIA\$1VALUE\$1ADDED\$1TAX |  부가가치세(라트비아만 해당).  | 

 **리히텐슈타인 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| LIECHTENSTEIN\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자(리히텐슈타인만 해당).  | 
| LIECHTENSTEIN\$1PASSPORT\$1NUMBER |  여권 번호(리히텐슈타인만 해당).  | 
| LIECHTENSTEIN\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(리히텐슈타인만 해당).  | 

 **리투아니아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| LITHUANIA\$1DRIVING\$1LICENSE |  운전면허증 번호(리투아니아만 해당).  | 
| LITHUANIA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  개인 식별자 번호(리투아니아만 해당).  | 
| LITHUANIA\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(리투아니아만 해당).  | 
| LITHUANIA\$1VALUE\$1ADDED\$1TAX |  부가가치세(리투아니아만 해당).  | 

 **룩셈부르크 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| LUXEMBOURG\$1DRIVING\$1LICENSE |  운전면허증 번호(룩셈부르크만 해당).  | 
| LUXEMBOURG\$1NATIONAL\$1INDIVIDUAL\$1NUMBER |  국가 식별자(룩셈부르크만 해당).  | 
| LUXEMBOURG\$1PASSPORT\$1NUMBER |  여권 번호(룩셈부르크만 해당).  | 
| LUXEMBOURG\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(룩셈부르크만 해당).  | 
| LUXEMBOURG\$1VALUE\$1ADDED\$1TAX |  부가가치세(룩셈부르크만 해당).  | 

 **말레이시아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| MALAYSIA\$1MYKAD\$1NUMBER |  국가 식별자(말레이시아만 해당).  | 
| MALAYSIA\$1PASSPORT\$1NUMBER |  여권 번호(말레이시아만 해당).  | 

 **몰타 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| MALTA\$1DRIVING\$1LICENSE |  운전면허증 번호(몰타만 해당).  | 
| MALTA\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자(몰타만 해당).  | 
| MALTA\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(몰타만 해당).  | 
| MALTA\$1VALUE\$1ADDED\$1TAX |  부가가치세(몰타만 해당).  | 

 **멕시코 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| MEXICO\$1CLABE\$1NUMBER |  멕시코 Clave Bancaria Estandarizada(CLABE) 은행 번호.  | 
| MEXICO\$1DRIVING\$1LICENSE |  운전면허증 번호(멕시코만 해당).  | 
| MEXICO\$1PASSPORT\$1NUMBER |  여권 번호(멕시코만 해당).  | 
| MEXICO\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(멕시코만 해당).  | 
| MEXICO\$1UNIQUE\$1POPULATION\$1REGISTRY\$1CODE |  멕시코의 고유 식별 코드(Clave Única de Registro de Población(CURP)).  | 

 **네덜란드 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| NETHERLANDS\$1CITIZEN\$1SERVICE\$1NUMBER |  네덜란드의 시민 번호(BSN, burgerservicenummer).  | 
| NETHERLANDS\$1DRIVING\$1LICENSE |  운전면허증 번호(네덜란드만 해당).  | 
| NETHERLANDS\$1PASSPORT\$1NUMBER |  여권 번호(네덜란드만 해당).  | 
| NETHERLANDS\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(네덜란드만 해당).  | 
| NETHERLANDS\$1VALUE\$1ADDED\$1TAX |  부가가치세(네덜란드만 해당).  | 
| NETHERLANDS\$1BANK\$1ACCOUNT |  은행 계좌 번호(네덜란드만 해당).  | 

 **뉴질랜드 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| NEW\$1ZEALAND\$1DRIVING\$1LICENSE |  운전면허증 번호(뉴질랜드만 해당).  | 
| NEW\$1ZEALAND\$1NATIONAL\$1HEALTH\$1INDEX\$1NUMBER |  뉴질랜드 국가 건강 지수 번호.  | 
| NEW\$1ZEALAND\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(내국세 번호라고도 함, 뉴질랜드만 해당).  | 

 **노르웨이 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| NORWAY\$1BIRTH\$1NUMBER |  노르웨이 국가 식별 번호.  | 
| NORWAY\$1DRIVING\$1LICENSE |  운전면허증 번호(노르웨이만 해당).  | 
| NORWAY\$1HEALTH\$1INSURANCE\$1NUMBER |  노르웨이 건강보험 번호.  | 
| NORWAY\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자 번호(노르웨이만 해당).  | 
| NORWAY\$1VALUE\$1ADDED\$1TAX |  부가가치세(노르웨이만 해당).  | 

 **필리핀 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| PHILIPPINES\$1DRIVING\$1LICENSE |  운전면허증 번호(필리핀만 해당).  | 
| PHILIPPINES\$1PASSPORT\$1NUMBER |  여권 번호(필리핀만 해당).  | 

 **폴란드 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| POLAND\$1DRIVING\$1LICENSE |  운전면허증 번호(폴란드만 해당).  | 
| POLAND\$1IDENTIFICATION\$1NUMBER |  폴란드 식별자.  | 
| POLAND\$1PASSPORT\$1NUMBER |  여권 번호(폴란드만 해당).  | 
| POLAND\$1REGON\$1NUMBER |  REGON 식별자 번호(통계 식별 번호라고도 함).  | 
| POLAND\$1SSN |  사회보장번호(폴란드인의 경우).  | 
| POLAND\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(폴란드만 해당).  | 
| POLAND\$1VALUE\$1ADDED\$1TAX |  부가가치세(폴란드만 해당).  | 

 **포르투갈 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| PORTUGAL\$1DRIVING\$1LICENSE |  운전면허증 번호(포르투갈만 해당).  | 
| PORTUGAL\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자 번호(포르투갈만 해당).  | 
| PORTUGAL\$1PASSPORT\$1NUMBER |  여권 번호(포르투갈만 해당).  | 
| PORTUGAL\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(포르투갈만 해당).  | 
| PORTUGAL\$1VALUE\$1ADDED\$1TAX |  부가가치세(포르투갈만 해당).  | 

 **루마니아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| ROMANIA\$1DRIVING\$1LICENSE |  운전면허증 번호(루마니아만 해당).  | 
| ROMANIA\$1NUMERICAL\$1PERSONAL\$1CODE |  개인 식별자 번호(루마니아만 해당).  | 
| ROMANIA\$1PASSPORT\$1NUMBER |  여권 번호(루마니아만 해당).  | 
| ROMANIA\$1VALUE\$1ADDED\$1TAX |  부가가치세(루마니아만 해당).  | 

 **싱가포르 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| SINGAPORE\$1DRIVING\$1LICENSE |  운전면허증 번호(싱가포르만 해당).  | 
| SINGAPORE\$1NATIONAL\$1REGISTRY\$1IDENTIFICATION\$1NUMBER |  싱가포르 국가 등록 신분증.  | 
| SINGAPORE\$1PASSPORT\$1NUMBER |  여권 번호(싱가포르만 해당).  | 
| SINGAPORE\$1UNIQUE\$1ENTITY\$1NUMBER |  싱가포르 고유 법인 번호.  | 

 **슬로바키아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| SLOVAKIA\$1DRIVING\$1LICENSE |  운전면허증 번호(슬로바키아만 해당).  | 
| SLOVAKIA\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자 번호(슬로바키아만 해당).  | 
| SLOVAKIA\$1PASSPORT\$1NUMBER |  여권 번호(슬로바키아만 해당).  | 
| SLOVAKIA\$1VALUE\$1ADDED\$1TAX |  부가가치세(슬로바키아만 해당).  | 

 **슬로베니아 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| SLOVENIA\$1DRIVING\$1LICENSE |  운전면허증 번호(슬로베니아만 해당).  | 
| SLOVENIA\$1PASSPORT\$1NUMBER |  여권 번호(슬로베니아만 해당).  | 
| SLOVENIA\$1TAX\$1IDENTIFICATION\$1NUMBER |  세금 식별 번호(슬로베니아만 해당).  | 
| SLOVENIA\$1UNIQUE\$1MASTER\$1CITIZEN\$1NUMBER |  슬로베니아 시민의 고유 마스터 시민 번호(JMBG).  | 
| SLOVENIA\$1VALUE\$1ADDED\$1TAX |  부가가치세(슬로베니아만 해당).  | 

 **남아프리카 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| SOUTH\$1AFRICA\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  개인 식별자 번호(남아프리카 공화국만 해당).  | 

 **일본 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| SPAIN\$1BANK\$1ACCOUNT |  은행 계좌 번호(스페인만 해당).  | 
| SPAIN\$1DNI |  스페인의 국가 신분증(Documento Nacional de Identidad).  | 
| SPAIN\$1DRIVING\$1LICENSE |  운전면허증 번호(스페인만 해당).  | 
| SPAIN\$1NIE |  외국인 신분증 번호(NIE라고도 함, 스페인만 해당).  | 
| SPAIN\$1NIF |  세금 식별 번호(NIF라고도 함, 스페인만 해당).  | 
| SPAIN\$1PASSPORT\$1NUMBER |  여권 번호(스페인만 해당).  | 
| SPAIN\$1SSN |  사회보장번호(스페인의 경우).  | 
| SPAIN\$1VALUE\$1ADDED\$1TAX |  부가가치세(스페인만 해당).  | 

 **스리랑카 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| SRI\$1LANKA\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자(스리랑카만 해당).  | 

 **스웨덴 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| SWEDEN\$1DRIVING\$1LICENSE |  운전면허증 번호(스웨덴만 해당).  | 
| SWEDEN\$1PASSPORT\$1NUMBER |  여권 번호(스웨덴만 해당).  | 
| SWEDEN\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자 번호(스웨덴만 해당).  | 
| SWEDEN\$1TAX\$1IDENTIFICATION\$1NUMBER |  스웨덴 세금 식별 번호(personnummer).  | 
| SWEDEN\$1VALUE\$1ADDED\$1TAX |  부가가치세(스웨덴만 해당).  | 

 **스위스 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| SWITZERLAND\$1AHV |  스위스인의 사회보장번호(AHV).  | 
| SWITZERLAND\$1HEALTH\$1INSURANCE\$1NUMBER |  스위스 건강보험 번호.  | 
| SWITZERLAND\$1PASSPORT\$1NUMBER |  여권 번호(스위스만 해당).  | 
| SWITZERLAND\$1VALUE\$1ADDED\$1TAX |  부가가치세(스위스만 해당).  | 

 **태국 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| THAILAND\$1PASSPORT\$1NUMBER |  여권 번호(태국만 해당).  | 
| THAILAND\$1PERSONAL\$1IDENTIFICATION\$1NUMBER |  개인 식별자 번호(태국만 해당).  | 

 **터키 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| TURKEY\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자 번호(튀르키예만 해당).  | 
| TURKEY\$1PASSPORT\$1NUMBER |  여권 번호(튀르기예만 해당).  | 
| TURKEY\$1VALUE\$1ADDED\$1TAX |  부가가치세(튀르키예만 해당).  | 

 **우크라이나 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| UKRAINE\$1INDIVIDUAL\$1IDENTIFICATION\$1NUMBER |  고유 식별자(우크라이나만 해당).  | 
| UKRAINE\$1PASSPORT\$1NUMBER\$1DOMESTIC |  국내 여권 번호(우크라이나만 해당).  | 
| UKRAINE\$1PASSPORT\$1NUMBER\$1INTERNATIONAL |  국제 여권 번호(우크라이나만 해당).  | 

 **아랍에미리트(UAE) 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| UNITED\$1ARAB\$1EMIRATES\$1PERSONAL\$1NUMBER |  개인 식별자 번호(UAE만 해당).  | 

 **영국 데이터 유형** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| UK\$1BANK\$1ACCOUNT |  영국 은행 계좌.  | 
| UK\$1BANK\$1SORT\$1CODE |   영국 은행 지점 코드. 지점 코드(sort code)는 해당 통관 기관을 통해 각 국가 안의 은행 간에 송금을 라우팅하기 위해 사용하는 은행 코드입니다.  | 
| UK\$1DRIVING\$1LICENSE |  영국 및 북아일랜드의 운전 면허증 번호(영국만 해당)  | 
| UK\$1ELECTORAL\$1ROLL\$1NUMBER |  선거인단 번호(ERN)는 영국 선거 등록을 위해 개인에게 발급하는 식별 번호입니다. 이 번호의 형식은 영국 내각 사무처의 영국 정부 표준에 명시되어 있습니다.  | 
| UK\$1NATIONAL\$1HEALTH\$1SERVICE\$1NUMBER |  국민 보건 서비스(NHS) 번호는 영국의 등록된 공중 보건 서비스 사용자에게 할당하는 고유 번호입니다.  | 
| UK\$1NATIONAL\$1INSURANCE\$1NUMBER |  국민 보험 번호(NINO)는 영국(UK)에서 국민 보험 프로그램 또는 사회 보장 제도를 위해 개인을 식별하는 데 사용하는 번호입니다. 일부 경우에 NI No 또는 NINO라고도 합니다.  | 
| UK\$1PASSPORT\$1NUMBER |  영국 여권 번호.  | 
| UK\$1UNIQUE\$1TAXPAYER\$1REFERENCE\$1NUMBER |  영국(UK) 고유 납세자 참조(UTR) 번호. 영국 정부가 과세 제도를 관리하기 위해 사용하는 식별자.  | 
| UK\$1VALUE\$1ADDED\$1TAX |  VAT는 최종 소비자가 부담하는 소비세입니다. VAT는 제조 및 유통 과정에서 이뤄지는 각 거래에 대해 지불합니다. 영국의 경우 VAT 번호는 사업체가 설립된 지역의 VAT 사무소에서 발급합니다.  | 
| UK\$1PHONE\$1NUMBER |  영국 전화번호.  | 

 **베네수엘라 데이터 형식** 


| 데이터 형식 | 설명 | 
| --- | --- | 
| VENEZUELA\$1DRIVING\$1LICENSE |  운전면허증 번호(베네수엘라만 해당).  | 
| VENEZUELA\$1NATIONAL\$1IDENTIFICATION\$1NUMBER |  국가 식별자 번호(베네수엘라만 해당).  | 
| VENEZUELA\$1VALUE\$1ADDED\$1TAX |  부가가치세(베네수엘라만 해당).  | 

# 세분화된 데이터 탐지 사용하기
<a name="sensitive-data-fine-grained-actions"></a>

**참고**  
 세분화된 동작은 AWS Glue 3.0 및 4.0에서만 사용할 수 있습니다. 여기에는 AWS Glue Studio 경험도 포함됩니다. 2.0에서는 영구 감사 로그 변경도 사용할 수 없습니다.  
 모든 AWS Glue Studio 3.0 및 4.0 비주얼 작업에는 세분화된 작업 API를 자동으로 사용하는 스크립트가 생성됩니다.

 민감 데이터 탐지 변환은 사용자가 정의하거나 AWS Glue에서 사전 정의한 엔터티를 탐지, 마스크 또는 제거하는 기능을 제공합니다. 또한 세분화된 액션을 통해 엔터티별로 특정 액션을 적용할 수 있습니다. 추가 혜택은 다음과 같습니다.
+  데이터가 감지되는 즉시 조치가 적용되므로 성능이 개선되었습니다.
+  특정 열을 포함하거나 제외하는 옵션.
+  부분 마스킹을 사용할 수 있습니다. 이렇게 하면 전체 문자열을 마스킹하는 대신 감지된 민감한 데이터 엔터티를 부분적으로 마스킹할 수 있습니다. 오프셋과 정규식이 있는 단순 매개 변수가 모두 지원됩니다.

 다음은 다음 섹션에서 참조할 샘플 작업에 사용되는 민감한 데이터 탐지 API와 세분화된 조치의 코드 스니펫입니다.

 **Detect API**- 세분화된 작업에는 새 `detectionParameters` 파라미터가 사용됩니다.

```
def detect(
    frame: DynamicFrame,
    detectionParameters: JsonOptions,
    outputColumnName: String = "DetectedEntities",
    detectionSensitivity: String = "LOW"
): DynamicFrame = {}
```

## 민감한 데이터 탐지 API와 세밀한 조치 사용
<a name="sensitive-data-fine-grained-actions-glue-jobs"></a>

 **detect**를 사용하는 민감한 데이터 탐지 API는 제공된 데이터를 분석하고, 행 또는 열이 민감한 데이터 항목 유형인지 확인하고 각 엔터티 유형에 대해 사용자가 지정한 작업을 실행합니다.

### 탐지 API를 사용하여 세부적인 조치를 취하십시오
<a name="sensitive-data-fine-grained-actions-glue-jobs-detect"></a>

 **detect** API를 사용하고 `outputColumnName` 및 ` detectionParameters`를 지정합니다.

```
    object GlueApp {
      def main(sysArgs: Array[String]) {
      
        val spark: SparkContext = new SparkContext()
        val glueContext: GlueContext = new GlueContext(spark)
        
        // @params: [JOB_NAME]
        val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME").toArray)
        Job.init(args("JOB_NAME"), glueContext, args.asJava)
        
        // Script generated for node S3 bucket. Creates DataFrame from data stored in S3.
        val S3bucket_node1 = glueContext.getSourceWithFormat(formatOptions=JsonOptions("""{"quoteChar": "\"", "withHeader": true, "separator": ",", "optimizePerformance": false}"""), connectionType="s3", format="csv", options=JsonOptions("""{"paths": ["s3://189657479688-ddevansh-pii-test-bucket/tiny_pii.csv"], "recurse": true}"""), transformationContext="S3bucket_node1").getDynamicFrame()
     
        // Script generated for node Detect Sensitive Data. Will run detect API for the DataFrame
        // detectionParameter contains information on which EntityType are being detected
        // and what actions are being applied to them when detected. 
        val DetectSensitiveData_node2 = EntityDetector.detect(
            frame = S3bucket_node1, 
            detectionParameters = JsonOptions(
             """
                {
                    "PHONE_NUMBER": [
                        {
                            "action": "PARTIAL_REDACT",
                            "actionOptions": {
                                "numLeftCharsToExclude": "3",
                                "numRightCharsToExclude": "4",
                                "redactChar": "#"
                            },
                            "sourceColumnsToExclude": [ "Passport No", "DL NO#" ]
                        }
                    ],
                    "USA_PASSPORT_NUMBER": [
                        {
                            "action": "SHA256_HASH",
                            "sourceColumns": [ "Passport No" ]
                        }
                    ],
                    "USA_DRIVING_LICENSE": [
                        {
                            "action": "REDACT",
                            "actionOptions": {
                                "redactText": "USA_DL"
                            },
                            "sourceColumns": [ "DL NO#" ]
                        }
                    ]
                    
                }
            """
            ),
            outputColumnName = "DetectedEntities"
        )
     
        // Script generated for node S3 bucket. Store Results of detect to S3 location
        val S3bucket_node3 = glueContext.getSinkWithFormat(connectionType="s3", options=JsonOptions("""{"path": "s3://amzn-s3-demo-bucket/test-output/", "partitionKeys": []}"""), transformationContext="S3bucket_node3", format="json").writeDynamicFrame(DetectSensitiveData_node2)
     
        Job.commit()
      }
```

 위 스크립트는 Amazon S3의 위치에서 DataFrame을 생성한 다음 `detect` API를 실행합니다. `detect` API는 Glue 객체로 표시되는 필드 `detectionParameters`(해당 엔터티에 사용할 모든 작업 설정을 나열하는 엔터티 이름 맵)를 AWS Glue의 `JsonOptions` 객체로 표시해야 하므로 API의 기능을 확장할 수도 있습니다.

 엔터티별로 지정된 각 작업에 대해 엔터티/액션 조합을 적용할 모든 열 이름 목록을 입력합니다. 이렇게 하면 데이터 세트의 모든 열을 감지하도록 항목을 사용자 지정하고 특정 열에 없는 것으로 알려진 항목은 건너뛸 수 있습니다. 또한 이러한 엔터티에 대해 불필요한 탐지 호출을 수행하지 않아도 되므로 작업 성능이 향상되고 각 열과 엔터티 조합에 고유한 작업을 수행할 수 있습니다.

 `detectionParameters`를 자세히 살펴보면 샘플 작업에는 세 가지 엔터티 유형이 있습니다. `Phone Number`, `USA_PASSPORT_NUMBER`, `USA_DRIVING_LICENSE`입니다. 이 같은 각 개체 유형에 대해 AWS Glue는 `PARTIAL_REDACT`, `SHA256_HASH`, `REDACT`, `DETECT` 같은 서로 다른 작업을 실행합니다. 각 개체 유형도 `sourceColumns`에 적용하거나 탐지된 경우 `sourceColumnsToExclude`에 적용해야 합니다.

**참고**  
 열당 내부 편집 작업(`PARTIAL_REDACT`, `SHA256_HASH`, 또는`REDACT`) 하나만 사용할 수 있지만 해당 `DETECT` 작업은 이러한 모든 작업에 사용할 수 있습니다.

 `detectionParameters` 필드 레이아웃은 다음과 같습니다.

```
    ENTITY_NAME -> List[Actions]
    {
    	"ENTITY_NAME": [{
    		Action, // required
    		ColumnSpecs,
    		ActionOptionsMap
        }],
        "ENTITY_NAME2": [{
    		...
        }]
    }
```

 `actions` 및 `actionOptions`의 유형은 다음과 같습니다.

```
DETECT
{
    # Required
    "action": "DETECT",
    # Optional, depending on action chosen
    "actionOptions": {
        // There are no actionOptions for DETECT 
    },
    # 1 of below required, both can also used
    "sourceColumns": [
        "COL_1", "COL_2", ..., "COL_N"
    ],
    "sourceColumnsToExclude": [
        "COL_5"
    ]
}

SHA256_HASH
{
    # Required
    "action": "SHA256_HASH",
    # Required or optional, depending on action chosen
    "actionOptions": {
        // There are no actionOptions for SHA256_HASH
    },
    
    # 1 of below required, both can also used
    "sourceColumns": [
        "COL_1", "COL_2", ..., "COL_N"
    ],
    "sourceColumnsToExclude": [
        "COL_5"
    ]
}

REDACT
{
    # Required
    "action": "REDACT",
    # Required or optional, depending on action chosen
    "actionOptions": {
        // The text that is being replaced
        "redactText": "USA_DL"
    },
    
    # 1 of below required, both can also used
    "sourceColumns": [
        "COL_1", "COL_2", ..., "COL_N"
    ],
    "sourceColumnsToExclude": [
        "COL_5"
    ]
}

PARTIAL_REDACT
{
    # Required
    "action": "PARTIAL_REDACT",
    # Required or optional, depending on action chosen
    "actionOptions": {
        // number of characters to not redact from the left side 
        "numLeftCharsToExclude": "3",
        // number of characters to not redact from the right side
        "numRightCharsToExclude": "4",
        // the partial redact will be made with this redacted character  
        "redactChar": "#",
        // regex pattern for partial redaction
        "matchPattern": "[0-9]"
    },
    
    # 1 of below required, both can also used
    "sourceColumns": [
        "COL_1", "COL_2", ..., "COL_N"
    ],
    "sourceColumnsToExclude": [
        "COL_5"
    ]
}
```

 스크립트가 실행되면 결과가 지정된 Amazon S3 위치에 출력됩니다. Amazon S3에서 데이터를 볼 수 있지만 선택한 엔터티 유형은 선택한 작업에 따라 구분됩니다. 이 경우 다음과 같은 행이 있을 것입니다.

```
{
    "Name": "Colby Schuster",
    "Address": "39041 Antonietta Vista, South Rodgerside, Nebraska 24151",
    "Car Owned": "Fiat",
    "Email": "Kitty46@gmail.com",
    "Company": "O'Reilly Group",
    "Job Title": "Dynamic Functionality Facilitator",
    "ITIN": "991-22-2906",
    "Username": "Cassandre.Kub43",
    "SSN": "914-22-2906",
    "DOB": "2020-08-27",
    "Phone Number": "1-2#######1718",
    "Bank Account No": "69741187",
    "Credit Card Number": "6441-6289-6867-2162-2711",
    "Passport No": "94f311e93a623c72ccb6fc46cf5f5b0265ccb42c517498a0f27fd4c43b47111e",
    "DL NO#": "USA_DL"
}
```

 위 스크립트에서는 `Phone Number`를 사용하여 부분적으로 `#`으로 수정되었습니다. `Passport No`가 SHA256 해시로 변경되었습니다. `DL NO# `는 미국 운전면허증 번호로 인식되어 `detectionParameters`에 명시된 대로 “USA\$1DL”로 수정되었습니다.

**참고**  
 classifyColumns API는 API의 특성상 세분화된 작업에는 사용할 수 없습니다. 이 API는 열 샘플링(사용자가 조정 가능하지만 기본값 사용)을 수행하여 탐지를 더 빠르게 수행합니다. 이러한 이유로 세밀한 작업을 수행하려면 모든 값을 반복해야 합니다.

### 영구 감사 로그
<a name="sensitive-data-fine-grained-actions-persistent-audit-log"></a>

 세분화된 작업과 함께 도입된 새로운 기능(일반 API를 사용할 때도 사용 가능)은 영구 감사 로그의 존재입니다. 현재 detect API를 실행하면 PII 탐지 메타데이터가 포함된 추가 열(`DetectedEntities`가 기본값이지만 `outputColumnName`을 통해 사용자 지정 가능) 매개변수가 추가됩니다. 이제 여기에는,`DETECT`, `PARTIAL_REDACT`, `SHA256_HASH`, `REDACT` 중 하나인 “actionUsed” 메타데이터 키가 있습니다.

```
"DetectedEntities": {
    "Credit Card Number": [
        {
            "entityType": "CREDIT_CARD",
            "actionUsed": "DETECT",
            "start": 0,
            "end": 19
        }
    ],
    "Phone Number": [
        {
            "entityType": "PHONE_NUMBER",
            "actionUsed": "REDACT",
            "start": 0,
            "end": 14
        }
    ]
}
```

 예를 들어 `detect(entityTypesToDetect, outputColumnName)`와 같이 세밀한 조치 없이 API를 사용하는 고객도 결과 데이터 프레임에서 이 영구 감사 로그를 볼 수 있습니다.

 세분화된 조치가 포함된 API를 사용하는 고객은 수정 여부에 관계없이 모든 작업을 볼 수 있습니다. 예제: 

```
+---------------------+----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Credit Card Number  |  Phone Number  |                                                                                            DetectedEntities                                                                                             |
+---------------------+----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 622126741306XXXX    | +12#####7890   | {"Credit Card Number":[{"entityType":"CREDIT_CARD","actionUsed":"PARTIAL_REDACT","start":0,"end":16}],"Phone Number":[{"entityType":"PHONE_NUMBER","actionUsed":"PARTIAL_REDACT","start":0,"end":12}]}} |
| 6221 2674 1306 XXXX | +12#######7890 | {"Credit Card Number":[{"entityType":"CREDIT_CARD","actionUsed":"PARTIAL_REDACT","start":0,"end":19}],"Phone Number":[{"entityType":"PHONE_NUMBER","actionUsed":"PARTIAL_REDACT","start":0,"end":14}]}} |
| 6221-2674-1306-XXXX | 22#######7890  | {"Credit Card Number":[{"entityType":"CREDIT_CARD","actionUsed":"PARTIAL_REDACT","start":0,"end":19}],"Phone Number":[{"entityType":"PHONE_NUMBER","actionUsed":"PARTIAL_REDACT","start":0,"end":14}]}} |
+---------------------+----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
```

 **DetectedEntities** 열을 보지 않으려면 사용자 지정 스크립트에 추가 열을 놓기만 하면 됩니다.

# AWS Glue Visual Job API
<a name="visual-job-api-chapter"></a>

 AWS Glue는 고객이 시각적 단계 워크플로를 나타내는 JSON 객체의 AWS Glue API를 사용하여 데이터 통합 작업을 생성할 수 있게 해주는 API를 제공합니다. 그러면 고객은 AWS Glue Studio의 시각적 편집기를 사용하여 이러한 작업을 수행할 수 있습니다.

 시각적 작업 API 데이터 형식에 대한 자세한 내용은 [Visual Job API](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-visual-job-api.html)를 참조하세요.

**Topics**
+ [

## API 설계 및 CRUD API
](#visual-job-api-design)
+ [

## 시작하기
](#getting-started-visual-job-api)
+ [

## 시각적 작업 제한 사항
](#visual-job-limitations)

## API 설계 및 CRUD API
<a name="visual-job-api-design"></a>

 이제 CreateJob 및 UpdateJob [ API ](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html)에서 선택적 추가 파라미터인 codeGenConfigurationNodes를 지원합니다. 이 필드에 비어 있지 않은 JSON 구조를 제공하면 생성된 작업에 대한 DAG가 AWS Glue Studio에 등록되고 관련 코드가 생성됩니다. 작업 생성 시 이 필드의 Null 값이나 빈 문자열은 무시됩니다.

 codeGenConfigurationNodes 필드에 대한 업데이트는 CreateJob과 비슷한 방식으로 UpdateJob AWS Glue API를 통해 수행됩니다. DAG가 원하는 대로 변경된 UpdateJob에 전체 필드를 지정해야 합니다. 제공된 Null 값은 무시되며 DAG에 대한 업데이트가 수행되지 않습니다. 빈 구조나 문자열을 제공하면 codeGenConfigurationNodes가 비어 있는 것으로 설정되고 이전 DAG는 모두 제거됩니다. GetJob API는 DAG를 반환합니다(존재하는 경우). DeleteJob API는 연결된 모든 DAG도 삭제합니다.

## 시작하기
<a name="getting-started-visual-job-api"></a>

 작업을 생성하려면 [CreateJob 작업](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html#aws-glue-api-jobs-job-CreateJob)을 사용합니다. `CreateJob` 요청 입력에는 JSON에서 DAG 객체를 지정할 수 있는 추가 필드인 ‘codeGenConfigurationNodes’가 있습니다.

 다음과 같은 사항에 유의하세요.
+  'codeGenConfigurationNodes' 필드는 nodeId를 노드에 매핑한 것입니다.
+  각 노드는 노드 종류를 식별하는 키로 시작합니다.
+  노드는 단일 유형만 가능하므로 하나의 키만 지정할 수 있습니다.
+  입력 필드에는 현재 노드의 상위 노드가 포함됩니다.

 다음은 **CreateJob** 입력의 JSON 표현입니다.

```
{
  "node-1": {
    "S3CatalogSource": {
      "Table": "csvFormattedTable",
      "PartitionPredicate": "",
      "Name": "S3 bucket",
      "AdditionalOptions": {},
      "Database": "myDatabase"
    }
  },
  "node-3": {
    "S3DirectTarget": {
      "Inputs": ["node-2"],
      "PartitionKeys": [],
      "Compression": "none",
      "Format": "json",
      "SchemaChangePolicy": { "EnableUpdateCatalog": false },
      "Path": "",
      "Name": "S3 bucket"
    }
  },
  "node-2": {
    "ApplyMapping": {
      "Inputs": ["node-1"],
      "Name": "ApplyMapping",
      "Mapping": [
        {
          "FromType": "long",
          "ToType": "long",
          "Dropped": false,
          "ToKey": "myheader1",
          "FromPath": ["myheader1"]
        },
        {
          "FromType": "long",
          "ToType": "long",
          "Dropped": false,
          "ToKey": "myheader2",
          "FromPath": ["myheader2"]
        },
        {
          "FromType": "long",
          "ToType": "long",
          "Dropped": false,
          "ToKey": "myheader3",
          "FromPath": ["myheader3"]
        }
      ]
    }
  }
}
```

 **작업 업데이트 및 가져오기** 

 *UpdateJob*에도 ‘codeGenConfigurationNodes’ 필드가 있으므로 입력 형식은 동일합니다. [UpdateJob](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html#aws-glue-api-jobs-job-UpdateJob) 작업을 참조하세요.

 *GetJob* 작업도 동일한 형식으로 ‘codeGenConfigurationNodes’ 필드를 반환합니다. [GetJob](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html#aws-glue-api-jobs-job-GetJob) 작업을 참조하세요.

## 시각적 작업 제한 사항
<a name="visual-job-limitations"></a>

 'codeGenConfigurationNodes' 파라미터가 기존 API에 추가되었으므로 해당 API의 모든 제한 사항이 상속됩니다. 또한 codeGenConfigurationNodes와 일부 노드는 크기가 제한됩니다. 자세한 내용은 [ 작업 구조 ](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html#aws-glue-api-jobs-job-Job)를 참조하세요.