조인 정책

조인 정책 (Join policies)

조인 정책(join policy)은 테이블이 쿼리될 때 조인이 요구되는지 여부를 제어하는 스키마 수준의 객체예요. 조인 정책이 테이블에 적용되면 해당 테이블에 대한 쿼리는 조인을 요구하거나 요구하지 않아요. 조인이 요구되는 경우 특정 조인 컬럼으로 제한할 수 있어요.

이런 종류의 정책을 사용해 특정 테이블과 뷰에 대한 쿼리에서 조인을 강제할 수 있어요. 이는 공유 테이블 간의 공통 정보를 찾는 수단이 돼요. 조인 정책이 할당된 테이블이나 뷰를 **보호(protected)**되었거나 **조인 제한(join-constrained)**되었다고 말해요.

출처: Join policies

본문

개요

Snowflake의 핵심 기능은 데이터 세트를 다른 엔티티와 공유하는 능력이에요. 조인 정책은 제공자(데이터 소유자)가 데이터를 소비자에게 공유한 후에도 데이터로 무엇을 할 수 있는지 제어할 수 있게 해줘요. 구체적으로 제공자는 테이블 소비자가 단일 테이블에서 레코드를 검색하는 대신 데이터를 다른 테이블에 조인하도록 요구할 수 있어요. 이 요구사항은 공통 데이터 세트를 가진 반신뢰(semi-trusted) 파트너 간 데이터 공유를 용이하게 해요. 단일 테이블에서의 데이터 선택은 일반적으로 유용하지 않아요. 한 소유자의 테이블이 소비자나 파트너가 소유한 유사한 테이블과 조인될 때 의미 있는 데이터가 제공돼요.

조인 정책이 테이블이나 뷰에 적용된 후 쿼리는 다음을 해야 해요:

  • 테이블이나 뷰를 다른 테이블이나 뷰에 조인할 것.
  • 지원되는 조인 유형을 지정할 것.
  • 허용된 조인 컬럼으로 조인 조건을 지정할 것.

조인에 참여하는 테이블이나 뷰 중 하나 이상은 보호되지 않아야 해요. 이 제한은 공격자가 같은 조직이 공유하고 일치하는 키 값을 가진 두 개의 보호된 테이블을 조인해 조인 정책을 우회하는 것을 방지해요.

조인 정책이 조인된 테이블에 대한 액세스를 제어하지만, 악의적인 행위자가 신중하게 구성된 쿼리로 조인 제한 테이블에서 민감 데이터를 얻지 못한다는 것을 보장하지는 않아요. 충분한 쿼리 시도를 통해 악의적인 행위자가 조인 요구사항을 우회할 가능성이 있어요. 조인 정책은 기존 신뢰 수준이 있는 파트너와 고객과 사용하기에 가장 적합해요. 또한 제공자는 데이터의 잠재적 오용(예: 리스팅에 대한 액세스 이력 검토)에 대해 경계해야 해요.

조인 정책 생성 및 구현

조인 정책을 생성하고 구현하려면:

  • 정책 자체를 생성.
  • 정책을 신규 또는 기존 테이블이나 뷰에 적용.
  • 몇 가지 쿼리를 실행해 정책의 예상 동작을 검증.

이 단계들은 다음 섹션에서 설명돼요. 기존 정책을 수정하고 예상 동작이 변경되는지 확인하고 싶을 수도 있어요.

언제든지 SHOW JOIN POLICIES와 DESCRIBE JOIN POLICY 명령으로 계정의 조인 정책을 볼 수 있어요. 정책의 실제 정의를 보려면 JOIN_POLICIES 뷰를 쿼리하세요. 어떤 테이블과 뷰가 정책에 연결되어 있는지 보려면 POLICY_REFERENCES Information Schema 테이블 함수를 쿼리하세요.

정책 관리에 대한 내용(커스텀 정책 관리 역할 설정 포함)은 조인 정책 관리를 참고하세요.

조인 정책 생성

조인 정책의 가장 단순한 형태는 사용자가 항상 테이블이나 뷰를 다른 테이블이나 뷰에 조인하도록 요구해요. 즉 조인 지정 없이 단일 테이블에 대한 쿼리는 허용되지 않아요. 예를 들어 jp1이라는 정책을 만드세요:

CREATE JOIN POLICY jp1
  AS () RETURNS JOIN_CONSTRAINT -> JOIN_CONSTRAINT(JOIN_REQUIRED => TRUE);

