원격 서비스에 대한 데이터와 함께 요청 및 응답 변환기 사용하기

요청 및 응답 변환기를 사용하면 외부 함수가 사용하는 원격 서비스로 보내고 받는 데이터 형식을 변경할 수 있습니다.

이 항목의 내용:

목적

Snowflake가 데이터를 원격 서비스로 보낼 때 Snowflake는 이러한 규칙 에 따라 데이터 형식을 지정합니다. 마찬가지로 Snowflake는 원격 서비스에서 데이터를 수신할 때 동일 규칙에 따라 데이터 형식이 지정될 것으로 예상합니다.

많은 원격 서비스는 다른 형식으로 데이터를 처리할 것으로 예상합니다. 요청 및 응답 변환기를 사용하면 다음을 편리하게 수행할 수 있습니다.

  • Snowflake의 형식에서 원격 서비스의 기본 입력 형식(요청 변환기)으로 데이터를 변환합니다.

  • 원격 서비스의 기본 출력 형식에서 Snowflake 형식(응답 변환기)으로 데이터를 변환합니다.

SQL 구현

Snowflake의 형식과 원격 서비스의 기본 입력 형식 간에 데이터를 변환하려면 JavaScript UDFs (사용자 정의 함수)를 사용합니다. 거의 항상 한 쌍의 UDF를 작성하는데, 하나는 요청을 변환하고 다른 하나는 응답을 변환합니다.

Snowflake는 이러한 함수를 각 외부 함수 호출의 일부로 호출합니다. 예를 들어, 원격 서비스에 대한 요청의 경우 Snowflake는 요청 변환기 함수를 호출하고 Snowflake 형식의 데이터를 전달한 후 반환되는 데이터를 가져와 원격 서비스로 보냅니다. 원격 서비스가 데이터를 반환하면 Snowflake는 응답 변환기 함수를 호출하여 Snowflake가 이해할 수 있는 형식으로 데이터를 다시 변환합니다.

사용자의 관점에서는 변환기가 변환 중일 때 외부 함수를 호출하는 것은 변환기 없이 외부 함수를 호출하는 것과 같습니다. CREATE EXTERNAL FUNCTION 문의 일부로 변환기를 지정한 이후에는 자동으로 호출됩니다.

외부 함수에는 한 번에 최대 1개의 요청 변환기와 1개의 응답 변환기가 있을 수 있습니다.

요청 및 응답 변환기 UDFs는 보안 UDFs 수 있습니다.

변환기 함수를 외부 함수에 지정

변환기로 사용할 사용자 정의 함수를 지정하려면 CREATE EXTERNAL FUNCTION 문에 REQUEST_TRANSLATORRESPONSE_TRANSLATOR 절을 포함합니다. 각각은 변환기 함수의 이름을 런타임 시에 사용합니다.

예:

CREATE EXTERNAL FUNCTION f(...)
    RETURNS OBJECT
    ...
    REQUEST_TRANSLATOR = my_request_translator_udf
    RESPONSE_TRANSLATOR = my_response_translator_udf
    ...
    AS <url_of_proxy_and_resource>;
Copy

CREATE EXTERNAL FUNCTION 문의 일부로 변환기를 지정하는 구문은 다음과 같습니다.

CREATE EXTERNAL FUNCTION f(...)
    RETURNS OBJECT
    ...
    [ REQUEST_TRANSLATOR = <request_translator_udf_name> ]
    [ RESPONSE_TRANSLATOR = <response_translator_udf_name> ]
    ...
Copy

여기서,

request_translator_udf_name

요청 변환기 함수의 이름입니다.

response_translator_udf_name

응답 변환기 함수의 이름입니다.

REQUEST_TRANSLATORRESPONSE_TRANSLATOR 매개 변수는 각각 OBJECT 타입의 매개 변수 1개를 갖습니다.

