Snowpark Container Services: SQL 실행

애플리케이션 컨테이너는 Snowflake에 연결하여 SQL을 실행할 수 있습니다. 이 항목에서는 컨테이너 코드가 인증 자격 증명, 서비스의 데이터베이스 및 스키마 컨텍스트, SQL 문을 실행하는 데 사용되는 웨어하우스 등 Snowflake에 연결하는 데 필요한 정보를 얻는 방법에 대해 설명합니다.

자격 증명 구성 옵션

Snowflake는 애플리케이션 컨테이너가 SQL을 실행할 때 Snowflake 제공 자격 증명을 사용하여 Snowflake에 인증할 것을 권장합니다. 외부 액세스 통합(EAI)을 통해 연결하여 다른 자격 증명을 사용할 수 있지만, EAI를 통해 연결하면 서비스가 Snowflake 외부에서 실행되고 인터넷을 통해 Snowflake에 연결되는 것처럼 처리됩니다.

서비스 컨테이너에서 Snowflake에 연결하는 3가지 옵션이 있습니다.

  • Snowflake 제공 서비스 사용자 자격 증명 사용: Snowflake는 모든 서비스에 서비스 자격 증명이라는 자격 증명을 제공합니다. 서비스는 이러한 자격 증명을 사용하여 서비스 사용자로 Snowflake에 연결합니다.

  • Snowflake 제공 호출자 자격 증명(호출자 권한) 사용: 호출자 권한으로 서비스를 구성하는 경우 Snowflake는 서비스가 호출하는 사용자로 Snowflake에 연결하기 위한 자격 증명도 제공합니다.

  • 다른 자격 증명 사용: 이 경우에는 외부 액세스 통합(EAI)를 사용하여 유효한 인증 자격 증명을 통해 서비스를 Snowflake의 인터넷 엔드포인트에 연결할 수 있습니다. 이 옵션을 사용하려면 관리자가 EAI를 생성한 후 서비스 소유자 역할에 통합에 대한 USAGE 권한을 부여해야 합니다.

    참고

    외부 액세스 통합을 사용하여 Snowflake에 액세스하는 경우 인터넷을 통해 민감한 정보가 전송될 수 있습니다.

다양한 Snowflake 드라이버를 사용하여 Snowflake에 연결하는 코드의 예제는 `Snowflake 연결 샘플<https://github.com/Snowflake-Labs/sf-samples/tree/main/samples/spcs/sf-connection>`_을 참조하세요.

Snowflake 제공 서비스 사용자 자격 증명 사용하기

Snowflake 제공 서비스 자격 증명을 사용하는 경우 다음과 같은 영향에 유의하세요.

  • Snowflake의 모든 오브젝트에는 오브젝트를 생성하는 데 사용되는 역할인 *소유자 역할*이 있습니다. 서비스의 소유자 역할에 따라 서비스가 Snowflake와 상호 작용할 때 허용되는 기능이 결정됩니다. 이러한 기능에는 SQL 실행, 스테이지 액세스, 서비스 간 네트워킹 수행이 포함됩니다.

  • 서비스를 생성하는 경우 Snowflake는 해당 서비스와 관련된 서비스 사용자도 생성합니다. 해당 서비스 사용자는 서비스 소유자 역할 및 ‘PUBLIC’ 역할의 두 역할에만 액세스할 수 있습니다. 서비스 사용자의 기본 역할은 서비스 소유자 역할입니다.

작업 서비스를 포함한 서비스를 시작하는 경우 Snowflake가 여러 작업을 수행합니다. Snowflake는 각 애플리케이션 컨테이너에서 컨테이너 코드가 드라이버를 사용하여 Snowflake에 연결하고 SQL을 실행할 수 있도록 지원합니다. 이는 Snowflake에 연결하는 컴퓨터의 다른 코드와 유사합니다. 다음 목록에서는 서비스를 시작할 때 Snowflake에서 수행하는 작업을 보여줍니다.

  • 이름이 :file:`/snowflake/session/token`인 파일의 컨테이너에 자격 증명(OAuth 토큰)을 제공합니다. 컨테이너 코드는 이러한 자격 증명을 사용하여 서비스 사용자로 인증합니다. 이 OAuth 토큰은 Snowpark Container Services 외부에서 사용할 수 없습니다.

  • 다음과 같은 환경 변수를 설정하여 서비스 코드에서 Snowflake 클라이언트를 구성할 수 있도록 합니다.

    • SNOWFLAKE_ACCOUNT: 이 변수는 현재 서비스가 실행 중인 Snowflake 계정의 :ref:`계정 로케이터<label-account_locator>`로 설정됩니다.

    • SNOWFLAKE_HOST: 이 변수는 Snowflake에 연결하는 데 사용되는 호스트 이름을 제공합니다.

