앱 간 통신

이 항목에서는 하나의 Snowflake Native App 이 앱 간 통신(IAC)을 통해 다른 Snowflake Native App 과 통신하는 방법에 대해 설명합니다.

앱 간 통신: 개요

앱 간 통신(IAC)을 통해 Snowflake Native App 은 다른 앱이 호출할 수 있는 함수 및 프로시저에 대한 액세스 권한을 제공하여 동일한 컨슈머 계정에서 다른 Snowflake Native Apps 에 추가 기능을 제공할 수 있습니다.

예를 들어, 고객 IDs를 확인하는 Snowflake Native App 은 다른 Snowflake Native Apps 이 다양한 벤더의 데이터 세트를 조인하여 고객 데이터를 개선하는 데 도움이 될 수 있습니다.

IAC는 둘 이상의 독립적인 앱이 관리 및 보안에 대한 요구 사항을 존중하면서 서로 통신할 수 있는 인프라를 제공합니다. 앱 개발자는 다음을 수행하여 앱에 대한 IAC를 활성화합니다.

  • 인터페이스 생성

  • 앱 역할을 사용하여 인터페이스에 대한 액세스를 제어합니다.

  • 동기 또는 비동기 상호 작용을 선택합니다. 동기 상호 작용은 다른 앱이 직접 호출할 수 있는 저장 프로시저나 함수를 사용하는 반면, 비동기 상호 작용은 다른 앱이 결과를 확인하기 위해 폴링할 수 있는 테이블 또는 뷰에 저장된 요청 결과에 대한 액세스 권한을 제공합니다.

용어

IAC에서는 다음 용어를 사용합니다.

클라이언트

연결 요청을 시작하고 서버 앱의 함수와 프로시저를 호출하는 앱입니다.

서버

앱 역할을 사용하여 함수와 프로시저에 대한 액세스를 제공하는 앱입니다.

컨슈머

클라이언트 및 서버 앱을 설치하는 사용자입니다.

애플리케이션 구성

클라이언트 앱이 서버 앱의 이름을 요청하는 데 사용하는 SQL 오브젝트입니다. IAC는 APPLICATION_NAME 유형의 애플리케이션 구성을 사용하여 서버 앱 이름을 저장합니다.

애플리케이션 사양

클라이언트 앱이 서버 앱에 대한 연결을 요청하기 위해 생성하는 SQL 오브젝트입니다. IAC는 CONNECTION 유형의 애플리케이션 사양을 사용합니다. 앱 사양에 대한 자세한 내용은 앱 사양 개요 섹션을 참조하세요.

앱 간 통신을 위한 워크플로

연결을 설정하고 사용하려면 클라이언트 앱과 서버 앱 간의 핸드셰이크 프로세스가 필요합니다.

  1. 서버 앱 공급자로부터 앱 역할 이름 가져오기: 클라이언트 앱 공급자는 Snowflake 외부의 서버 앱 공급자와 협력하여 연결 사양에서 요청할 서버 앱 역할을 결정합니다.

  2. 대상 앱 식별: 클라이언트 앱은 서버 앱의 이름을 요청하는 구성 정의 오브젝트를 생성합니다. 컨슈머는 수신 요청을 감지하고 구성 오브젝트를 통해 클라이언트 앱에 서버 앱 이름을 제공합니다.

  3. 연결 요청 및 승인: 클라이언트 앱은 서버 앱에 대한 연결을 요청하는 애플리케이션 사양을 생성하며, 컨슈머는 연결 요청을 승인합니다.

  4. Server App과 통신: 클라이언트 앱은 서버 앱의 프로시저 또는 함수를 호출합니다.

대상 앱 식별

클라이언트 앱이 서버 앱과 통신하려면 먼저 앱의 정확한 이름을 식별해야 합니다. 컨슈머는 설치 중에 앱의 사용자 지정 이름을 선택할 수 있으므로 클라이언트 앱은 먼저 서버 앱의 정확한 이름을 식별해야 합니다.

클라이언트 앱의 설정 스크립트는 CONFIGURATION DEFINITION 오브젝트를 생성하여 이 정보를 요청합니다.