이 명령의 전체 구문과 JOIN_CONSTRAINT 함수에 대해서는 CREATE JOIN POLICY를 참고하세요.

조인 정책을 테이블이나 뷰에 적용

조인 정책을 만든 후 특정 테이블이나 뷰에 할당해 구현해요:

  • 테이블이나 뷰가 이미 존재하면 ALTER TABLE 또는 ALTER VIEW 명령을 사용.
  • 새 테이블이나 뷰라면 CREATE TABLE 또는 CREATE VIEW 명령을 사용.

두 경우 모두 JOIN POLICY 파라미터를 지정해 조인 정책을 식별해요. 예를 들어 다음 명령은 jp 정책을 join_table 테이블에 할당해요:

CREATE OR REPLACE TABLE join_table (
  col1 INT,
  col2 VARCHAR,
  col3 NUMBER )
  JOIN POLICY jp1;

선택적으로 특정 조인 컬럼만 사용하도록 조인을 제한하려면 ALLOWED JOIN KEYS 파라미터도 지정할 수 있어요. 특정 컬럼에 대한 조인 제한을 참고하세요.

테이블이나 뷰는 주어진 시점에 하나의 조인 정책만 할당받을 수 있어요. 조인 정책 교체를 참고하세요.

몇 가지 쿼리로 조인 정책 테스트

다음 쿼리들은 jp1 정책이 join_table 테이블에 적용된 상태의 예상 동작을 보여줘요. 이 테이블은 로드할 필요가 없어요. 빈 테이블로도 예상 동작을 보여주기에 충분해요.

조인이 없는 쿼리는 예상대로 오류를 반환해요:

SELECT * FROM join_table;
506037 (23001): SQL compilation error: Join Policy violation, please contact the policy admin for details

col1에 대한 명시적 inner join이 있는 쿼리는 결과를 반환해요:

SELECT * FROM join_table jt1 INNER JOIN join_table_2 jt2 ON jt1.col1=jt2.col1;
+------+------+------+------+------+------+
| COL1 | COL2 | COL3 | COL1 | COL2 | COL3 |
|------+------+------+------+------+------|
+------+------+------+------+------+------+

col2에 대한 명시적 inner join이 있는 쿼리도 결과를 반환해요:

SELECT * FROM join_table jt1 INNER JOIN join_table_2 jt2 ON jt1.col2=jt2.col2;
+------+------+------+------+------+------+
| COL1 | COL2 | COL3 | COL1 | COL2 | COL3 |
|------+------+------+------+------+------|
+------+------+------+------+------+------+

특정 컬럼에 대한 조인 제한

조인 정책 동작을 더 테스트하려면 테이블에서 정책을 분리(unset)하고, 조인 정책을 드롭·재생성한 다음 ALLOWED JOIN KEYS 파라미터를 포함한 DDL로 join_table을 재생성하세요:

ALTER TABLE join_table UNSET JOIN POLICY;

DROP JOIN POLICY jp1;

CREATE JOIN POLICY jp1
  AS () RETURNS JOIN_CONSTRAINT -> JOIN_CONSTRAINT(JOIN_REQUIRED => TRUE);

CREATE OR REPLACE TABLE join_table (
  col1 INT,
  col2 VARCHAR,
  col3 NUMBER )
  JOIN POLICY jp1 ALLOWED JOIN KEYS (col1);

이제 이전 쿼리 중 하나를 조인 컬럼으로 col2를 사용해 다시 시도해 보세요. col2가 허용된 조인 키가 아니므로 쿼리가 실패해요:

SELECT * FROM join_table jt1 INNER JOIN join_table_2 jt2 ON jt1.col2=jt2.col2;
506038 (23001): SQL compilation error: Join Policy violation, invalid join condition with reason: Disallowed join key used.

조인 조건으로 jt1.col1=jt2.col1을 사용한 같은 쿼리는 성공해요. 이 두 테이블의 자연 조인은 col1과 col2 모두에 대해 조인하려 하기 때문에 실패해요.

조인 정책 표시 및 설명

SHOW JOIN POLICIES와 DESCRIBE JOIN POLICY 명령으로 계정의 기존 조인 정책에 대한 기본 정보를 얻을 수 있어요. 더 자세한 조인 정책 정보를 얻으려면 조인 정책 모니터링을 참고하세요.