서비스 사용자로 Snowflake에 대한 연결을 생성하는 경우 컨테이너 코드는 SNOWFLAKE_HOST, SNOWFLAKE_ACCOUNT 및 OAuth 토큰을 사용해야 합니다. OAuth 토큰은 SNOWFLAKE_HOST를 사용하지 않고는 사용할 수 없습니다.

자습서 2<tutorials/tutorial-2>`(:file:`main.py 참조)에서 코드는 다음 예제와 같이 환경 변수를 읽습니다.

SNOWFLAKE_ACCOUNT = os.getenv('SNOWFLAKE_ACCOUNT')
SNOWFLAKE_HOST = os.getenv('SNOWFLAKE_HOST')
Copy

이 코드는 선택한 Snowflake 클라이언트의 연결 생성 코드에 이러한 변수를 전달합니다. 컨테이너는 이러한 자격 증명을 통해 서비스의 소유자 역할을 세션의 기본 역할로 사용하여 새 세션을 생성해 쿼리를 실행합니다. 다음 예제는 Python에서 Snowflake 연결을 생성하는 데 필요한 최소 코드를 보여줍니다.

def get_login_token():
  with open('/snowflake/session/token', 'r') as f:
    return f.read()

conn = snowflake.connector.connect(
  host = os.getenv('SNOWFLAKE_HOST'),
  account = os.getenv('SNOWFLAKE_ACCOUNT'),
  token = get_login_token(),
  authenticator = 'oauth'
)
Copy

이 OAuth 토큰에 대한 다음 세부 정보를 참고하세요.

  • Snowflake는 몇 분마다 /snowflake/session/token 파일의 내용을 새로 고칩니다. 모든 토큰은 최대 1시간 동안 유효합니다. 컨테이너가 Snowflake에 제대로 연결되면 사용자가 직접 생성한 세션과 마찬가지로 연결에 만료 시간이 적용되지 않습니다.

  • 이 OAuth 토큰은 특정 Snowflake 서비스 내에서만 유효합니다. OAuth 토큰을 복사하여 서비스 외부에서 사용할 수 없습니다.

  • OAuth 토큰을 사용하여 연결하면 새 세션이 생성됩니다. OAuth 토큰은 기존 SQL 세션과 연결되지 않습니다.

    참고

    저장 프로시저 실행과 서비스 실행의 중요한 차이점은 저장 프로시저가 해당 프로시저를 실행하는 SQL과 동일한 세션에서 실행된다는 점입니다. 그러나 컨테이너가 새로운 연결을 설정할 때마다 새로운 세션이 생성됩니다.

특정 서비스 사용자가 발행한 쿼리를 보려면 ACCOUNTADMIN 역할을 사용하여 쿼리 기록 을 볼 수 있습니다. 서비스 사용자의 사용자 이름은 다음 형식으로 표시됩니다.

  • 8.35 서버 릴리스 이전에 생성된 서비스의 경우 서비스 사용자 이름은 SF$SERVICE$unique-id 형식을 갖습니다.

  • 8.35 서버 릴리스 이후에 생성된 서비스의 경우 서비스 사용자 이름은 서비스 이름과 동일합니다.

참고

서비스의 소유자 역할은 서비스를 생성한 역할입니다. 서비스가 노출하는 엔드포인트에 대한 액세스를 관리하기 위해 하나 이상의 서비스 역할을 정의할 수 있습니다. 자세한 내용은 서비스 관련 권한 관리하기 섹션을 참조하십시오.

Snowflake 제공 호출자 자격 증명 사용 정보(호출자 권한)

특정 애플리케이션 시나리오에서는 이전 섹션에서 설명한 대로 서비스 사용자가 아닌 최종 사용자의 컨텍스트를 사용하여 쿼리를 실행해야 할 수도 있습니다. 호출자의 권한 기능은 이러한 컨텍스트에서 사용됩니다.