다음 예제에서는 클라이언트 앱의 설정 스크립트가 CONFIGURATION DEFINITION 오브젝트를 생성하여 서버 앱의 이름을 요청하는 방법을 보여줍니다.

ALTER APPLICATION
  SET CONFIGURATION DEFINITION my_server_app_name_configuration
    TYPE = APPLICATION_NAME
    LABEL = 'Server App'
    DESCRIPTION = 'Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.'
    APPLICATION_ROLES = (my_server_app_role);
Copy

다음 예제에서는 수신되는 구성 정의 요청을 컨슈머가 확인하는 방법을 보여줍니다.

SHOW CONFIGURATIONS IN APPLICATION my_server_app_name;
Copy

이 명령은 다음과 유사한 결과를 반환합니다.

name                             | created_on              | updated_on              | type               | ...
my_server_app_name_configuration | 2026-02-09 10:00:00.000 | 2026-02-09 10:00:00.000 | APPLICATION_NAME   | ...

그런 다음 컨슈머는 다음 명령을 사용하여 서버 앱 이름을 제공합니다.

ALTER APPLICATION my_client_app_name
  SET CONFIGURATION my_server_app_name_configuration
  VALUE = MY_SERVER_APP_NAME;
Copy

연결 요청 및 승인

클라이언트 앱에 서버 앱의 이름이 있으면 :code:`APPLICATION SPECIFICATION`을 생성하여 서버 앱에 대한 연결을 요청합니다. 애플리케이션 역할 이름은 Snowflake 외부의 오프라인 통신을 통해 얻습니다.

다음 예제에서는 이름이 ``my_server_app_name``인 서버 앱에 연결하기 위해 :code:`APPLICATION SPECIFICATION`을 생성하는 방법을 보여줍니다.

ALTER APPLICATION SET SPECIFICATION my_server_app_name_connection_specification
  TYPE = CONNECTION
  LABEL = 'Server App'
  DESCRIPTION = 'Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.'
  SERVER_APPLICATION = MY_SERVER_APP_NAME -- server name obtained from Step 1
  SERVER_APPLICATION_ROLES = (my_server_app_role);
Copy

클라이언트 앱은 애플리케이션 사양을 생성하여 앱 사양에 지정된 서버 앱 역할을 부여받도록 요청합니다.

참고

앱 사양에서 LABELDESCRIPTION`에 대해 주어진 값은 1단계에서 생성된 :code:`CONFIGURATION DEFINITION 오브젝트에서 LABEL 및 :code:`DESCRIPTION`에 지정된 값과 일치해야 합니다. 값이 일치하지 않으면 Snowsight 에 연결이 올바르게 표시되지 않습니다.

효율적인 연결 워크플로를 생성하려면 클라이언트 앱이 before_configuration_change 동기 콜백에서 애플리케이션 사양을 생성하는 것이 좋습니다. 이 콜백은 ALTER APPLICATION SET CONFIGURATION VALUE 명령이 실행되는 경우 실행됩니다. 콜백에 대한 자세한 내용은 콜백 섹션을 참조하세요. before_configuration_change 동기 콜백에서 애플리케이션 사양을 생성하는 설정 스크립트의 예제는 섹션을 참조하세요.

클라이언트 앱이 앱 사양을 생성하면 컨슈머는 연결 요청을 검토하고 승인하거나 거부할 수 있습니다.

SQL을 사용하여 연결 요청 승인하기

다음 예제에서는 컨슈머가 SQL을 사용하여 연결 요청을 승인하는 방법을 보여줍니다.

ALTER APPLICATION my_server_app_name
  APPROVE SPECIFICATION my_server_app_name_connection_specification
  SEQUENCE_NUMBER = 1;
Copy

|sf-web-interface|을 사용하여 연결 요청 승인하기