ALTER FUNCTION 명령에 요청 또는 응답 변환기를 지정할 수도 있습니다. 다음을 할 수 있습니다.

  • 외부 함수에 아직 변환기가 없으면 번역기를 추가합니다.

  • 기존 변환기를 교체합니다.

  • 변환기를 제거합니다.

SET 키워드를 사용하여 새 변환기를 추가하거나 기존 변환기를 교체합니다.

변환기를 추가 또는 교체하려면:

ALTER FUNCTION ...
    SET [REQUEST_TRANSLATOR | RESPONSE_TRANSLATOR] = <udf_name>;
Copy

여기서

udf_name

이전에 만든 JavaScript UDF의 이름입니다.

변환기를 제거하려면:

ALTER FUNCTION ...
    UNSET [REQUEST_TRANSLATOR | RESPONSE_TRANSLATOR];
Copy

SQL 요구 사항

  • CREATE EXTERNAL FUNCTION 또는 ALTER FUNCTION 문에서 변환기 함수의 이름은 다음 중 하나여야 합니다.

    • 정규화된 이름(예: MyDatabase.MySchema.MyJavaScriptUDF).

    • 이를 사용하는 외부 함수와 동일한 데이터베이스 및 스키마에 정의됩니다.

  • CREATE EXTERNAL FUNCTION 또는 ALTER FUNCTION 문에 변환기를 지정하는 경우에는 UDF 변환기가 이미 있어야 합니다. 이름을 먼저 지정하고 나중에 UDF를 생성할 수는 없습니다. UDF를 생성하기 전에 외부 함수를 호출하지 않더라도 마찬가지입니다.

  • 변환기로 사용되는 UDF는 이를 사용하는 모든 외부 함수에서 먼저 제거하지 않고 삭제해서는 안 됩니다. (외부 함수 호출 시 변환기가 없으면 Snowflake가 오류와 함께 실패합니다.)

  • 변환기 UDF가 (ALTER FUNCTION 을 통해) 수정되면 동일한 인터페이스 요구 사항을 유지해야 합니다. 인터페이스 요구 사항을 유지하지 않으면 외부 함수를 실행하기 전에 예외가 발생합니다.

JavaScript 구현

런타임에 SQL은 OBJECT 를 변환기 UDF에 전달합니다. JavaScript 코드는 이것을 JavaScript 오브젝트로 받습니다.

요청 변환기 구현하기

요청 변환기 입력 속성

변환기 UDF가 이름이 event 인 JavaScript 오브젝트를 수신합니다. 이 오브젝트에 포함된 속성은 다음과 같습니다.

  • body: data 필드의 형식은 기존 Snowflake 행 세트 배치(즉, 행 배열)와 동일합니다.

    예를 들어,

    {
      "body": {
              "data": [
                        [0,"cat"],
                        [1,"dog"]
                      ]
              }
    }
    
    Copy

    기존 데이터는 외부 본문 아래에 중첩됩니다.

  • serviceUrl: 호출할 외부 함수의 정의된 URL입니다.

  • contextHeaders: 모든 컨텍스트 관련 헤더를 포함하는 오브젝트로, 여기서 이름은 필드 이름입니다. 예를 들어, 오브젝트는 《SF_CONTEXT_CURRENT_DATABASE》 필드 이름을 포함할 수 있으며 해당 값은 현재 데이터베이스 이름을 포함하는 문자열입니다.

요청 변환기 출력 속성