예를 들어, 공용 엔드포인트를 노출하는 서비스를 생성하여 Snowflake에 저장된 데이터를 통해 대시보드를 표시하는 웹 애플리케이션을 가정해 보겠습니다. :ref:`서비스 역할<label-spcs_manage_service_related_privileges>`을 부여하여 Snowflake 계정의 다른 사용자에게 대시보드에 대한 액세스 권한을 부여합니다. 사용자가 로그인하면 대시보드에 사용자에게 액세스 권한이 부여된 데이터만 표시됩니다.

그러나 컨테이너는 기본적으로 서비스 사용자 및 서비스 소유자 역할을 사용하여 쿼리를 실행하기 때문에 대시보드에는 엔드포인트에 연결된 최종 사용자에 관계없이 서비스 소유자 역할이 액세스할 수 있는 데이터가 표시됩니다. 결과적으로 대시보드는 최종 사용자에게 액세스 권한이 부여된 데이터로 제한되지 않으므로 로그인한 사용자가 액세스해서는 안 되는 데이터를 볼 수 있습니다.

대시보드에 로그인한 사용자가 액세스할 수 있는 데이터만 표시되도록 제한하려면 애플리케이션 컨테이너가 최종 사용자에게 부여된 권한을 사용하여 SQL을 실행해야 합니다. 애플리케이션에서 호출자 권한을 사용하여 이를 활성화할 수 있습니다.

참고

  • 호출자 권한 기능은 네트워크 수신을 사용하여 서비스에 액세스하는 경우에만 지원됩니다. 서비스 함수를 사용하여 서비스에 액세스할 때는 이 기능을 사용할 수 없습니다.

  • 호출자 권한 함수는 현재 Snowflake Native App (컨테이너를 사용하는 앱)에서는 지원되지 않습니다.

서비스에 대한 호출자의 권한 구성하기

애플리케이션에 대한 호출자 권한 구성은 2단계의 프로시저로 이루어집니다.

  1. 다음 사양 조각에 표시된 대로 :doc:`서비스 사양</developer-guide/snowpark-container-services/specification-reference>`에서 ``executeAsCaller``를 ``true``로 설정합니다.

    spec:
      containers:
      ...
    capabilities:
      securityContext:
        executeAsCaller: true
    
    Copy

    이러한 설정을 통해 애플리케이션이 호출자의 권한을 사용하려는 의도를 Snowflake에 알리고 애플리케이션 컨테이너로 요청을 보내기 전에 수신되는 모든 요청에 Sf-Context-Current-User-Token 헤더를 삽입하게 됩니다. 이 사용자 토큰은 호출 사용자로서 쿼리 실행을 용이하게 합니다. 지정하지 않으면 executeAsCaller 기본값은 false 입니다.

    executeAsCaller 옵션을 지정해도 서비스 사용자 및 서비스 소유자 역할로서 쿼리를 실행하는 서비스 기능에는 영향을 미치지 않습니다. executeAsCaller 를 활성화하면 호출 사용자 및 서비스 사용자로 Snowflake에 연결할 수 있습니다.

  2. 호출하는 사용자를 대신하여 Snowflake 연결을 설정하려면 애플리케이션 코드를 업데이트하여 Snowflake가 서비스에 제공한 OAuth 토큰Sf-Context-Current-User-Token 헤더의 사용자 토큰을 모두 포함하는 로그인 토큰을 생성합니다.

    로그인 토큰은 <service-oauth-token>.<Sf-Context-Current-User-Token> 형식을 따라야 합니다.

    이 업데이트는 다음 Python 코드 조각에서 확인할 수 있습니다.

    # Environment variables below will be automatically populated by Snowflake.
    SNOWFLAKE_ACCOUNT = os.getenv("SNOWFLAKE_ACCOUNT")
    SNOWFLAKE_HOST = os.getenv("SNOWFLAKE_HOST")
    
    def get_login_token():
        with open("/snowflake/session/token", "r") as f:
            return f.read()
    
    def get_connection_params(ingress_user_token = None):
        # start a Snowflake session as ingress user
        # (if user token header provided)
        if ingress_user_token:
            logger.info("Creating a session on behalf of the current user.")
            token = get_login_token() + "." + ingress_user_token
        else:
            logger.info("Creating a session as the service user.")
            token = get_login_token()
    
        return {
            "account": SNOWFLAKE_ACCOUNT,
            "host": SNOWFLAKE_HOST,
            "authenticator": "oauth",
            "token": token
        }
    
    def run_query(request, query):
        ingress_user_token = request.headers.get('Sf-Context-Current-User-Token')
        # ingress_user_token is None if header not present
        connection_params = get_connection_params(ingress_user_token)
        with Session.builder.configs(connection_params).create() as session:
          # use the session to execute a query.
    
    Copy