Snowsight 에서 연결 요청을 확인하고 승인하려면 다음을 수행합니다.

  1. Snowsight 에 로그인합니다.

  2. 앱을 선택합니다. 제목이 Application connections`인 섹션이 :ui:`Configurations 아래에 나타납니다. 보류 중인 각 연결에는 연결의 이름 또는 레이블, 연결에 대한 간략한 설명, Review 버튼이 표시됩니다.

  3. Review 버튼을 클릭합니다. 연결 요청의 세부 정보가 나타납니다.

  4. :ui:`Select from your apps`에서 대상 앱을 선택합니다.

  5. Next 를 클릭합니다. 다음 정보가 표시됩니다.

    • 클라이언트 앱과 서버 앱의 연결 및 앱이 사용할 역할을 보여주는 다이어그램.

    • 연결의 세부 정보.

    • 클라이언트 앱에 부여될 서버 권한의 하위 세트. IAC의 보안 고려 사항에 대한 자세한 내용은 보안 고려 사항 섹션을 참조하세요.

    • Approve Connection 토글 스위치. 스위치가 :ui:`On`으로 설정됩니다.

  6. 연결을 승인하려면 토글 스위치가 :ui:`On`으로 설정된 상태로 두고 :ui:`Save`를 클릭합니다. 연결 상태를 보여주는 업데이트된 연결 목록이 나타납니다.

  7. 연결을 거부하려면 토글 스위치를 :ui:`Off`로 전환합니다.

  8. 연결을 승인하거나 거부하지 않고 검토 페이지를 종료하려면 Cancel 버튼을 클릭합니다.

사후 승인

컨슈머가 연결 요청을 승인하는 경우 Snowflake Native App Framework 는 요청된 서버 앱 역할을 클라이언트 앱에 부여합니다. 또한 이 승인을 통해 클라이언트 앱에 대한 USAGE 권한이 서버 앱에 부여됩니다. 이를 통해 서버 앱은 연결된 클라이언트 앱을 알 수 있습니다.

컨슈머가 연결 요청을 승인하면 클라이언트 앱과 서버 앱에서 각각 다음 콜백이 트리거됩니다.

  • :ref:`after_server_connection_change <label-native_apps_connection_callbacks_after_server_connection_change>`가 클라이언트 앱에서 트리거됨

  • :ref:`after_client_connection_change <label-native_apps_connection_callbacks_after_client_connection_change>`가 서버 앱에서 트리거됨

이러한 콜백을 사용하면 연결이 설정될 때 서버 및 클라이언트 앱이 추가 작업을 수행할 수 있습니다.

애플리케이션 사양 승인에 대한 자세한 내용은 다음 항목을 참조하세요.

서버 앱과 통신

연결이 설정되고 클라이언트 앱에 요청된 서버 앱 역할이 부여되면 클라이언트 앱이 서버 앱과 통신할 수 있습니다.

참고

서버 앱 메서드를 호출하기 전에 클라이언트 앱은 런타임 시 승인된 애플리케이션 사양에서 서버 앱의 이름을 검색하여 서버 앱의 이름이 변경된 경우 올바른 이름을 사용하는지 확인해야 합니다. 다음 예제에서는 런타임 시 서버 앱의 이름을 검색하는 방법을 보여줍니다.

SHOW APPROVED SPECIFICATIONS ->>
  SELECT PARSE_JSON("definition"):"SERVER_APPLICATION"::STRING
  FROM $1
  WHERE "name" = 'MY_SERVER_APP_NAME_CONNECTION_SPECIFICATION';
Copy

클라이언트 앱은 서버 앱과 동기적으로 또는 비동기적으로 통신할 수 있습니다.

  • 동기 통신에는 서버 앱의 프로시저 또는 함수를 직접 호출하는 작업이 포함됩니다.

  • 비동기 통신에는 테이블과 같은 데이터 오브젝트에 저장된 큐를 사용하는 작업이 포함됩니다. 예를 들어, 서버 앱은 테이블에 레코드를 요청으로 삽입하는 프로시저를 제공할 수 있으며, 그러면 서버 앱에서 이를 주기적으로 처리합니다. 그런 다음 클라이언트 앱은 서버에서 제공하는 다른 프로시저를 사용하여 테이블에서 결과를 확인할 수 있습니다.

동기 작업의 다음 예제에서는 Python을 사용하여 서버 앱의 프로시저를 호출하는 클라이언트 앱을 보여줍니다.