요청 변환기는 외부 서비스 API 게이트웨이와 통신하기 위해 사용되는 필드가 있는 오브젝트를 반환합니다. 해당 오브젝트에는 다음과 같은 세 가지 선택적 필드가 있습니다.

  • body: 서비스에 전달할 실제 본문을 정의합니다. 정의되지 않으면 본문이 없습니다. body 값은 문자열 또는 원격 서비스에 필요한 형식의 JSON 오브젝트여야 합니다. 값이 문자열인 경우 해당 문자열은 내부 구조를 포함할 수 있습니다(예: JSON 호환 가능). 값이 JSON 오브젝트인 경우 해당 오브젝트는 HTTP POST 명령 문자열의 일부로 포함될 수 있도록 문자열로 변환됩니다.

  • urlSuffix: serviceUrl 값의 끝에 추가되는 서비스 URL의 접미사를 설정합니다. 이 접미사에는 쿼리 매개 변수도 포함될 수 있습니다. 매개 변수 이름과 값은 URL로 인코딩되어야 합니다. 예를 들어 a 라는 매개 변수를 my param 값으로 설정하려면 공백 문자의 URL 인코딩을 수행해야 하므로 매개 변수는 ?a=my%20param 이 됩니다.

  • translatorData: 요청 변환기에서 응답 변환기로 전달됩니다. 이 필드는 입력 본문, 서비스 URL 또는 접미사 또는 컨텍스트 헤더와 같은 컨텍스트 정보를 전달할 수 있습니다.

세 필드 모두 선택 사항입니다. 그러나 실제에서 대부분의 요청 변환기는 최소한으로 본문 데이터를 반환합니다.

응답 변환기 구현하기

응답 변환기 입력 속성

응답 변환기 함수의 입력 매개 변수는 오브젝트입니다. 아래 예에서는 EVENT 를 사용하며, 여기에는 다음의 속성 2개가 포함됩니다.

  • body: 외부 서비스 응답에서 디코딩할 응답입니다.

  • translatorData: 요청 변환기가 이 필드를 반환하면 Snowflake는 이를 응답 변환기로 전달합니다.

응답 변환기 출력 속성

응답 변환기 응답은 body 요소 아래에 오브젝트로 반환되며, 형식은 기존 외부 함수 형식(행 배열)입니다. 예:

{
  "body": {
          "data": [
                    [0, "Life"],
                    [1, "the universe"],
                    [2, "and everything"]
                  ]
           }
}
Copy

변환기 함수 요구 사항

각 변환기 UDF는 다음 요구 사항을 충족해야 합니다.

  • JavaScript UDF 여야 합니다.

  • 행 배치를 나타내는 OBJECT 형식의 매개 변수를 정확히 하나 취해야 합니다.

  • 행 배치를 나타내는 OBJECT 형식의 값 하나를 반환해야 합니다.

  • 스칼라 UDF여야 합니다(전달된 각 행(OBJECT)에 대해 하나의 행 반환).

    참고

    변환기는 스칼라이지만 변환기에 전달되는 OBJECT는 OBJECT의 JSON 내부에 여러 행을 포함할 수 있습니다(일반적으로 포함됨).

  • 응답 변환기 UDF가 반환하는 행(OBJECT 내)의 수 및 순서는 요청 변환기 UDF(OBJECT 내)에 전달되는 행의 수 및 순서와 같아야 합니다.

요청 변환기 및 응답 변환기의 예

다음 예는 데이터를 감정 분석을 수행하는 외부 서비스인 Amazon Comprehend BatchDetectSentiment 에 필요한 형식으로 변환하는 데 사용되는 요청 변환기 및 응답 변환기를 보여줍니다. 요청 변환기는 백엔드 서비스에 필요한 형식과 일치하도록 HTTP 요청을 형성합니다.

변환기를 사용하려면 API 게이트웨이가 필요합니다. 이 예에서는 감정 분석 서비스와 통신하도록 이미 구성된 API 게이트웨이를 사용합니다. Amazon Web Services(AWS) 서비스를 백엔드로 통합하는 방법에 대한 자세한 내용은 AWS 설명서의 API Gateway 콘솔을 사용하여 API 통합 요청 설정하기 를 참조하십시오.

변환기를 추가하기 전에 API 통합이 성공적으로 작동하도록 하는 것이 좋습니다.

설정

데모 데이터를 보유할 데이터베이스를 설정합니다.

외부 함수를 생성할 권한이 있는 역할을 선택합니다.

USE ROLE ACCOUNTADMIN;
Copy

사용할 웨어하우스, 데이터베이스, 스키마를 지정합니다.

USE WAREHOUSE w;
USE DATABASE a;
USE SCHEMA b;
Copy