위의 예에서:

  • get_login_token 함수는 컨테이너가 사용할 OAuth 토큰을 Snowflake가 복사한 파일을 읽습니다.

  • get_connection_params 함수는 OAuth 토큰과 Sf-Context-Current-User-Token 헤더의 사용자 토큰을 연결하여 토큰을 생성합니다. 이 함수는 애플리케이션이 Snowflake에 연결하는 데 사용하는 매개 변수 사전에 이 토큰을 포함합니다.

참고

서비스가 호출자 권한을 사용하는 경우 여러 사용자로 Snowflake에 연결할 수 있습니다. Snowflake에서 관리하지 않는 리소스에 대한 액세스 권한 관리는 사용자 본인의 책임입니다.

예를 들어, Streamlit 앱에서 st.connection 오브젝트는 전역 상태에서 ``st.cache_resource``를 통해 연결을 자동으로 캐시하므로 다른 사용자가 시작한 Streamlit 세션에서 액세스할 수 있습니다. 호출자 권한을 사용하는 경우에는 사용자 간의 연결 공유를 방지하기 위해 ``st.session_state``를 사용하여 세션별로 연결을 저장하는 것이 좋습니다.

단계별 지침이 포함된 예는 호출자 권한이 활성화된 서비스 만들기 섹션을 참조하십시오.

호출자 권한이 구성된 서비스 액세스하기

*호출자의 권한 구성*은 서비스가 호출자를 대신하여 Snowflake 연결을 설정하는 것입니다. 서비스 수신 엔드포인트에 로그인하는 방법(프로그래밍 방식 또는 브라우저 사용)은 동일하게 유지됩니다. 로그인하면 다음 동작과 옵션이 적용됩니다.

  • 브라우저를 사용하여 공용 엔드포인트에 액세스하기: 엔드포인트에 로그인하면 서비스가** 사용자의 기본 역할을 사용하여 호출하는 사용자를 대신해 Snowflake에 연결을 설정합니다. 사용자에 대해 구성된 기본 역할이 없는 경우 PUBLIC 역할이 사용됩니다.

  • 프로그래밍 방식으로 공용 엔드포인트에 액세스하기: JWT 토큰을 사용하여 프로그래밍 방식으로 엔드포인트에 로그인<label-oauth_token_exchange>`하는 경우 선택적으로 ``scope` 매개 변수를 설정하여 활성화할 역할을 지정할 수 있습니다.

현재 서비스가 호출자를 대신하여 Snowflake에 대한 호출자의 올바른 연결을 설정한 후에는 역할 전환이 지원되지 않습니다. 애플리케이션에서 다른 역할을 사용하여 다른 오브젝트에 액세스해야 하는 경우 사용자의 기본 보조 역할 속성을 변경해야 합니다.

  • 기본적으로 모든 보조 역할이 활성화되도록 사용자를 설정하려면 ALTER USER 명령을 사용하여 다음 예제와 같이 사용자의 DEFAULT_SECONDARY_ROLES 속성을 (‘ALL’)로 설정합니다.

ALTER USER my_user SET DEFAULT_SECONDARY_ROLES = ( 'ALL' );
Copy

서비스에 대한 호출자 권한 관리하기

서비스에서 호출자 권한 세션을 만들면 세션은 서비스 사용자가 아닌 호출하는 사용자로 작업합니다. 이 세션을 사용하여 작업을 수행하면 Snowflake는 두 가지 권한 검사 시퀀스를 적용합니다.

  1. 첫 번째 권한 검사는 사용자가 세션을 직접 생성한 것처럼 수행됩니다. 이 검사는 Snowflake가 사용자에 대해 수행하는 일반적인 권한 검사의 일부입니다.

  2. 두 번째 권한 검사는 서비스가 사용자를 대신하여 작업을 수행할 수 있는지 확인합니다. Snowflake는 서비스 소유자 역할에 필요한 호출자 권한이 부여되었는지 확인하여 이를 검증합니다.