session.call("server_app_name.customer_schema.get_customer_data", customer_id);
Copy

비동기 작업의 다음 예제에서는 Python을 사용하여 서버 앱의 프로시저를 호출하는 클라이언트 앱을 보여줍니다. 클라이언트 앱은 서버 앱의 프로시저를 호출하여 테이블에 요청을 생성한 다음 서버 앱에서 이를 처리합니다. 클라이언트 앱은 테이블을 폴링하여 결과에 대해 업데이트된 레코드가 있는지 확인할 수 있습니다.

session.call("server_app_name.customer_schema.request_customer_data_async", customer_id);
Copy

그런 다음 클라이언트 앱은 테이블을 폴링하여 결과에 대해 업데이트된 레코드가 있는지 확인할 수 있습니다.

session.call("server_app_name.customer_schema.check_customer_data_requests_async", customer_id);
Copy

연결 관리하기

Snowsight 에서 기존 연결을 확인하려면 다음을 수행합니다.

  1. Snowsight 에 로그인합니다.

  2. 탐색 메뉴에서 Catalog » Apps 를 선택합니다.

  3. 앱을 선택합니다. 모든 앱 연결은 :ui:`Configurations`라는 제목의 섹션에 표시됩니다. 해당 섹션 아래에는 :ui:`Application connections`라는 제목의 하위 섹션이 있습니다.

  4. 연결을 수정하려면 연결의 연필 아이콘을 클릭합니다. 다음을 변경할 수 있습니다.

    • 앱에 연결된 앱

    • 연결의 승인 상태

  5. 연결된 앱을 확인하려면 View app 버튼을 클릭합니다.

  6. 연결에 대한 보안 설정을 변경하려면 기어 아이콘을 클릭합니다.

보안 고려 사항

컨슈머는 사양 요청을 승인할 때 서버 앱에 클라이언트 앱에 대한 액세스 권한을 부여하면 클라이언트 앱의 권한이 상승할 수 있다는 점에 유의해야 합니다. 예를 들어, 서버 앱에 외부 액세스 권한이 있는 경우 클라이언트 앱은 서버 앱을 통해 인터넷 또는 기타 외부 리소스에 간접적으로 액세스할 수 있습니다. 서버 앱이 다른 서버 앱의 클라이언트 앱인 경우 클라이언트 앱은 첫 번째 서버 앱을 통해 다른 서버 앱의 리소스에 액세스할 수 있습니다.

컨슈머는 연결을 승인하기 전에 서버 앱의 기능과 권한을 검사해야 합니다. 관리자 역할(예: ACCOUNTADMIN)을 사용하여 서버의 기능을 검사합니다. 권한이 낮은 역할로 서버를 검사하면 서버의 모든 기능과 권한이 확인되지 않습니다. 컨슈머는 서버 앱 코드가 컨슈머에게 표시되지 않으며 컨슈머가 연결을 승인한 후에는 서버 앱 권한과 기능이 변경될 수 있다는 점에 유의해야 합니다.

서버 앱의 기능과 권한을 검사하는 SQL 명령의 예에는 다음이 포함되지만, 이에 국한되지 않습니다.

  • SHOW GRANTS TO APPLICATION: 이 명령은 클라이언트 앱에 대한 권한 중 서버 앱에 부여된 권한을 나열합니다.

  • SHOW PRIVILEGES IN APPLICATION: 이 명령은 클라이언트 앱에 부여할 수 있는 잠재적인 계정 수준 권한을 나열합니다.

  • SHOW REFERENCES IN APPLICATION: 이 명령은 클라이언트 앱이 권한 부여를 사용하지 않고 잠재적으로 사용할 수 있는 참조를 나열합니다.

  • SHOW SPECIFICATIONS IN APPLICATION: 이 명령은 외부 액세스 통합(EAIs), 보안 통합, 공유, 목록 및 연결을 비롯하여 컨슈머가 승인한 애플리케이션 사양을 나열합니다.

SQL 참조

다음 SQL 명령은 앱 간 통신을 관리하는 데 사용됩니다.