테스트 문장을 보유할 테이블을 만듭니다.

CREATE TABLE demo(vc varchar);
INSERT INTO demo VALUES('Today is a good day'),('I am feeling mopey');
Copy

변환 전 요청 본문

이 외부 함수에는 요청 변환기 또는 응답 변환기가 없습니다.

CREATE OR REPLACE EXTERNAL FUNCTION ComprehendSentiment(thought varchar)
RETURNS VARIANT
API_INTEGRATION = aws_comprehend_gateway
AS 'https://<MY_GATEWAY>.execute-api.us-east-1.amazonaws.com/test/comprehend_proxy';
Copy

데모 테이블의 테스트 데이터를 사용하여 외부 함수를 호출할 수 있습니다.

SELECT ComprehendSentiment(vc), vc FROM demo;
Copy

생성된 요청 본문에서는 Snowflake 외부 함수 데이터 형식을 사용합니다.

{"body":{"data:" [[0, "Today is a good day"],[1,"I am feeling mopey"]]}}
Copy

그러나 외부 감정 분석 서비스에는 언어 및 문자열 배열을 지정하는 다른 형식이 필요합니다.

{"body": { Language: "en", TextList: [ "Today is a good day", "I am feeling mopey"]}}
Copy

다음 섹션에서는 요청 본문을 필요한 형식으로 변경하기 위해 요청 변환기를 추가하는 방법에 대해 설명합니다.

요청 본문 변환

요청 변환기를 사용하여 위에서 설명한 기본 입력(Snowflake 데이터 형식)을 외부 서비스에 필요한 형식으로 변환할 수 있습니다.

다음 SQL에서는 awscomprehendrequest_translator 변환기 함수가 생성됩니다.

CREATE OR REPLACE FUNCTION AWSComprehendrequest_translator(EVENT OBJECT)
RETURNS OBJECT
LANGUAGE JAVASCRIPT AS
'
var textlist = []
for(i = 0; i < EVENT.body.data.length; i++) {
   let row = EVENT.body.data[i];
   // row[0] is the row number and row[1] is the input text.
   textlist.push(row[1]); //put text into the textlist
}
// create the request for the service. Also pass the input request as part of the output.
return { "body": { "LanguageCode": "en", "TextList" : textlist }, "translatorData": EVENT.body }
';
Copy

요청 변환기 함수에서 코드는:

  • 각 입력 행을 반복합니다. 각 행에 대해 row[1] 에 있는 문자열을 textlist 배열에 추가합니다. row[0] 의 값은 행 번호이며 무시할 수 있습니다.

  • 외부 서비스의 요구 사항과 일치하는 언어 코드 및 텍스트 목록이 포함된 JSON 본문을 반환합니다.

  • translatorData 필드를 통해 데이터를 반환합니다. 이는 응답 변환기에서 사용됩니다. 이 예에서는 원래 입력 데이터를 보내고 있습니다. 얼마나 많은 입력 요청이 있었는지 살펴보려면 응답 변환기의 입력 데이터 길이를 사용할 수 있습니다.

요청 변환기를 직접 호출하여 테스트할 수 있습니다.

SELECT AWSComprehendrequest_translator(parse_json('{"body":{"data": [[0, "I am so happy we got a sunny day for my birthday."], [1, "$$$$$."], [2, "Today is my last day in the old house."]]}}'));
Copy

요청 변환기는 외부 서비스에 필요한 형태로 본문을 넣습니다.

{"body":{
   "LanguageCode": "en",
   "TextList": [
      "I am so happy we got a sunny day for my birthday.",
      "$$$$$.",
      "Today is my last day in the old house."
               ]
         },
   "translatorData": {
      "data": [[0, "I am so happy we got a sunny day for my birthday."],
               [1, "$$$$$."],
               [2, "Today is my last day in the old house."]]
                     }
}
Copy

요청 변환기 추가 이전의 응답 본문

외부 서비스의 응답 본문은 다음과 같습니다.