SHOW JOIN POLICIES;
+-------------------------------+------+---------------+----------------+-------------+--------------+---------+-----------------+---------+
| created_on                    | name | database_name | schema_name    | kind        | owner        | comment | owner_role_type | options |
|-------------------------------+------+---------------+----------------+-------------+--------------+---------+-----------------+---------|
| 2024-12-04 15:15:49.591 -0800 | JP1  | POLICY1_DB    | POLICY1_SCHEMA | JOIN_POLICY | POLICY1_ROLE |         | ROLE            |         |
+-------------------------------+------+---------------+----------------+-------------+--------------+---------+-----------------+---------+
DESCRIBE JOIN POLICY jp1;
+------+-----------+-----------------+----------------------------------------+
| name | signature | return_type     | body                                   |
|------+-----------+-----------------+----------------------------------------|
| JP1  | ()        | JOIN_CONSTRAINT | JOIN_CONSTRAINT(JOIN_REQUIRED => TRUE) |
+------+-----------+-----------------+----------------------------------------+

조건부 조인 정책 생성 및 적용

정책 관리자는 쿼리를 실행하는 사용자의 역할 같은 요인에 따라 서로 다른 쿼리에 서로 다른 제한이 있도록 조인 정책의 SQL 식을 정의할 수 있어요. 이 전략을 통해 한 사용자는 제한 없이 테이블을 쿼리하고 다른 사용자는 조인을 사용하도록 요구할 수 있어요.

예를 들어 다음 조인 정책은 ACCOUNTADMIN, FINANCE_ROLE, HR_ROLE 역할을 가진 사용자에게 테이블에 대한 무제한 액세스를 주고 다른 모든 사용자에게는 조인을 지정하도록 요구해요:

CREATE JOIN POLICY my_join_policy
  AS () RETURNS JOIN_CONSTRAINT ->
    CASE
      WHEN CURRENT_ROLE() = 'ACCOUNTADMIN'
          OR CURRENT_ROLE() = 'FINANCE_ROLE'
          OR CURRENT_ROLE() = 'HR_ROLE'
        THEN JOIN_CONSTRAINT(JOIN_REQUIRED => FALSE)
      ELSE JOIN_CONSTRAINT(JOIN_REQUIRED => TRUE)
    END;

팁: 조건부 정책에서 CURRENT_ROLE 같은 컨텍스트 함수를 사용할 때 다음 전략을 사용할 수 있어요:

  • 컨텍스트 함수는 문자열을 반환하므로 이들을 사용한 비교는 대소문자를 구분해요. 대소문자 구분 없는 비교를 원한다면 LOWER를 사용해 문자열을 모두 소문자로 변환할 수 있어요.
  • POLICY_CONTEXT 함수는 컨텍스트 함수나 SYS_CONTEXT 속성이 특정 값을 반환할 때 정책 본문이 올바른 값을 반환하는지 평가하는 데 도움을 줘요. POLICY_CONTEXT 함수는 활성화된 역할, 에이전트 유형 같은 하나 이상의 컨텍스트 함수나 SYS_CONTEXT 네임스페이스 속성의 특정 값을 기반으로 쿼리 결과를 시뮬레이션해요.

실행 컨텍스트에 에이전트가 활성 상태일 때 조인 정책에서 IS_AGENT_ACTIVATED를 사용해, 사용자의 역할이 그렇지 않으면 조인 없이 쿼리를 허용하더라도 조인을 요구할 수 있어요. 에이전트가 활성 상태가 아니면 ACCOUNTADMIN 역할이 조인 없이 쿼리할 수 있어요:

CREATE OR REPLACE JOIN POLICY join_when_agent AS ()
  RETURNS JOIN_CONSTRAINT ->
  CASE
    WHEN SYS_CONTEXT('SNOWFLAKE$CURRENT', 'IS_AGENT_ACTIVATED')::BOOLEAN = TRUE
      THEN JOIN_CONSTRAINT(JOIN_REQUIRED => TRUE)
    WHEN CURRENT_ROLE() = 'ACCOUNTADMIN'
      THEN JOIN_CONSTRAINT(JOIN_REQUIRED => FALSE)
    ELSE JOIN_CONSTRAINT(JOIN_REQUIRED => TRUE)
  END;

조인 쿼리 요구사항

조인 제한 테이블이나 뷰에 대한 쿼리는 조인 정책이 적용되기 위해 다음 요구사항을 따라야 해요:

지원되는 조인 유형