콜백

Snowflake Native App Framework 는 앱 간 통신 워크플로를 관리하는 데 도움이 되는 수명 주기 콜백을 제공합니다. 이러한 콜백을 통해 앱은 구성, 연결 및 사양의 변경 사항에 대응할 수 있습니다. 콜백을 사용하려면 앱 매니페스트 파일의 lifecycle_callbacks 섹션에 등록합니다.

콜백에 대한 일반적인 정보는 콜백 섹션을 참조하세요.

구성 콜백

이러한 콜백은 구성 값이 설정되거나 설정 해제될 때 트리거됩니다. 일반적인 사용 사례는 컨슈머가 서버 앱 이름을 제공할 때 before_configuration_change 콜백을 사용하여 연결 사양을 자동으로 생성하는 것입니다.

validate_configuration_change

ALTER APPLICATION SET CONFIGURATION VALUE 명령의 일부로 호출되는 동기 콜백입니다. 앱이 제공된 값에 대해 사용자 지정 유효성 검사를 수행할 수 있도록 합니다. 콜백이 오류를 반환하면 명령이 실패하고 새 값이 설정되지 않습니다.

before_configuration_change

ALTER APPLICATION SET CONFIGURATION VALUEALTER APPLICATION UNSET CONFIGURATION 명령의 일부로 호출되는 동기 콜백입니다. 앱이 구성 값을 기반으로 작업을 수행한 후 저장되도록 합니다.

after_configuration_change

ALTER APPLICATION SET CONFIGURATION VALUE 또는 ALTER APPLICATION UNSET CONFIGURATION 명령이 완료된 후 호출되는 비동기 콜백입니다. 알림 또는 추적 목적으로 앱이 변경 사항에 대응할 수 있도록 합니다.

연결 콜백

이러한 콜백은 연결이 설정, 거부, 삭제되거나 연결된 앱이 삭제될 때와 같이 연결 상태가 변경될 때 트리거됩니다.

after_server_connection_change

사양 승인, 거부, 삭제 또는 서버 앱 삭제 등 연결 상태에 영향을 미치는 모든 작업에 의해 클라이언트 앱에서 트리거되는 비동기 콜백입니다.

after_client_connection_change

사양 승인, 거부, 삭제 또는 클라이언트 앱 삭제 등 연결 상태에 영향을 미치는 모든 작업에 의해 서버 앱에서 트리거되는 비동기 콜백입니다.

after_server_version_change

서버 앱의 버전 또는 패치 번호가 변경된 후 클라이언트 앱에서 호출되는 비동기 콜백입니다. 클라이언트 앱이 업그레이드 또는 다운그레이드에 대응할 수 있도록 합니다.

다음 예제에서는 앱 간 통신을 사용하도록 앱을 구성하는 방법을 보여줍니다.

예: 설정 스크립트 및 매니페스트 파일

다음 예제에서는 클라이언트 앱의 설정 스크립트(setup.sql)를 보여줍니다.

CREATE OR ALTER VERSIONED SCHEMA app_schema;

-- create a callback that creates the connection request before the config value of the server name is saved
CREATE OR REPLACE PROCEDURE app_schema.before_config_change_callback(config_name STRING, config_value STRING)
RETURNS STRING
LANGUAGE SQL
AS
$$
DECLARE
    spec_name VARCHAR;
    existing_target VARCHAR;
BEGIN
    IF (config_value IS NOT NULL AND config_name = 'MY_SERVER_APP_NAME_CONFIGURATION') THEN
        SHOW SPECIFICATIONS;
        SELECT PARSE_JSON("definition"):SERVER_APPLICATION::STRING
            INTO existing_target
            FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()));

        IF(existing_target IS NOT NULL AND UPPER(existing_target) != UPPER(config_value)) THEN
            EXECUTE IMMEDIATE 'ALTER APPLICATION DROP SPECIFICATION CONNECTION_' || UPPER(existing_target);
        END IF;

        spec_name := 'CONNECTION_' || UPPER(config_value);
        EXECUTE IMMEDIATE
        'ALTER APPLICATION SET SPECIFICATION ' || spec_name || '
            TYPE = CONNECTION
            LABEL = ''Server App''
            DESCRIPTION = ''Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.''
            SERVER_APPLICATION = ' || config_value || '
            SERVER_APPLICATION_ROLES = (my_server_app_role)';
    END IF;