호출자 권한 세션에서 일반 권한 확인과 서비스 소유자 역할의 호출자 권한 부여 확인 모두 작업을 허용해야 하며, 이를 제한된 호출자 권한 이라고 합니다. 기본적으로 서비스에는 사용자를 대신하여 어떤 작업도 수행할 수 있는 권한이 없습니다. 서비스가 호출자의 권한으로 실행될 수 있도록 서비스에 명시적으로 호출자 권한을 부여해야 합니다.

예를 들어 U1 사용자가 테이블 T1``에 대해 SELECT 권한이 있는 ``R1 역할을 사용한다고 가정해 보겠습니다. U1 이 호출자의 권한을 사용하도록 구성된 서비스 엔드포인트(example_service)에 로그인을 하면, 서비스는 U1 을 대신하여 Snowflake와 연결을 설정합니다.

서비스가 U1 대신 테이블 T1 을 쿼리할 수 있도록 하려면 서비스의 소유자 역할에 다음 권한을 부여해야 합니다.

  • 해당 테이블의 데이터베이스 및 스키마에 대해 USAGE 권한으로 서비스를 실행할 수 있는 호출자 권한을 부여하여 테이블의 이름을 확인할 수 있는 권한.

  • 웨어하우스에서 USAGE 권한으로 서비스를 실행할 수 있는 호출자 권한을 부여하여 웨어하우스를 사용하여 쿼리를 실행할 수 있는 권한.

  • 테이블 T1 에 대해 SELECT 권한으로 서비스를 실행할 수 있는 호출자 권한을 부여하여 테이블을 쿼리할 수 있는 권한.

다음 예제에서는 이러한 권한으로 서비스의 소유자 역할을 부여하는 방법을 보여줍니다.

-- Permissions to resolve the table's name.
GRANT CALLER USAGE ON DATABASE <db_name> TO ROLE <service_owner_role>;
GRANT CALLER USAGE ON SCHEMA <schema_name> TO ROLE <service_owner_role>;
-- Permissions to use a warehouse
GRANT CALLER USAGE ON WAREHOUSE <warehouse_name> TO ROLE <service_owner_role>;
-- Permissions to query the table.
GRANT CALLER SELECT ON TABLE T1 TO ROLE <service_owner_role>;
Copy

전역 MANAGE CALLER GRANT 권한이 있는 계정의 모든 역할은 호출자 권한을 부여할 수 있습니다. 호출자 권한 부여에 대한 자세한 내용은 GRANT CALLER제한된 호출자의 권한 섹션을 참조하십시오.

사용자를 대신하여 SQL 쿼리를 실행할 때 호출자의 권한 함수를 사용하는 서비스의 예제가 제공됩니다. 자세한 내용은 호출자 권한이 활성화된 서비스 만들기 섹션을 참조하십시오.

다른 자격 증명을 사용하여 Snowflake에 연결하기

Snowflake에서 제공하는 OAuth 토큰뿐만 아니라 다른 형식의 인증을 사용하여 Snowflake에 연결할 수 있습니다. 이를 수행하려면 컨테이너가 Snowflake 외부에서 실행 중이고 인터넷을 통해 연결되는 것처럼 Snowflake에 연결할 수 있도록 지원하는 외부 액세스 통합(EAI)을 생성합니다. 이 방법으로 연결하면 클라이언트에서 사용하는 호스트를 구성할 필요가 없습니다.

참고

이러한 연결은 EAI를 통과하므로 Snowflake 인증은 네트워크 정책도 적용합니다. 비즈니스에 네트워크 정책이 필요한 경우 다른 자격 증명을 사용한 연결은 지원되지 않습니다.

예를 들어, 다음 연결에서는 인증할 사용자 이름과 비밀번호를 지정합니다.

conn = snowflake.connector.connect(
  account = '<acct-name>',
  user = '<user-name>',
  password = '<password>'
)
Copy