조인 제한 테이블에 대해 다음 명시적 조인 유형이 지원돼요:

  • INNER JOIN (선택적 INNER 키워드 사용 가능; JOIN은 필수).
  • LEFT OUTER JOIN 및 RIGHT OUTER JOIN — 조인 제한 테이블이 "반대" 테이블인 경우. 조인 제한 테이블이 첫 번째 또는 "왼쪽" 테이블이면 outer join은 RIGHT OUTER JOIN이어야 해요. 조인 제한 테이블이 두 번째 또는 "오른쪽" 테이블이면 outer join은 LEFT OUTER JOIN이어야 해요.
  • NATURAL JOIN (공통 이름을 가진 컬럼에 대한 inner join).

Inner 및 outer join은 FROM 절 안에서 ON 또는 USING 조인 조건과 함께 명시적으로 지정해야 해요. 이 조인들은 WHERE 절에서는 지정할 수 없어요.

지원되지 않는 조인 유형

다음 조인 유형은 지원되지 않아요:

  • FULL OUTER JOIN
  • ASOF JOIN
  • LATERAL 조인
  • WHERE 절의 암시적 조인
  • 크로스 조인 (데카르트 곱)

여러 조인 제한 테이블이 있는 조인

조인 쿼리의 테이블 둘 다(또는 전부)에 조인 정책이 할당되어 있으면 쿼리는 오류와 함께 실패해요. 두 테이블의 조인에서 하나만 조인 제한일 수 있어요.

UNION, INTERSECT, EXCEPT

  • UNION과 UNION ALL 집합 연산은 조인 제한 테이블에 대한 쿼리에서 지원되지 않아요.
  • INTERSECT 집합 연산은 inner join과 의미상 동일하므로 지원돼요.
  • MINUS와 EXCEPT 집합 연산은 조인 제한 테이블이 연산자의 필터링된 쪽(즉 두 번째 쿼리 블록)에 있을 때만 지원돼요.

데이터 타입 변환

SELECT 문에 데이터 타입 변환 함수를 포함하는 쿼리는 함수의 TRY 버전을 사용해야 해요. 예를 들어 TRY_CAST 함수는 허용되지만 CAST 함수는 금지돼요. 숫자 타입에 대해 다음 데이터 타입 변환 함수가 허용돼요:

  • TRY_CAST
  • TRY_TO_DECFLOAT
  • TRY_TO_DECIMAL
  • TRY_TO_DOUBLE
  • TRY_TO_NUMBER
  • TRY_TO_NUMERIC

조인 제한 테이블에 대한 쿼리의 예상 오류

다음 예제들은 테이블이나 뷰에 조인 정책이 적용되어 있어 쿼리가 실패할 것으로 예상되는 일부 경우를 보여줘요. 배경 정보는 조인 쿼리 요구사항을 참고하세요. 이 쿼리들의 테이블에는 행이 없으므로 쿼리는 빈 결과(성공) 또는 오류(실패)를 반환해요.

조인이 없는 쿼리는 실패

join_table에 조인 정책이 할당되어 있으면 조인이 없는 단순 쿼리는 실패해요. 다음 쿼리는 오류를 반환해요:

SELECT col1, col2 FROM join_table;

WHERE 절 조인은 금지

join_table(별칭 jt1)이 조인 제한 테이블이면 다음 WHERE 절 조인은 오류를 반환해요:

SELECT *
  FROM join_table jt1, join_table_2 jt2
  WHERE jt1.col1=jt2.col1;

Left 및 Right outer join은 테이블 순서에 따라 달라짐

다음 예제들은 outer join의 예상 동작을 보여줘요. 여기서 join_table(별칭 jt1)이 조인 제한 테이블이에요. 첫 번째 쿼리는 오류를 반환해요:

SELECT * FROM join_table jt1
  LEFT OUTER JOIN join_table_2 jt2 ON jt1.col1=jt2.col1;

두 번째 쿼리는 결과를 반환해요:

SELECT * FROM join_table jt1
  RIGHT OUTER JOIN join_table_2 jt2 ON jt1.col1=jt2.col1;

조인 제한 테이블 두 개의 조인은 지원되지 않음

join_table과 join_table_2 둘 다 조인 정책이 할당되어 있으면 다음 조인 쿼리는 오류를 반환해요:

SELECT * FROM join_table jt1 JOIN join_table_2 jt2 ON jt1.col1=jt2.col1;

UNION 집합 연산은 금지되지만 INTERSECT 연산은 허용

이 예제들에서 join_table은 조인 정책이 있지만 join_table_3은 없어요. UNION 쿼리는 실패하지만 유사한 INTERSECT 쿼리는 성공해요.

SELECT * FROM JOIN_TABLE
UNION
SELECT * FROM JOIN_TABLE_3;
SELECT * FROM JOIN_TABLE
INTERSECT
SELECT * FROM JOIN_TABLE_3;