RETURN 'success';
END;
$$;

CREATE APPLICATION ROLE IF NOT EXISTS client_app_user;
GRANT USAGE ON SCHEMA app_schema TO APPLICATION ROLE client_app_user;
ALTER APPLICATION SET CONFIGURATION DEFINITION my_server_app_name_configuration
    TYPE = APPLICATION_NAME
    LABEL = 'Server App'
    DESCRIPTION = 'Request for an application that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2'
    APPLICATION_ROLES = (client_app_user);
Copy

다음 예제에서는 클라이언트 앱의 매니페스트 파일(manifest.yml)을 보여줍니다.

manifest_version: 2

artifacts:
  setup_script: setup.sql

lifecycle_callbacks:
    before_configuration_change: app_schema.before_config_change_callback
Copy

앞의 코드 예제와 관련하여 다음 사항에 유의하세요.

  • before_configuration_change 콜백에서 앱은 구성의 이전 값과 일치하는 기존 연결 사양이 있는지 확인하고, 있는 경우 삭제합니다. 그런 다음 콜백은 새로 제공된 서버 앱 이름에 대한 새 연결 사양을 생성합니다. 서버 이름이 설정된 상태에서 새 연결을 생성하면 중복 연결 사양이 생성되는 것을 방지할 수 있습니다.

예: 앱 간의 비동기 통신

다음 예제에서는 비동기 통신을 위한 서버 앱의 설정 스크립트(setup.sql)에서 프로시저를 생성하는 방법을 보여줍니다. 서버 앱은 처리 큐 테이블을 생성하고 앱 역할을 통해 큐에 요청을 추가하는 submit_request 및 완료된 요청의 결과를 검색하는 fetch_response``의 가지 프로시저를 클라이언트 앱에 제공합니다. 서버 앱은 주기적으로 ``process_requests 프로시저를 사용하여 보류 중인 모든 요청을 처리합니다.

CREATE TABLE IF NOT EXISTS app_schema.processing_queue (
  request_id NUMBER AUTOINCREMENT,
  operation STRING,
  input STRING,
  status STRING DEFAULT 'PENDING',
  response STRING DEFAULT ''
);

CREATE OR REPLACE PROCEDURE app_schema.submit_request(operation STRING, input STRING)
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
BEGIN
    INSERT INTO app_schema.processing_queue (operation, input) VALUES (:operation, :input);
    RETURN 'Request submitted successfully';
END;
$$;

CREATE OR REPLACE PROCEDURE app_schema.process_requests()
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
DECLARE
    -- Cursor to find all PENDING requests
    c1 CURSOR FOR SELECT * FROM app_schema.processing_queue WHERE status = 'PENDING';
    result STRING;
BEGIN
    FOR request IN c1 DO

        IF (request.operation = 'OPERATION_X') THEN
            -- assuming there is a UDF func_x(input) to perform operation_x
            result := (SELECT func_x(:request.input));
        END IF;

        -- update the processing queue with the result
        LET stmt STRING :=
            'UPDATE app_schema.processing_queue SET status = 'DONE', response = ' ||
            result ||
            ' WHERE request_id = ' ||
            request.request_id;
        EXECUTE IMMEDIATE (:stmt);

    END FOR;

    RETURN 'Processed pending requests.';
END;
$$;

CREATE OR REPLACE PROCEDURE app_schema.fetch_response(operation STRING, input STRING)
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
BEGIN
    LET res STRING := (SELECT response FROM app_schema.processing_queue WHERE operation = :operation AND input = :input);
    RETURN res;
END;
$$;

CREATE APPLICATION ROLE IF NOT EXISTS my_server_app_role;
GRANT USAGE ON SCHEMA app_schema TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.submit_request(string, string) TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.process_requests() TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.fetch_response(string, string) TO APPLICATION ROLE my_server_app_role;
Copy