기본 호스트 이름을 사용하려면 서비스에서 계정의 Snowflake 인터넷 호스트 이름에 액세스할 수 있는 네트워크 규칙을 사용하는 외부 액세스 통합이 필요합니다. 예를 들어, 계정 이름이 조직의 인 경우 호스트 이름은 입니다. 자세한 내용은 섹션을 참조하세요. 예를 들어, 기관 ``MYORG``에서 계정 이름이 ``MYACCOUNT``인 경우 호스트 이름은 ``myorg-myaccount.snowflakecomputing.com``입니다. 자세한 내용은 네트워크 송신 구성하기 섹션을 참조하십시오. Privatelink 호스트 이름은 지원되지 않습니다.

  • 계정의 Snowflake API 호스트 이름과 일치하는 네트워크 규칙을 만듭니다.

    CREATE OR REPLACE NETWORK RULE snowflake_egress_access
      MODE = EGRESS
      TYPE = HOST_PORT
      VALUE_LIST = ('myorg-myaccount.snowflakecomputing.com');
    
    Copy
  • 이전 네트워크 규칙을 사용하는 통합을 만듭니다.

    CREATE EXTERNAL ACCESS INTEGRATION snowflake_egress_access_integration
      ALLOWED_NETWORK_RULES = (snowflake_egress_access)
      ENABLED = TRUE;
    
    Copy

SQL 실행을 위한 데이터베이스 및 스키마 컨텍스트 구성하기

Snowflake는 자격 증명을 제공할 뿐만 아니라 서비스가 생성되는 데이터베이스 및 스키마 컨텍스트도 제공합니다. 컨테이너 코드는 이 정보를 사용하여 서비스와 동일한 데이터베이스 및 스키마 컨텍스트의 SQL을 실행합니다.

이 섹션에서는 다음 두 가지 개념을 설명합니다.

  • Snowflake가 서비스를 생성할 데이터베이스와 스키마를 결정하는 데 사용하는 논리.

  • Snowflake가 이 정보를 컨테이너에 전달하여 컨테이너 코드가 동일한 데이터베이스 및 스키마 컨텍스트에서 SQL을 실행할 수 있도록 지원하는 방법.

Snowflake는 서비스 이름을 사용하여 서비스를 생성할 데이터베이스와 스키마를 결정합니다.

  • 예 1: 다음 CREATE SERVICE 및 EXECUTE JOB SERVICE 명령에서는 서비스 이름에 데이터베이스 및 스키마 이름을 명시적으로 지정하지 않습니다. Snowflake는 현재 데이터베이스와 스키마에서 서비스와 작업 서비스를 생성합니다.

    -- Create a service.
    CREATE SERVICE test_service IN COMPUTE POOL ...
    
    -- Execute a job service.
    EXECUTE JOB SERVICE
      IN COMPUTE POOL tutorial_compute_pool
      NAME = example_job_service ...
    
    Copy
  • 예 2: 다음 CREATE SERVICE 및 EXECUTE JOB SERVICE 명령에서 서비스 이름에는 데이터베이스 및 스키마 이름이 포함됩니다. Snowflake는 현재 스키마에 관계없이 지정된 데이터베이스(test_db)와 스키마(test_schema)에서 서비스와 작업 서비스를 생성합니다.

    -- Create a service.
    CREATE SERVICE test_db.test_schema.test_service IN COMPUTE POOL ...
    
    -- Execute a job service.
    EXECUTE JOB SERVICE
      IN COMPUTE POOL tutorial_compute_pool
      NAME = test_db.test_schema.example_job_service ...
    
    Copy

Snowflake는 서비스를 시작할 때 다음 환경 변수를 사용하여 실행 중인 컨테이너에 데이터베이스 및 스키마 정보를 제공합니다.

  • SNOWFLAKE_DATABASE

  • SNOWFLAKE_SCHEMA

컨테이너 코드는 다음 예제와 같이 연결 코드에 환경 변수를 사용하여 사용할 데이터베이스와 스키마를 결정할 수 있습니다.

conn = snowflake.connector.connect(
  host = os.getenv('SNOWFLAKE_HOST'),
  account = os.getenv('SNOWFLAKE_ACCOUNT'),
  token = get_login_token(),
  authenticator = 'oauth',
  database = os.getenv('SNOWFLAKE_DATABASE'),
  schema = os.getenv('SNOWFLAKE_SCHEMA')
)
Copy