EXCEPT 동작은 쿼리 블록 순서에 따라 달라짐

EXCEPT 동작은 쿼리 블록의 순서에 따라 달라져요. 첫 번째 쿼리는 조인 제한 테이블에서 먼저 선택하므로 오류를 반환해요:

SELECT * FROM JOIN_TABLE
EXCEPT
SELECT * FROM JOIN_TABLE_3;

두 번째 쿼리는 성공해요:

SELECT * FROM JOIN_TABLE_3
EXCEPT
SELECT * FROM JOIN_TABLE;

조인 제한 테이블의 뷰도 보호됨

join_table에 조인 정책 jp1이 할당되었다고 가정하세요. 테이블에 뷰를 만드세요:

CREATE VIEW join_table_view AS
  SELECT * FROM join_table;

이제 조인을 지정하지 않고 뷰를 쿼리해요:

SELECT * FROM join_table_view;

join_table의 정책을 위반하므로 쿼리가 실패해요. 뷰에 대한 쿼리는 조인을 포함해야 해요. 뷰와 함께 조인 정책 동작에 대한 자세한 내용은 뷰 및 구체화된 뷰를 참고하세요.

조인 정책 관리

조인 정책을 수정, 교체, 분리, 설명, 모니터링할 수 있어요. 다음 섹션에서 이러한 관리 작업을 다뤄요.

조인 정책 수정

ALTER JOIN POLICY 명령으로 조인 정책 규칙을 수정할 수 있어요. 정책 이름을 바꾸거나 주석을 변경할 수도 있어요.

조인 정책을 수정하기 전에 DESCRIBE JOIN POLICY 명령이나 GET_DDL 함수를 실행해 정책의 현재 SQL 식을 검토하세요.

예를 들어 다음 명령을 실행해 jp3 조인 정책의 SQL 식을 조인이 필요하지 않도록 업데이트하세요:

ALTER JOIN POLICY jp3 SET BODY -> JOIN_CONSTRAINT(JOIN_REQUIRED => FALSE);

조인 정책 교체

조인 정책을 교체하는 권장 방법은 ALTER TABLE 문에서 FORCE 파라미터를 사용하는 것이에요. 이 방법은 단일 명령으로 기존 정책을 분리하고 새 정책을 할당해요. 이 접근 방식은 보호에 공백이 없도록 기존 정책을 원자적으로 교체할 수 있게 해줘요.

예를 들어 이미 조인 제한된 테이블에 새 조인 정책을 할당하려면:

ALTER TABLE join_table SET JOIN POLICY jp2 FORCE;

한 문에서 테이블이나 뷰에서 정책을 분리(UNSET JOIN POLICY 사용)한 다음 다른 문에서 새 정책을 설정(SET JOIN POLICY 사용)할 수도 있어요. 이 방법을 선택하면 두 작업 사이의 중간 기간에 테이블이 조인 정책으로 보호되지 않아요. 이 기간 동안 쿼리가 잠재적으로 민감 데이터에 접근할 수 있어요.

조인 정책 분리

ALTER TABLE 또는 ALTER VIEW 명령의 UNSET JOIN POLICY 절을 사용해 테이블이나 뷰에서 조인 정책을 분리해요. 객체는 하나 이상의 정책을 가질 수 없으므로 정책 이름은 필요하지 않아요. 예를 들어:

ALTER VIEW join_view UNSET JOIN POLICY;

조인 정책 모니터링

다음 방법으로 조인 정책 사용을 모니터링할 수 있어요:

  • 공유 SNOWFLAKE 데이터베이스의 Account Usage 스키마에 있는 JOIN_POLICIES 뷰를 쿼리. 이 뷰는 Snowflake 계정의 모든 조인 정책에 대한 카탈로그예요.
  • POLICY_REFERENCES Information Schema 테이블 함수를 쿼리해 조인 정책 참조를 식별하고 현재 어떤 테이블과 뷰에 정책이 적용되어 있는지 확인.
조인 정책 정보 얻기

기존 조인 정책에 대한 정보를 얻으려면 공유 SNOWFLAKE 데이터베이스의 Account Usage 스키마에 있는 JOIN_POLICIES 뷰를 쿼리해요. 이 뷰는 계정의 모든 조인 정책에 대한 카탈로그예요. 예를 들어 특정 조인 정책의 정책 본문을 반환할 수 있어요:

SELECT policy_name, policy_body, created
  FROM SNOWFLAKE.ACCOUNT_USAGE.JOIN_POLICIES
  WHERE policy_name='JP2' AND created LIKE '2024-11-26%';
+-------------+----------------------------------------------------------+-------------------------------+
| POLICY_NAME | POLICY_BODY                                              | CREATED                       |
|-------------+----------------------------------------------------------+-------------------------------|
| JP2         | CASE                                                     | 2024-11-26 11:22:54.848 -0800 |
|             |           WHEN CURRENT_ROLE() = 'ACCOUNTADMIN'           |                               |
|             |             THEN JOIN_CONSTRAINT(JOIN_REQUIRED => FALSE) |                               |
|             |           ELSE JOIN_CONSTRAINT(JOIN_REQUIRED => TRUE)    |                               |
|             |         END                                              |                               |
+-------------+----------------------------------------------------------+-------------------------------+
조인 정책에 연결된 테이블과 뷰 정보 얻기

POLICY_REFERENCES Information Schema 테이블 함수는 기존 조인 정책에 연결된 테이블과 뷰에 대한 정보를 반환해요. 두 가지 다른 구문 옵션을 사용할 수 있어요:

  • 지정된 조인 정책이 설정된 각 객체(테이블 또는 뷰)에 대해 행 반환:
USE DATABASE my_db;
USE SCHEMA INFORMATION_SCHEMA;
SELECT
 policy_name,
 policy_kind,
 ref_entity_name,
 ref_entity_domain,
 ref_column_name,
 ref_arg_column_names,
 policy_status
  FROM TABLE(INFORMATION_SCHEMA.POLICY_REFERENCES(policy_name => 'my_db.my_schema.jp1'));
  • join_table에 할당된 정책에 대한 정보 반환:
USE DATABASE my_db;
USE SCHEMA INFORMATION_SCHEMA;
SELECT
 policy_name,
 policy_kind,
 ref_entity_name,
 ref_entity_domain,
 ref_column_name,
 ref_arg_column_names,
 policy_status
  FROM TABLE(INFORMATION_SCHEMA.POLICY_REFERENCES(ref_entity_name => 'my_db.my_schema.join_table', ref_entity_domain => 'table'));
+-------------+-------------+-----------------+-------------------+-----------------+----------------------+---------------+
| POLICY_NAME | POLICY_KIND | REF_ENTITY_NAME | REF_ENTITY_DOMAIN | REF_COLUMN_NAME | REF_ARG_COLUMN_NAMES | POLICY_STATUS |
|-------------+-------------+-----------------+-------------------+-----------------+----------------------+---------------|
| JP1         | JOIN_POLICY | JOIN_TABLE      | TABLE             | NULL            | [ "COL1" ]           | ACTIVE        |
+-------------+-------------+-----------------+-------------------+-----------------+----------------------+---------------+

정책 관리 모범 사례

조인 정책을 만들고 테이블에 정책을 할당하는 것은 마스킹, 프로젝션, 집계 정책 같은 다른 정책을 만들고 할당하는 것과 같은 일반적인 절차를 요구해요:

  • 중앙 집중형 관리 방식을 사용한다면 정책을 관리할 커스텀 역할(예: join_policy_admin)을 만들거나 기존 역할을 사용할 수 있어요.
  • 이 역할에 조인 정책을 만들고 할당할 권한을 부여.
  • 조인 정책 생성.
  • 정책을 테이블에 할당하고 조인 컬럼(ALLOWED JOIN KEYS)을 허용하도록 테이블 생성 또는 변경.
  • 테이블에서 조인 및 비조인 쿼리를 몇 가지 테스트.

테이블에 대한 성공적인 쿼리는 데이터를 다른 테이블이나 뷰에 조인해야 하고 허용된 컬럼에서 조인해야 해요.

액세스 제어 관리자 작업

  • 조인 정책을 관리할 커스텀 역할 생성. 기존 역할을 재사용할 수도 있어요.
USE ROLE USERADMIN;

CREATE ROLE join_policy_admin;
  • join_policy_admin 커스텀 역할에 스키마에서 조인 정책을 만들고 Snowflake 계정의 테이블이나 뷰에 정책을 할당할 권한을 부여. 이 단계는 조인 정책이 privacy.join_policies라는 데이터베이스와 스키마에 저장되고 이 데이터베이스·스키마가 이미 존재한다고 가정해요:
GRANT USAGE ON DATABASE privacy TO ROLE join_policy_admin;
GRANT USAGE ON SCHEMA privacy.join_policies TO ROLE join_policy_admin;