{"body":{
   "ErrorList": [ { "ErrorCode": 57, "ErrorMessage": "Language unknown", "Index": 1} ],
   "ResultList":[ { "Index": 0, "Sentiment": "POSITIVE",
                    "SentimentScore": { "Mixed": 25, "Negative": 5, "Neutral": 1, "Positive": 90 }},
                  { "Index": 2, "Sentiment": "NEGATIVE",
                    "SentimentScore": { "Mixed": 25, "Negative": 75, "Neutral": 30, "Positive": 20 }}
                ]
         }
}
Copy

응답 본문 변환

응답 변환기는 외부 서비스에서 얻은 결과를 처리합니다. 결과에는 ErrorList 의 오류 조합과 ResultList 의 결과가 포함됩니다.

응답 변환기 코드는 이러한 결과를 함께 결합하여, 외부 서비스에 전달된 행의 순서와 일치하는 완전한 세트를 만듭니다. 응답 변환기는 결과를 Snowflake 형식으로 반환합니다.

다음 SQL에서는 awscomprehendresponse_translator 변환기 함수가 생성됩니다.

CREATE OR REPLACE FUNCTION AWSComprehendresponse_translator(EVENT OBJECT)
RETURNS OBJECT
LANGUAGE JAVASCRIPT AS
'
// Combine the scored results and the errors into a single list.
var responses = new Array(EVENT.translatorData.data.length);
// output format: array of {
// "Sentiment": (POSITIVE, NEUTRAL, MIXED, NEGATIVE, or ERROR),
// "SentimentScore": <score>, "ErrorMessage": ErrorMessage }.
// If error, set ErrorMessage; otherwise, set SentimentScore.
// Insert good results into proper position.
for(i = 0; i < EVENT.body.ResultList.length; i++) {
   let row = EVENT.body.ResultList[i];
   let result = [row.Index, {"Sentiment": row.Sentiment, "SentimentScore": row.SentimentScore}]
   responses[row.Index] = result
}
// Insert errors.
for(i = 0; i < EVENT.body.ErrorList.length; i++) {
   let row = EVENT.body.ErrorList[i];
   let result = [row.Index, {"Sentiment": "Error", "ErrorMessage": row.ErrorMessage}]
   responses[row.Index] = result
}
return { "body": { "data" : responses } };
';
Copy

응답 변환기 함수에서 코드는:

  • translatorData 배열 길이의 입력 크기로 이름이 responses 인 배열을 초기화합니다. 사용자는 테스트 문자열의 원래 목록을 전달하기 위해 요청 변환기에서 응답 변환기로 translatorData 를 보냈습니다.

  • 오류가 아닌 각 결과를 반복하여 결과 목록에 넣습니다.

  • 오류 결과를 반복하여 결과 목록에 넣습니다. 결과 목록에는 항목이 무엇인지 알려주는 색인 위치가 있습니다. 생성된 결과의 순서는 입력 순서와 일치해야 합니다. 결과 목록에는 감정 정보도 포함됩니다.

모든 응답이 수집된 후, Snowflake가 예상하는 형식으로 JSON 본문으로 반환됩니다.

다음 직접 테스트에서는 올바른 형식의 JSON 본문이 반환됩니다.

SELECT AWSComprehendresponse_translator(
    parse_json('{
        "translatorData": {
            "data": [[0, "I am so happy we got a sunny day for my birthday."],
                    [1, "$$$$$."],
                    [2, "Today is my last day in the old house."]]
                          }
        "body": {
            "ErrorList":  [ { "ErrorCode": 57,  "ErrorMessage": "Language unknown",  "Index": 1 } ],
            "ResultList": [
                            { "Index": 0,  "Sentiment": "POSITIVE",
                              "SentimentScore": { "Mixed": 25,  "Negative": 5,  "Neutral": 1,  "Positive": 90 }
                            },
                            { "Index": 2, "Sentiment": "NEGATIVE",
                              "SentimentScore": { "Mixed": 25,  "Negative": 75,  "Neutral": 30,  "Positive": 20 }
                            }
                          ]
            },
        }'
    )
);
Copy