자습서 2 에서는 Snowflake와 연결하고 SQL 문을 실행하는 Snowflake 작업 서비스를 만듭니다. 다음 단계에서는 자습서 코드가 환경 변수를 사용하는 방법을 요약합니다.

  1. 공통 설정(공통 설정 섹션 참조)에서는 데이터베이스와 스키마를 포함한 리소스를 만듭니다. 또한 세션에 대한 현재 데이터베이스와 스키마를 설정합니다.

    USE DATABASE tutorial_db;
    ...
    USE SCHEMA data_schema;
    
    Copy
  2. 작업 서비스를 생성(EXECUTE JOB SERVICE를 실행하여)한 후 Snowflake는 컨테이너를 시작하고 컨테이너에서 다음 환경 변수를 세션의 현재 데이터베이스 및 스키마로 설정합니다.

    • SNOWFLAKE_DATABASE가 “TUTORIAL_DB”로 설정됨

    • SNOWFLAKE_SCHEMA가 “DATA_SCHEMA”로 설정됨

  3. 작업 코드(자습서 2의 main.py 참조)는 다음 환경 변수를 읽습니다.

    SNOWFLAKE_DATABASE = os.getenv('SNOWFLAKE_DATABASE')
    SNOWFLAKE_SCHEMA = os.getenv('SNOWFLAKE_SCHEMA')
    
    Copy
  4. 작업 코드는 데이터베이스와 스키마를 SQL 문을 실행할 컨텍스트로 설정합니다(main.pyrun_job() 함수).

    {
       "account": SNOWFLAKE_ACCOUNT,
       "host": SNOWFLAKE_HOST,
       "authenticator": "oauth",
       "token": get_login_token(),
       "warehouse": SNOWFLAKE_WAREHOUSE,
       "database": SNOWFLAKE_DATABASE,
       "schema": SNOWFLAKE_SCHEMA
    }
    ...
    
    Copy

    참고

    SNOWFLAKE_ACCOUNT, SNOWFLAKE_HOST, SNOWFLAKE_DATABASE, SNOWFLAKE_SCHEMA는 Snowflake가 애플리케이션 컨테이너에 대해 생성하는 환경 변수이지만 SNOWFLAKE_WAREHOUSE 는 그렇지 않습니다(Snowflake가 웨어하우스 이름을 컨테이너에 전달하지 않으므로 자습서 2 애플리케이션 코드에서 이 변수를 생성함).

컨테이너용 웨어하우스 지정하기

서비스가 Snowflake에 연결하여 Snowflake 웨어하우스에서 쿼리를 실행하는 경우 웨어하우스를 지정하는 다음 옵션이 있습니다.

  • 애플리케이션 코드에서 웨어하우스를 지정합니다. 코드에서 쿼리를 실행하려면 Snowflake 세션을 시작할 때 연결 구성의 일부로 웨어하우스를 지정하십시오. 예를 보려면 자습서 2 를 참조하십시오.

  • 서비스 생성 시 기본 웨어하우스를 지정합니다. 기본 웨어하우스를 제공하려면 CREATE SERVICE 명령 또는 EXECUTE JOB SERVICE 명령에 선택적 QUERY_WAREHOUSE 매개 변수를 지정합니다. 애플리케이션 코드가 연결 구성의 일부로 웨어하우스를 제공하지 않는 경우 Snowflake는 기본 웨어하우스를 사용합니다. ALTER SERVICE 명령을 사용하여 기본 웨어하우스를 변경합니다.

    참고

    QUERY_WAREHOUSE 매개 변수를 사용하여 지정된 웨어하우스는 :doc:`서비스 사용자</developer-guide/snowpark-container-services/spcs-execute-sql>`의 경우에만 기본값입니다 서비스가 다른 사용자를 대신하여 Snowflake에 연결하는 경우 :ref:`호출자 권한 시나리오<label-spcs_additional_considerations_configuring_callers_rights>`의 컨텍스트에서 Snowflake는 사용자의 기본 웨어하우스를 사용합니다.

두 가지 방법을 모두 사용하여 웨어하우스를 지정하는 경우 애플리케이션 코드에 지정된 웨어하우스가 사용됩니다.

서비스 사용자 쿼리 기록에 액세스하기

``user_type``이 SNOWFLAKE_SERVICE인 경우 QUERY_HISTORY 뷰 또는 QUERY_HISTORY 함수를 필터링하여 서비스 사용자로 서비스에서 실행된 쿼리를 찾을 수 있습니다.