GRANT CREATE JOIN POLICY
  ON SCHEMA privacy.join_policies TO ROLE join_policy_admin;

GRANT APPLY JOIN POLICY ON ACCOUNT TO ROLE join_policy_admin;

이제 join_policy_admin 역할을 하나 이상의 사용자에게 할당할 수 있어요. 조인 정책 작업에 필요한 권한에 대한 내용은 조인 정책 권한을 참고하세요.

조인 정책 관리자 작업

  • 조인 정책 생성:
USE ROLE join_policy_admin;
USE SCHEMA privacy.join_policies;

CREATE OR REPLACE JOIN POLICY jp1
  AS () RETURNS JOIN_CONSTRAINT -> JOIN_CONSTRAINT(JOIN_REQUIRED => TRUE);

조인 정책과 다른 Snowflake 기능의 상호작용

다음 섹션들은 조인 정책이 다른 Snowflake 기능·서비스와 어떻게 상호작용하는지 요약해요.

다른 정책

이 섹션은 조인 정책이 마스킹 정책, 행 액세스 정책, 집계 정책, 프로젝션 정책을 포함한 다른 정책과 어떻게 상호작용하는지 설명해요.

조인 제한 테이블에 다른 정책을 연결할 수 있어요. 테이블에 대한 성공적인 쿼리는 모든 정책의 요구사항을 충족해야 해요.

행 액세스 정책이 조인 제한 테이블에 할당된 경우, 행 액세스 정책에 따라 쿼리 결과에서 제외된 행은 조인 결과 계산에 포함되지 않아요.

마스킹 정책, 행 액세스 정책, 집계 정책, 프로젝션 정책의 본문은 조인 제한 테이블(자신의 컬럼 포함)을 참조할 수 없어요.

뷰 및 구체화된 뷰

뷰와 구체화된 뷰 둘 다에 조인 정책을 할당할 수 있어요. 조인 정책이 뷰에 적용되면 기본 테이블은 조인 제한되지 않아요. 이 기본 테이블은 제한 없이 계속 쿼리할 수 있어요.

조인 제한 테이블에서 뷰를 만들 수 있는지 여부는 뷰 유형에 따라 달라져요:

  • 하나 이상의 조인 제한 테이블에서 일반 뷰를 만들 수 있어요. 하지만 해당 뷰에 대한 쿼리는 기본 테이블의 제한을 충족하는 방식으로 데이터를 조인해야 해요. 테이블에 뷰를 만들어 보호된 테이블의 조인 정책을 우회할 수는 없어요. 테이블의 정책은 뷰에 대한 쿼리에서 존중되고 강제돼요. 예는 조인 제한 테이블의 뷰도 보호됨을 참고하세요.
  • 조인 제한 테이블이나 뷰를 기반으로 구체화된 뷰를 만들 수 없으며, 구체화된 뷰의 기반이 되는 테이블이나 뷰에 조인 정책을 할당할 수도 없어요.

클론된 객체

다음 접근 방식은 클론된 데이터베이스나 스키마에 저장된 클론된 테이블이나 뷰에 대한 SELECT 권한을 가진 사용자로부터 데이터를 보호하는 데 도움을 줘요:

  • 개별 조인 정책 객체의 클로닝은 지원되지 않아요.
  • 데이터베이스 클로닝은 데이터베이스 내의 모든 조인 정책의 클로닝을 초래해요.
  • 스키마 클로닝은 스키마 내의 모든 조인 정책의 클로닝을 초래해요.
  • 클론된 테이블은 소스 테이블과 동일한 조인 정책에 매핑돼요.

테이블이 상위 스키마의 클로닝 맥락에서 클로닝될 때, 소스 테이블이 같은 상위 스키마의 조인 정책(즉 로컬 참조)에 대한 참조를 가지면 클론된 테이블은 클론된 조인 정책에 대한 참조를 갖게 돼요. 소스 테이블이 다른 스키마의 조인 정책(즉 외부 참조)을 참조하면 클론된 테이블은 외부 참조를 유지해요.

자세한 내용은 CREATE <object> … CLONE를 참고하세요.

복제

조인 정책과 그 할당은 데이터베이스 복제와 복제 그룹을 사용해 복제할 수 있어요.

데이터베이스 복제의 경우 다음 조건 중 하나가 참이면 복제 작업이 실패해요:

  • 기본 데이터베이스가 Enterprise(이상) 계정에 있고 정책을 포함하지만 복제 승인된 계정 중 하나 이상이 더 낮은 에디션에 있는 경우.
  • 기본 데이터베이스에 포함된 테이블이나 뷰가 다른 데이터베이스의 정책에 대한 매달린(dangling) 참조를 가진 경우.

