

# 사용자 정의 함수를 사용한 쿼리
<a name="querying-udf"></a>

Amazon Athena의 사용자 정의 함수(UDF)를 사용하면 사용자 지정 함수를 만들어 레코드 또는 레코드 그룹을 처리할 수 있습니다. UDF는 파라미터를 수락하고 작업을 수행한 다음 결과를 반환합니다.

Athena에서 UDF를 사용하려면 SQL 쿼리의 `SELECT` 문 앞에 `USING EXTERNAL FUNCTION` 절을 작성합니다. `SELECT` 문은 UDF를 참조하고 쿼리가 실행될 때 UDF에 전달되는 변수를 정의합니다. SQL 쿼리는 UDF를 호출할 때 Java 런타임을 사용하여 Lambda 함수를 호출합니다. UDF는 Lambda 함수 내에 Java 배포 패키지의 메서드로 정의됩니다. Lambda 함수에 대해 동일한 Java 배포 패키지에 여러 UDF를 정의할 수 있습니다. 또한 `USING EXTERNAL FUNCTION` 절에 Lambda 함수의 이름을 지정합니다.

Athena UDF에 대한 Lambda 함수를 배포하는 데는 두 가지 옵션이 있습니다. Lambda를 사용하여 함수를 직접 배포하거나 AWS Serverless Application Repository을 사용할 수 있습니다. UDF에 대한 기존 Lambda 함수를 찾으려면 퍼블릭 AWS Serverless Application Repository 또는 프라이빗 리포지토리를 검색한 다음 Lambda에 배포하면 됩니다. 또한 Java 소스 코드를 생성 또는 수정하거나, JAR 파일로 패키지하거나, Lambda 또는 AWS Serverless Application Repository을 사용하여 배포할 수 있습니다. 시작하기 위한 Java 소스 코드 및 패키지 예제는 [Lambda를 사용하여 UDF 생성 및 배포](udf-creating-and-deploying.md) 단원을 참조하세요. Lambda에 대한 자세한 내용은 [AWS Lambda 개발자 안내서](https://docs.aws.amazon.com/lambda/latest/dg/)를 참조하세요. AWS Serverless Application Repository에 대한 자세한 내용은 [AWS Serverless Application Repository개발자 안내서](https://docs.aws.amazon.com/serverlessrepo/latest/devguide/) 단원을 참조하세요.

Athena에서 UDF를 사용하여 텍스트를 번역하고 분석하는 예제는 AWS 기계 학습 블로그 항목 [Translate and analyze text using SQL functions with Amazon Athena, Amazon Translate, and Amazon Comprehend](https://aws.amazon.com/blogs/machine-learning/translate-and-analyze-text-using-sql-functions-with-amazon-athena-amazon-translate-and-amazon-comprehend/)를 참조하거나 [video](udf-videos.md#udf-videos-xlate)를 시청하세요.

Amazon Athena에서 UDF를 사용하여 지리 공간 쿼리를 확장하는 예제는 *AWS 빅 데이터 블로그*의 [Extend geospatial queries in Amazon Athena with UDFs and AWS Lambda](https://aws.amazon.com/blogs/big-data/extend-geospatial-queries-in-amazon-athena-with-udfs-and-aws-lambda/)를 참조하세요.

**Topics**
+ [Athena의 UDF에 관한 동영상](udf-videos.md)
+ [고려 사항 및 제한 사항](udf-considerations-limitations.md)
+ [UDF 쿼리 구문을 사용한 쿼리](udf-query-syntax.md)
+ [Lambda를 사용하여 UDF 생성 및 배포](udf-creating-and-deploying.md)

# Athena의 UDF에 관한 동영상
<a name="udf-videos"></a>

Athena에서 UDF 사용하기에 대해 자세히 알아보려면 다음 동영상을 시청하세요.

**동영상: Amazon Athena의 사용자 정의 함수(UDF) 소개**  
다음 동영상은 Amazon Athena에서 UDF를 사용하여 민감한 정보를 수정하는 방법을 보여줍니다.

**참고**  
이 동영상의 구문은 사전 시연용이지만 개념은 동일합니다. `AmazonAthenaPreviewFunctionality` 작업 그룹 없이 Athena를 사용합니다.

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


**동영상: Amazon Athena에서 SQL 쿼리를 사용하여 텍스트 필드 번역, 분석 및 수정**  
다음 동영상은 다른 AWS 서비스와 함께 Amazon Athena의 UDF를 사용하여 텍스트를 번역하고 분석할 수 있는 방법을 보여줍니다.

**참고**  
이 동영상의 구문은 사전 시연용이지만 개념은 동일합니다. 정확한 구문은 *AWS 기계 학습 블로그*에서 관련 블로그 게시물 [Translate, redact, and analyze text using SQL functions with Amazon Athena, Amazon Translate, and Amazon Comprehend](https://aws.amazon.com/blogs/machine-learning/translate-and-analyze-text-using-sql-functions-with-amazon-athena-amazon-translate-and-amazon-comprehend/)를 참조하세요.

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


# 고려 사항 및 제한 사항
<a name="udf-considerations-limitations"></a>

Athena에서 사용자 정의 함수(UDF)를 사용할 때는 다음 사항을 고려하세요.
+ **기본 제공 Athena 함수** - Athena의 기본 제공 함수는 고성능으로 설계되었습니다. 가능한 경우 UDF를 통해 기본 제공 함수를 사용하는 것이 좋습니다. 기본 제공 함수에 대한 자세한 내용은 [Amazon Athena의 함수](functions.md) 단원을 참조하세요.
+ **스칼라 UDF만 지원** - Athena는 한 번에 한 행을 처리하여 하나의 열 값을 반환하는 스칼라 UDF만 지원합니다. Athena는 Lambda를 호출할 때마다 UDF에 행 배치를 전달합니다(병렬로 전달 가능). UDF와 쿼리를 설계할 때는 이 처리의 네트워크 트래픽에 미칠 수 있는 영향을 염두에 두어야 합니다.
+ **UDF 핸들러 함수는 축약 형식을 사용합니다.**— UDF 함수에 대해 축약 형식(전체 형식이 아님)을 사용합니다(예: `package.Class::method` 대신 `package.Class`).
+ **UDF 메서드는 소문자여야 합니다.**— UDF 메서드는 소문자여야 합니다. 낙타 대문자는 허용되지 않습니다.
+ **UDF 메서드에 파라미터가 필요합니다.** - UDF 메서드에 하나 이상의 파라미터가 있어야 합니다. 입력 파라미터 없이 정의된 UDF를 간접적으로 호출하려고 하면 런타임 예외가 발생합니다. UDF는 데이터 레코드에서 함수를 수행하도록 고안되었지만 인수가 없는 UDF는 데이터를 받아들이지 않으므로 예외가 발생합니다.
+ **Java 런타임 지원** - 현재 Athena UDF는 Lambda용 Java 8, Java 11 및 Java 17 런타임을 지원합니다. 자세한 내용은 *AWS Lambda 개발자 안내서*의 [Java로 Lambda 함수 구축](https://docs.aws.amazon.com/lambda/latest/dg/lambda-java.html)을 참조하세요.
**참고**  
 Java 17의 경우 `JAVA_TOOL_OPTIONS` 환경 변수의 값을 Lambda에서 `--add-opens=java.base/java.nio=ALL-UNNAMED`로 설정해야 합니다.
+ **IAM 권한** – Athena에서 UDF 쿼리 문을 실행하고 생성하려면 쿼리를 실행하는 IAM 보안 주체가 Athena 함수 외의 작업을 수행할 수 있어야 합니다. 자세한 내용은 [Athena UDF에 대한 액세스 허용: 정책 예제](udf-iam-access.md) 단원을 참조하세요.
+ **Lambda 할당량** - Lambda 할당량이 UDF에 적용됩니다. 자세한 내용은 *AWS Lambda 개발자 안내서*에서 [Lambda 할당량](https://docs.aws.amazon.com/lambda/latest/dg/limits.html)을 참조하세요.
+ **행 수준 필터링** - UDF에서 Lake Formation 행 수준 필터링은 지원되지 않습니다.
+ **뷰** – UDF에는 뷰를 사용할 수 없습니다.
+ **알려진 문제** - 알려진 문제의 최신 목록은 GitHub의 awslabs/aws-athena-query-federation 섹션에서 [제한 사항 및 문제](https://github.com/awslabs/aws-athena-query-federation/wiki/Limitations_And_Issues)를 참조하세요.

# UDF 쿼리 구문을 사용한 쿼리
<a name="udf-query-syntax"></a>

`USING EXTERNAL FUNCTION` 절은 쿼리의 후속 `SELECT` 문에서 참조할 수 있는 단일 UDF 또는 여러 UDF를 지정합니다. UDF의 메서드 이름과 UDF를 호스팅하는 Lambda 함수의 이름이 필요합니다. Lambda 함수 이름 대신 Lambda ARN을 사용할 수 있습니다. 크로스 계정 시나리오에서는 Lambda ARN이 필요합니다.

## 시놉시스
<a name="udf-synopsis"></a>

```
USING EXTERNAL FUNCTION UDF_name(variable1 data_type[, variable2 data_type][,...])
RETURNS data_type
LAMBDA 'lambda_function_name_or_ARN'
[, EXTERNAL FUNCTION UDF_name2(variable1 data_type[, variable2 data_type][,...]) 
RETURNS data_type 
LAMBDA 'lambda_function_name_or_ARN'[,...]]
SELECT  [...] UDF_name(expression) [, UDF_name2(expression)] [...]
```

## 파라미터
<a name="udf-parameters"></a>

**USING EXTERNAL FUNCTION *UDF\$1name*(*variable1* *data\$1type*[, *variable2* *data\$1type*][,...])**  
*UDF\$1name*은 참조된 Lambda 함수 내에서 Java 메서드에 해당하는 UDF의 이름을 지정합니다. 각 *variable data\$1type*은 UDF가 입력으로 수락하는 명명된 변수와 해당 데이터 형식을 지정합니다. *data\$1type*은 다음 표에 나열된 지원되는 Athena 데이터 형식 중 하나여야 하며 해당 Java 데이터 형식에 매핑되어야 합니다.      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/athena/latest/ug/udf-query-syntax.html)

**RETURNS *data\$1type***  
`data_type`은 UDF가 출력으로 반환하는 SQL 데이터 형식을 지정합니다. 위의 표에 나열된 Athena 데이터 형식이 지원됩니다. `DECIMAL` 데이터 형식의 경우 *precision*과 *scale*이 정수인 `RETURNS DECIMAL(precision, scale)` 구문을 사용합니다.

**LAMBDA '*lambda\$1function*'**  
*lambda\$1function*은 UDF를 실행할 때 호출되는 Lambda 함수의 이름을 지정합니다.

**SELECT [...] *UDF\$1name*(*expression*) [...]**  
UDF에 값을 전달하고 결과를 반환하는 `SELECT` 쿼리입니다. *UDF\$1name*은 사용할 UDF를 지정하며, 값을 전달하기 위해 평가되는 *expression*이 뒤에 옵니다. 전달되고 반환되는 값은 `USING EXTERNAL FUNCTION` 절의 UDF에 대해 지정된 해당 데이터 유형과 일치해야 합니다.

### 예제
<a name="udf-examples"></a>

GitHub의 [AthenaUDFHandler.java](https://github.com/awslabs/aws-athena-query-federation/blob/master/athena-udfs/src/main/java/com/amazonaws/athena/connectors/udfs/AthenaUDFHandler.java) 코드에 기반한 쿼리 예제는 GitHub [Amazon Athena UDF 커넥터](https://github.com/awslabs/aws-athena-query-federation/tree/master/athena-udfs)페이지를 참조하세요.

# Lambda를 사용하여 UDF 생성 및 배포
<a name="udf-creating-and-deploying"></a>

사용자 지정 UDF를 생성하려면 `UserDefinedFunctionHandler` 클래스를 확장하여 새 Java 클래스를 생성합니다. SDK의 [UserDefinedFunctionHandler.java](https://github.com/awslabs/aws-athena-query-federation/blob/master/athena-federation-sdk/src/main/java/com/amazonaws/athena/connector/lambda/handlers/UserDefinedFunctionHandler.java)용 소스 코드는 GitHub의 awslabs/aws-athena-query-federation/athena-federation-sdk [리포지토리](https://github.com/awslabs/aws-athena-query-federation/tree/master/athena-federation-sdk)에서 이용할 수 있습니다. 이와 함께 사용자 지정 UDF를 생성하기 위해 검토하고 수정할 수 있는 [UDF 구현 예제](https://github.com/awslabs/aws-athena-query-federation/tree/master/athena-udfs)도 제공합니다.

이 섹션의 단계에서는 명령줄과 배포에서 [Apache Maven](https://maven.apache.org/index.html)을 사용하여 사용자 지정 UDF Jar 파일을 작성하고 구축하는 방법을 보여줍니다.

Maven을 사용하여 Athena용 사용자 지정 UDF를 생성하려면 다음 단계를 수행합니다.

1. [SDK 복제 및 개발 환경 준비](#udf-create-install-sdk-prep-environment)

1. [Maven 프로젝트 만들기](#create-maven-project)

1. [Maven 프로젝트에 종속성 및 플러그인 추가](#udf-add-maven-dependencies)

1. [UDF에 대한 Java 코드 작성](#udf-write-java)

1. [JAR 파일 구축](#udf-create-package-jar)

1. [AWS Lambda에 JAR 배포](#udf-create-deploy)

## SDK 복제 및 개발 환경 준비
<a name="udf-create-install-sdk-prep-environment"></a>

시작하기 전에 git가 `sudo yum install git -y`를 사용하여 시스템에 설치되어 있는지 확인하세요.

**AWS query federation SDK를 설치하려면**
+ 명령줄에 다음을 입력하여 SDK 리포지토리를 복제합니다. 이 리포지토리에는 SDK, 예제 및 데이터 소스 커넥터 제품군이 포함되어 있습니다. 데이터 소스 커넥터에 대한 자세한 내용은 [Amazon Athena 페더레이션 쿼리 사용](federated-queries.md) 단원을 참고하세요.

  ```
  git clone https://github.com/awslabs/aws-athena-query-federation.git
  ```

**이 절차의 사전 조건을 설치하려면**

이미 Apache Maven, AWS CLI 및AWS Serverless Application Model 빌드 도구가 설치된 개발 머신에서 작업하는 경우 이 단계를 건너뛸 수 있습니다.

1. 복제할 때 생성한 `aws-athena-query-federation` 디렉터리의 루트에서 개발 환경을 준비하는 [prepare\$1dev\$1env.sh](https://github.com/awslabs/aws-athena-query-federation/blob/master/tools/prepare_dev_env.sh) 스크립트를 실행합니다.

1. 을 업데이트하여 설치 프로세스에서 생성된 새 변수를 소싱하거나 터미널 세션을 다시 시작합니다.

   ```
   source ~/.profile
   ```
**중요**  
이 단계를 건너뛰면 나중에 Lambda 함수를 게시할 수 없는 AWS CLI 또는 AWS SAM 빌드 도구에 대한 오류가 발생합니다.

## Maven 프로젝트 만들기
<a name="create-maven-project"></a>

다음 명령을 실행하여 Maven 프로젝트를 만듭니다. *groupId*를 고유한 조직 ID로 바꾸고 *my-athena-udf*를 애플리케이션 이름으로 바꿉니다. 자세한 내용은 Apache Maven 문서에서 [첫 번째 Maven 프로젝트를 만들려면 어떻게 해야 합니까?](https://maven.apache.org/guides/getting-started/index.html#How_do_I_make_my_first_Maven_project)를 참조하세요.

```
mvn -B archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DgroupId=groupId \
-DartifactId=my-athena-udfs
```

## Maven 프로젝트에 종속성 및 플러그인 추가
<a name="udf-add-maven-dependencies"></a>

Maven 프로젝트 `pom.xml` 파일에 다음 구성을 추가합니다. 예를 들어 GitHub의 [pom.xml](https://github.com/awslabs/aws-athena-query-federation/blob/master/athena-udfs/pom.xml) 파일을 참조하세요.

```
<properties>
    <aws-athena-federation-sdk.version>2022.47.1</aws-athena-federation-sdk.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-athena-federation-sdk</artifactId>
        <version>${aws-athena-federation-sdk.version}</version>
    </dependency>
</dependencies>
    
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.1</version>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
                <filters>
                    <filter>
                        <artifact>*:*</artifact>
                        <excludes>
                            <exclude>META-INF/*.SF</exclude>
                            <exclude>META-INF/*.DSA</exclude>
                            <exclude>META-INF/*.RSA</exclude>
                        </excludes>
                    </filter>
                </filters>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
```

## UDF에 대한 Java 코드 작성
<a name="udf-write-java"></a>

[UserDefinedFunctionHandler.java](https://github.com/awslabs/aws-athena-query-federation/blob/master/athena-federation-sdk/src/main/java/com/amazonaws/athena/connector/lambda/handlers/UserDefinedFunctionHandler.java)를 확장하여 새 클래스를 만듭니다. 클래스 내부에 UDF를 작성합니다.

다음 예제에서는 UDF에 대한 두 개의 Java 메서드인 `compress()` 및 `decompress()`가 클래스 `MyUserDefinedFunctions` 내에 만들어집니다.

```
*package *com.mycompany.athena.udfs;

public class MyUserDefinedFunctions
        extends UserDefinedFunctionHandler
{
    private static final String SOURCE_TYPE = "MyCompany";

    public MyUserDefinedFunctions()
    {
        super(SOURCE_TYPE);
    }

    /**
     * Compresses a valid UTF-8 String using the zlib compression library.
     * Encodes bytes with Base64 encoding scheme.
     *
     * @param input the String to be compressed
     * @return the compressed String
     */
    public String compress(String input)
    {
        byte[] inputBytes = input.getBytes(StandardCharsets.UTF_8);

        // create compressor
        Deflater compressor = new Deflater();
        compressor.setInput(inputBytes);
        compressor.finish();

        // compress bytes to output stream
        byte[] buffer = new byte[4096];
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(inputBytes.length);
        while (!compressor.finished()) {
            int bytes = compressor.deflate(buffer);
            byteArrayOutputStream.write(buffer, 0, bytes);
        }

        try {
            byteArrayOutputStream.close();
        }
        catch (IOException e) {
            throw new RuntimeException("Failed to close ByteArrayOutputStream", e);
        }

        // return encoded string
        byte[] compressedBytes = byteArrayOutputStream.toByteArray();
        return Base64.getEncoder().encodeToString(compressedBytes);
    }

    /**
     * Decompresses a valid String that has been compressed using the zlib compression library.
     * Decodes bytes with Base64 decoding scheme.
     *
     * @param input the String to be decompressed
     * @return the decompressed String
     */
    public String decompress(String input)
    {
        byte[] inputBytes = Base64.getDecoder().decode((input));

        // create decompressor
        Inflater decompressor = new Inflater();
        decompressor.setInput(inputBytes, 0, inputBytes.length);

        // decompress bytes to output stream
        byte[] buffer = new byte[4096];
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(inputBytes.length);
        try {
            while (!decompressor.finished()) {
                int bytes = decompressor.inflate(buffer);
                if (bytes == 0 && decompressor.needsInput()) {
                    throw new DataFormatException("Input is truncated");
                }
                byteArrayOutputStream.write(buffer, 0, bytes);
            }
        }
        catch (DataFormatException e) {
            throw new RuntimeException("Failed to decompress string", e);
        }

        try {
            byteArrayOutputStream.close();
        }
        catch (IOException e) {
            throw new RuntimeException("Failed to close ByteArrayOutputStream", e);
        }

        // return decoded string
        byte[] decompressedBytes = byteArrayOutputStream.toByteArray();
        return new String(decompressedBytes, StandardCharsets.UTF_8);
    }
}
```

## JAR 파일 구축
<a name="udf-create-package-jar"></a>

`mvn clean install`을 실행하여 프로젝트를 빌드합니다. 성공적으로 빌드되면 JAR 파일이 `artifactId-version.jar`이라는 프로젝트의 `target` 폴더에 생성됩니다. 여기서 *artifactId*는 Maven 프로젝트에서 제공한 이름입니다(예: `my-athena-udfs`).

## AWS Lambda에 JAR 배포
<a name="udf-create-deploy"></a>

Lambda에 코드를 배포하는 두 가지 옵션이 있습니다.
+ AWS Serverless Application Repository을 사용하여 배포(권장)
+ JAR 파일에서 Lambda 함수 만들기

### 옵션 1: AWS Serverless Application Repository에 배포
<a name="udf-create-deploy-sar"></a>

AWS Serverless Application Repository에 JAR 파일을 배포할 때 애플리케이션의 아키텍처를 나타내는 AWS SAM 템플릿 YAML 파일을 만듭니다. 그런 다음 이 YAML 파일과, 애플리케이션의 아티팩트를 업로드하여 AWS Serverless Application Repository에 공개하는 Amazon S3 버킷을 지정합니다. 아래 절차에서는 앞서 복제했던 Athena Query Federation SDK의 `athena-query-federation/tools` 디렉터리에 위치한 [publish.sh](https://github.com/awslabs/aws-athena-query-federation/blob/master/tools/publish.sh) 스크립트를 사용합니다.

자세한 내용과 요구 사항은 *AWS Serverless Application Repository 개발자 안내서*의 [애플리케이션 게시](https://docs.aws.amazon.com/serverlessrepo/latest/devguide/serverlessrepo-publishing-applications.html), *AWS Serverless Application Model 개발자 안내서*의 [AWS SAM 템플릿 개념](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-template-basics.html) 및 [AWS SAM CLI를 사용하여 서버리스 애플리케이션 게시](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-template-publishing-applications.html)를 참조하세요.

다음 예제에서는 YAML 파일의 파라미터를 보여줍니다. YAML 파일에 유사한 파라미터를 추가하고 프로젝트 디렉터리에 저장합니다. 전체 예제는 GitHub에서 [athena-udf.yaml](https://github.com/awslabs/aws-athena-query-federation/blob/master/athena-udfs/athena-udfs.yaml)을 참조하세요.

```
Transform: 'AWS::Serverless-2016-10-31'
Metadata:
  'AWS::ServerlessRepo::Application':
    Name: MyApplicationName
    Description: 'The description I write for my application'
    Author: 'Author Name'
    Labels:
      - athena-federation
    SemanticVersion: 1.0.0
Parameters:
  LambdaFunctionName:
    Description: 'The name of the Lambda function that will contain your UDFs.'
    Type: String
  LambdaTimeout:
    Description: 'Maximum Lambda invocation runtime in seconds. (min 1 - 900 max)'
    Default: 900
    Type: Number
  LambdaMemory:
    Description: 'Lambda memory in MB (min 128 - 3008 max).'
    Default: 3008
    Type: Number
Resources:
  ConnectorConfig:
    Type: 'AWS::Serverless::Function'
    Properties:
      FunctionName: !Ref LambdaFunctionName
      Handler: "full.path.to.your.handler. For example, com.amazonaws.athena.connectors.udfs.MyUDFHandler"
      CodeUri: "Relative path to your JAR file. For example, ./target/athena-udfs-1.0.jar"
      Description: "My description of the UDFs that this Lambda function enables."
      Runtime: java8
      Timeout: !Ref LambdaTimeout
      MemorySize: !Ref LambdaMemory
```

YAML 파일을 저장한 프로젝트 디렉터리에 `publish.sh` 스크립트를 복사하고 다음 명령을 실행합니다.

```
./publish.sh MyS3Location MyYamlFile
```

예를 들어 버킷 위치가 `s3://amzn-s3-demo-bucket/mysarapps/athenaudf`이고 YAML 파일이 `my-athena-udfs.yaml`로 저장된 경우:

```
./publish.sh amzn-s3-demo-bucket/mysarapps/athenaudf my-athena-udfs
```

**Lambda 함수 생성**

1. [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)에서 Lambda 콘솔을 열고 **함수 생성**을 선택한 다음 **서버리스 앱 리포지토리 찾아보기**를 선택합니다.

1. **프라이빗 애플리케이션**을 선택하거나 목록에서 애플리케이션을 찾거나 키워드를 사용하여 애플리케이션을 검색한 다음 선택합니다.

1. 애플리케이션 세부 정보를 검토하고 제공한 다음 **배포**를 선택합니다.

   이제 Lambda 함수 JAR 파일에 정의된 메서드 이름을 Athena의 UDF로 사용할 수 있습니다.

### 옵션 2: 직접 Lambda 함수 생성
<a name="udf-create-deploy-lambda"></a>

콘솔 또는 AWS CLI를 사용하여 직접 Lambda 함수를 만들 수도 있습니다. 다음은 Lambda `create-function` CLI 명령을 사용하는 예제입니다.

```
aws lambda create-function \
 --function-name MyLambdaFunctionName \
 --runtime java8 \
 --role arn:aws:iam::1234567890123:role/my_lambda_role \
 --handler com.mycompany.athena.udfs.MyUserDefinedFunctions \
 --timeout 900 \
 --zip-file fileb://./target/my-athena-udfs-1.0-SNAPSHOT.jar
```