예 1: 서비스에서 실행되는 쿼리를 가져옵니다.

SELECT *
FROM snowflake.account_usage.query_history
WHERE user_type = 'SNOWFLAKE_SERVICE'
AND user_name = '<service_name>'
AND user_database_name = '<service_db_name>'
AND user_schema_name = '<service_schema_name>'
order by start_time;
Copy

WHERE 절에서:

  • user_name = '<service_name>': 서비스가 :doc:`서비스 사용자</developer-guide/snowpark-container-services/spcs-execute-sql>`로 쿼리를 실행하므로 서비스 이름을 사용자 이름으로 지정하고, 서비스 사용자 이름은 서비스 이름과 동일합니다.

  • user_type = 'SNOWFLAKE_SERVICE'user_name = '<서비스_이름>': 서비스에서 실행된 쿼리만 검색되도록 쿼리 결과를 제한합니다.

  • user_database_nameuser_schema_name: 서비스 사용자의 경우 서비스의 데이터베이스와 스키마입니다.

QUERY_HISTORY 함수를 호출하여 동일한 결과를 얻을 수 있습니다.

SELECT *
FROM TABLE(<service_db_name>.information_schema.query_history())
WHERE user_database_name = '<service_db_name>'
AND user_schema_name = '<service_schema_name>'
AND user_type = 'SNOWFLAKE_SERVICE'
AND user_name = '<service_name>'
order by start_time;
Copy

WHERE 절에서:

  • user_type = 'SNOWFLAKE_SERVICE'user_name = '<서비스_이름>' 은 쿼리 결과를 서비스에서 실행된 쿼리만 검색하도록 제한합니다.

  • user_database_nameuser_schema_name 이름은 (서비스 사용자에 대한) 서비스의 데이터베이스 및 스키마입니다.

예 2: 서비스에서 실행되는 쿼리 및 해당 서비스 정보를 가져옵니다.

SELECT query_history.*, services.*
FROM snowflake.account_usage.query_history
JOIN snowflake.account_usage.services
ON query_history.user_name = services.service_name
AND query_history.user_schema_id = services.service_schema_id
AND query_history.user_type = 'SNOWFLAKE_SERVICE'
Copy

쿼리는 QUERY_HISTORY 및 SERVICES 뷰를 결합하여 쿼리를 실행한 쿼리 및 서비스에 대한 정보를 검색합니다. 다음 사항을 참고하십시오.

  • 서비스에서 실행되는 쿼리의 경우 query_history.user_name 은 서비스 사용자의 이름이며, 이는 서비스 이름과 동일합니다.

  • 스키마를 삭제한 후 다시 생성하면 스키마 ID는 변경되지만 이름은 그대로 유지되므로, 쿼리는 스키마 이름이 아닌 스키마 IDs를 사용하여 뷰를 조인해 동일한 스키마를 참조하도록 합니다.

쿼리에 선택적 필터를 추가할 수 있습니다. 예:

  • 특정 쿼리를 실행한 서비스만 검색하려면 query_history 를 필터링합니다.

  • 특정 서비스에서 실행된 쿼리만 검색하려면 services 를 필터링합니다.

예 3: 모든 서비스에 대해 서비스 사용자 정보를 가져옵니다.

SELECT services.*, users.*
FROM snowflake.account_usage.users
JOIN snowflake.account_usage.services
ON users.name = services.service_name
AND users.schema_id = services.service_schema_id
AND users.type = 'SNOWFLAKE_SERVICE'
Copy

쿼리는 ACCOUNT_USAGE 스키마에서 SERVICES 및 USERS 뷰를 조인하여 서비스 및 서비스 사용자 정보를 검색합니다. 다음 사항을 참고하십시오.

  • 서비스가 쿼리를 실행할 때 서비스 사용자 권한으로 쿼리를 실행하고 서비스 사용자의 이름은 서비스 이름과 동일합니다. 따라서 조인 조건 users.name = services.service_name 을 지정합니다.

  • 서비스 이름은 스키마 내에서만 고유합니다. 따라서 쿼리는 각 서비스 사용자가 속한 특정 서비스(다른 스키마에서 실행되는 다른 동일한 이름의 서비스가 아닌)에 대해 일치하도록 조인 조건(users.schema_id = services.service_schema_id)을 지정합니다.