복제 그룹에서 여러 데이터베이스를 복제할 때 데이터베이스 복제의 매달린 참조 동작을 피할 수 있어요.

권한 및 명령

다음 하위 섹션은 조인 정책을 관리하는 데 도움이 되는 정보를 제공해요.

조인 정책 권한

Snowflake는 조인 정책 객체에 대해 다음 권한을 지원해요.

스키마의 객체에 대해 작업하려면 상위 데이터베이스에 대한 권한이 하나 이상, 상위 스키마에 대한 권한이 하나 이상 필요해요.

| 권한 | 용도 | | APPLY | 테이블에 조인 정책을 설정·해제하는 연산을 활성화. | | OWNERSHIP | 조인 정책의 소유권을 이전하며 정책에 대한 완전한 제어를 부여. 조인 정책의 대부분 속성을 변경하는 데 필요. |

자세한 내용은 DDL 명령·연산·권한 요약을 참고하세요.

조인 정책 DDL 참조

Snowflake는 조인 정책을 만들고 관리하기 위해 다음 DDL 명령을 지원해요.

  • CREATE JOIN POLICY
  • ALTER JOIN POLICY
  • DESCRIBE JOIN POLICY
  • DROP JOIN POLICY
  • SHOW JOIN POLICIES

DDL 명령·연산·권한 요약

다음 표는 조인 정책 권한과 DDL 연산 간의 관계를 요약해요.

스키마의 객체에 대해 작업하려면 상위 데이터베이스에 대한 권한이 하나 이상, 상위 스키마에 대한 권한이 하나 이상 필요해요.

| 연산 | 필요 권한 | | 조인 정책 생성 | 같은 스키마에서 CREATE JOIN POLICY 권한이 있는 역할. | | 조인 정책 변경 | 조인 정책에 대한 OWNERSHIP 권한이 있는 역할. | | 조인 정책 설명 | 다음 중 하나: 글로벌 APPLY JOIN POLICY 권한이 있는 역할. 조인 정책에 대한 OWNERSHIP 권한이 있는 역할. 조인 정책에 대한 APPLY 권한이 있는 역할. | | 조인 정책 삭제 | 조인 정책에 대한 OWNERSHIP 권한이 있는 역할. | | 조인 정책 표시 | 다음 중 하나: 조인 정책이 있는 스키마에 대한 USAGE 권한이 있는 역할. 계정에 대한 APPLY JOIN POLICY 권한이 있는 역할. | | 테이블에 조인 정책 설정 또는 해제 | 다음 중 하나: 계정에 대한 APPLY JOIN POLICY 권한이 있는 역할. 조인 정책에 대한 APPLY 권한과 테이블 또는 뷰에 대한 OWNERSHIP 권한이 있는 역할. |

Snowflake는 객체에 조인 정책을 만들고 설정하는 서로 다른 권한을 지원해요.

  • join_policy_admin 커스텀 역할이 모든 테이블에 조인 정책을 만들고 설정하는 중앙 집중형 정책 관리 방식에는 다음 권한이 필요해요:
USE ROLE securityadmin;
GRANT USAGE ON DATABASE mydb TO ROLE join_policy_admin;
GRANT USAGE ON SCHEMA mydb.schema TO ROLE join_policy_admin;
GRANT CREATE JOIN POLICY ON SCHEMA mydb.schema TO ROLE join_policy_admin;
GRANT APPLY ON JOIN POLICY ON ACCOUNT TO ROLE join_policy_admin;
  • 하이브리드 관리 방식에서는 단일 역할이 CREATE JOIN POLICY 권한을 가져 조인 정책 이름이 일관되게 지정되도록 하고 개별 팀이나 역할이 특정 조인 정책에 대한 APPLY 권한을 가져요. 예를 들어 커스텀 역할 finance_role에 역할이 소유한(즉 역할이 테이블이나 뷰에 대한 OWNERSHIP 권한을 가진) 테이블과 뷰에 조인 정책 cost_center를 설정할 권한을 부여할 수 있어요:
USE ROLE securityadmin;
GRANT CREATE JOIN POLICY ON SCHEMA mydb.schema TO ROLE join_policy_admin;
GRANT APPLY ON JOIN POLICY cost_center TO ROLE finance_role;

더 알아보기 (Learn more)