

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

# Hudi
<a name="emr-hudi"></a>

[Apache Hudi](https://hudi.apache.org/)는 증분 데이터 처리 및 데이터 파이프라인 개발을 간소화하는 데 사용되는 오픈 소스 데이터 관리 프레임워크로, 레코드 수준의 삽입, 업데이트, 업서트 및 삭제 기능을 제공합니다. *Upsert*란 레코드가 존재하지 않은 경우 기존 데이터 세트에 레코드를 삽입하거나 레코드가 존재하는 경우 레코드를 업데이트할 수 있는 기능입니다. Hudi를 이용해 Amazon S3에 데이터를 배치하는 방법을 효율적으로 관리함으로써 거의 실시간으로 데이터를 수집하고 업데이트할 수 있습니다. Hudi에서는 데이터 세트에 수행된 작업의 메타데이터가 세심히 관리되므로 작업의 원자성 및 일관성을 보장하는 데 도움이 됩니다.

Hudi는 [Apache Spark](https://aws.amazon.com/emr/features/spark/), [Apache Hive](https://hive.apache.org/), [Presto](https://prestodb.github.io)와 통합됩니다. Amazon EMR 릴리스 버전 6.1.0 이상에서 Hudi는 [Trino(PrestoSQL)](https://trino.io/)와도 통합되었습니다.

Amazon EMR 릴리스 버전 5.28.0 이상에서 EMR은 Spark, Hive, Presto 또는 Flink가 설치된 경우 기본적으로 Hudi 구성 요소를 설치합니다. Spark 또는 Hudi DeltaStreamer 유틸리티를 사용하여 Hudi 데이터 세트를 만들거나 업데이트할 수 있습니다. Hive, Spark, Presto 또는 Flink를 사용하여 Hudi 데이터 세트를 대화식으로 쿼리하거나 *증분 풀*을 사용하여 데이터 처리 파이프라인을 구축할 수 있습니다. 증분 풀이란 두 작업 간에 변경된 데이터만 가져올 수 있는 기능입니다.

이러한 기능을 통해 다음 사용 사례에서 Hudi를 사용하여 유리합니다.
+ 특정 데이터 삽입 및 업데이트 이벤트가 필요한 센서 및 기타 사물 인터넷(IoT) 디바이스에서의 스트리밍 데이터 작업.
+ 사용자가 데이터 사용 방법에 대한 동의를 잊어버릴 수 있거나 수정할 수도 있는 애플리케이션의 데이터 프라이버시 규정 준수.
+ 시간이 지남에 따라 데이터 세트에 변경 사항을 적용할 수 있는 [데이터 캡처 변경(CDC) 시스템](https://en.wikipedia.org/wiki/Change_data_capture) 구현.

다음 테이블에는 Amazon EMR이 Hudi를 통해 설치하는 구성 요소와 함께 Amazon EMR 7.x 시리즈의 최신 릴리스에 포함된 Hudi의 버전이 나열되어 있습니다.

이 릴리스에서 Hudi와 함께 설치된 구성 요소의 버전은 [릴리스 7.12.0 구성 요소 버전을 참조하세요](emr-7120-release.md).


**emr-7.12.0용 Hudi 버전 정보**  

| Amazon EMR 릴리스 레이블 | Hudi 버전 | Hudi와 함께 설치된 구성 요소 | 
| --- | --- | --- | 
| emr-7.12.0 | Hudi 1.0.2-amzn-1 | Not available. | 

다음 테이블에는 Amazon EMR이 Hudi를 통해 설치하는 구성 요소와 함께 Amazon EMR 6.x 시리즈의 최신 릴리스에 포함된 Hudi의 버전이 나열되어 있습니다.

이 릴리스에서 Hudi와 함께 설치된 구성 요소의 버전은 [릴리스 6.15.0 구성 요소 버전](emr-6150-release.md)을 참조하세요.


**emr-6.15.0용 Hudi 버전 정보**  

| Amazon EMR 릴리스 레이블 | Hudi 버전 | Hudi와 함께 설치된 구성 요소 | 
| --- | --- | --- | 
| emr-6.15.0 | Hudi 0.14.0-amzn-0 | Not available. | 

**참고**  
Amazon EMR 릴리스 6.8.0은 [Apache Hudi](https://hudi.apache.org/) 0.11.1과 함께 제공되지만, Amazon EMR 6.8.0 클러스터는 Hudi 0.12.0의 오픈 소스 `hudi-spark3.3-bundle_2.12`와도 호환됩니다.

다음 테이블에는 Amazon EMR이 Hudi를 통해 설치하는 구성 요소와 함께 Amazon EMR 5.x 시리즈의 최신 릴리스에 포함된 Hudi의 버전이 나열되어 있습니다.

이 릴리스에서 Hudi와 함께 설치된 구성 요소의 버전은 [릴리스 5.36.2 구성 요소 버전](emr-5362-release.md)을 참조하세요.


**emr-5.36.2용 Hudi 버전 정보**  

| Amazon EMR 릴리스 레이블 | Hudi 버전 | Hudi와 함께 설치된 구성 요소 | 
| --- | --- | --- | 
| emr-5.36.2 | Hudi 0.10.1-amzn-1 | Not available. | 

**Topics**
+ [Hudi 작동 방식](emr-hudi-how-it-works.md)
+ [Amazon EMR 기반 Hudi 사용 시 고려 사항 및 제한 사항](emr-hudi-considerations.md)
+ [Hudi가 설치된 클러스터 생성](emr-hudi-installation-and-configuration.md)
+ [Hudi 데이터 세트 작업](emr-hudi-work-with-dataset.md)
+ [Hudi CLI 사용](emr-hudi-cli.md)
+ [Hudi 릴리스 기록](Hudi-release-history.md)

# Hudi 작동 방식
<a name="emr-hudi-how-it-works"></a>

Amazon EMR에서 Hudi를 사용하는 경우 Spark 데이터 소스 API 또는 Hudi DeltaStreamer 유틸리티를 사용하여 데이터 세트에 데이터를 쓸 수 있습니다. Hudi는 데이터 세트를 기존 Hive 테이블과 유사한 `basepath` 아래 파티셔닝된 디렉터리 구조로 구성합니다. 데이터가 이러한 디렉터리의 파일로 배치되는 방법에 대한 세부 사항은 선택한 데이터 세트 유형에 따라 다릅니다. CoW(쓸 때 복사) 또는 MoR(읽을 때 병합) 중 하나를 선택할 수 있습니다.

데이터 세트 유형에 상관없이 데이터 세트의 각 파티션은 `basepath`와(과) 관련된 `partitionpath`에 의해 고유하게 식별됩니다. 각 파티션 내에서 레코드는 여러 데이터 파일로 배포됩니다. 자세한 내용은 Apache Hudi 설명서의 [파일 관리](https://hudi.apache.org/docs/concepts.html#file-management)를 참조하세요.

Hudi의 각 작업에는 해당하는 커밋이 있으며, 이 커밋은 일정하게 증가하는 타임스탬프(*인스턴트*라고도 함)로 식별됩니다. Hudi는 데이터 세트에서 수행된 일련의 모든 작업을 타임라인으로 유지합니다. Hudi는 타임라인을 통해 리더와 라이터 간 스냅샷 격리를 제공하고 이전 시점으로 롤백할 수 있도록 합니다. Hudi 레코드 및 작업 상태에 대한 자세한 내용은 Apache Hudi 설명서에서 [Timeline](https://hudi.apache.org/docs/concepts.html#timeline)을 참조하세요.

## 데이터 세트 스토리지 유형 이해: 쓸 때 복사 및 읽을 때 병합
<a name="emr-hudi-data-files"></a>

Hudi 데이터 세트를 만들 때 데이터 세트를 쓸 때 복사 또는 읽을 때 병합으로 지정합니다.
+ **쓸 때 복사(CoW)** - 데이터가 열 기반 형식(Parquet)으로 저장되며, 각 업데이트마다 쓰기 중에 새 버전의 파일을 만듭니다. CoW가 기본 스토리지 유형입니다.
+ **읽을 때 병합(MoR)** - 데이터가 열 기반 형식(Parquet)과 행 기반(Avro) 형식을 조합하여 저장됩니다. 업데이트는 행 기반 *delta* 파일에 기록되며 새 버전의 열 형식 파일을 작성할 때 필요에 따라 압축됩니다.

CoW 데이터 세트를 사용하면 레코드에 대한 업데이트가 있을 때마다 레코드가 포함된 파일이 업데이트된 값으로 다시 작성됩니다. MoR 데이터 세트를 사용하면 Hudi는 업데이트가 있을 때마다 변경된 레코드에 대한 행만 씁니다. MoR은 읽기 수행이 적고 쓰기 또는 변경이 많은 워크로드에 더 적합합니다. CoW는 자주 변경되지 않는 데이터에서 읽기 수행이 많은 워크로드에 더 적합합니다.

Hudi는 데이터에 액세스하기 위한 세 가지 논리 뷰를 제공합니다:
+ **읽기 최적화 보기** - CoW 테이블의 최신 커밋된 데이터 세트와 MoR 테이블의 최신 압축 데이터 세트를 제공합니다.
+ **증분 보기** - 다운스트림 작업을 내보내고 워크플로를 추출, 변환, 로드(ETL)하기 위해 CoW 데이터 세트의 두 작업 간에 변경 스트림을 제공합니다.
+ **실시간 보기** - 열 및 행 기반 파일을 인라인으로 병합하여 MoR 테이블에서 커밋된 최신 데이터를 제공합니다.

읽기 최적화 뷰를 쿼리하면 쿼리는 압축된 모든 데이터를 반환하지만 최신 델타 커밋은 포함하지 않습니다. 이러한 데이터를 쿼리하면 읽기 성능은 뛰어나지만 최신 데이터는 생략됩니다. 실시간 뷰를 쿼리하는 경우 Hudi는 읽을 때 압축된 데이터를 델타 커밋과 병합합니다. 최신 데이터는 쿼리할 수 있지만 병합의 컴퓨팅 오버헤드로 인해 쿼리 성능은 떨어집니다. 압축된 데이터 또는 실시간 데이터를 쿼리할 수 있으므로 쿼리할 때 성능과 유연성 중에서 선택할 수 있습니다.

스토리지 유형 간의 장단점에 대한 자세한 내용은 Apache Hudi 설명서에서 [Storage types & views](https://hudi.apache.org/docs/concepts.html#storage-types--views)를 참조하세요.

Hudi는 MoR용 Hive 메타스토어에 테이블을 두 개 만듭니다. 즉, 사용자가 지정한 이름을 가진 테이블(읽기 최적화 보기)과 `_rt`가 추가된 동일한 이름을 가진 테이블(실시간 보기)입니다. 두 테이블을 모두 쿼리할 수 있습니다.

## Hudi 데이터 세트를 메타스토어에 등록
<a name="emr-hudi-hive-metastore"></a>

Hudi 테이블을 Hive 메타스토dj에 등록할 때 기타 모든 테이블처럼 Hive, Spark SQL 또는 Presto를 사용하여 Hudi 테이블을 쿼리할 수 있습니다. 또한 Glue 데이터 카탈로그를 AWS 메타스토어로 사용하도록 Hive 및 Spark를 구성하여 Hudi를 AWS Glue와 통합할 수 있습니다. MoR 테이블의 경우 Hudi는 메타스토어에 두 개의 테이블로 데이터 세트를 등록합니다. 즉, 사용자가 지정한 이름을 가진 테이블(읽기 최적화 보기)과 `_rt`가 추가된 동일한 이름을 가진 테이블(실시간 보기)입니다.

`HIVE_SYNC_ENABLED_OPT_KEY` 옵션을 `"true"`로 설정하고 다른 필수 속성을 제공하여 Hudi 데이터 세트를 만드는 데 Spark를 사용하는 경우 Hudi 테이블을 Hive 메타스토어에 등록합니다. 자세한 내용은 [Hudi 데이터 세트 작업](emr-hudi-work-with-dataset.md) 단원을 참조하십시오. 또한 hive\$1sync\$1tool 명령줄 유틸리티를 사용하여 Hudi 데이터 세트를 메타스토어의 테이블로 별도로 등록할 수 있습니다.

# Amazon EMR 기반 Hudi 사용 시 고려 사항 및 제한 사항
<a name="emr-hudi-considerations"></a>
+ **레코드 키 필드의 경우 null이거나 비워둘 수 없음** - 레코드 키 필드로 지정하는 필드는 `null`이거나 빈 값일 수 없습니다.
+ **업서트 및 삽입 시 기본적으로 업데이트되는 스키마** - Hudi는 입력 DataFrame과 기존 Hudi 데이터 세트를 병합하여 업데이트된 새 데이터 세트를 생성하는 방법을 결정하는 인터페이스 `HoodieRecordPayload`를 제공합니다. Hudi는 입력 DataFrame에 지정된 대로 기존 레코드를 덮어쓰고 스키마를 업데이트하는 이 클래스의 기본 구현(`OverwriteWithLatestAvroPayload`)을 제공합니다. 병합 및 부분 업데이트 구현을 위해 이 논리를 사용자 지정하려면 `DataSourceWriteOptions.PAYLOAD_CLASS_OPT_KEY` 파라미터를 사용하여 `HoodieRecordPayload` 인터페이스 구현을 제공할 수 있습니다.
+ **삭제 시 스키마 필요** - 삭제할 때는 레코드 키, 파티션 키 및 사전 결합 키 필드를 지정해야 합니다. 다른 열은 `null`이거나 비워둘 수 있지만 전체 스키마가 필요합니다.
+ **MoR 테이블 제한** - MoR 테이블은 세이브 포인트 기능을 지원하지 않습니다. Spark SQL, Presto 또는 Hive의 읽기 최적화 보기 또는 실시간 보기(`tableName_rt`)를 사용하여 MoR 테이블을 쿼리할 수 있습니다. 읽기 최적화 보기를 사용하면 기본 파일 데이터만 노출되고 기본 및 로그 데이터의 병합된 보기는 노출되지 않습니다.
+ **Hive**
  + 테이블을 Hive 메타스토어에 등록하는 경우 Hudi는 Hive Thrift 서버가 기본 포트인 `10000`에서 실행될 것으로 예상합니다. 이 포트를 사용자 지정 포트로 재정의하는 경우 다음 예와 같이 `HIVE_URL_OPT_KEY` 옵션을 전달합니다.

    ```
    .option(DataSourceWriteOptions.HIVE_URL_OPT_KEY, "jdbc:hive2://localhost:override-port-number
    ```
  + Spark의 `timestamp` 데이터 유형은 Hive의 `long` 유형이 아닌 Hive의 `timestamp` 데이터 유형으로 등록됩니다.
+ **Presto**
  + Presto는 0.6.0 미만의 Hudi 버전에서 MoR 실시간 테이블 읽기를 지원하지 않습니다.
  + Presto는 스냅샷 쿼리만 지원합니다.
  + Presto에서 Hudi 데이터 세트 열을 올바르게 해석하려면 `hive.parquet_use_column_names` 값을 `true`로 설정합니다.
    + 세션의 값을 설정하려면 Presto 셸에서 다음 명령을 실행합니다.

      ```
      set session hive.parquet_use_column_names=true
      ```
    + 클러스터 수준에서 값을 설정하려면 다음 예와 같이 `presto-connector-hive` 구성 분류를 사용하여 `hive.parquet.use_column_names`을(를) `true`로 설정합니다. 자세한 내용은 [애플리케이션 구성](emr-configure-apps.md) 단원을 참조하십시오.

      ```
      [
        {
          "Classification": "presto-connector-hive",
          "Properties": {
            "hive.parquet.use-column-names": "true"
          }
        }
      ]
      ```
+ **HBase 인덱스**
  + Hudi를 *빌드*하는 데 사용된 HBase 버전은 EMR 릴리스 안내서에 나온 버전과 다를 수 있습니다. Spark 세션에 올바른 종속 항목을 가져오려면 다음 명령을 실행합니다.

    ```
    spark-shell \
    --jars /usr/lib/spark/external/lib/spark-avro.jar,/usr/lib/hudi/cli/lib/*.jar \
    --conf "spark.serializer=org.apache.spark.serializer.KryoSerializer" \
    --conf "spark.sql.hive.convertMetastoreParquet=false"
    ```
+ **최상의 성능을 위한 설정** - EMR 7.3\$1/Hudi 0.15\$1의 경우 Kryo 직렬화 오버헤드를 줄이기 위해이 구성을 설정하는 것이 좋습니다.

  ```
  --conf 'spark.kryo.registrator=org.apache.spark.HoodieKryoRegistrar'
  ```
**참고**  
EMR Serverless에서 세분화된 액세스 제어(FGAC)를 사용하는 경우 사용자가 KryoSerializer 대신 JavaSerializer를 사용해야 하므로 이 구성은 필요하지 않습니다.

# Hudi가 설치된 클러스터 생성
<a name="emr-hudi-installation-and-configuration"></a>

Amazon EMR 릴리스 버전 5.28.0 이상에서 EMR은 Spark, Hive 또는 Presto가 설치된 경우 기본적으로 Hudi 구성 요소를 설치합니다. Amazon EMR 기반 Hudi를 사용하려면 다음 애플리케이션 중 하나 이상 설치된 클러스터를 생성합니다.
+ Hadoop
+ Hive
+ Spark
+ Presto
+ Flink

 AWS CLI, 또는 Amazon EMR API AWS Management Console를 사용하여 클러스터를 생성할 수 있습니다.

## 를 사용하여 Hudi로 클러스터를 생성하려면 AWS Management Console
<a name="emr-hudi-create-cluster-console"></a>

1. 새 Amazon EMR 콘솔로 이동하고 측면 탐색에서 **이전 콘솔로 전환**을 선택합니다. 이전 콘솔로 전환할 때 예상되는 사항에 대한 자세한 내용은 [이전 콘솔 사용](https://docs.aws.amazon.com/emr/latest/ManagementGuide/whats-new-in-console.html#console-opt-in)을 참조하세요.

1. **클러스터 생성** 및 **고급 옵션으로 이동**을 선택합니다.

1. 소프트웨어 구성에서 **릴리스**로 **emr-5.28.0** 이상을 선택하고 클러스터에 필요한 다른 애플리케이션과 함께 **Hadoop**, **Hive**, **Spark**, **Presto**, **Tez**를 선택합니다.

1. 애플리케이션에 필요한 기타 옵션을 구성한 후 [**Next**]를 선택합니다.

1. **하드웨어** 및 **일반 클러스터 설정에** 대한 옵션을 원하는 대로 구성합니다.

1. **보안 옵션**의 경우 SSH를 사용하여 마스터 노드 명령줄에 연결하는 데 사용할 수 있는 **EC2 키 페어**를 선택하는 것이 좋습니다. 이렇게 하면 이 안내서에 설명된 Spark 쉘 명령, Hive CLI 명령 및 Hudi CLI 명령을 실행할 수 있습니다.

1. 기타 보안 옵션을 원하는 대로 선택하고 **클러스터 생성**을 선택합니다.

# Hudi 데이터 세트 작업
<a name="emr-hudi-work-with-dataset"></a>

Hudi는 Spark를 통해 Hudi 데이터 세트에서의 데이터 삽입, 업데이트 및 삭제를 지원합니다. 자세한 내용은 Apache Hudi 설명서에서 [Writing Hudi tables](https://hudi.apache.org/docs/writing_data.html)를 참조하세요.

다음 예제에서는 대화식 Spark 쉘을 시작하거나 Spark 제출을 사용하거나 Amazon EMR에서 Hudi를 작업하기 위해 Amazon EMR Notebooks를 사용하는 방법을 보여줍니다. 또한 Hudi DeltaStreamer 유틸리티 또는 기타 도구를 사용하여 데이터 세트에 쓸 수도 있습니다. 이 섹션에 소개된 예에서는 SSH를 기본 `hadoop` 사용자로 사용하여 마스터 노드에 연결되어 있는 동안 Spark 셸을 사용하여 데이터 세트로 작업하는 방법을 보여줍니다.

## Amazon EMR 6.7 이상을 사용하여 Spark 쉘 시작
<a name="hudi-datasets-67"></a>

Amazon EMR 6.7.0 이상을 사용하여 `spark-shell`, `spark-submit` 또는 `spark-sql`을 실행하는 경우 다음 명령을 전달합니다.

**참고**  
Amazon EMR 6.7.0은 [Apache Hudi](https://hudi.apache.org/) 0.11.0-amzn-0을 사용하며, 이는 이전 Hudi 버전에 비해 크게 개선되었습니다. 자세한 내용은 [Apache Hudi 0.11.0 Migration Guide](https://hudi.apache.org/releases/release-0.11.0/#migration-guide)를 참조하세요. 이 탭의 예제에는 이러한 변경 사항이 반영되어 있습니다.

**프라이머리 노드에서 Spark 쉘을 여는 방법**

1. SSH를 사용하여 프라이머리 노드에 연결합니다. 자세한 내용은 *Amazon EMR 관리 안내서*에서 [SSH를 사용하여 프라이머리 노드에 연결](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)을 참조하세요.

1. Spark 셸을 시작하려면 다음 명령을 입력합니다. PySpark 쉘을 사용하려면 *spark-shell*을 *pyspark*로 바꿉니다.

   ```
   spark-shell --jars /usr/lib/hudi/hudi-spark-bundle.jar \
   --conf "spark.serializer=org.apache.spark.serializer.KryoSerializer" \    
   --conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.hudi.catalog.HoodieCatalog"  \
   --conf "spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension"
   ```

## Amazon EMR 6.6 이하를 사용하여 Spark 쉘 시작
<a name="hudi-datasets-67"></a>

Amazon EMR 6.6.x 이하를 사용하여 `spark-shell`, `spark-submit` 또는 `spark-sql`을 실행하는 경우 다음 명령을 전달합니다.

**참고**  
Amazon EMR 6.2 및 5.31 이상(Hudi 0.6.x 이상)에서는 구성에서 `spark-avro.jar`을 생략할 수 있습니다.
Amazon EMR 6.5 및 5.35 이상(Hudi 0.9.x 이상)에서는 구성에서 `spark.sql.hive.convertMetastoreParquet=false`를 생략할 수 있습니다.
Amazon EMR 6.6 및 5.36 이상(Hudi 0.10.x 이상)에서는 [Version: 0.10.0 Spark Guide](https://hudi.apache.org/docs/0.10.0/quick-start-guide/)에 설명된 대로 `HoodieSparkSessionExtension` 구성을 포함해야 합니다.  

  ```
  --conf  "spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension" \
  ```

**프라이머리 노드에서 Spark 쉘을 여는 방법**

1. SSH를 사용하여 프라이머리 노드에 연결합니다. 자세한 내용은 *Amazon EMR 관리 안내서*에서 [SSH를 사용하여 프라이머리 노드에 연결](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)을 참조하세요.

1. Spark 셸을 시작하려면 다음 명령을 입력합니다. PySpark 쉘을 사용하려면 *spark-shell*을 *pyspark*로 바꿉니다.

   ```
   spark-shell \
   --conf "spark.serializer=org.apache.spark.serializer.KryoSerializer" \
   --conf "spark.sql.hive.convertMetastoreParquet=false" \
   --jars /usr/lib/hudi/hudi-spark-bundle.jar,/usr/lib/spark/external/lib/spark-avro.jar
   ```

## Amazon EMR 6.7 이상을 사용하는 Amazon EMR Notebooks에서 Hudi 사용
<a name="hudi-datasets-notebooks"></a>

Amazon EMR Notebooks에서 Hudi를 사용하려면 먼저 로컬 파일 시스템의 Hudi jar 파일을 노트북 클러스터의 프라이머리 노드에 있는 HDFS로 복사해야 합니다. 그런 다음, 노트북 편집기를 이용해 Hudi를 사용하도록 EMR 노트북을 구성합니다.

**Amazon EMR Notebooks에서 Hudi를 사용하는 방법**

1. Amazon EMR Notebooks에 대한 클러스터를 생성하고 시작합니다. 자세한 내용은 *Amazon EMR 관리 안내서*에서 [노트북에 대한 Amazon EMR 클러스터 생성](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-managed-notebooks-cluster.html)을 참조하세요.

1. SSH를 사용하여 클러스터의 마스터 노드에 연결하고 다음 예와 같이 로컬 파일 시스템의 jar 파일을 HDFS로 복사합니다. 이 예에서는 파일 관리의 명확성을 위해 HDFS에 디렉터리를 만듭니다. 원할 경우 HDFS에서 자체 대상을 선택할 수 있습니다.

   ```
   hdfs dfs -mkdir -p /apps/hudi/lib
   ```

   ```
   hdfs dfs -copyFromLocal /usr/lib/hudi/hudi-spark-bundle.jar /apps/hudi/lib/hudi-spark-bundle.jar
   ```

1. 노트북 편집기를 열고 다음 예의 코드를 입력하고 실행합니다.

   ```
   %%configure
   { "conf": {
               "spark.jars":"hdfs:///apps/hudi/lib/hudi-spark-bundle.jar",
               "spark.serializer":"org.apache.spark.serializer.KryoSerializer",
               "spark.sql.catalog.spark_catalog": "org.apache.spark.sql.hudi.catalog.HoodieCatalog",
               "spark.sql.extensions":"org.apache.spark.sql.hudi.HoodieSparkSessionExtension"
             }}
   ```

## Amazon EMR 6.6 이하를 사용하는 Amazon EMR Notebooks에서 Hudi 사용
<a name="hudi-datasets-notebooks-66"></a>

Amazon EMR Notebooks에서 Hudi를 사용하려면 먼저 로컬 파일 시스템의 Hudi jar 파일을 노트북 클러스터의 프라이머리 노드에 있는 HDFS로 복사해야 합니다. 그런 다음, 노트북 편집기를 이용해 Hudi를 사용하도록 EMR 노트북을 구성합니다.

**Amazon EMR Notebooks에서 Hudi를 사용하는 방법**

1. Amazon EMR Notebooks에 대한 클러스터를 생성하고 시작합니다. 자세한 내용은 *Amazon EMR 관리 안내서*에서 [노트북에 대한 Amazon EMR 클러스터 생성](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-managed-notebooks-cluster.html)을 참조하세요.

1. SSH를 사용하여 클러스터의 마스터 노드에 연결하고 다음 예와 같이 로컬 파일 시스템의 jar 파일을 HDFS로 복사합니다. 이 예에서는 파일 관리의 명확성을 위해 HDFS에 디렉터리를 만듭니다. 원할 경우 HDFS에서 자체 대상을 선택할 수 있습니다.

   ```
   hdfs dfs -mkdir -p /apps/hudi/lib
   ```

   ```
   hdfs dfs -copyFromLocal /usr/lib/hudi/hudi-spark-bundle.jar /apps/hudi/lib/hudi-spark-bundle.jar
   ```

   ```
   hdfs dfs -copyFromLocal /usr/lib/spark/external/lib/spark-avro.jar /apps/hudi/lib/spark-avro.jar
   ```

1. 노트북 편집기를 열고 다음 예의 코드를 입력하고 실행합니다.

   ```
   { "conf": {
               "spark.jars":"hdfs:///apps/hudi/lib/hudi-spark-bundle.jar,hdfs:///apps/hudi/lib/spark-avro.jar",
               "spark.serializer":"org.apache.spark.serializer.KryoSerializer",
               "spark.sql.hive.convertMetastoreParquet":"false"
             }}
   ```

## Hudi용 Spark 세션 초기화
<a name="emr-hudi-initialize-session"></a>

Scala를 사용할 때는 Spark 세션에서 다음 클래스를 가져와야 합니다. Spark 세션당 한 번 이 작업을 수행하면 됩니다.

```
import org.apache.spark.sql.SaveMode
import org.apache.spark.sql.functions._
import org.apache.hudi.DataSourceWriteOptions
import org.apache.hudi.DataSourceReadOptions
import org.apache.hudi.config.HoodieWriteConfig
import org.apache.hudi.hive.MultiPartKeysValueExtractor
import org.apache.hudi.hive.HiveSyncConfig
import org.apache.hudi.sync.common.HoodieSyncConfig
```

## Hudi 데이터 세트에 쓰기
<a name="emr-hudi-dataframe"></a>

다음 예제에서는 DataFrame을 생성하고 Hudi 데이터 세트로 쓰는 방법을 보여줍니다.

**참고**  
코드 샘플을 Spark 셸에 붙여넣으려면 프롬프트에 **:paste**를 입력하고 예제를 붙여넣은 다음 **CTRL** \$1 **D**를 누릅니다.

Hudi 데이터 세트에 DataFrame을 쓸 때마다 `DataSourceWriteOptions`을 지정해야 합니다. 이러한 옵션 대부분이 쓰기 작업 간에 동일할 수 있습니다. 다음 예에서는 `hudiOptions` 변수를 사용하여 일반 옵션을 지정합니다. 이 변수는 그 다음 예제에서도 사용합니다.

### Amazon EMR 6.7 이상에서 Scala를 사용하여 작성
<a name="scala-examples-67"></a>

**참고**  
Amazon EMR 6.7.0은 [Apache Hudi](https://hudi.apache.org/) 0.11.0-amzn-0을 사용하며, 이는 이전 Hudi 버전에 비해 크게 개선되었습니다. 자세한 내용은 [Apache Hudi 0.11.0 Migration Guide](https://hudi.apache.org/releases/release-0.11.0/#migration-guide)를 참조하세요. 이 탭의 예제에는 이러한 변경 사항이 반영되어 있습니다.

```
// Create a DataFrame
val inputDF = Seq(
 ("100", "2015-01-01", "2015-01-01T13:51:39.340396Z"),
 ("101", "2015-01-01", "2015-01-01T12:14:58.597216Z"),
 ("102", "2015-01-01", "2015-01-01T13:51:40.417052Z"),
 ("103", "2015-01-01", "2015-01-01T13:51:40.519832Z"),
 ("104", "2015-01-02", "2015-01-01T12:15:00.512679Z"),
 ("105", "2015-01-02", "2015-01-01T13:51:42.248818Z")
 ).toDF("id", "creation_date", "last_update_time")

//Specify common DataSourceWriteOptions in the single hudiOptions variable 
val hudiOptions = Map[String,String](
  HoodieWriteConfig.TBL_NAME.key -> "tableName",
  DataSourceWriteOptions.TABLE_TYPE.key -> "COPY_ON_WRITE", 
  DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY -> "id",
  DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY -> "creation_date",
  DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY -> "last_update_time",
  DataSourceWriteOptions.HIVE_SYNC_ENABLED_OPT_KEY -> "true",
  DataSourceWriteOptions.HIVE_TABLE_OPT_KEY -> "tableName",
  DataSourceWriteOptions.HIVE_PARTITION_FIELDS_OPT_KEY -> "creation_date",
  HoodieSyncConfig.META_SYNC_PARTITION_EXTRACTOR_CLASS.key -> "org.apache.hudi.hive.MultiPartKeysValueExtractor",
  HoodieSyncConfig.META_SYNC_ENABLED.key -> "true",
  HiveSyncConfig.HIVE_SYNC_MODE.key -> "hms",
  HoodieSyncConfig.META_SYNC_TABLE_NAME.key -> "tableName",
  HoodieSyncConfig.META_SYNC_PARTITION_FIELDS.key -> "creation_date"
)

// Write the DataFrame as a Hudi dataset
(inputDF.write
    .format("hudi")
    .options(hudiOptions)
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY,"insert")
    .mode(SaveMode.Overwrite)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### Amazon EMR 6.6 이하에서 Scala를 사용하여 작성
<a name="scala-examples-66"></a>

```
// Create a DataFrame
val inputDF = Seq(
 ("100", "2015-01-01", "2015-01-01T13:51:39.340396Z"),
 ("101", "2015-01-01", "2015-01-01T12:14:58.597216Z"),
 ("102", "2015-01-01", "2015-01-01T13:51:40.417052Z"),
 ("103", "2015-01-01", "2015-01-01T13:51:40.519832Z"),
 ("104", "2015-01-02", "2015-01-01T12:15:00.512679Z"),
 ("105", "2015-01-02", "2015-01-01T13:51:42.248818Z")
 ).toDF("id", "creation_date", "last_update_time")

//Specify common DataSourceWriteOptions in the single hudiOptions variable 
val hudiOptions = Map[String,String](
  HoodieWriteConfig.TABLE_NAME -> "tableName",
  DataSourceWriteOptions.TABLE_TYPE_OPT_KEY -> "COPY_ON_WRITE", 
  DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY -> "id",
  DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY -> "creation_date",
  DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY -> "last_update_time",
  DataSourceWriteOptions.HIVE_SYNC_ENABLED_OPT_KEY -> "true",
  DataSourceWriteOptions.HIVE_TABLE_OPT_KEY -> "tableName",
  DataSourceWriteOptions.HIVE_PARTITION_FIELDS_OPT_KEY -> "creation_date",
  DataSourceWriteOptions.HIVE_PARTITION_EXTRACTOR_CLASS_OPT_KEY -> classOf[MultiPartKeysValueExtractor].getName
)

// Write the DataFrame as a Hudi dataset
(inputDF.write
    .format("org.apache.hudi")
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY, DataSourceWriteOptions.INSERT_OPERATION_OPT_VAL)
    .options(hudiOptions)
    .mode(SaveMode.Overwrite)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### PySpark를 사용하여 작성
<a name="pyspark-examples"></a>

```
# Create a DataFrame
inputDF = spark.createDataFrame(
    [
        ("100", "2015-01-01", "2015-01-01T13:51:39.340396Z"),
        ("101", "2015-01-01", "2015-01-01T12:14:58.597216Z"),
        ("102", "2015-01-01", "2015-01-01T13:51:40.417052Z"),
        ("103", "2015-01-01", "2015-01-01T13:51:40.519832Z"),
        ("104", "2015-01-02", "2015-01-01T12:15:00.512679Z"),
        ("105", "2015-01-02", "2015-01-01T13:51:42.248818Z"),
    ],
    ["id", "creation_date", "last_update_time"]
)

# Specify common DataSourceWriteOptions in the single hudiOptions variable
hudiOptions = {
'hoodie.table.name': 'tableName',
'hoodie.datasource.write.recordkey.field': 'id',
'hoodie.datasource.write.partitionpath.field': 'creation_date',
'hoodie.datasource.write.precombine.field': 'last_update_time',
'hoodie.datasource.hive_sync.enable': 'true',
'hoodie.datasource.hive_sync.table': 'tableName',
'hoodie.datasource.hive_sync.partition_fields': 'creation_date',
'hoodie.datasource.hive_sync.partition_extractor_class': 'org.apache.hudi.hive.MultiPartKeysValueExtractor'
}

# Write a DataFrame as a Hudi dataset
inputDF.write \
.format('org.apache.hudi') \
.option('hoodie.datasource.write.operation', 'insert') \
.options(**hudiOptions) \
.mode('overwrite') \
.save('s3://amzn-s3-demo-bucket/myhudidataset/')
```

**참고**  
코드 예제 및 알림에서 Hudi 대신 'hoodie'가 표시될 수 있습니다. Hudi 코드베이스는 예전의 'hoodie' 철자를 널리 사용합니다.


**Hudi에 대한 DataSourceWriteOptions 참조**  

| 옵션 | 설명 | 
| --- | --- | 
|  TABLE\$1NAME  |  데이터 세트를 등록할 테이블 이름입니다.  | 
|  TABLE\$1TYPE\$1OPT\$1KEY  |  선택 사항. 데이터 세트를 `"COPY_ON_WRITE"` 또는 `"MERGE_ON_READ"`로 생성할지 여부를 지정합니다. 기본값은 `"COPY_ON_WRITE"`입니다.  | 
|  RECORDKEY\$1FIELD\$1OPT\$1KEY  |  값의 레코드 키 필드는 `recordKey`의 `HoodieKey` 구성 요소로 사용됩니다. 실제 값은 필드 값의 `.toString()`을 호출하여 얻을 수 있습니다. 중첩 필드는 점 표기법을 사용하여 지정할 수 있습니다(예: `a.b.c`).  | 
|  PARTITIONPATH\$1FIELD\$1OPT\$1KEY  |  값의 파티션 경로 필드는 `HoodieKey`의 `partitionPath` 구성 요소로 사용됩니다. 실제 값은 필드 값의 `.toString()`을 호출하여 얻을 수 있습니다.  | 
|  PRECOMBINE\$1FIELD\$1OPT\$1KEY  |  실제로 쓰기 전에 미리 결합하는 데 사용되는 필드입니다. 두 레코드에 동일한 키 값이 있는 경우 Hudi는 `Object.compareTo(..)`에 의해 결정된 사전 결합 필드에 대해 가장 큰 값을 가진 레코드를 선택합니다.  | 

다음 옵션은 메타스토어에 Hudi 데이터 세트 테이블을 등록하는 데에만 필요합니다. Hudi 데이터 세트를 Hive 메타스토어의 테이블로 등록하지 않은 경우 이러한 옵션이 필요하지 않습니다.


**Hive에 대한 DataSourceWriteOptions 참조**  

| 옵션 | 설명 | 
| --- | --- | 
|  HIVE\$1DATABASE\$1OPT\$1KEY  |  동기화할 Hive 데이터베이스입니다. 기본값은 `"default"`입니다.  | 
|  HIVE\$1PARTITION\$1EXTRACTOR\$1CLASS\$1OPT\$1KEY  |  파티션 필드 값을 Hive 파티션 열로 추출하는 데 사용되는 클래스입니다.  | 
|  HIVE\$1PARTITION\$1FIELDS\$1OPT\$1KEY  |  Hive 파티션 열을 결정하는 데 사용할 데이터 세트의 필드입니다.  | 
|  HIVE\$1SYNC\$1ENABLED\$1OPT\$1KEY  |  `"true"`로 설정하면 데이터 세트를 Apache Hive 메타스토어에 등록합니다. 기본값은 `"false"`입니다.  | 
|  HIVE\$1TABLE\$1OPT\$1KEY  |  필수 사항입니다. 동기화할 Hive의 테이블의 이름입니다. 예를 들어 `"my_hudi_table_cow"`입니다.  | 
|  HIVE\$1USER\$1OPT\$1KEY  |  선택 사항. 동기화할 때 사용할 Hive 사용자 이름입니다. 예를 들어 `"hadoop"`입니다.  | 
|  HIVE\$1PASS\$1OPT\$1KEY  |  선택 사항. `HIVE_USER_OPT_KEY`에 의해 지정된 사용자의 Hive 암호입니다.  | 
|  HIVE\$1URL\$1OPT\$1KEY  |  Hive 메타스토어 URL입니다.  | 

## 데이터 업서트
<a name="emr-hudi-upsert-to-datasets"></a>

다음 예제에서는 DataFrame를 작성하여 데이터를 업서트하는 방법을 보여줍니다. 이전의 삽입 예제와 달리 `OPERATION_OPT_KEY` 값은 `UPSERT_OPERATION_OPT_VAL`로 설정됩니다. 또한 레코드가 추가되어야 함을 나타내기 위해 `.mode(SaveMode.Append)`가 지정됩니다.

### Amazon EMR 6.7 이상에서 Scala를 사용하여 업서트
<a name="scala-upsert-67"></a>

**참고**  
Amazon EMR 6.7.0은 [Apache Hudi](https://hudi.apache.org/) 0.11.0-amzn-0을 사용하며, 이는 이전 Hudi 버전에 비해 크게 개선되었습니다. 자세한 내용은 [Apache Hudi 0.11.0 Migration Guide](https://hudi.apache.org/releases/release-0.11.0/#migration-guide)를 참조하세요. 이 탭의 예제에는 이러한 변경 사항이 반영되어 있습니다.

```
// Create a new DataFrame from the first row of inputDF with a different creation_date value
val updateDF = inputDF.limit(1).withColumn("creation_date", lit("new_value"))

(updateDF.write
    .format("hudi")
    .options(hudiOptions)
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY, "upsert")
    .mode(SaveMode.Append)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### Amazon EMR 6.6 이하에서 Scala를 사용하여 업서트
<a name="scala-upsert-66"></a>

```
// Create a new DataFrame from the first row of inputDF with a different creation_date value
val updateDF = inputDF.limit(1).withColumn("creation_date", lit("new_value"))

(updateDF.write
    .format("org.apache.hudi")
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY, DataSourceWriteOptions.UPSERT_OPERATION_OPT_VAL)
    .options(hudiOptions)
    .mode(SaveMode.Append)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### PySpark를 사용하여 업서트
<a name="pyspark-upsert"></a>

```
from pyspark.sql.functions import lit

# Create a new DataFrame from the first row of inputDF with a different creation_date value
updateDF = inputDF.limit(1).withColumn('creation_date', lit('new_value'))

updateDF.write \
    .format('org.apache.hudi') \
    .option('hoodie.datasource.write.operation', 'upsert') \
    .options(**hudiOptions) \
    .mode('append') \
    .save('s3://amzn-s3-demo-bucket/myhudidataset/')
```

## 레코드 삭제
<a name="emr-hudi-delete-from-datasets"></a>

레코드를 하드 삭제하려면 빈 페이로드를 업서트할 수 있습니다. 이 경우 `PAYLOAD_CLASS_OPT_KEY` 옵션은 `EmptyHoodieRecordPayload` 클래스를 지정합니다. 이 예제에서는 동일한 레코드를 지정하도록 업서트 예제에서 사용된 동일한 DataFrame(`updateDF`)을 사용합니다.

### Amazon EMR 6.7 이상에서 Scala를 사용하여 삭제
<a name="scala-delete-67"></a>

**참고**  
Amazon EMR 6.7.0은 [Apache Hudi](https://hudi.apache.org/) 0.11.0-amzn-0을 사용하며, 이는 이전 Hudi 버전에 비해 크게 개선되었습니다. 자세한 내용은 [Apache Hudi 0.11.0 Migration Guide](https://hudi.apache.org/releases/release-0.11.0/#migration-guide)를 참조하세요. 이 탭의 예제에는 이러한 변경 사항이 반영되어 있습니다.

```
(updateDF.write
    .format("hudi")
    .options(hudiOptions)
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY, "delete")
    .mode(SaveMode.Append)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### Amazon EMR 6.6 이하에서 Scala를 사용하여 삭제
<a name="scala-delete-66"></a>

```
(updateDF.write
    .format("org.apache.hudi")
    .option(DataSourceWriteOptions.OPERATION_OPT_KEY, DataSourceWriteOptions.UPSERT_OPERATION_OPT_VAL)
    .option(DataSourceWriteOptions.PAYLOAD_CLASS_OPT_KEY, "org.apache.hudi.common.model.EmptyHoodieRecordPayload")
    .mode(SaveMode.Append)
    .save("s3://amzn-s3-demo-bucket/myhudidataset/"))
```

### PySpark를 사용하여 삭제
<a name="pyspark-delete"></a>

```
updateDF.write \
    .format('org.apache.hudi') \
    .option('hoodie.datasource.write.operation', 'upsert') \
    .option('hoodie.datasource.write.payload.class', 'org.apache.hudi.common.model.EmptyHoodieRecordPayload') \
    .options(**hudiOptions) \
    .mode('append') \
    .save('s3://amzn-s3-demo-bucket/myhudidataset/')
```

제출한 데이터 세트의 모든 레코드를 제거하도록 `OPERATION_OPT_KEY `를 `DELETE_OPERATION_OPT_VAL`로 설정하여 데이터를 하드 삭제할 수도 있습니다. 소프트 삭제 수행 지침 및 Hudi 테이블에 저장된 데이터 삭제에 대한 자세한 내용은 Apache Hudi 설명서에서 [Deletes](https://hudi.apache.org/docs/writing_data.html#deletes)를 참조하세요.

## Hudi 데이터 세트에서 읽기
<a name="emr-hudi-read-dataset"></a>

Hudi는 현재 특정 시점에서 데이터를 검색하기 위해 기본적으로 스냅샷 쿼리를 수행합니다. 다음은 [Hudi 데이터 세트에 쓰기](#emr-hudi-dataframe)에서 S3에 기록된 데이터 세트를 쿼리하는 예제입니다. *s3://amzn-s3-demo-bucket/myhudidataset*를 테이블 경로로 바꾸고 각 파티션 수준에 대한 와일드카드 별표와 *하나의 추가 별표*를 추가합니다. 이 예제에서는 파티션 수준이 하나이므로 와일드카드 기호를 두 개 추가했습니다.

### Amazon EMR 6.7 이상에서 Scala를 사용하여 읽기
<a name="scala-read-67"></a>

**참고**  
Amazon EMR 6.7.0은 [Apache Hudi](https://hudi.apache.org/) 0.11.0-amzn-0을 사용하며, 이는 이전 Hudi 버전에 비해 크게 개선되었습니다. 자세한 내용은 [Apache Hudi 0.11.0 Migration Guide](https://hudi.apache.org/releases/release-0.11.0/#migration-guide)를 참조하세요. 이 탭의 예제에는 이러한 변경 사항이 반영되어 있습니다.

```
val snapshotQueryDF = spark.read
    .format("hudi")
    .load("s3://amzn-s3-demo-bucket/myhudidataset") 
    .show()
```

### Amazon EMR 6.6 이하에서 Scala를 사용하여 읽기
<a name="scala-read-66"></a>

```
(val snapshotQueryDF = spark.read
    .format("org.apache.hudi")
    .load("s3://amzn-s3-demo-bucket/myhudidataset" + "/*/*"))

snapshotQueryDF.show()
```

### PySpark를 사용하여 읽기
<a name="pyspark-read"></a>

```
snapshotQueryDF = spark.read \
    .format('org.apache.hudi') \
    .load('s3://amzn-s3-demo-bucket/myhudidataset' + '/*/*')
    
snapshotQueryDF.show()
```

### 증분 쿼리
<a name="emr-hudi-incremental-query"></a>

Hudi에서 증분 쿼리를 수행하여 지정된 커밋 타임스탬프 이후 변경된 레코드 스트림을 가져올 수도 있습니다. 이렇게 하려면 `QUERY_TYPE_OPT_KEY` 필드를 `QUERY_TYPE_INCREMENTAL_OPT_VAL`로 설정합니다. 그런 다음 `BEGIN_INSTANTTIME_OPT_KEY`에 대한 값을 추가하여 지정된 시간 이후에 기록된 모든 레코드를 가져옵니다. 증분 쿼리는 변경된 레코드만 처리하므로 배치 쿼리보다 보통 10배 더 효율적입니다.

증분 쿼리를 수행할 때는 스냅샷 쿼리에 와일드카드 별표를 사용하지 않고 루트(기본) 테이블 경로를 사용합니다.

**참고**  
Presto는 증분 쿼리를 지원하지 않습니다.

#### Scala를 사용한 증분 쿼리
<a name="scala-incremental-queries"></a>

```
val incQueryDF = spark.read
    .format("org.apache.hudi")
    .option(DataSourceReadOptions.QUERY_TYPE_OPT_KEY, DataSourceReadOptions.QUERY_TYPE_INCREMENTAL_OPT_VAL)
    .option(DataSourceReadOptions.BEGIN_INSTANTTIME_OPT_KEY, <beginInstantTime>)
    .load("s3://amzn-s3-demo-bucket/myhudidataset")
     
incQueryDF.show()
```

#### PySpark를 사용한 증분 쿼리
<a name="pyspark-incremental-queries"></a>

```
readOptions = {
  'hoodie.datasource.query.type': 'incremental',
  'hoodie.datasource.read.begin.instanttime': <beginInstantTime>,
}

incQueryDF = spark.read \
    .format('org.apache.hudi') \
    .options(**readOptions) \
    .load('s3://amzn-s3-demo-bucket/myhudidataset')
    
incQueryDF.show()
```

Hudi 데이터 세트에서 읽는 방법에 대한 자세한 내용은 Apache Hudi 설명서에서 [Querying Hudi tables](https://hudi.apache.org/docs/querying_data.html)를 참조하세요.

# Hudi CLI 사용
<a name="emr-hudi-cli"></a>

Hudi CLI를 사용하여 Hudi 데이터 세트를 관리하고 커밋, 파일 시스템, 통계 등에 대한 정보를 볼 수 있습니다. 또한 CLI를 사용하여 수동으로 압축을 수행하거나, 압축을 예약하거나, 예약된 압축을 취소할 수도 있습니다. 자세한 내용은 Apache Hudi 설명서에서 [Interacting via CLI](https://hudi.apache.org/docs/cli/)를 참조하세요.

**Hudi CLI를 시작하고 데이터 세트에 연결하는 방법**

1. SSH를 사용하여 마스터 노드에 연결합니다. 자세한 내용은 *Amazon EMR 관리 안내서*에서 [SSH를 사용하여 프라이머리 노드에 연결](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)을 참조하세요.

1. 명령줄에 `/usr/lib/hudi/cli/bin/hudi-cli.sh`를 입력합니다.

   명령 프롬프트가 `hudi->`로 바뀝니다.

1. 다음 명령을 사용하여 데이터세트에 연결합니다. *s3://amzn-s3-demo-bucket/myhudidataset*를 작업하려는 데이터세트의 경로로 바꿉니다. 여기서 사용하는 값은 이전 예에서 설정한 값과 동일합니다.

   ```
   connect --path s3://amzn-s3-demo-bucket/myhudidataset
   ```

   다음 예와 같이 연결한 데이터 세트를 포함하도록 명령 프롬프트가 변경됩니다.

   ```
   hudi:myhudidataset->
   ```

기본적으로 Amazon EMR 릴리스 7.3.0\$17.8.0의 `hudi-cli.sh` 스크립트는 `hudi-cli-bundle.jar`을 사용합니다. 문제가 발생하면 다음 명령을 사용하여 클래식 Hudi CLI로 다시 전환할 수 있습니다.

```
/usr/lib/hudi/cli/bin/hudi-cli.sh --cliBundle false
```

이 명령은 `hudi-cli.sh` 스크립트를 실행하고, `--cliBundle` 플래그를 설정하며, 번들에 포함된 JAR 대신 개별 JAR 파일을 사용하도록 CLI에 지시합니다. 기본적으로 `--cliBundle`은 true로 설정되어 있습니다. 즉, CLI는 대신 번들에 포함된 JAR을 사용합니다.

## Amazon EMR 릴리스 7.9.0 이상에는 Tez가 포함되어 있습니다.
<a name="emr-hudi-cli-start"></a>

**참고**  
 EMR 릴리스 7.9.0 이상에서는 **hudi-cli.sh** 스크립트가 더 이상 사용되지 않습니다. Amazon EMR 릴리스 7.9.0 이상에서는 **hudi-cli-bundle.jar**을 사용합니다.

**Hudi CLI를 시작하고 데이터세트에 연결하는 방법:**

1. SSH를 사용하여 마스터 노드에 연결합니다. 자세한 내용은 *Amazon EMR 관리 안내서*에서 [SSH를 사용하여 프라이머리 노드에 연결](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html)을 참조하세요.

1. 명령줄에서 **/usr/lib/hudi/cli-bundle/bin/hudi-cli-with-bundle.sh**를 입력하거나 **hudi-cli-with-bundle** 또는 **>hudi-cli**를 입력합니다.

   명령 프롬프트가 **hudi- >**로 바뀝니다.

1. 다음 명령을 사용하여 데이터세트에 연결합니다. **s3://amzn-s3-demo-bucket/myhudidataset**를 작업하려는 데이터세트의 경로로 바꿉니다. 여기서 사용하는 값은 이전 예에서 설정한 값과 동일합니다.

   ```
   connect --path s3://amzn-s3-demo-bucket/myhudidataset
   ```

1. 다음 예와 같이 연결한 데이터 세트를 포함하도록 명령 프롬프트가 변경됩니다.

   ```
   hudi:myhudidataset->
   ```

# Hudi 릴리스 기록
<a name="Hudi-release-history"></a>

다음 테이블에는 애플리케이션과 함께 설치된 구성 요소 외에도 Amazon EMR의 최신 릴리스에 포함된 Hudi의 버전이 나열되어 있습니다. 각 릴리스의 구성 요소 버전은 [Amazon EMR 7.x 릴리스 버전](emr-release-7x.md), [Amazon EMR 6.x 릴리스 버전](emr-release-6x.md) 또는 [Amazon EMR 5.x 릴리스 버전](emr-release-5x.md)의 릴리스의 구성 요소 버전 섹션을 참조하세요.


**Hudi 버전 정보**  

| Amazon EMR 릴리스 레이블 | Hudi 버전 | Hudi와 함께 설치된 구성 요소 | 
| --- | --- | --- | 
| emr-7.12.0 | 1.0.2-amzn-1 | Not available. | 
| emr-7.11.0 | 1.0.2-amzn-0 | Not available. | 
| emr-7.10.0 | 0.15.0-amzn-7 | Not available. | 
| emr-7.9.0 | 0.15.0-amzn-6 | Not available. | 
| emr-7.8.0 | 0.15.0-amzn-5 | Not available. | 
| emr-7.7.0 | 0.15.0-amzn-4 | Not available. | 
| emr-7.6.0 | 0.15.0-amzn-3 | Not available. | 
| emr-7.5.0 | 0.15.0-amzn-2 | Not available. | 
| emr-7.4.0 | 0.15.0-amzn-1 | Not available. | 
| emr-7.3.0 | 0.15.0-amzn-0 | Not available. | 
| emr-7.2.0 | 0.14.1-amzn-1 | Not available. | 
| emr-5.36.2 | 0.10.1-amzn-1 | Not available. | 
| emr-7.1.0 | 0.14.1-amzn-0 | Not available. | 
| emr-7.0.0 | 0.14.0-amzn-1 | Not available. | 
| emr-6.15.0 | 0.14.0-amzn-0 | Not available. | 
| emr-6.14.0 | 0.13.1-amzn-2 | Not available. | 
| emr-6.13.0 | 0.13.1-amzn-1 | Not available. | 
| emr-6.12.0 | 0.13.1-amzn-0 | Not available. | 
| emr-6.11.1 | 0.13.0-amzn-0 | Not available. | 
| emr-6.11.0 | 0.13.0-amzn-0 | Not available. | 
| emr-6.10.1 | 0.12.2-amzn-0 | Not available. | 
| emr-6.10.0 | 0.12.2-amzn-0 | Not available. | 
| emr-6.9.1 | 0.12.1-amzn-0 | Not available. | 
| emr-6.9.0 | 0.12.1-amzn-0 | Not available. | 
| emr-6.8.1 | 0.11.1-amzn-0 | Not available. | 
| emr-6.8.0 | 0.11.1-amzn-0 | Not available. | 
| emr-6.7.0 | 0.11.0-amzn-0 | Not available. | 
| emr-5.36.1 | 0.10.1-amzn-1 | Not available. | 
| emr-5.36.0 | 0.10.1-amzn-1 | Not available. | 
| emr-6.6.0 | 0.10.1-amzn-0 | Not available. | 
| emr-5.35.0 | 0.9.0-amzn-2 | Not available. | 
| emr-6.5.0 | 0.9.0-amzn-1 | Not available. | 
| emr-6.4.0 | 0.8.0-amzn-0 | Not available. | 
| emr-6.3.1 | 0.7.0-amzn-0 | Not available. | 
| emr-6.3.0 | 0.7.0-amzn-0 | Not available. | 
| emr-6.2.1 | 0.6.0-amzn-1 | Not available. | 
| emr-6.2.0 | 0.6.0-amzn-1 | Not available. | 
| emr-6.1.1 | 0.5.2-incubating-amzn-2 | Not available. | 
| emr-6.1.0 | 0.5.2-incubating-amzn-2 | Not available. | 
| emr-6.0.1 | 0.5.0-incubating-amzn-1 | Not available. | 
| emr-6.0.0 | 0.5.0-incubating-amzn-1 | Not available. | 
| emr-5.34.0 | 0.9.0-amzn-0 | Not available. | 
| emr-5.33.1 | 0.7.0-amzn-1 | Not available. | 
| emr-5.33.0 | 0.7.0-amzn-1 | Not available. | 
| emr-5.32.1 | 0.6.0-amzn-0 | Not available. | 
| emr-5.32.0 | 0.6.0-amzn-0 | Not available. | 
| emr-5.31.1 | 0.6.0-amzn-0 | Not available. | 
| emr-5.31.0 | 0.6.0-amzn-0 | Not available. | 
| emr-5.30.2 | 0.5.2-incubating | Not available. | 
| emr-5.30.1 | 0.5.2-incubating | Not available. | 
| emr-5.30.0 | 0.5.2-incubating | Not available. | 
| emr-5.29.0 | 0.5.0-incubating | Not available. | 
| emr-5.28.1 | 0.5.0-incubating | Not available. | 
| emr-5.28.0 | 0.5.0-incubating | Not available. | 