변환기를 외부 함수에 지정

외부 함수에 함수 이름을 request_translatorresponse_translator 매개 변수에 값으로 할당하여 요청 및 응답 변환기 함수를 추가합니다. 이를 통해 외부 함수가 실행될 때 자동으로 호출됩니다.

CREATE OR REPLACE EXTERNAL FUNCTION ComprehendSentiment(thought varchar)
RETURNS VARIANT
API_INTEGRATION = aws_comprehend_gateway
request_translator = db_name.schema_name.AWSComprehendrequest_translator
response_translator = db_name.schema_name.AWSComprehendresponse_translator
AS 'https://<MY_GATEWAY>.execute-api.us-east-1.amazonaws.com/test/comprehend_proxy';
Copy

함수에 대한 정보를 얻기 위해 함수를 설명할 수 있습니다.

DESCRIBE FUNCTION ComprehendSentiment(VARCHAR);
Copy

외부 함수 호출하기

단일 문장으로 호출하여 외부 함수를 테스트합니다.

SELECT ComprehendSentiment('Today is a good day');
Copy

감정 분석 결과를 볼 수 있습니다.

{"Sentiment": "POSITIVE",
 "SentimentScore":{"Mixed":0.002436627633869648,
                   "Negative":0.0014803812373429537,
                   "Neutral":0.015923455357551575,
                   "Positive": 0.9801595211029053}}
Copy

여러 문장으로 호출하여 외부 함수를 테스트합니다. 이전에 생성한 것과 동일한 demo 테이블을 사용합니다.

SELECT ComprehendSentiment(vc), vc FROM demo;
Copy

감정 분석 결과가 표시됩니다.

A table showing the sentiment analysis results.

외부 함수가 호출되면 요청 변환기는 자동으로 데이터를 외부 서비스에 필요한 형식으로 변환했습다. 그런 다음 응답 변환기는 외부 서비스의 응답을 Snowflake에 필요한 형식으로 다시 자동으로 변환했습니다.

요청 및 응답 변환기 테스트 관련 팁

  • 테스트 케이스 값은 일반적으로 OBJECT 값(키-값 페어의 모음)입니다. 이러한 규칙 의 요구 사항을 충족하도록 형식이 지정되어야 합니다.

  • 문자열로 변환된 예시 입력을 전달하여 요청 변환기 또는 응답 변환기 테스트를 시작할 수 있습니다. 예:

    select my_request_translator_function(parse_json('{"body": {"data": [ [0,"cat",867], [1,"dog",5309] ] } }'));
    
    Copy

    (PARSE_JSON() 에 대한 입력은 JSON 형식의 문자열이어야 합니다.)

  • 적절한 경우 NULL 값으로 테스트하십시오.

    • 테스트 케이스에 하나 이상의 SQL NULL 값을 포함하십시오.

    • 테스트 케이스에 하나 이상의 JSON NULL 값을 포함하십시오.

  • 요청 변환과 응답 변환은 흔히 반대의 프로세스입니다. 개념적으로:

    my_response_translator_udf(my_request_translator_udf(x)) = x
    
    Copy

    데이터 형식이 일치하는 경우 요청 변환기 및 응답 변환기를 테스트하는 데 도움이 되도록 이 특성을 사용할 수 있습니다. 좋은 테스트 값으로 테이블을 만든 다음, 다음과 유사한 명령을 실행합니다.

    SELECT test_case_column
        FROM test_table
        WHERE my_response_translator_udf(my_request_translator_udf(x)) != x;
    
    Copy

    쿼리는 행을 반환하지 않아야 합니다.

    요청 변환과 응답 변환이 항상 정확히 반대되는 것은 아닙니다. 반대가 아닐 수 있는 경우의 예는 TO_JSON() 함수 에 대한 설명서의 《사용법 노트》 섹션에서 반대 함수에 대한 설명을 참조하십시오.