

 Amazon Redshift는 패치 198부터 새 Python UDF 생성을 더 이상 지원하지 않습니다. 기존 Python UDF는 2026년 6월 30일까지 계속 작동합니다. 자세한 내용은 [블로그 게시물](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)을 참조하세요.

# 데이터베이스 보안
<a name="r_Database_objects"></a>

어느 사용자가 어느 데이터베이스 객체에 액세스할 수 있는지 제어하여 데이터베이스 보안을 관리합니다. 사용자에게 역할이나 그룹을 할당할 수 있으며 사용자, 역할 또는 그룹에 부여하는 권한에 따라 액세스할 수 있는 데이터베이스 객체가 결정됩니다.

**Topics**
+ [Amazon Redshift 보안 개요](c_security-overview.md)
+ [기본 데이터베이스 사용자 권한](r_Privileges.md)
+ [superuser](r_superusers.md)
+ [사용자](r_Users.md)
+ [그룹](r_Groups.md)
+ [스키마](r_Schemas_and_tables.md)
+ [역할 기반 액세스 제어(RBAC)](t_Roles.md)
+ [행 수준 보안](t_rls.md)
+ [메타데이터 보안](t_metadata_security.md)
+ [동적 데이터 마스킹](t_ddm.md)
+ [범위가 지정된 권한](t_scoped-permissions.md)

데이터베이스 객체에 대한 액세스는 사용자 또는 역할에 부여하는 권한에 따라 달라집니다. 다음 지침은 데이터베이스 보안의 작동 원리를 요약합니다.
+ 기본적으로 객체 소유자에게만 권한이 부여됩니다.
+ Amazon Redshift 데이터베이스 사용자는 데이터베이스에 연결할 수 있는 명명된 사용자입니다. 사용자는 두 가지 방법으로 권한이 부여됩니다. 권한을 계정에 직접 할당하는 명시적인 방법과 권한이 부여되는 그룹의 구성원으로 만드는 묵시적인 방법입니다.
+ 그룹은 보안 유지 관리를 간소화하기 위해 집단적으로 권한이 할당될 수 있는 사용자의 모음입니다.
+ 스키마는 데이터베이스 테이블과 그 밖의 데이터베이스 객체의 모음입니다. 스키마는 중첩될 수 없다는 점만 빼면 파일 시스템 디렉터리와 비슷합니다. 사용자에게 단일 스키마 또는 여러 스키마에 대한 액세스 권한을 부여할 수 있습니다.

또한 Amazon Redshift는 다음 기능을 사용하여 어떤 사용자가 어떤 데이터베이스 객체에 액세스할 수 있는지를 보다 세밀하게 제어할 수 있습니다.
+  역할 기반 액세스 제어(RBAC)를 사용하면 역할에 권한을 할당한 다음 사용자에게 적용할 수 있으므로 대규모 사용자 그룹에 대한 권한을 제어할 수 있습니다. 그룹과 달리 역할은 다른 역할의 권한을 상속할 수 있습니다.

  행 수준 보안(RLS)을 사용하면 선택한 행에 대한 액세스를 제한하는 정책을 정의한 다음 해당 정책을 사용자 또는 그룹에 적용할 수 있습니다.

   동적 데이터 마스킹(DDM)은 쿼리 런타임에 데이터를 변환하여 사용자가 민감한 세부 정보를 노출하지 않고 데이터에 액세스할 수 있도록 하여 데이터를 추가로 보호합니다.

보안 구현의 예는 [사용자 및 그룹 액세스 제어 예](t_user_group_examples.md) 섹션을 참조하세요.

데이터 보호에 대한 자세한 내용은 *Amazon Redshift 관리 가이드*의 [Amazon Redshift의 보안](https://docs.aws.amazon.com/redshift/latest/mgmt/iam-redshift-user-mgmt.html) 섹션을 참조하세요.

# Amazon Redshift 보안 개요
<a name="c_security-overview"></a>



Amazon Redshift 데이터베이스 보안은 다른 Amazon Redshift 보안 유형과 구분됩니다. Amazon Redshift는 이 섹션에서 설명하는 데이터베이스 보안 외에 다음과 같은 보안 관리 기능을 제공합니다.
+  **로그인 자격 증명** - Amazon Redshift AWS 관리 콘솔에 대한 액세스는 AWS 계정 권한에 의해 제어됩니다. 자세한 내용은 [로그인 자격 증명](https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html)을 참조하세요.
+  **액세스 관리** - 특정 Amazon Redshift 리소스에 대한 액세스를 제어하려면 AWS Identity and Access Management(IAM) 계정을 정의합니다. 자세한 내용은 [Amazon Redshift 리소스에 대한 액세스 제어](https://docs.aws.amazon.com/redshift/latest/mgmt/iam-redshift-user-mgmt.html) 섹션을 참조하세요.
+  **클러스터 보안 그룹** - 다른 사용자에게 Amazon Redshift 클러스터에 대한 인바운드 액세스 권한을 부여하려면 클러스터 보안 그룹을 정의하고 클러스터에 연결합니다. 자세한 내용은 [Amazon Redshift 클러스터 보안 그룹](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-security-groups.html) 섹션을 참조하세요.
+  **VPC** - 가상 네트워킹 환경을 사용하여 클러스터에 대한 액세스를 보호하기 위해 Amazon Virtual Private Cloud(VPC)에서 클러스터를 시작할 수 있습니다. 자세한 내용은 [Virtual Private Cloud(VPC)에서 클러스터 관리](https://docs.aws.amazon.com/redshift/latest/mgmt/managing-clusters-vpc.html)를 참조하세요.
+  **클러스터 암호화** - 모든 사용자 생성 테이블에서 데이터를 암호화하기 위해 클러스터를 시작할 때 클러스터 암호화를 활성화할 수 있습니다. 자세한 내용은 [Amazon Redshift 클러스터](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html) 섹션을 참조하세요.
+  **SSL 연결** - SQL 클라이언트와 클러스터 간 연결을 암호화하기 위해 보안 소켓 계층(SSL) 암호화를 사용할 수 있습니다. 자세한 내용은 [SSL을 사용하여 클러스터에 연결](https://docs.aws.amazon.com/redshift/latest/mgmt/connecting-ssl-support.html)을 참조하세요.
+  **로드 데이터 암호화** - Amazon S3에 업로드할 때 테이블 로드 데이터를 암호화하기 위해 서버 측 암호화 또는 클라이언트 측 암호화를 사용할 수 있습니다. 서버 측 암호화된 데이터에서 로드할 때는 Amazon S3가 복호화를 투명하게 처리합니다. 클라이언트 측 암호화된 데이터에서 로드할 때는 Amazon Redshift COPY 명령이 테이블을 로드하면서 데이터를 복호화합니다. 자세한 내용은 [Amazon S3에 암호화된 데이터 업로드](t_uploading-encrypted-data.md) 섹션을 참조하세요.
+ **전송 중인 데이터** - AWS 클라우드 내에서 전송 중인 데이터를 보호하기 위해 Amazon Redshift는 COPY, UNLOAD, 백업 및 복원 작업을 위해 하드웨어 가속 SSL을 사용하여 Amazon S3 또는 Amazon DynamoDB와 통신합니다.
+ **열 수준 액세스 제어** - Amazon Redshift의 데이터에 대해 열 수준 액세스 제어를 사용하려면 보기 기반 액세스 제어를 구현하거나 다른 시스템을 사용할 필요 없이 열 수준 권한 부여 및 취소 문을 사용합니다.
+ **행 수준 보안 제어** - Amazon Redshift의 데이터에 대한 행 수준 보안 제어를 수행하려면 정책에 정의된 행에 대한 액세스를 제한하는 정책을 생성하여 역할 또는 사용자에게 연결합니다.

# 기본 데이터베이스 사용자 권한
<a name="r_Privileges"></a>

데이터베이스 객체를 생성하면 해당 객체의 소유자가 됩니다. 기본적으로 슈퍼 사용자 또는 객체의 소유자만 객체를 쿼리, 수정하거나 객체에 대한 권한을 부여할 수 있습니다. 사용자가 객체를 사용하려면 사용자 또는 해당 사용자를 포함하는 그룹에 필요한 권한을 부여해야 합니다. 데이터베이스 슈퍼 사용자는 데이터베이스 소유자와 동일한 권한을 갖습니다.

Amazon Redshift는 SELECT, INSERT, UPDATE, DELETE, REFERENCES, CREATE, TEMPORARY, USAGE 권한을 지원합니다. 권한마다 연결되는 객체 유형이 다릅니다. Amazon Redshift가 지원하는 데이터베이스 객체 권한에 대해서는 [GRANT](r_GRANT.md) 명령을 참조하세요.

소유자에게만 객체를 수정 또는 삭제할 수 있는 권한이 있습니다.

기본적으로 모든 사용자는 데이터베이스의 PUBLIC 스키마에서 CREATE 및 USAGE 권한을 갖습니다. 사용자가 데이터베이스의 PUBLIC 스키마에 객체를 생성하는 것을 허용하지 않으려면 REVOKE 명령을 사용하여 해당 권한을 제거하세요.

이전에 부여한 권한을 취소하려면 [REVOKE](r_REVOKE.md) 명령을 사용하세요. DROP, GRANT, REVOKE 권한 등 객체 소유자의 권한은 묵시적이며 부여하거나 취소할 수 없습니다. 객체 소유자는 본인의 일반적 권한을 취소하여 예컨대 테이블을 본인 및 다른 사용자에게 읽기 전용으로 만들 수 있습니다. 슈퍼 사용자는 GRANT 및 REVOKE 명령과 상관없이 모든 권한을 보유합니다.

# 슈퍼 사용자
<a name="r_superusers"></a>

<a name="def_superusers"></a>데이터베이스 슈퍼 사용자는 모든 데이터베이스에 대해 데이터베이스 소유자와 동일한 권한을 갖습니다.

클러스터를 시작할 때 생성한 사용자인 *관리자*는 슈퍼 사용자입니다.

슈퍼 사용자만이 슈퍼 사용자를 만들 수 있습니다.

Amazon Redshift 시스템 테이블과 시스템 뷰는 슈퍼 사용자에게만 표시되거나 모든 사용자에게 표시됩니다. "슈퍼 사용자에게 보임"으로 지정된 시스템 테이블 및 시스템 보기는 슈퍼 사용자만이 쿼리할 수 있습니다. 자세한 내용은 [SYS 모니터링 뷰](serverless_views-monitoring.md) 섹션을 참조하세요.

슈퍼 사용자는 모든 카탈로그 테이블을 볼 수 있습니다. 자세한 내용은 [시스템 카탈로그 테이블](c_intro_catalog_views.md) 섹션을 참조하세요.

데이터베이스 슈퍼 사용자는 모든 권한 검사를 우회합니다. 슈퍼 사용자는 GRANT 및 REVOKE 명령과 상관없이 모든 권한을 보유합니다. 슈퍼 사용자 역할을 사용할 때는 주의하세요. 대부분의 작업은 슈퍼 사용자가 아닌 역할로 수행하는 것이 좋습니다. 보다 제한적인 권한이 있는 관리자 역할을 만들 수 있습니다. 역할 생성에 대한 자세한 내용은 [역할 기반 액세스 제어(RBAC)](t_Roles.md) 섹션을 참조하세요.

새 데이터베이스 슈퍼 사용자를 만들려면 슈퍼 사용자로 데이터베이스에 로그온하고 CREATEUSER 권한을 사용하여 CREATE USER 명령이나 ALTER USER 명령을 실행합니다.

```
CREATE USER adminuser CREATEUSER PASSWORD '1234Admin';
ALTER USER adminuser CREATEUSER;
```

슈퍼 사용자를 생성, 변경 또는 삭제하려면 동일한 명령을 사용하여 사용자를 관리합니다. 자세한 내용은 [사용자 생성, 변경 및 삭제](r_Users-creatingaltering-and-deleting-users.md) 섹션을 참조하세요.

# 사용자
<a name="r_Users"></a>

Amazon Redshift SQL 명령 CREATE USER 및 ALTER USER 명령을 사용하여 데이터베이스 사용자를 만들고 관리할 수 있습니다. 또는 사용자 정의 Amazon Redshift JDBC 또는 ODBC 드라이버를 사용하여 SQL 클라이언트를 구성할 수 있습니다. 이들은 데이터베이스 로그온 프로세스의 일환으로 데이터베이스 사용자 및 임시 암호 생성 프로세스를 관리합니다.

드라이버는 AWS Identity and Access Management(IAM) 인증을 바탕으로 데이터베이스 사용자를 인증합니다. 이미 AWS 밖에서 사용자 자격 증명을 관리하고 있는 경우 SAML 2.0을 준수하는 자격 증명 공급자(IdP)를 통해 Amazon Redshift 리소스에 대한 액세스를 관리할 수 있습니다. IAM 역할을 사용해 IdP 및 AWS를 구성하고 페더레이션 사용자가 임시 데이터베이스 자격 증명을 새로 만들고 Amazon Redshift 데이터베이스에 로그온하도록 허용할 수 있습니다. 자세한 내용은 [IAM 인증을 이용한 데이터베이스 사용자 자격 증명 생성](https://docs.aws.amazon.com/redshift/latest/mgmt/generating-user-credentials.html)을 참조하세요.

Amazon Redshift 사용자는 데이터베이스 슈퍼 사용자만 생성하고 삭제할 수 있습니다. 사용자는 Amazon Redshift에 로그온할 때 인증됩니다. 데이터베이스 및 데이터베이스 객체(예: 테이블)를 소유할 수 있습니다. 또한 이러한 객체에 대한 권한을 사용자, 그룹 및 스키마에 부여하여 누가 어느 객체에 액세스할 수 있는지 제어할 수 있습니다. CREATE DATABASE 권리가 있는 사용자는 데이터베이스를 만들고 이러한 데이터베이스에 대한 권한을 부여할 수 있습니다. 슈퍼 사용자는 모든 데이터베이스에 대해 데이터베이스 소유 권한을 갖습니다.

# 사용자 생성, 변경 및 삭제
<a name="r_Users-creatingaltering-and-deleting-users"></a>

데이터베이스 사용자는 데이터 웨어하우스 클러스터에서 전역적입니다(개별 데이터베이스에 따라 달라지지 않음).
+  사용자를 만들려면 [CREATE USER](r_CREATE_USER.md) 명령을 사용하세요.
+  슈퍼 사용자를 만들려면 CREATEUSER 옵션과 함께 [CREATE USER](r_CREATE_USER.md) 명령을 사용하세요.
+ 기존 사용자를 제거하려면 [DROP USER](r_DROP_USER.md) 명령을 사용하세요.
+ 사용자를 변경하려면(예: 암호 변경) [ALTER USER](r_ALTER_USER.md) 명령을 사용하세요.
+ 사용자 목록을 보려면 PG\$1USER 카탈로그 테이블을 쿼리하세요.

  ```
  select * from pg_user;
  
    usename   | usesysid | usecreatedb | usesuper | usecatupd |  passwd  | valuntil | useconfig
  ------------+----------+-------------+----------+-----------+----------+----------+-----------
   rdsdb      |        1 | t           | t        | t         | ******** |          |
   masteruser |      100 | t           | t        | f         | ******** |          |
   dwuser     |      101 | f           | f        | f         | ******** |          |
   simpleuser |      102 | f           | f        | f         | ******** |          |
   poweruser  |      103 | f           | t        | f         | ******** |          |
   dbuser     |      104 | t           | f        | f         | ******** |          |
  (6 rows)
  ```

# 그룹
<a name="r_Groups"></a>

그룹은 그룹에 연결된 어떤 권한이건 모두 부여되는 사용자들의 모음입니다. 그룹을 사용하여 권한을 부여할 수 있습니다. 예를 들어 영업, 관리, 지원을 위한 다양한 그룹을 생성하여 각 그룹의 사용자에게 업무에 필요한 데이터에 액세스할 수 있는 적절한 권한을 부여할 수 있습니다. 그룹 수준에서 권한을 부여하거나 취소할 수 있으며, 이러한 변경 사항은 슈퍼 사용자를 제외한 그룹의 모든 구성원에게 적용됩니다.

모든 사용자 그룹을 보려면 PG\$1GROUP 시스템 카탈로그 테이블을 쿼리합니다.

```
select * from pg_group;
```

예를 들어 모든 데이터베이스 사용자를 그룹별로 나열하려면 다음 SQL을 실행합니다.

```
SELECT u.usesysid
,g.groname
,u.usename
FROM pg_user u
LEFT JOIN pg_group g ON u.usesysid = ANY (g.grolist)
```

# 그룹 생성, 변경 및 삭제
<a name="r_Groups-creating-altering-and-deleting-groups"></a>

슈퍼 사용자만이 그룹을 생성, 변경 또는 삭제할 수 있습니다.

다음 작업을 수행할 수 있습니다.
+ 그룹을 만들려면 [create group](r_CREATE_GROUP.md) 명령을 사용하세요.
+ 기존 그룹에 사용자를 추가하거나 기존 그룹에서 제거하려면 [ALTER GROUP](r_ALTER_GROUP.md) 명령을 사용하세요.
+ 그룹을 삭제하려면 [DROP GROUP](r_DROP_GROUP.md) 명령을 사용하세요. 이 명령은 그룹만을 삭제하며 그룹 구성원인 사용자는 삭제하지 않습니다.

# 사용자 및 그룹 액세스 제어 예
<a name="t_user_group_examples"></a>

이 예는 사용자 그룹과 사용자를 만든 다음 이들에게 웹 애플리케이션 클라이언트에 연결되는 Amazon Redshift 데이터베이스에 대한 권한을 부여합니다. 이 예에서는 웹 애플리케이션 일반 사용자, 웹 애플리케이션 파워 유저, 웹 개발자 등 세 가지 사용자 그룹을 가정합니다.

그룹에서 사용자를 제거하는 방법에 대한 자세한 내용은 [ALTER GROUP](r_ALTER_GROUP.md) 섹션을 참조하세요.

1. 사용자가 할당될 그룹을 만듭니다. 다음 명령 세트는 세 가지 사용자 그룹을 만듭니다.

   ```
   create group webappusers;
   
   create group webpowerusers;
   
   create group webdevusers;
   ```

1.  권한이 서로 다른 몇몇 데이터베이스 사용자를 만들어 그룹에 추가합니다.  

   1.  두 명의 사용자를 만들어 WEBAPPUSERS 그룹에 추가합니다.  

      ```
      create user webappuser1 password 'webAppuser1pass'
      in group webappusers;
      
      create user webappuser2 password 'webAppuser2pass'
      in group webappusers;
      ```

   1.  웹 개발자용 계정을 만들어 WEBDEVUSERS 그룹에 추가합니다.  

      ```
      create user webdevuser1 password 'webDevuser2pass'
      in group webdevusers;
      ```

   1.  슈퍼 사용자를 생성합니다. 이 사용자는 다른 사용자를 생성하는 관리 권한을 갖습니다.  

      ```
      create user webappadmin  password 'webAppadminpass1'
      createuser;
      ```

1.  웹 애플리케이션이 사용하는 데이터베이스 테이블에 연결될 스키마를 생성하고 다양한 사용자 그룹에 이 스키마에 대한 액세스 권한을 부여합니다.

   1.  WEBAPP 스키마를 생성합니다.

      ```
      create schema webapp;
      ```

   1.  WEBAPPUSERS 그룹에 USAGE 권한을 부여합니다.  

      ```
      grant usage on schema webapp to group webappusers;
      ```

   1.  WEBPOWERUSERS 그룹에 USAGE 권한을 부여합니다.  

      ```
      grant usage on schema webapp to group webpowerusers;
      ```

   1.  WEBDEVUSERS 그룹에 ALL 권한을 부여합니다.

      ```
      grant all on schema webapp to group webdevusers;
      ```

   기본적인 사용자 및 그룹이 이제 설정되었습니다. 이제 사용자와 그룹을 변경할 수 있습니다.

1.  예를 들어 다음 명령은 WEBAPPUSER1의 search\$1path 파라미터를 변경합니다.

   ```
   alter user webappuser1 set search_path to webapp, public;
   ```

   SEARCH\$1PATH는 테이블과 함수 같은 데이터베이스 객체를 스키마가 지정되지 않은 단순한 이름으로 참조할 때 객체에 대한 스키마 검색 순서를 지정합니다.

1.  그룹을 생성한 후 사용자를 그룹에 추가할 수 있습니다. 예를 들어 WEBAPPUSER2를 WEBPOWERUSERS 그룹에 추가할 수 있습니다.

   ```
   alter group webpowerusers add user webappuser2;
   ```

# 스키마
<a name="r_Schemas_and_tables"></a>

데이터베이스에는 하나 이상의 명명된 스키마가 포함되어 있습니다. 데이터베이스의 각 스키마에는 테이블과 그 밖의 명명된 객체가 포함됩니다. 기본적으로 데이터베이스에는 PUBLIC이라는 이름의 스키마가 하나 있습니다. 스키마를 사용하여 일반 이름으로 데이터베이스 객체를 그룹화할 수 있습니다. 스키마는 중첩될 수 없다는 점만 빼면 파일 시스템 디렉터리와 비슷합니다.

같은 데이터베이스 내의 다른 스키마에서 동일한 데이터베이스 객체 이름을 충돌 없이 사용할 수 있습니다. 예를 들어 MY\$1SCHEMA와 YOUR\$1SCHEMA에 MYTABLE이라는 이름의 테이블이 모두 포함될 수 있습니다. 필요한 권한이 있는 사용자는 데이터베이스의 여러 스키마에서 객체에 액세스할 수 있습니다.

기본적으로 데이터베이스의 검색 경로의 첫 번째 스키마 내에서 객체가 생성됩니다. 자세한 내용은 이 섹션의 후반부에서 [검색 경로](#c_Search_path) 섹션을 참조하세요.

스키마는 다음과 같은 방법으로 다중 사용자 환경에서 조직 및 동시성 문제에 도움이 될 수 있습니다.
+ 여러 개발자가 서로 간섭 없이 같은 데이터베이스에서 작업이 가능.
+ 보다 관리하기 쉽게 데이터베이스 객체를 논리적 그룹으로 체계화.
+ 다른 애플리케이션에서 사용하는 객체의 이름과 충돌하지 않도록 객체를 별도의 스키마에 넣는 능력을 애플리케이션에 제공.

## 검색 경로
<a name="c_Search_path"></a>

검색 경로는 쉼표로 분리된 스키마 이름 목록을 사용하여 search\$1path 파라미터에서 정의됩니다. 검색 경로는 테이블이나 함수와 같은 객체를 스키마 한정자가 포함되지 않은 단순한 이름으로 참조할 때 스키마가 검색되는 순서를 지정합니다.

대상 스키마를 지정하지 않고 생성된 객체는 검색 경로에 나열되는 첫 번째 스키마에 추가됩니다. 동일한 이름의 객체가 다른 스키마에 존재하는 경우, 스키마를 지정하지 않은 객체 이름은 검색 경로에서 해당 이름의 객체가 포함된 첫 번째 스키마를 참조합니다.

현재 세션의 기본 스키마를 변경하려면 [SET](r_SET.md) 명령을 사용합니다.

자세한 내용은 구성 참조의 [search\$1path](r_search_path.md) 설명을 참조하세요.

# 스키마 생성, 변경 및 삭제
<a name="r_Schemas_and_tables-creating-altering-and-deleting-schemas"></a>

모든 사용자는 직접 스키마를 생성하고 변경하거나 삭제할 수 있습니다.

다음 작업을 수행할 수 있습니다.
+ 스키마를 생성하려면 [CREATE SCHEMA](r_CREATE_SCHEMA.md) 명령을 사용합니다.
+ 스키마의 소유자를 변경하려면 [ALTER SCHEMA](r_ALTER_SCHEMA.md) 명령을 사용합니다.
+ 스키마와 그 객체를 삭제하려면 [DROP SCHEMA](r_DROP_SCHEMA.md) 명령을 사용합니다.
+ 스키마 내에 테이블을 생성하려면 *schema\$1name.table\$1name* 형식으로 테이블을 생성합니다.

모든 스키마 목록을 보려면 PG\$1NAMESPACE 시스템 카탈로그 테이블을 쿼리합니다.

```
select * from pg_namespace;
```

스키마에 속한 테이블의 목록을 보려면 PG\$1TABLE\$1DEF 시스템 카탈로그 테이블을 쿼리합니다. 예를 들어 다음 쿼리는 PG\$1CATALOG 스키마에 있는 테이블의 목록을 반환합니다.

```
select distinct(tablename) from pg_table_def
where schemaname = 'pg_catalog';
```

# 스키마 기반 권한
<a name="r_Schemas_and_tables-schema-based-privileges"></a>

 스키마 기반 권한은 스키마 소유자에 의해 결정됩니다.
+ 기본적으로 모든 사용자는 데이터베이스의 PUBLIC 스키마에서 CREATE 및 USAGE 권한을 갖습니다. 사용자가 데이터베이스의 PUBLIC 스키마에 객체를 생성하는 것을 허용하지 않으려면 [REVOKE](r_REVOKE.md) 명령을 사용하여 해당 권한을 제거하세요.
+ 객체 소유자에 의해 USAGE 권한이 부여되지 않은 경우, 사용자는 소유하지 않은 스키마의 어떤 객체에도 액세스할 수 없습니다.
+ 다른 사용자가 생성한 스키마에 대한 CREATE 권한을 부여받은 사용자는 해당 스키마에서 객체를 만들 수 있습니다.

# 역할 기반 액세스 제어(RBAC)
<a name="t_Roles"></a>

역할 기반 액세스 제어(RBAC)를 사용하여 Amazon Redshift에서 데이터베이스 권한을 관리하면 Amazon Redshift에서 보안 권한 관리를 간소화할 수 있습니다. 사용자가 광범위하거나 세밀한 수준에서 수행할 수 있는 작업을 제어하여 민감한 데이터에 대한 액세스를 보호할 수 있습니다. 또한 일반적으로 슈퍼 사용자로 제한되는 작업에 대한 사용자 액세스를 제어할 수도 있습니다. 서로 다른 역할에 서로 다른 권한을 할당하고 이를 다른 사용자에게 할당하여 사용자 액세스를 보다 세부적으로 제어할 수 있습니다.

역할이 할당된 사용자는 권한이 부여된 할당된 역할에 의해 지정된 작업만 수행할 수 있습니다. 예를 들어 CREATE TABLE 및 DROP TABLE 권한이 있는 할당된 역할이 있는 사용자는 이러한 작업을 수행할 수 있는 권한만 부여됩니다. 서로 다른 사용자가 작업에 필요한 데이터에 액세스할 수 있도록 서로 다른 수준의 보안 권한을 부여하여 사용자의 액세스를 제어할 수 있습니다.

RBAC는 관련된 객체 유형에 상관없이 역할 요구 사항에 따라 사용자에게 최소 권한의 원칙을 적용합니다. 권한 부여 및 취소는 개별 데이터베이스 객체에 대한 권한을 업데이트할 필요 없이 역할 수준에서 수행됩니다.

RBAC를 사용하면 슈퍼 사용자 권한을 요구했던 명령을 실행할 수 있는 권한을 갖는 역할을 만들 수 있습니다. 사용자는 이러한 권한을 포함하는 역할로 권한이 부여되는 한 이러한 명령을 실행할 수 있습니다. 마찬가지로 역할을 만들어 특정 명령에 대한 액세스를 제한하고 역할을 통해 권한이 부여된 슈퍼 사용자 또는 사용자에게 역할을 할당할 수도 있습니다.

Amazon Redshift RBAC 작동 방식에 대해 알아보려면 다음 동영상을 시청하세요.

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


# 역할 계층 구조
<a name="t_role_hierarchy"></a>

*역할*은 사용자 또는 다른 역할에 할당할 수 있는 권한 모음입니다. 역할에 시스템 또는 데이터베이스 권한을 할당할 수 있습니다. 사용자는 할당된 역할에서 권한을 상속합니다.

RBAC에서 사용자는 중첩된 역할을 가질 수 있습니다. 사용자와 역할 모두에 역할을 부여할 수 있습니다. 사용자에게 역할을 부여할 때 이 역할이 포함하는 모든 권한을 사용자에게 부여합니다. 사용자에게 역할 r1을 부여할 때 r1의 권한을 사용자에게 부여합니다. 이제 사용자는 r1의 권한과 이미 가지고 있는 모든 기존 권한을 갖습니다.

역할(r1)을 다른 역할(r2)에 부여할 때 r1의 모든 권한을 r2에 부여합니다. 또한 r2를 다른 역할(r3)에 부여할 때 r3의 권한은 r1 및 r2의 권한의 조합입니다. 역할 계층 구조는 r2가 r1에서 권한을 상속하도록 합니다. Amazon Redshift는 각 역할 권한 부여로 권한을 전파합니다. r1을 r2에 부여한 다음 r2를 r3에 부여하면 세 역할의 모든 권한을 r3에 부여합니다. 따라서 사용자에게 r3을 부여하면 사용자는 세 역할의 모든 권한을 갖습니다.

Amazon Redshift는 역할 권한 부여 순환 생성을 허용하지 않습니다. 역할 권한 부여 순환은 중첩된 역할이 역할 계층 구조에서 이전 역할에 다시 할당될 때 발생합니다(예: r3이 다시 r1에 할당됨). 역할 생성 및 관리에 대한 자세한 내용은 [RBAC에서 역할 관리](r_roles-managing.md) 섹션을 참조하세요.

# 역할 할당
<a name="t_role_assignment"></a>

CREATE ROLE 권한이 있는 슈퍼 사용자 및 일반 사용자는 CREATE ROLE 문을 사용하여 역할을 만들 수 있습니다. 슈퍼 사용자 및 역할 관리자는 GRANT ROLE 문을 사용하여 다른 사용자에게 역할을 부여할 수 있습니다. REVOKE ROLE 문을 사용하여 다른 사용자의 역할을 취소하고 DROP ROLE 문을 사용하여 역할을 삭제할 수 있습니다. 역할 관리자에는 ADMIN OPTION 권한이 있는 역할이 부여된 역할 소유자 및 사용자가 포함됩니다.

슈퍼 사용자 또는 역할 관리자만이 역할을 부여 및 취소할 수 있습니다. 하나 이상의 역할 또는 사용자에게 하나 이상의 역할을 부여하거나 취소할 수 있습니다. GRANT ROLE 문에서 WITH ADMIN OPTION 옵션을 사용하여 모든 피부여자에게 부여된 모든 역할에 대한 관리 옵션을 제공하세요.

Amazon Redshift는 여러 역할을 부여하거나 여러 피부여자를 갖는 등 다양한 역할 할당 조합을 지원합니다. WITH ADMIN OPTION은 사용자에게만 적용되며 역할에는 적용되지 않습니다. 마찬가지로 REVOKE ROLE 문에서 WITH ADMIN OPTION 옵션을 사용하여 피부여자의 역할 및 관리 권한 부여를 제거하세요. ADMIN OPTION과 함께 사용하면 역할의 관리 권한 부여만 취소됩니다.

다음 예에는 `user2`에서 `sample_role2` 역할의 관리 권한 부여를 취소합니다.

```
REVOKE ADMIN OPTION FOR sample_role2 FROM user2;
```

역할 생성 및 관리에 대한 자세한 내용은 [RBAC에서 역할 관리](r_roles-managing.md) 섹션을 참조하세요.

# Amazon Redshift 시스템 정의 역할
<a name="r_roles-default"></a>

Amazon Redshift는 특정 권한으로 정의된 몇 가지 시스템 정의 역할을 제공합니다. 시스템 관련 역할은 `sys:` 접두사로 시작합니다. 적절하게 액세스하는 사용자만이 시스템 정의 역할을 변경하거나 사용자 지정 시스템 정의 역할을 만들 수 있습니다. 사용자 지정 시스템 정의 역할에 `sys:` 접두사를 사용할 수 없습니다.

다음 표에는 역할과 그 권한이 요약되어 있습니다.

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/r_roles-default.html)

## 데이터 공유를 위한 시스템 정의 역할 및 사용자
<a name="r_roles-datashare"></a>

 Amazon Redshift는 데이터 공유 및 데이터 공유 소비자에 해당하는 내부 용도의 역할과 사용자를 생성합니다. 각 내부 역할 이름과 사용자 이름에는 예약된 네임스페이스 접두사 `ds:`가 있습니다. 다음과 같은 형식을 보유합니다.

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/r_roles-default.html)

 각 데이터 공유별로 데이터 공유 역할이 생성됩니다. 현재 데이터 공유에 부여된 모든 권한을 보유합니다. 데이터 공유의 각 소비자별로 데이터 공유 사용자가 생성됩니다. 단일 데이터 공유 역할에 대한 권한이 부여됩니다. 여러 데이터 공유에 추가된 소비자는 각 데이터 공유별로 데이터 공유 사용자를 한 명씩 생성하게 됩니다.

데이터 공유가 제대로 작동하려면 이러한 사용자와 역할이 필요합니다. 수정하거나 삭제할 수 없으며 고객이 실행하는 태스크에 액세스하거나 사용할 수 없습니다. 이 내용은 안심하고 무시해도 됩니다. 데이터 공유에 대한 자세한 내용은 [Amazon Redshift에서 클러스터 간 데이터 공유](https://docs.aws.amazon.com/redshift/latest/dg/datashare-overview.html)를 참조하세요.

**참고**  
`ds:` 접두사를 사용하여 사용자 정의 역할 또는 사용자를 생성할 수는 없습니다.

# RBAC에 대한 시스템 권한
<a name="r_roles-system-privileges"></a>

다음은 역할에서 부여하거나 취소할 수 있는 시스템 권한 목록입니다.

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/redshift/latest/dg/r_roles-system-privileges.html)

# 데이터베이스 객체 권한
<a name="r_roles-database-privileges"></a>

시스템 권한 외에도 Amazon Redshift는 액세스 옵션을 정의하는 데이터베이스 객체 권한을 포함합니다. 테이블 및 보기의 데이터 읽기, 데이터 쓰기, 테이블 생성 및 테이블 삭제 기능과 같은 옵션을 포함합니다. 자세한 내용은 [GRANT](r_GRANT.md) 섹션을 참조하세요.

RBAC를 사용하여 시스템 권한과 비슷한 방법으로 데이터베이스 객체 권한을 역할에 할당할 수 있습니다. 그런 다음 사용자에게 역할을 할당하고, 시스템 권한이 있는 사용자에게 권한을 부여하고, 데이터베이스 권한이 있는 사용자에게 권한을 부여할 수 있습니다.

# RBAC에 대한 ALTER DEFAULT PRIVILEGES
<a name="r_roles-alter-default-privileges"></a>

ALTER DEFAULT PRIVILEGES 문을 사용하여 앞으로 지정된 사용자가 만들 객체에 적용되는 기본 액세스 권한 집합을 정의하세요. 기본적으로 사용자는 자신의 기본 액세스 권한만 변경할 수 있습니다. RBAC를 사용하여 역할의 기본 액세스 권한을 설정할 수 있습니다. 자세한 내용은 [ALTER DEFAULT PRIVILEGES](r_ALTER_DEFAULT_PRIVILEGES.md) 명령을 참조하세요.

RBAC를 사용하여 시스템 권한과 비슷하게 데이터베이스 객체 권한을 역할에 할당할 수 있습니다. 그런 다음 사용자에게 역할을 할당하고 시스템 및/또는 데이터베이스 권한이 있는 사용자에게 권한을 부여할 수 있습니다.

# RBAC에서 역할 사용에 대한 고려 사항
<a name="r_role-usage-notes"></a>

RBAC 역할을 사용하여 작업 시 다음 사항을 고려하세요.
+ Amazon Redshift는 역할 권한 부여 순환을 허용하지 않습니다. r1을 r2에 부여한 다음 r2를 r1에 부여할 수 없습니다.
+ RBAC는 네이티브 Amazon Redshift 객체와 Amazon Redshift Spectrum 테이블 모두에서 작동합니다.
+ Amazon Redshift 관리자는 클러스터를 최신 유지 관리 패치로 업그레이드함으로써 RBAC를 활성화하여 시작할 수 있습니다.
+ CREATE ROLE 시스템 권한이 있는 슈퍼 사용자 및 사용자만 역할을 만들 수 있습니다.
+ 슈퍼 사용자 및 역할 관리자만 역할을 수정하거나 삭제할 수 있습니다.
+ 역할 이름은 사용자 이름과 같을 수 없습니다.
+ 역할 이름은 “:/\$1n.”과 같은 잘못된 문자를 포함할 수 없습니다.
+ 역할 이름은 PUBLIC과 같은 예약어가 될 수 없습니다.
+ 역할 이름은 기본 역할에 대해 예약된 접두사 `sys:`로 시작할 수 없습니다.
+ 다른 역할에 부여된 경우 RESTRICT 파라미터가 있는 역할은 삭제할 수 없습니다. 기본 설정은 RESTRICT입니다. 다른 역할을 상속한 역할을 삭제하려고 하면 Amazon Redshift에서 오류가 발생합니다.
+ 역할에 대한 관리자 권한이 없는 사용자는 역할을 부여하거나 취소할 수 없습니다.
+ RBAC는 시스템 테이블 및 뷰에서 완전히 지원되지 않습니다. 시스템 테이블 및 뷰에서의 RBAC 권한은 업그레이드, 다운그레이드 또는 크기 조정을 통해 유지되지 않습니다. [Amazon Redshift 시스템 정의 역할데이터 공유를 위한 시스템 정의 역할 및 사용자](r_roles-default.md)를 사용하여 시스템 테이블을 관리하고 권한을 확인하는 것이 좋습니다. 시스템 테이블에 관한 자세한 내용은 [시스템 테이블 및 뷰 참조](cm_chap_system-tables.md) 섹션으로 이동해 참조하시기 바랍니다.

# RBAC에서 역할 관리
<a name="r_roles-managing"></a>

다음 작업을 수행하려면 다음 명령을 사용하세요.
+ 역할을 만들려면 [CREATE ROLE](r_CREATE_ROLE.md) 명령을 사용하세요.
+ 역할의 이름을 바꾸거나 역할의 소유자를 변경하려면 [역할 변경](r_ALTER_ROLE.md) 명령을 사용하세요.
+ 역할을 삭제하려면 [DROP ROLE](r_DROP_ROLE.md) 명령을 사용하세요.
+ 사용자에게 역할을 부여하려면 [GRANT](r_GRANT.md) 명령을 사용하세요.
+ 사용자에게서 역할을 취소하려면 [REVOKE](r_REVOKE.md) 명령을 사용하세요.
+ 역할에 시스템 권한을 부여하려면 [GRANT](r_GRANT.md) 명령을 사용하세요.
+ 역할에서 시스템 권한을 취소하려면 [REVOKE](r_REVOKE.md) 명령을 사용하세요.

클러스터 또는 작업 그룹의 역할 목록을 보려면 [SVV\$1ROLES](r_SVV_ROLES.md) 섹션을 참조하세요.

# 자습서: RBAC를 사용한 역할 생성 및 쿼리
<a name="r_tutorial-RBAC"></a>

RBAC를 사용하면 슈퍼 사용자 권한을 요구했던 명령을 실행할 수 있는 권한을 갖는 역할을 만들 수 있습니다. 사용자는 이러한 권한을 포함하는 역할로 권한이 부여되는 한 이러한 명령을 실행할 수 있습니다.

이 자습서에서는 생성하는 데이터베이스에서 역할 기반 액세스 제어(RBAC)를 사용하여 권한을 관리합니다. 그런 다음 데이터베이스에 연결하고 서로 다른 두 역할로 데이터베이스를 쿼리하여 RBAC의 기능을 테스트합니다.

데이터베이스를 쿼리할 때 만들고 사용하는 두 가지 역할은 `sales_ro`와 `sales_rw`입니다. `sales_ro` 역할을 생성하고 `sales_ro` 역할을 가진 사용자로 데이터를 쿼리합니다. `sales_ro` 사용자는 SELECT 명령만 사용할 수 있고 UPDATE 명령은 사용할 수 없습니다. 그런 다음 `sales_rw` 역할을 생성하고 `sales_rw` 역할을 가진 사용자로 데이터를 쿼리합니다. `sales_rw` 사용자는 SELECT 명령과 UPDATE 명령을 사용할 수 있습니다.

마찬가지로 역할을 생성하여 특정 명령으로만 액세스를 제한하고 슈퍼 사용자 또는 사용자에게 역할을 할당합니다.

**작업**
+ [사전 조건](#tutorial-rbac-prereqs)
+ [1단계: 관리 사용자 생성](#tutorial-rbac-step1)
+ [2단계: 스키마 설정](#tutorial-rbac-step2)
+ [3단계: 읽기 전용 사용자 생성](#tutorial-rbac-step3)
+ [4단계: 읽기 전용 사용자로 데이터 쿼리](#tutorial-rbac-step4)
+ [5단계: 읽기-쓰기 사용자 생성](#tutorial-rbac-step5)
+ [6단계: 상속한 읽기 전용 역할을 가진 사용자로 데이터 쿼리](#tutorial-rbac-step6)
+ [7단계: 읽기-쓰기 역할에 업데이트 및 삽입 권한 부여](#tutorial-rbac-step7)
+ [8단계: 읽기-쓰기 사용자로 데이터 쿼리](#tutorial-rbac-step8)
+ [9단계: 관리 사용자로 데이터베이스의 테이블 분석 및 정리](#tutorial-rbac-step9)
+ [10단계: 읽기-쓰기 사용자로 테이블 자르기](#tutorial-rbac-step10)
+ [RBAC용 시스템 함수(선택 사항)](#tutorial-rbac-system-functions)
+ [RBAC용 시스템 보기(선택 사항)](#tutorial-rbac-system-views)
+ [RBAC와 함께 행 수준 보안 사용(선택 사항)](#tutorial-rbac-rls)

## 사전 조건
<a name="tutorial-rbac-prereqs"></a>
+ TICKIT 샘플 데이터베이스와 함께 로드되는 Amazon Redshift 클러스터 또는 서버리스 작업 그룹을 생성합니다. Serverless 작업 그룹을 만들려면 [Amazon Redshift Serverless](https://docs.aws.amazon.com/redshift/latest/gsg/new-user-serverless.html)를 참조하세요. 클러스터를 생성하려면 [샘플 Amazon Redshift 클러스터 생성](https://docs.aws.amazon.com/redshift/latest/gsg/rs-gsg-launch-sample-cluster.html)을 참조하세요. TICKIT 샘플 데이터베이스에 대한 자세한 내용은 [샘플 데이터베이스](c_sampledb.md)를 참조하세요.
+ 슈퍼 사용자 또는 역할 관리자 권한을 가진 사용자에 대한 액세스를 확보합니다. 슈퍼 사용자 또는 역할 관리자만 역할을 부여하거나 취소할 수 있습니다. RBAC에 필요한 권한에 대한 자세한 내용은 [RBAC에 대한 시스템 권한](r_roles-system-privileges.md) 섹션을 참조하세요.
+ [RBAC에서 역할 사용에 대한 고려 사항](r_role-usage-notes.md)을(를) 검토합니다.

## 1단계: 관리 사용자 생성
<a name="tutorial-rbac-step1"></a>

이 자습서를 진행하기 위해 설정하려면 이 단계에서 데이터베이스 관리자 역할을 만들어 데이터베이스 관리 사용자에게 연결합니다. 슈퍼 사용자 또는 역할 관리자로서 데이터베이스 관리자를 생성해야 합니다.

Amazon Redshift [쿼리 에디터 v2](https://docs.aws.amazon.com/redshift/latest/mgmt/query-editor-v2-using.html)에서 모든 쿼리를 실행합니다.

1. 관리자 역할 db\$1admin을 생성하려면 다음 예시를 사용하세요.

   ```
   CREATE ROLE db_admin;
   ```

1. dbadmin이라는 데이터베이스 사용자를 생성하려면 다음 예시를 사용하세요.

   ```
   CREATE USER dbadmin PASSWORD 'Test12345';
   ```

1. sys:dba라는 시스템 정의 역할을 db\$1admin 역할에 부여하려면 다음 예시를 사용하세요. sys:dba 역할이 부여되면 dbadmin 사용자는 스키마와 테이블을 생성할 수 있습니다. 자세한 내용은 [Amazon Redshift 시스템 정의 역할데이터 공유를 위한 시스템 정의 역할 및 사용자](r_roles-default.md) 섹션을 참조하세요.

## 2단계: 스키마 설정
<a name="tutorial-rbac-step2"></a>

이 단계에서는 데이터베이스 관리자로 데이터베이스에 연결합니다. 그런 다음 두 개의 스키마를 만들고 여기에 데이터를 추가합니다.

1. 쿼리 에디터 v2를 사용하여 dbadmin 사용자로 dev 데이터베이스에 연결합니다. 데이터베이스에 연결하는 방법에 관한 자세한 내용은 [쿼리 에디터 v2 작업](https://docs.aws.amazon.com/redshift/latest/mgmt/query-editor-v2-using.html)을 참조하세요.

1. 영업 및 마케팅 데이터베이스 스키마를 생성하려면 다음 예시를 사용하세요.

   ```
   CREATE SCHEMA sales;
   CREATE SCHEMA marketing;
   ```

1. 영업 스키마의 테이블을 생성하고 값을 삽입하려면 다음 예시를 사용하세요.

   ```
   CREATE TABLE sales.cat(
   catid smallint,
   catgroup varchar(10),
   catname varchar(10),
   catdesc varchar(50)
   );
   INSERT INTO sales.cat(SELECT * FROM category);
   
   CREATE TABLE sales.dates(
   dateid smallint,
   caldate date,
   day char(3),
   week smallint,
   month char(5),
   qtr char(5),
   year smallint,
   holiday boolean
   );
   INSERT INTO sales.dates(SELECT * FROM date);
   
   CREATE TABLE sales.events(
   eventid integer,
   venueid smallint,
   catid smallint,
   dateid smallint,
   eventname varchar(200),
   starttime timestamp
   );
   INSERT INTO sales.events(SELECT * FROM event);
   
    CREATE TABLE sales.sale(
   salesid integer,
   listid integer,
   sellerid integer,
   buyerid integer,
   eventid integer,
   dateid smallint,
   qtysold smallint,
   pricepaid decimal(8,2),
   commission decimal(8,2),
   saletime timestamp
   );
   INSERT INTO sales.sale(SELECT * FROM sales);
   ```

1. 마케팅 스키마의 테이블을 생성하고 값을 삽입하려면 다음 예시를 사용하세요.

   ```
   CREATE TABLE marketing.cat(
   catid smallint,
   catgroup varchar(10),
   catname varchar(10),
   catdesc varchar(50)
   );
   INSERT INTO marketing.cat(SELECT * FROM category);
   
   CREATE TABLE marketing.dates(
   dateid smallint,
   caldate date,
   day char(3),
   week smallint,
   month char(5),
   qtr char(5),
   year smallint,
   holiday boolean
   );
   INSERT INTO marketing.dates(SELECT * FROM date);
   
   CREATE TABLE marketing.events(
   eventid integer,
   venueid smallint,
   catid smallint,
   dateid smallint,
   eventname varchar(200),
   starttime timestamp
   );
   INSERT INTO marketing.events(SELECT * FROM event);
   
   CREATE TABLE marketing.sale(
   marketingid integer,
   listid integer,
   sellerid integer,
   buyerid integer,
   eventid integer,
   dateid smallint,
   qtysold smallint,
   pricepaid decimal(8,2),
   commission decimal(8,2),
   saletime timestamp
   );
   INSERT INTO marketing.sale(SELECT * FROM marketing);
   ```

## 3단계: 읽기 전용 사용자 생성
<a name="tutorial-rbac-step3"></a>

이 단계에서는 읽기 전용 역할과 읽기 전용 역할에 대한 salesanalyst 사용자를 생성합니다. 영업 분석가는 커미션이 가장 큰 이벤트를 찾는 임무를 수행하기 위해 영업 스키마의 테이블에 대한 읽기 전용 액세스만 있으면 됩니다.

1. dbadmin 사용자로 데이터베이스에 연결합니다.

1. sales\$1ro 역할을 생성하려면 다음 예시를 사용하세요.

   ```
   CREATE ROLE sales_ro;
   ```

1. salesanalyst 사용자를 생성하려면 다음 예시를 사용하세요.

   ```
   CREATE USER salesanalyst PASSWORD 'Test12345';
   ```

1. sales\$1ro 역할 사용과 영업 스키마의 객체에 대한 선택 액세스를 허용하려면 다음 예시를 사용하세요.

   ```
   GRANT USAGE ON SCHEMA sales TO ROLE sales_ro;
   GRANT SELECT ON ALL TABLES IN SCHEMA sales TO ROLE sales_ro;
   ```

1. salesanalyst 사용자에게 sales\$1ro 역할을 부여하려면 다음 예시를 사용하세요.

   ```
   GRANT ROLE sales_ro TO salesanalyst;
   ```

## 4단계: 읽기 전용 사용자로 데이터 쿼리
<a name="tutorial-rbac-step4"></a>

이 단계에서 salesanalyst 사용자는 영업 스키마의 데이터를 쿼리합니다. 그런 다음 salesanalyst 사용자는 테이블 업데이트를 시도하고 마케팅 스키마의 테이블을 읽으려고 합니다.

1. salesanalyst 사용자로 데이터베이스에 연결합니다.

1. 커미션이 가장 큰 10개의 영업을 찾으려면 다음 예시를 사용하세요.

   ```
   SET SEARCH_PATH TO sales;
   SELECT DISTINCT events.dateid, sale.commission, cat.catname
   FROM sale, events, dates, cat   
   WHERE events.dateid=dates.dateid AND events.dateid=sale.dateid AND events.catid = cat.catid
   ORDER BY 2 DESC LIMIT 10;
                  
   +--------+------------+----------+
   | dateid | commission | catname  |
   +--------+------------+----------+
   |   1880 |     1893.6 | Pop      |
   |   1880 |     1893.6 | Opera    |
   |   1880 |     1893.6 | Plays    |
   |   1880 |     1893.6 | Musicals |
   |   1861 |       1500 | Plays    |
   |   2003 |       1500 | Pop      |
   |   1861 |       1500 | Opera    |
   |   2003 |       1500 | Plays    |
   |   1861 |       1500 | Musicals |
   |   1861 |       1500 | Pop      |
   +--------+------------+----------+
   ```

1. 영업 스키마의 이벤트 테이블에서 10개의 이벤트를 선택하려면 다음 예시를 사용하세요.

   ```
   SELECT * FROM sales.events LIMIT 10;
                  
   +---------+---------+-------+--------+--------------------+---------------------+
   | eventid | venueid | catid | dateid |     eventname      |      starttime      |
   +---------+---------+-------+--------+--------------------+---------------------+
   |    4836 |      73 |     9 |   1871 | Soulfest           | 2008-02-14 19:30:00 |
   |    5739 |      41 |     9 |   1871 | Fab Faux           | 2008-02-14 19:30:00 |
   |     627 |     229 |     6 |   1872 | High Society       | 2008-02-15 14:00:00 |
   |    2563 |     246 |     7 |   1872 | Hamlet             | 2008-02-15 20:00:00 |
   |    7703 |      78 |     9 |   1872 | Feist              | 2008-02-15 14:00:00 |
   |    7903 |      90 |     9 |   1872 | Little Big Town    | 2008-02-15 19:30:00 |
   |    7925 |     101 |     9 |   1872 | Spoon              | 2008-02-15 19:00:00 |
   |    8113 |      17 |     9 |   1872 | Santana            | 2008-02-15 15:00:00 |
   |     463 |     303 |     8 |   1873 | Tristan und Isolde | 2008-02-16 19:00:00 |
   |     613 |     236 |     6 |   1873 | Pal Joey           | 2008-02-16 15:00:00 |
   +---------+---------+-------+--------+--------------------+---------------------+
   ```

1. eventid 1의 eventname을 업데이트하려고 시도하려면 다음 예시를 실행하세요. 이 예시는 권한 거부됨 오류를 반환합니다. salesanalyst 사용자에게 영업 스키마의 이벤트 테이블에 대한 SELECT 권한만 있기 때문입니다. 이벤트 테이블을 업데이트하려면 sales\$1ro 역할에 UPDATE 권한을 부여해야 합니다. 테이블 업데이트 권한 부여에 대한 자세한 내용은 [GRANT](r_GRANT.md)의 UPDATE 파라미터를 참조하세요. UPDATE 명령에 대한 자세한 내용은 [UPDATE](r_UPDATE.md) 섹션을 참조하세요.

   ```
   UPDATE sales.events
   SET eventname = 'Comment event'
   WHERE eventid = 1;
                     
   ERROR: permission denied for relation events
   ```

1. 마케팅 스키마의 모든 이벤트 테이블을 선택하려고 시도하려면 다음 예시를 사용하세요. 이 예시는 권한 거부됨 오류를 반환합니다. salesanalyst 사용자에게 영업 스키마의 이벤트 테이블에 대한 SELECT 권한만 있기 때문입니다. 마케팅 스키마의 이벤트 테이블에서 데이터를 선택하려면 sales\$1ro 역할에 마케팅 스키마의 이벤트 테이블에 대한 SELECT 권한을 부여해야 합니다.

   ```
   SELECT * FROM marketing.events;
                  
                  ERROR: permission denied for schema marketing
   ```

## 5단계: 읽기-쓰기 사용자 생성
<a name="tutorial-rbac-step5"></a>

이 단계에서는 영업 스키마의 데이터 처리를 위한 추출, 전환, 적재(ETL) 파이프라인 구축을 담당하는 영업 엔지니어에게 읽기 전용 액세스 권한을 부여하지만 나중에는 업무를 수행할 수 있도록 읽기 및 쓰기 액세스 권한을 부여합니다.

1. dbadmin 사용자로 데이터베이스에 연결합니다.

1. 영업 스키마에서 sales\$1rw 역할을 생성하려면 다음 예시를 사용하세요.

   ```
   CREATE ROLE sales_rw;
   ```

1. salesengineer 사용자를 생성하려면 다음 예시를 사용하세요.

   ```
   CREATE USER salesengineer PASSWORD 'Test12345';
   ```

1. sales-ro 역할을 할당하여 sales\$1rw 역할 사용과 영업 스키마의 객체에 대한 선택 액세스를 허용하려면 다음 예시를 사용하세요. Amazon Redshift에서 역할이 권한을 상속하는 방법에 대한 자세한 내용은 [역할 계층 구조](t_role_hierarchy.md) 섹션을 참조하세요.

   ```
   GRANT ROLE sales_ro TO ROLE sales_rw;
   ```

1. salesengineer 사용자에게 sales\$1rw 역할을 할당하려면 다음 예시를 사용하세요.

   ```
   GRANT ROLE sales_rw TO salesengineer;
   ```

## 6단계: 상속한 읽기 전용 역할을 가진 사용자로 데이터 쿼리
<a name="tutorial-rbac-step6"></a>

이 단계에서 salesengineer 사용자는 읽기 권한을 부여받기 전에 이벤트 테이블을 업데이트하려고 합니다.

1. salesengineer 사용자로 데이터베이스에 연결합니다.

1. salesengineer 사용자는 영업 스키마의 이벤트 테이블에서 데이터를 성공적으로 읽을 수 있습니다. 영업 스키마의 이벤트 테이블에서 eventid가 1인 이벤트를 선택하려면 다음 예시를 사용하세요.

   ```
   SELECT * FROM sales.events where eventid=1;
                     
   +---------+---------+-------+--------+-----------------+---------------------+
   | eventid | venueid | catid | dateid |    eventname    |      starttime      |
   +---------+---------+-------+--------+-----------------+---------------------+
   |       1 |     305 |     8 |   1851 | Gotterdammerung | 2008-01-25 14:30:00 |
   +---------+---------+-------+--------+-----------------+---------------------+
   ```

1. 마케팅 스키마의 모든 이벤트 테이블을 선택하려고 시도하려면 다음 예시를 사용하세요. salesengineer 사용자에게는 마케팅 스키마의 테이블에 대한 권한이 없으므로 이 쿼리는 권한 거부됨 오류를 반환합니다. 마케팅 스키마의 이벤트 테이블에서 데이터를 선택하려면 sales\$1rw 역할에 마케팅 스키마의 이벤트 테이블에 대한 SELECT 권한을 부여해야 합니다.

   ```
   SELECT * FROM marketing.events;
   
   ERROR: permission denied for schema marketing
   ```

1. eventid 1의 eventname을 업데이트하려고 시도하려면 다음 예시를 실행하세요. 이 예시는 권한 거부됨 오류를 반환합니다. salesengineer 사용자에게 영업 스키마의 이벤트 테이블에 대한 선택 권한만 있기 때문입니다. 이벤트 테이블을 업데이트하려면 sales\$1rw 역할에 UPDATE 권한을 부여해야 합니다.

   ```
   UPDATE sales.events
   SET eventname = 'Comment event'
   WHERE eventid = 1;
   
   ERROR: permission denied for relation events
   ```

## 7단계: 읽기-쓰기 역할에 업데이트 및 삽입 권한 부여
<a name="tutorial-rbac-step7"></a>

이 단계에서는 sales\$1rw 역할에 업데이트 및 삽입 권한을 부여합니다.

1. dbadmin 사용자로 데이터베이스에 연결합니다.

1. sales\$1rw 역할에 UPDATE, INSERT, DELETE 권한을 부여하려면 다음 예시를 사용하세요.

   ```
   GRANT UPDATE, INSERT, ON ALL TABLES IN SCHEMA sales TO role sales_rw;
   ```

## 8단계: 읽기-쓰기 사용자로 데이터 쿼리
<a name="tutorial-rbac-step8"></a>

이 단계에서는 salesengineer의 역할에 삽입 및 업데이트 권한이 부여된 후 salesengineer가 테이블을 성공적으로 업데이트합니다. 그런 다음 salesengineer는 이벤트 테이블을 분석하고 정리하려고 시도하지만 실패합니다.

1. salesengineer 사용자로 데이터베이스에 연결합니다.

1. eventid 1의 eventname을 업데이트하려면 다음 예시를 실행하세요.

   ```
   UPDATE sales.events
   SET eventname = 'Comment event'
   WHERE eventid = 1;
   ```

1. 이전 쿼리에서 변경한 내용을 보려면 다음 예시를 사용하여 영업 스키마의 이벤트 테이블에서 eventid가 1인 이벤트를 선택하세요.

   ```
   SELECT * FROM sales.events WHERE eventid=1;
   
   +---------+---------+-------+--------+---------------+---------------------+
   | eventid | venueid | catid | dateid |   eventname   |      starttime      |
   +---------+---------+-------+--------+---------------+---------------------+
   |       1 |     305 |     8 |   1851 | Comment event | 2008-01-25 14:30:00 |
   +---------+---------+-------+--------+---------------+---------------------+
   ```

1. 영업 스키마의 업데이트된 이벤트 테이블을 분석하려면 다음 예시를 사용하세요. 이 예시는 권한 거부됨 오류를 반환합니다. salesengineer 사용자에게 필요한 권한이 없으며 salesengineer는 영업 스키마에 있는 이벤트 테이블의 소유자가 아니기 때문입니다. 이벤트 테이블을 분석하려면 GRANT 명령을 사용하여 sales\$1rw 역할에 ANALYZE 권한을 부여해야 합니다. ANALYZE 명령에 대한 자세한 내용은 [ANALYZE](r_ANALYZE.md) 섹션을 참조하세요.

   ```
   ANALYZE sales.events;
                  
                  ERROR: skipping "events" --- only table or database owner can analyze
   ```

1. 업데이트된 이벤트 테이블을 정리하려면 다음 예시를 사용하세요. 이 예시는 권한 거부됨 오류를 반환합니다. salesengineer 사용자에게 필요한 권한이 없으며 salesengineer는 영업 스키마에 있는 이벤트 테이블의 소유자가 아니기 때문입니다. 이벤트 테이블을 정리하려면 GRANT 명령을 사용하여 sales\$1rw 역할에 VACUUM 권한을 부여해야 합니다. VACUUM 명령에 대한 자세한 내용은 [VACUUM](r_VACUUM_command.md) 섹션을 참조하세요.

   ```
   VACUUM sales.events;
                     
   ERROR: skipping "events" --- only table or database owner can vacuum it
   ```

## 9단계: 관리 사용자로 데이터베이스의 테이블 분석 및 정리
<a name="tutorial-rbac-step9"></a>

이 단계에서 dbadmin 사용자는 모든 테이블을 분석하고 정리합니다. 이 사용자는 이 데이터베이스에 대한 관리자 권한을 가지고 있으므로 이러한 명령을 실행할 수 있습니다.

1. dbadmin 사용자로 데이터베이스에 연결합니다.

1. 영업 스키마의 이벤트 테이블을 분석하려면 다음 예시를 사용하세요.

   ```
   ANALYZE sales.events;
   ```

1. 영업 스키마의 이벤트 테이블을 정리하려면 다음 예시를 사용하세요.

   ```
   VACUUM sales.events;
   ```

1. 마케팅 스키마의 이벤트 테이블을 분석하려면 다음 예시를 사용하세요.

   ```
   ANALYZE marketing.events;
   ```

1. 마케팅 스키마의 이벤트 테이블을 정리하려면 다음 예시를 사용하세요.

   ```
   VACUUM marketing.events;
   ```

## 10단계: 읽기-쓰기 사용자로 테이블 자르기
<a name="tutorial-rbac-step10"></a>

이 단계에서 salesengineer 사용자는 영업 스키마의 이벤트 테이블을 자르려고 시도하지만 dbadmin 사용자가 자르기 권한을 부여한 경우에만 성공합니다.

1. salesengineer 사용자로 데이터베이스에 연결합니다.

1. 영업 스키마의 이벤트 테이블에서 모든 행을 삭제하려면 다음 예시를 사용하세요. 이 예시는 오류를 반환합니다. salesengineer 사용자에게 필요한 권한이 없으며 salesengineer는 영업 스키마에 있는 이벤트 테이블의 소유자가 아니기 때문입니다. 이벤트 테이블을 자르려면 GRANT 명령을 사용하여 sales\$1rw 역할에 TRUNCATE 권한을 부여해야 합니다. TRUNCATE 명령에 대한 자세한 내용은 [TRUNCATE](r_TRUNCATE.md) 섹션을 참조하세요.

   ```
   TRUNCATE sales.events;
                  
   ERROR: must be owner of relation events
   ```

1. dbadmin 사용자로 데이터베이스에 연결합니다.

1. sales\$1rw 역할에 테이블 자르기 권한을 부여하려면 다음 예시를 사용하세요.

   ```
   GRANT TRUNCATE TABLE TO role sales_rw;
   ```

1. 쿼리 에디터 v2를 사용하여 salesengineer 사용자로 데이터베이스에 연결합니다.

1. 영업 스키마의 이벤트 테이블에서 처음 10개의 이벤트를 읽으려면 다음 예시를 사용하세요.

   ```
   SELECT * FROM sales.events ORDER BY eventid LIMIT 10;
                  
   +---------+---------+-------+--------+-----------------------------+---------------------+
   | eventid | venueid | catid | dateid |          eventname          |      starttime      |
   +---------+---------+-------+--------+-----------------------------+---------------------+
   |       1 |     305 |     8 |   1851 | Comment event               | 2008-01-25 14:30:00 |
   |       2 |     306 |     8 |   2114 | Boris Godunov               | 2008-10-15 20:00:00 |
   |       3 |     302 |     8 |   1935 | Salome                      | 2008-04-19 14:30:00 |
   |       4 |     309 |     8 |   2090 | La Cenerentola (Cinderella) | 2008-09-21 14:30:00 |
   |       5 |     302 |     8 |   1982 | Il Trovatore                | 2008-06-05 19:00:00 |
   |       6 |     308 |     8 |   2109 | L Elisir d Amore            | 2008-10-10 19:30:00 |
   |       7 |     309 |     8 |   1891 | Doctor Atomic               | 2008-03-06 14:00:00 |
   |       8 |     302 |     8 |   1832 | The Magic Flute             | 2008-01-06 20:00:00 |
   |       9 |     308 |     8 |   2087 | The Fly                     | 2008-09-18 19:30:00 |
   |      10 |     305 |     8 |   2079 | Rigoletto                   | 2008-09-10 15:00:00 |
   +---------+---------+-------+--------+-----------------------------+---------------------+
   ```

1. 영업 스키마의 이벤트 테이블을 자르려면 다음 예시를 사용하세요.

   ```
   TRUNCATE sales.events;
   ```

1. 영업 스키마의 업데이트된 이벤트 테이블에서 데이터를 읽으려면 다음 예시를 사용하세요.

   ```
   SELECT * FROM sales.events ORDER BY eventid LIMIT 10;
                  
   +---------+---------+-------+--------+-----------------------------+---------------------+
   | eventid | venueid | catid | dateid |          eventname          |      starttime      |
   +---------+---------+-------+--------+-----------------------------+---------------------+
   ```

### 마케팅 스키마에 대한 읽기 전용 및 읽기-쓰기 역할 생성(선택 사항)
<a name="tutorial-rbac-create-marketing-schema"></a>

이 단계에서는 마케팅 스키마에 대한 읽기 전용 및 읽기-쓰기 역할을 생성합니다.

1. dbadmin 사용자로 데이터베이스에 연결합니다.

1. 마케팅 스키마에 대한 읽기 전용 및 읽기-쓰기 역할을 생성하려면 다음 예시를 사용하세요.

   ```
   CREATE ROLE marketing_ro;
   
   CREATE ROLE marketing_rw;
   
   GRANT USAGE ON SCHEMA marketing TO ROLE marketing_ro, ROLE marketing_rw;
   
   GRANT SELECT ON ALL TABLES IN SCHEMA marketing TO ROLE marketing_ro;
   
   GRANT ROLE marketing_ro TO ROLE marketing_rw;
   
   GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA marketing TO ROLE marketing_rw;
   
   CREATE USER marketinganalyst PASSWORD 'Test12345';
   
   CREATE USER marketingengineer PASSWORD 'Test12345';
   
   GRANT ROLE marketing_ro TO marketinganalyst;
   
   GRANT ROLE marketing_rw TO marketingengineer;
   ```

## RBAC용 시스템 함수(선택 사항)
<a name="tutorial-rbac-system-functions"></a>

Amazon Redshift에는 추가 그룹 또는 역할의 사용자 멤버십 및 역할 멤버십에 대한 시스템 정보를 제공하는 두 가지 함수가 있습니다. 바로 role\$1is\$1member\$1of와 user\$1is\$1member\$1of입니다. 이러한 함수는 슈퍼 사용자와 일반 사용자가 사용할 수 있습니다. 슈퍼 사용자는 모든 역할 멤버십을 확인할 수 있습니다. 일반 사용자는 자신에게 액세스 권한이 부여된 역할의 멤버십만 확인할 수 있습니다.

role\$1is\$1member\$1of 함수를 사용하는 방법

1. salesengineer 사용자로 데이터베이스에 연결합니다.

1. sales\$1rw 역할이 sales\$1ro 역할의 멤버인지 확인하려면 다음 예시를 사용하세요.

   ```
   SELECT role_is_member_of('sales_rw', 'sales_ro');
                  
   +-------------------+
   | role_is_member_of |
   +-------------------+
   | true              |
   +-------------------+
   ```

1. sales\$1ro 역할이 sales\$1rw 역할의 멤버인지 확인하려면 다음 예시를 사용하세요.

   ```
   SELECT role_is_member_of('sales_ro', 'sales_rw');
                  
   +-------------------+
   | role_is_member_of |
   +-------------------+
   | false             |
   +-------------------+
   ```

user\$1is\$1member\$1of 함수를 사용하는 방법

1. salesengineer 사용자로 데이터베이스에 연결합니다.

1. 다음 예시에서는 salesanalyst 사용자의 사용자 멤버십을 확인하려고 시도합니다. 이 쿼리는 오류를 반환합니다. salesengineer에게 salesanalyst에 대한 액세스 권한이 없기 때문입니다. 이 명령을 성공적으로 실행하려면 salesanalyst 사용자로 데이터베이스에 연결하고 예시를 사용하세요.

   ```
   SELECT user_is_member_of('salesanalyst', 'sales_ro');
                  
   ERROR
   ```

1. 슈퍼 사용자로 데이터베이스에 연결합니다.

1. 슈퍼 사용자로 연결했을 때 salesanalyst 사용자의 멤버십을 확인하려면 다음 예시를 사용하세요.

   ```
   SELECT user_is_member_of('salesanalyst', 'sales_ro');
                  
   +-------------------+
   | user_is_member_of |
   +-------------------+
   | true              |
   +-------------------+
   ```

1. dbadmin 사용자로 데이터베이스에 연결합니다.

1. salesengineer 사용자의 멤버십을 확인하려면 다음 예시를 사용하세요.

   ```
   SELECT user_is_member_of('salesengineer', 'sales_ro');
                  
   +-------------------+
   | user_is_member_of |
   +-------------------+
   | true              |
   +-------------------+
                  
   SELECT user_is_member_of('salesengineer', 'marketing_ro');
   
   +-------------------+
   | user_is_member_of |
   +-------------------+
   | false             |
   +-------------------+
                  
   SELECT user_is_member_of('marketinganalyst', 'sales_ro');
                  
   +-------------------+
   | user_is_member_of |
   +-------------------+
   | false             |
   +-------------------+
   ```

## RBAC용 시스템 보기(선택 사항)
<a name="tutorial-rbac-system-views"></a>

역할, 사용자에 대한 역할 할당, 역할 계층 구조 및 역할을 통한 데이터베이스 객체 권한을 보려면 Amazon Redshift의 시스템 보기를 사용하세요. 이러한 보기는 슈퍼 사용자와 일반 사용자가 사용할 수 있습니다. 슈퍼 사용자는 모든 역할 세부 정보를 확인할 수 있습니다. 일반 사용자는 자신에게 액세스 권한이 부여된 역할의 세부 정보만 확인할 수 있습니다.

1. 클러스터에서 명시적으로 역할이 부여된 사용자 목록을 보려면 다음 예시를 사용하세요.

   ```
   SELECT * FROM svv_user_grants;
   ```

1. 클러스터에서 명시적으로 역할이 부여된 역할 목록을 보려면 다음 예시를 사용하세요.

   ```
   SELECT * FROM svv_role_grants;
   ```

시스템 보기의 전체 목록은 [SVV 메타데이터 뷰](svv_views.md) 섹션을 참조하세요.

## RBAC와 함께 행 수준 보안 사용(선택 사항)
<a name="tutorial-rbac-rls"></a>

민감한 데이터에 대한 액세스를 세부적으로 제어하려면 행 수준 보안(RLS)을 사용하세요. RLS에 대한 자세한 내용은 [행 수준 보안](t_rls.md) 섹션을 참조하세요.

이 섹션에서는 Major League Baseball의 `catdesc` 값이 있는 `cat` 테이블의 행만 볼 수 있는 권한을 `salesengineer` 사용자에게 부여하는 RLS 정책을 생성합니다. 그런 다음 `salesengineer` 사용자로 데이터베이스를 쿼리합니다.

1. `salesengineer` 사용자로 데이터베이스에 연결합니다.

1. `cat` 테이블의 처음 5개 항목을 보려면 다음 예시를 사용하세요.

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                     
   +-------+----------+---------+---------------------------------+
   | catid | catgroup | catname |             catdesc             |
   +-------+----------+---------+---------------------------------+
   |     1 | Sports   | MLB     | Major League Baseball           |
   |     2 | Sports   | NHL     | National Hockey League          |
   |     3 | Sports   | NFL     | National Football League        |
   |     4 | Sports   | NBA     | National Basketball Association |
   |     5 | Sports   | MLS     | Major League Soccer             |
   +-------+----------+---------+---------------------------------+
   ```

1. `dbadmin` 사용자로 데이터베이스에 연결합니다.

1. `cat` 테이블의 `catdesc` 열에 대한 RLS 정책을 생성하려면 다음 예시를 사용하세요.

   ```
   CREATE RLS POLICY policy_mlb_engineer
   WITH (catdesc VARCHAR(50)) 
   USING (catdesc = 'Major League Baseball');
   ```

1. RLS 정책을 `sales_rw` 역할에 연결하려면 다음 예시를 사용하세요.

   ```
   ATTACH RLS POLICY policy_mlb_engineer ON sales.cat TO ROLE sales_rw; 
   ```

1. RLS를 활성화하도록 테이블을 변경하려면 다음 예시를 사용하세요.

   ```
   ALTER TABLE sales.cat ROW LEVEL SECURITY ON; 
   ```

1. `salesengineer` 사용자로 데이터베이스에 연결합니다.

1. `cat` 테이블의 처음 5개 항목을 보려고 시도하려면 다음 예시를 사용하세요. `catdesc` 열이 `Major League Baseball`일 때만 항목이 표시된다는 점을 유의하세요.

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                  
   +-------+----------+---------+-----------------------+
   | catid | catgroup | catname |        catdesc        |
   +-------+----------+---------+-----------------------+
   |     1 | Sports   | MLB     | Major League Baseball |
   +-------+----------+---------+-----------------------+
   ```

1. `salesanalyst` 사용자로 데이터베이스에 연결합니다.

1. `cat` 테이블의 처음 5개 항목을 보려고 시도하려면 다음 예시를 사용하세요. 기본값인 모두 거부 정책이 적용되므로 항목이 표시되지 않는다는 점을 유의하세요.

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                  
   +-------+----------+---------+-----------------------+
   | catid | catgroup | catname |        catdesc        |
   +-------+----------+---------+-----------------------+
   ```

1. `dbadmin` 사용자로 데이터베이스에 연결합니다.

1. `sales_ro` 역할에 IGNORE RLS 권한을 부여하려면 다음 예시를 사용하세요. 이렇게 하면 `salesanalyst` 사용자가 `sales_ro` 역할의 구성원이므로 RLS 정책을 무시할 수 있는 권한이 부여됩니다.

   ```
   GRANT IGNORE RLS TO ROLE sales_ro; 
   ```

1. `salesanalyst` 사용자로 데이터베이스에 연결합니다.

1. `cat` 테이블의 처음 5개 항목을 보려면 다음 예시를 사용하세요.

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                  
   +-------+----------+---------+---------------------------------+
   | catid | catgroup | catname |             catdesc             |
   +-------+----------+---------+---------------------------------+
   |     1 | Sports   | MLB     | Major League Baseball           |
   |     2 | Sports   | NHL     | National Hockey League          |
   |     3 | Sports   | NFL     | National Football League        |
   |     4 | Sports   | NBA     | National Basketball Association |
   |     5 | Sports   | MLS     | Major League Soccer             |
   +-------+----------+---------+---------------------------------+
   ```

1. `dbadmin` 사용자로 데이터베이스에 연결합니다.

1. `sales_ro` 역할에서 IGNORE RLS 권한을 취소하려면 다음 예시를 사용하세요.

   ```
   REVOKE IGNORE RLS FROM ROLE sales_ro;
   ```

1. `salesanalyst` 사용자로 데이터베이스에 연결합니다.

1. `cat` 테이블의 처음 5개 항목을 보려고 시도하려면 다음 예시를 사용하세요. 기본값인 모두 거부 정책이 적용되므로 항목이 표시되지 않는다는 점을 유의하세요.

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                  
   +-------+----------+---------+-----------------------+
   | catid | catgroup | catname |        catdesc        |
   +-------+----------+---------+-----------------------+
   ```

1. `dbadmin` 사용자로 데이터베이스에 연결합니다.

1. `cat` 테이블에서 RLS 정책을 분리하려면 다음 예시를 사용하세요.

   ```
   DETACH RLS POLICY policy_mlb_engineer ON cat FROM ROLE sales_rw;
   ```

1. `salesanalyst` 사용자로 데이터베이스에 연결합니다.

1. `cat` 테이블의 처음 5개 항목을 보려고 시도하려면 다음 예시를 사용하세요. 기본값인 모두 거부 정책이 적용되므로 항목이 표시되지 않는다는 점을 유의하세요.

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                  
   +-------+----------+---------+---------------------------------+
   | catid | catgroup | catname |             catdesc             |
   +-------+----------+---------+---------------------------------+
   |     1 | Sports   | MLB     | Major League Baseball           |
   |     2 | Sports   | NHL     | National Hockey League          |
   |     3 | Sports   | NFL     | National Football League        |
   |     4 | Sports   | NBA     | National Basketball Association |
   |     5 | Sports   | MLS     | Major League Soccer             |
   +-------+----------+---------+---------------------------------+
   ```

1. `dbadmin` 사용자로 데이터베이스에 연결합니다.

1. RLS 정책을 삭제하려면 다음 예시를 사용하세요.

   ```
   DROP RLS POLICY policy_mlb_engineer;
   ```

1. RLS를 제거하려면 다음 예시를 사용하세요.

   ```
   ALTER TABLE cat ROW LEVEL SECURITY OFF;
   ```

## 관련 주제
<a name="tutorial-rbac-related-topics"></a>

RBAC에 대한 자세한 내용은 다음 설명서를 참조하세요.
+ [역할 계층 구조](t_role_hierarchy.md)
+ [역할 할당](t_role_assignment.md)
+ [데이터베이스 객체 권한](r_roles-database-privileges.md)
+ [RBAC에 대한 ALTER DEFAULT PRIVILEGES](r_roles-alter-default-privileges.md)

# 행 수준 보안
<a name="t_rls"></a>

Amazon Redshift의 행 수준 보안(RLS)을 사용하면 민감한 데이터에 대한 액세스를 세부적으로 제어할 수 있습니다. 데이터베이스 객체 수준에서 정의된 보안 정책에 따라, 스키마 또는 테이블 내의 특정 데이터 레코드에 액세스할 수 있는 사용자나 역할을 결정할 수 있습니다. 사용자에게 열 하위 집합에 대한 권한을 부여할 수 있는 열 수준 보안 외에도, RLS 정책을 사용하여 표시되는 열의 특정 행에 대한 액세스를 추가로 제한합니다. 열 수준 보안에 대한 자세한 내용은 [열 수준 액세스 제어 사용 시 주의 사항](r_GRANT-usage-notes.md#r_GRANT-usage-notes-clp) 섹션을 참조하세요.

테이블에 RLS 정책을 적용할 때 쿼리 실행 시에 반환되는 결과 집합을 제한할 수 있습니다.

RLS 정책을 생성할 때 Amazon Redshift Redshift가 쿼리에서 테이블의 기존 행을 반환할지 여부를 결정하는 표현식을 지정할 수 있습니다. 액세스를 제한하는 RLS 정책을 만들면 쿼리에 조건을 추가하거나 추가 조건을 외부화할 필요가 없습니다.

RLS 정책을 만들 때는 정책을 간단하게 만들고 정책에 복잡한 문은 사용하지 않는 것이 좋습니다. RLS 정책을 정의할 때 정책을 기반으로 하는 테이블 조인을 정책 정의에 과도하게 사용하지 마세요.

정책이 조회 테이블을 참조하는 경우 Amazon Redshift는 정책이 존재하는 테이블 외에도 추가 테이블을 스캔합니다. RLS 정책이 연결된 사용자와 정책이 연결되지 않은 사용자에 대한 동일한 쿼리 간에 성능 차이가 나타날 수 있습니다.

# SQL 문에 RLS 정책 사용
<a name="t_rls_statements"></a>

SQL 문에 RLS 정책을 사용할 때 Amazon Redshift는 다음 규칙을 적용합니다.
+ Amazon Redshift는 기본적으로 SELECT, UPDATE 및 DELETE 문에 RLS 정책을 적용합니다.
+ SELECT 및 UNLOAD의 경우 Amazon Redshift는 정의된 정책에 따라 행을 필터링합니다.
+ UPDATE의 경우 Amazon Redshift는 사용자에게 표시되는 행만 업데이트합니다. 정책이 테이블 행의 하위 집합을 제한하는 경우 해당 행을 업데이트할 수 없습니다.
+ DELETE의 경우 표시되는 행만 삭제할 수 있습니다. 정책이 테이블 행의 하위 집합을 제한하는 경우 해당 행을 삭제할 수 없습니다. TRUNCATE의 경우 테이블을 자를 수 있습니다.
+ CREATE TABLE LIKE의 경우 LIKE 옵션을 사용하여 생성된 테이블은 소스 테이블에서 권한 설정을 상속하지 않습니다. 마찬가지로, 대상 테이블은 소스 테이블에서 RLS 정책을 상속하지 않습니다.

# 사용자별로 여러 정책 결합
<a name="t_rls_combine_policies"></a>

Amazon Redshift에서 RLS는 사용자 및 객체별로 여러 정책을 연결하는 기능을 지원합니다. 한 사용자에 대해 여러 정책이 정의되어 있는 경우, Amazon Redshift는 테이블에 대한 RLS CONJUNCTION TYPE 설정에 따라 AND 또는 OR 구문을 사용하여 모든 정책을 적용합니다. 접속사 유형에 대한 자세한 정보는 [ALTER TABLE](r_ALTER_TABLE.md) 섹션을 참고하세요.

테이블에 대한 여러 정책이 사용자에게 연결될 수 있습니다. 사용자에게 여러 정책이 직접 연결되어 있거나 사용자가 여러 역할에 속해 있으며, 역할별로 서로 다른 정책이 연결되어 있습니다.

주어진 관계에서 여러 정책이 행 액세스를 제한해야 하는 경우 관계의 RLS CONJUNCTION TYPE을 AND로 설정할 수 있습니다. 다음 예제를 살펴보세요. Alice는 지정된 정책으로 'catname'이 NBA인 Sports 이벤트만 볼 수 있습니다.

```
-- Create an analyst role and grant it to a user named Alice.
CREATE ROLE analyst;
CREATE USER alice WITH PASSWORD 'Name_is_alice_1';
GRANT ROLE analyst TO alice;

-- Create an RLS policy that only lets the user see sports.
CREATE RLS POLICY policy_sports
WITH (catgroup VARCHAR(10))
USING (catgroup = 'Sports');

-- Create an RLS policy that only lets the user see NBA.
CREATE RLS POLICY policy_nba
WITH (catname VARCHAR(10))
USING (catname = 'NBA');

-- Attach both to the analyst role.
ATTACH RLS POLICY policy_sports ON category TO ROLE analyst;
ATTACH RLS POLICY policy_nba ON category TO ROLE analyst;

-- Activate RLS on the category table with AND CONJUNCTION TYPE. 
ALTER TABLE category ROW LEVEL SECURITY ON CONJUNCTION TYPE AND;

-- Change session to Alice.
SET SESSION AUTHORIZATION alice;

-- Select all from the category table.
SELECT catgroup, catname
FROM category;

 catgroup | catname 
---------+---------
 Sports   | NBA
(1 row)
```

주어진 관계에서 여러 정책이 사용자가 더 많은 행을 보도록 허용해야 하는 경우 관계의 RLS CONJUNCTION TYPE을 OR로 설정할 수 있습니다. 다음 예제를 살펴보세요. Alice는 지정된 정책으로 'Concerts'와 'Sports'만 볼 수 있습니다.

```
-- Create an analyst role and grant it to a user named Alice.
CREATE ROLE analyst;
CREATE USER alice WITH PASSWORD 'Name_is_alice_1';
GRANT ROLE analyst TO alice;

-- Create an RLS policy that only lets the user see concerts.
CREATE RLS POLICY policy_concerts
WITH (catgroup VARCHAR(10))
USING (catgroup = 'Concerts');

-- Create an RLS policy that only lets the user see sports.
CREATE RLS POLICY policy_sports
WITH (catgroup VARCHAR(10))
USING (catgroup = 'Sports');

-- Attach both to the analyst role.
ATTACH RLS POLICY policy_concerts ON category TO ROLE analyst;
ATTACH RLS POLICY policy_sports ON category TO ROLE analyst;

-- Activate RLS on the category table with OR CONJUNCTION TYPE. 
ALTER TABLE category ROW LEVEL SECURITY ON CONJUNCTION TYPE OR;

-- Change session to Alice.
SET SESSION AUTHORIZATION alice;

-- Select all from the category table.
SELECT catgroup, count(*)
FROM category
GROUP BY catgroup ORDER BY catgroup;

 catgroup | count 
---------+-------
 Concerts |  3
 Sports   |  5
(2 rows)
```

# RLS 정책 소유권 및 관리
<a name="t_rls_ownership"></a>

슈퍼 사용자, 보안 관리자 또는 sys:secadmin 역할이 부여된 사용자는 RLS 정책을 만들고 수정하고 연결하고 분리할 수 있습니다. RLS 정책은 테이블, 뷰, 지연 바인딩 뷰(LBV) 및 구체화된 뷰(MV)에 연결될 수 있습니다. 테이블의 스키마 정의를 수정하지 않고, 객체 수준에서 행 수준 보안을 설정하거나 해제할 수 있습니다.

행 수준 보안을 시작하기 위해 사용할 수 있는 SQL 문은 다음과 같습니다.
+ ALTER TABLE 문을 사용하여 테이블, 뷰 또는 지연 바인딩 뷰에 대해 RLS를 설정하거나 해제합니다. 자세한 내용은 [ALTER TABLE](r_ALTER_TABLE.md) 섹션을 참조하세요.
+ ALTER MATERIALIZED VIEW 문을 사용하여 구체화된 뷰(MV)에서 RLS를 설정하거나 해제합니다. 자세한 내용은 [ALTER MATERIALIZED VIEW](r_ALTER_MATERIALIZED_VIEW.md) 섹션을 참조하세요.
+ CREATE RLS POLICY 문을 사용하여 하나 이상의 테이블에 대한 보안 정책을 생성하고, 정책에서 하나 이상의 사용자 또는 역할을 지정합니다.

  자세한 내용은 [CREATE RLS POLICY](r_CREATE_RLS_POLICY.md) 섹션을 참조하세요.
+ ALTER RLS POLICY 명령문을 사용하여 정책 정의 변경과 같은 정책을 변경할 수 있습니다. 여러 테이블 또는 뷰에 동일한 정책을 사용할 수 있습니다.

  자세한 내용은 [ALTER RLS POLICY](r_ALTER_RLS_POLICY.md) 섹션을 참조하세요.
+ ATTACH RLS POLICY 문을 사용하여 하나 이상의 관계, 하나 이상의 사용자 또는 역할에 정책을 연결합니다.

  자세한 내용은 [ATTACH RLS POLICY](r_ATTACH_RLS_POLICY.md) 섹션을 참조하세요.
+ DETACH RLS POLICY 문을 사용하여 하나 이상의 관계, 하나 이상의 사용자 또는 역할에서 정책을 분리합니다.

  자세한 내용은 [DETACH RLS POLICY](r_DETACH_RLS_POLICY.md) 섹션을 참조하세요.
+ DROP RLS POLICY 문을 사용하여 정책을 삭제합니다.

  자세한 내용은 [DROP RLS POLICY](r_DROP_RLS_POLICY.md) 섹션을 참조하세요.
+ GRANT 및 REVOKE 문을 사용하여 조회 테이블을 참조하는 RLS 정책에 SELECT 권한을 명시적으로 부여하고 취소합니다. 자세한 내용은 [GRANT](r_GRANT.md) 및 [REVOKE](r_REVOKE.md) 섹션을 참조하세요.

sys:secadmin은 [SVV\$1RLS\$1POLICY](r_SVV_RLS_POLICY.md) 및 [SVV\$1RLS\$1ATTACHED\$1POLICY](r_SVV_RLS_ATTACHED_POLICY.md)을 통해 생성된 정책을 모니터링할 수 있습니다.

RLS로 보호된 관계를 나열하기 위해 sys:secadmin은 [SVV\$1RLS\$1RELATION](r_SVV_RLS_RELATION.md)을 볼 수 있습니다.

수퍼유저, sys:operator 또는 ACCESS SYSTEM TABLE 시스템 권한이 있는 모든 사용자는 [SVV\$1RLS\$1APPLIED\$1POLICY](r_SVV_RLS_APPLIED_POLICY.md)를 통해 RLS로 보호되는 관계를 참조하는 쿼리에 대한 RLS 정책의 적용을 추적할 수 있습니다. sys:secadmin에게는 기본적으로 이러한 권한이 부여되지 않습니다.

사용자에게 RLS로 보호된 관계에 대한 전체 액세스 권한을 허용하려면 IGNORE RLS 권한을 부여하면 됩니다. 슈퍼 사용자 또는 sys:secadmin에게는 자동으로 IGNORE RLS 권한이 부여됩니다. 자세한 내용은 [GRANT](r_GRANT.md) 섹션을 참조하세요.

EXPLAIN 계획에서 쿼리의 RLS 정책 필터를 설명하여 RLS 관련 쿼리 문제를 해결하려면, 사용자에게 EXPLAIN RLS 권한을 부여합니다. 자세한 내용은 [GRANT](r_GRANT.md) 및 [EXPLAIN](r_EXPLAIN.md) 섹션을 참조하세요.

# 정책 종속 객체 및 원칙
<a name="t_rls_object_dependency"></a>

애플리케이션의 보안을 제공하고 정책 객체가 오래되거나 잘못되는 것을 방지하기 위해, Amazon Redshift는 RLS 정책에서 참조하는 객체를 삭제하거나 변경하는 것을 허용하지 않습니다.

다음은 Amazon Redshift가 RLS 정책에 대해 추적하는 스키마 객체 종속성의 목록입니다.
+ 대상 테이블의 스키마 객체 종속성을 추적할 때 Amazon Redshift는 다음 규칙을 따릅니다.
  + Amazon Redshift는 대상 테이블을 삭제할 때 관계, 사용자, 역할 또는 퍼블릭 객체로부터 정책을 분리합니다.
  + 대상 테이블의 이름을 바꾸더라도 연결된 정책에는 영향을 주지 않습니다.
  + 먼저 정책을 삭제하거나 분리하면, 정책 정의 내에서 참조되는 대상 테이블의 열만 삭제할 수 있습니다. 이는 CASCADE 옵션이 지정된 경우에도 적용됩니다. 대상 테이블의 다른 열은 삭제할 수 있습니다.
  + 대상 테이블에서 참조된 열의 이름은 바꿀 수 없습니다. 참조된 열의 이름을 바꾸려면 먼저 정책을 분리합니다. 이는 CASCADE 옵션이 지정된 경우에도 적용됩니다.
  + CASCADE 옵션을 지정하는 경우에도 참조된 열의 유형은 변경할 수 없습니다.
+ 조회 테이블의 스키마 객체 종속성을 추적할 때 Amazon Redshift는 다음 규칙을 따릅니다.
  + 조회 테이블은 삭제할 수 없습니다. 조회 테이블을 삭제하려면 조회 테이블을 참조하는 정책을 먼저 삭제합니다.
  + 조회 테이블의 이름을 바꿀 수 없습니다. 조회 테이블의 이름을 바꾸려면 조회 테이블을 참조하는 정책을 먼저 삭제합니다. 이는 CASCADE 옵션이 지정된 경우에도 적용됩니다.
  + 정책 정의에 사용된 조회 테이블 열은 삭제할 수 없습니다. 정책 정의에 사용된 조회 테이블 열을 삭제하려면 조회 테이블을 참조하는 정책을 먼저 삭제합니다. 이는 ALTER TABLE DROP COLUMN 문에 CASCADE 옵션이 지정되어 있는 경우에도 적용됩니다. 조회 테이블의 다른 열은 삭제할 수 있습니다.
  + 조회 테이블에서 참조된 열의 이름은 바꿀 수 없습니다. 참조된 열의 이름을 바꾸려면 조회 테이블을 참조하는 정책을 먼저 삭제합니다. 이는 CASCADE 옵션이 지정된 경우에도 적용됩니다.
  + 참조된 열의 유형은 변경할 수 없습니다.
+ 사용자 또는 역할이 삭제되면 Amazon Redshift가 사용자 또는 역할에 연결된 모든 정책을 자동으로 분리합니다.
+ DROP SCHEMA 문에 CASCADE 옵션을 사용하면 Amazon Redshift가 스키마의 관계도 삭제합니다. 또한 삭제된 스키마의 관계에 종속된 다른 스키마의 관계도 삭제합니다. 정책의 조회 테이블인 관계의 경우, Amazon Redshift에서 DROP SCHEMA DDL이 실패합니다. DROP SCHEMA 문에 의해 삭제된 관계의 경우, Amazon Redshift는 해당 관계에 연결된 모든 정책을 분리합니다.
+ 해당 정책도 삭제하는 경우에만 조회 함수(정책 정의 내에서 참조되는 함수)를 삭제할 수 있습니다. 이는 CASCADE 옵션이 지정된 경우에도 적용됩니다.
+ 정책이 테이블에 연결되면 Amazon Redshift가 이 테이블이 다른 정책에서 조회 테이블인지 확인합니다. 이 경우 Amazon Redshift는 이 테이블에 정책을 연결하도록 허용하지 않습니다.
+ RLS 정책을 생성할 때 Amazon Redshift는 이 테이블이 다른 RLS 정책의 대상 테이블인지 확인합니다. 이 경우 Amazon Redshift는 이 테이블에 대한 정책을 생성하도록 허용하지 않습니다.

## 예제
<a name="t_rls_object_dependency-example"></a>

다음 예제는 스키마 종속성이 추적되는 방법을 보여 줍니다.

```
-- The CREATE and ATTACH policy statements for `policy_events` references some
-- target and lookup tables.
-- Target tables are tickit_event_redshift and target_schema.target_event_table.
-- Lookup table is tickit_sales_redshift.
-- Policy `policy_events` has following dependencies:
--   table tickit_sales_redshift column eventid, qtysold
--   table tickit_event_redshift column eventid
--   table target_event_table column eventid
--   schema public and target_schema
CREATE RLS POLICY policy_events
WITH (eventid INTEGER)
USING (
    eventid IN (SELECT eventid FROM tickit_sales_redshift WHERE qtysold <3)
);

ATTACH RLS POLICY policy_events ON tickit_event_redshift TO ROLE analyst;

ATTACH RLS POLICY policy_events ON target_schema.target_event_table TO ROLE consumer;
```

# RLS 정책 사용 고려 사항 및 제한 사항
<a name="t_rls_usage"></a>

## 고려 사항
<a name="t_rls_considerations"></a>

다음은 RLS 정책 작업에 대한 고려 사항입니다.
+ Amazon Redshift는 SELECT, UPDATE 또는 DELETE 문에 RLS 정책을 적용합니다.
+ Amazon Redshift는 INSERT, COPY, ALTER TABLE APPEND 문에 RLS 정책을 적용하지 않습니다.
+ RLS 정책은 테이블, 뷰, 지연 바인딩 뷰(LBV) 및 구체화된 뷰(MV)에 연결될 수 있습니다.
+ 행 수준 보안은 열 수준 보안과 함께 작동하며 데이터를 보호합니다.
+ 소스 관계에 대해 RLS가 활성화되면 Amazon Redshift는 수퍼유저, 시스템 권한 IGNORE RLS 또는 sys:secadmin 역할이 명시적으로 부여된 사용자에 대해 ALTER TABLE APPEND 문을 지원합니다. 이 경우 ALTER TABLE APPEND 문을 실행하여 기존 소스 테이블에서 데이터를 이동하는 방법으로 대상 테이블에 행을 추가할 수 있습니다. Amazon Redshift는 소스 관계의 모든 튜플을 대상 관계로 이동합니다. 대상 관계의 RLS 상태는 ALTER TABLE APPEND 문에는 영향을 미치지 않습니다.
+ 다른 데이터 웨어하우스 시스템에서 손쉽게 마이그레이션하려면, 변수 이름 및 값을 지정하여 연결에 대한 사용자 지정 세션 컨텍스트 변수를 설정하고 검색하면 됩니다.

  다음 예는 행 수준 보안(RLS) 정책에 대한 세션 컨텍스트 변수를 설정합니다.

  ```
  -- Set a customized context variable.
  SELECT set_config(‘app.category’, ‘Concerts’, FALSE);
  
  -- Create a RLS policy using current_setting() to get the value of a customized context variable.
  CREATE RLS POLICY policy_categories
  WITH (catgroup VARCHAR(10)) 
  USING (catgroup = current_setting('app.category', FALSE));
  
  -- Set correct roles and attach the policy on the target table to one or more roles.
  ATTACH RLS POLICY policy_categories ON tickit_category_redshift TO ROLE analyst, ROLE dbadmin;
  ```

  사용자 지정 세션 컨텍스트 변수를 설정 및 검색하는 방법을 자세히 알아보려면 [SET](r_SET.md), [SET\$1CONFIG](r_SET_CONFIG.md), [SHOW](r_SHOW.md), [CURRENT\$1SETTING](r_CURRENT_SETTING.md), [reset](r_RESET.md) 섹션으로 이동하세요. 일반적인 서버 구성 수정 방법을 자세히 알아보려면 [서버 구성 수정](cm_chap_ConfigurationRef.md#t_Modifying_the_default_settings) 섹션으로 이동하세요.
**중요**  
 RLS 정책 내에서 세션 컨텍스트 변수를 사용하는 경우 보안 정책은 정책을 간접 호출하는 사용자 또는 역할에 따라 달라집니다. RLS 정책에서 세션 컨텍스트 변수를 사용할 때는 보안 취약성이 발생하지 않도록 주의하세요.
+ DECLARE와 FETCH 사이 또는 후속 FETCH 문 사이에서 SET SESSION AUTHORIZATION을 사용하여 세션 사용자를 변경하면 DECLARE 시간에 사용자 정책을 기반으로 이미 준비된 계획이 새로 고쳐지지 않습니다. 커서가 RLS 보호 테이블과 함께 사용되는 경우 세션 사용자를 변경하지 마세요.
+ 뷰 객체 내의 기본 객체가 RLS로 보호되는 경우 쿼리를 실행하는 사용자에게 연결된 정책이 각 기본 객체에 적용됩니다. 이는 뷰 기본 객체에 대해 뷰 소유자의 권한을 확인하는 객체 수준 권한 확인과 다릅니다. EXPLAIN 계획 출력에서 쿼리의 RLS 보호 관계를 볼 수 있습니다.
+ 사용자에게 연결된 관계의 RLS 정책에서 사용자 정의 함수 (UDF) 를 참조하는 경우 사용자는 UDF에 대한 EXECUTE 권한이 있어야 관계를 쿼리할 수 있습니다.
+  행 수준 보안은 쿼리 최적화를 제한할 수 있습니다. 대규모 데이터 세트에 RLS로 보호되는 뷰를 배포하기 전에 쿼리 성능을 신중하게 평가하는 것이 좋습니다.
+  지연 바인딩 뷰에 적용된 행 수준 보안 정책은 페더레이션된 테이블로 푸시될 수 있습니다. 이러한 RLS 정책은 외부 처리 엔진 로그에서 볼 수 있습니다.

## 제한 사항
<a name="t_rls_limitations"></a>

RLS 정책과 관련한 작업을 할 때의 제한 사항은 다음과 같습니다.
+ RLS 정책은 외부 테이블 및 다른 여러 관계 유형에 연결할 수 없습니다. 자세한 내용은 [ATTACH RLS POLICY](r_ATTACH_RLS_POLICY.md) 섹션을 참조하세요.
+ Amazon Redshift는 복잡한 조인이 있는 조회를 사용하는 특정 RLS 정책에 대해 SELECT 문을 지원하지만 UPDATE 또는 DELETE 문은 지원하지 않습니다. UPDATE 또는 DELETE 문의 경우 Amazon Redshift는 다음 오류를 반환합니다.

  ```
  ERROR: One of the RLS policies on target relation is not supported in UPDATE/DELETE.
  ```
+ 사용자에게 연결된 관계의 RLS 정책에서 사용자 정의 함수(UDF)를 참조할 때마다, 사용자는 UDF에 대한 EXECUTE 권한이 있어야 관계를 쿼리할 수 있습니다.
+ 연관된 하위 쿼리는 지원되지 않습니다. Amazon Redshift는 다음 오류를 반환합니다.

  ```
  ERROR: RLS policy could not be rewritten.
  ```
+ Amazon Redshift Redshift는 RLS와의 데이터 공유를 지원하지 않습니다. 관계에서 데이터 공유에 대한 RLS를 끄지 않은 경우, 다음 오류가 표시되면서 소비자 클러스터에서 쿼리가 실패하게 됩니다.

  ```
  RLS-protected relation "rls_protected_table" cannot be accessed via datasharing query.
  ```

  ROW LEVEL SECURITY OFF FOR DATASHARES 파라미터와 함께 ALTER TABLE 명령을 사용하여 데이터 공유에 대한 RLS를 해제할 수 있습니다. 테이블 변경을 사용하여 RLS를 활성화 또는 비활성화하는 방법에 대한 자세한 내용은 [ALTER TABLE](r_ALTER_TABLE.md) 섹션을 참조하세요.
+ 데이터베이스 간 쿼리에서 Amazon Redshift는 RLS 보호 관계에 대한 읽기를 차단합니다. IGNORE RLS 권한이 있는 사용자는 데이터베이스 간 쿼리를 사용하여 보호된 관계에 액세스할 수 있습니다. IGNORE RLS 권한이 없는 사용자가 데이터베이스 간 쿼리를 통해 RLS 보호 관계에 액세스하면 다음 오류가 나타납니다.

  ```
  RLS-protected relation "rls_protected_table" cannot be accessed via cross-database query.
  ```
+ ALTER RLS POLICY는 USING(using\$1predicate\$1exp) 절을 사용하여 RLS 정책을 수정하는 것만 지원합니다. ALTER RLS POLICY를 실행할 때는 WITH 절을 사용하여 RLS 정책을 수정할 수 없습니다.
+ 다음 구성 옵션의 값이 세션의 기본값과 일치하지 않는 경우 행 수준 보안이 설정된 관계를 쿼리할 수 없습니다.
  +  `enable_case_sensitive_super_attribute` 
  +  `enable_case_sensitive_identifier` 
  +  `downcase_delimited_identifier` 

  행 수준 보안이 설정된 상태에서 관계를 쿼리하려고 할 때 "대/소문자 구분이 기본값과 다른 경우 RLS 보호 관계가 세션 수준 구성을 지원하지 않습니다."라는 메시지가 표시되는 경우 세션의 구성 옵션을 재설정해 보세요.
+  프로비저닝된 클러스터 또는 서버리스 네임스페이스에 행 수준 보안 정책이 있는 경우 일반 사용자에게는 다음 명령이 차단됩니다.

  ```
  ALTER <current_user> SET enable_case_sensitive_super_attribute/enable_case_sensitive_identifier/downcase_delimited_identifier
  ```

  RLS 정책을 만들 때 일반 사용자의 기본 구성 옵션 설정을 정책을 만들 당시의 세션의 구성 옵션 설정과 일치하도록 변경하는 것이 좋습니다. 슈퍼유저 및 ALTER USER 권한이 있는 사용자는 파라미터 그룹 설정 또는 ALTER USER 명령을 사용하여 이 작업을 수행할 수 있습니다. 파라미터 그룹에 대한 자세한 내용은 **Amazon Redshift 관리 안내서의 [Amazon Redshift 파라미터 그룹](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-parameter-groups.html)을 참조하세요. ALTER USER 명령에 대한 자세한 내용은 [ALTER USER](r_ALTER_USER.md) 섹션을 참조하세요.
+  행 수준 보안 정책이 적용된 뷰와 지연 바인딩 뷰는 일반 사용자가 [CREATE VIEW](r_CREATE_VIEW.md) 명령을 사용하여 교체할 수 없습니다. RLS 정책이 적용된 뷰 또는 LBV를 바꾸려면 먼저 연결된 RLS 정책을 분리하고 뷰 또는 LBV를 교체한 다음, 정책을 다시 연결합니다. 슈퍼 사용자 및 `sys:secadmin permission`이 있는 사용자는 정책을 분리하지 않고도 RLS 정책이 적용된 뷰 또는 LBV에 CREATE VIEW를 사용할 수 있습니다.
+  행 수준 보안 정책이 적용된 뷰는 시스템 테이블과 시스템 뷰를 참조할 수 없습니다.
+  일반 뷰에서 참조하는 지연 바인딩 뷰는 RLS로 보호될 수 없습니다.
+  RLS로 보호되는 관계와 데이터 레이크의 중첩 데이터는 동일한 쿼리에서 액세스할 수 없습니다.

# RLS 성능 관련 모범 사례
<a name="t_rls_performance"></a>

다음은 RLS로 보호되는 테이블에서 높은 Amazon Redshift 성능을 보장하기 위한 모범 사례입니다.

## 연산자 및 함수의 안전
<a name="t_rls_safe_operators"></a>

RLS 보호 테이블을 쿼리할 때 특정 연산자나 함수를 사용하면 성능이 저하될 수 있습니다. Amazon Redshift는 RLS 보호 테이블을 쿼리할 때 연산자와 함수를 안전하거나 안전하지 않은 것으로 분류합니다. 함수나 연산자는 입력에 따라 관찰 가능한 부작용이 없는 경우 RLS 안전으로 분류됩니다. 구체적으로 살펴보면, RLS 안전 함수 또는 연산자는 다음 중 하나일 수 없습니다.
+ 오류 메시지를 포함하거나 포함하지 않은 상태로, 입력 값 또는 입력 값에 종속된 값을 출력합니다.
+ 입력 값에 종속된 오류를 실패 처리하거나 반환합니다.

RLS 불안전 연산자는 다음과 같습니다.
+ 산술 연산자: \$1, -, /, \$1, %.
+ 텍스트 연산자: LIKE 및 SIMILAR TO
+ 변환 운영자
+ UDF

다음 SELECT 문을 사용하여 연산자와 함수의 안전성을 검사합니다.

```
SELECT proname, proc_is_rls_safe(oid) FROM pg_proc;
```

Amazon Redshift는 RLS 보호 테이블에 대한 쿼리를 계획할 때 RLS 불안전 연산자 및 함수를 포함하는 사용자 조건자의 평가 순서를 제한합니다. RLS 불안전 연산자 또는 함수를 참조하는 쿼리는 RLS 보호 테이블을 쿼리할 때 성능이 저하될 수 있습니다. Amazon Redshift가 정렬 키를 활용하기 위해 RLS 불안전 조건자를 기본 테이블 스캔으로 푸시다운할 수 없는 경우 성능이 크게 저하될 수 있습니다. 더 나은 성능을 얻으려면 정렬 키를 활용하는 RLS 불안전 조건자를 사용하는 쿼리는 사용하지 마세요. Amazon Redshift가 연산자와 함수를 푸시다운할 수 있는지 확인하려면 EXPLAIN 문을 시스템 권한 EXPLAIN RLS와 함께 사용하면 됩니다.

## 결과 캐싱
<a name="t_rls_result_cache"></a>

쿼리 런타임을 줄이고 시스템 성능을 향상시키기 위해 Amazon Redshift는 특정 형식의 쿼리 결과를 리더 노드의 메모리에 캐시합니다.

Amazon Redshift는 보호되지 않은 테이블에 대한 조건이 모두 충족되고 다음 조건이 모두 충족될 경우, 새 쿼리 스캐닝 RLS 보호 테이블에 캐싱된 결과를 사용합니다.
+ 정책의 테이블 또는 보기가 수정되지 않았습니다.
+ 정책은 실행 시마다 평가되어야 하는 함수(예: GETDATE 또는 CURRENT\$1USER)를 사용하지 않습니다.

성능을 높이려면, 이전 조건을 충족하지 않는 정책 조건자를 사용하지 마세요.

Amazon Redshift의 결과 캐싱에 대한 자세한 내용은 [결과 캐싱](c_challenges_achieving_high_performance_queries.md#result-caching) 섹션을 참조하세요.

## 복잡한 정책
<a name="t_rls_complex_policies"></a>

성능을 높이려면 여러 테이블을 조인하는 하위 쿼리에 복잡한 정책을 사용하지 마세요.

# 행 수준 보안 엔드 투 엔드 예제
<a name="t_rls-example"></a>

다음은 수퍼유저가 몇 가지 사용자와 역할을 만드는 방법을 보여주는 자세한 예입니다. 그러면 secadmin 역할이 부여된 사용자가 RLS 정책을 생성, 연결, 분리 및 삭제합니다. 이 예에서는 tickit 샘플 데이터베이스를 사용합니다. 자세한 내용은 *Amazon Redshift 시작 안내서*의 [Amazon S3에서 Amazon Redshift로 데이터 로드](https://docs.aws.amazon.com/redshift/latest/gsg/rs-gsg-create-sample-db.html)를 참조하세요.

```
-- Create users and roles referenced in the policy statements.
CREATE ROLE analyst;
CREATE ROLE consumer;
CREATE ROLE dbadmin;
CREATE ROLE auditor;
CREATE USER bob WITH PASSWORD 'Name_is_bob_1';
CREATE USER alice WITH PASSWORD 'Name_is_alice_1';
CREATE USER joe WITH PASSWORD 'Name_is_joe_1';
CREATE USER molly WITH PASSWORD 'Name_is_molly_1';
CREATE USER bruce WITH PASSWORD 'Name_is_bruce_1';
GRANT ROLE sys:secadmin TO bob;
GRANT ROLE analyst TO alice;
GRANT ROLE consumer TO joe;
GRANT ROLE dbadmin TO molly;
GRANT ROLE auditor TO bruce;
GRANT ALL ON TABLE tickit_category_redshift TO PUBLIC;
GRANT ALL ON TABLE tickit_sales_redshift TO PUBLIC;
GRANT ALL ON TABLE tickit_event_redshift TO PUBLIC;

-- Create table and schema referenced in the policy statements.
CREATE SCHEMA target_schema;
GRANT ALL ON SCHEMA target_schema TO PUBLIC;
CREATE TABLE target_schema.target_event_table (LIKE tickit_event_redshift);
GRANT ALL ON TABLE target_schema.target_event_table TO PUBLIC;

-- Change session to analyst alice.
SET SESSION AUTHORIZATION alice;

-- Check the tuples visible to analyst alice.
-- Should contain all 3 categories.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Change session to security administrator bob.
SET SESSION AUTHORIZATION bob;

CREATE RLS POLICY policy_concerts
WITH (catgroup VARCHAR(10))
USING (catgroup = 'Concerts');

SELECT poldb, polname, polalias, polatts, polqual, polenabled, polmodifiedby FROM svv_rls_policy WHERE poldb = CURRENT_DATABASE();

ATTACH RLS POLICY policy_concerts ON tickit_category_redshift TO ROLE analyst, ROLE dbadmin;

ALTER TABLE tickit_category_redshift ROW LEVEL SECURITY ON;

SELECT * FROM svv_rls_attached_policy;

-- Change session to analyst alice.
SET SESSION AUTHORIZATION alice;

-- Check that tuples with only `Concert` category will be visible to analyst alice.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Change session to consumer joe.
SET SESSION AUTHORIZATION joe;

-- Although the policy is attached to a different role, no tuples will be
-- visible to consumer joe because the default deny all policy is applied.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Change session to dbadmin molly.
SET SESSION AUTHORIZATION molly;

-- Check that tuples with only `Concert` category will be visible to dbadmin molly.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Check that EXPLAIN output contains RLS SecureScan to prevent disclosure of
-- sensitive information such as RLS filters.
EXPLAIN SELECT catgroup, count(*) FROM tickit_category_redshift GROUP BY catgroup ORDER BY catgroup;

-- Change session to security administrator bob.
SET SESSION AUTHORIZATION bob;

-- Grant IGNORE RLS permission so that RLS policies do not get applicable to role dbadmin.
GRANT IGNORE RLS TO ROLE dbadmin;

-- Grant EXPLAIN RLS permission so that anyone in role auditor can view complete EXPLAIN output.
GRANT EXPLAIN RLS TO ROLE auditor;

-- Change session to dbadmin molly.
SET SESSION AUTHORIZATION molly;

-- Check that all tuples are visible to dbadmin molly because `IGNORE RLS` is granted to role dbadmin.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Change session to auditor bruce.
SET SESSION AUTHORIZATION bruce;

-- Check explain plan is visible to auditor bruce because `EXPLAIN RLS` is granted to role auditor.
EXPLAIN SELECT catgroup, count(*) FROM tickit_category_redshift GROUP BY catgroup ORDER BY catgroup;

-- Change session to security administrator bob.
SET SESSION AUTHORIZATION bob;

DETACH RLS POLICY policy_concerts ON tickit_category_redshift FROM ROLE analyst, ROLE dbadmin;

-- Change session to analyst alice.
SET SESSION AUTHORIZATION alice;

-- Check that no tuples are visible to analyst alice.
-- Although the policy is detached, no tuples will be visible to analyst alice
-- because of default deny all policy is applied if the table has RLS on.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Change session to security administrator bob.
SET SESSION AUTHORIZATION bob;

CREATE RLS POLICY policy_events
WITH (eventid INTEGER) AS ev
USING (
    ev.eventid IN (SELECT eventid FROM tickit_sales_redshift WHERE qtysold <3)
);

ATTACH RLS POLICY policy_events ON tickit_event_redshift TO ROLE analyst;
ATTACH RLS POLICY policy_events ON target_schema.target_event_table TO ROLE consumer;

RESET SESSION AUTHORIZATION;

-- Can not cannot alter type of dependent column.
ALTER TABLE target_schema.target_event_table ALTER COLUMN eventid TYPE float;
ALTER TABLE tickit_event_redshift ALTER COLUMN eventid TYPE float;
ALTER TABLE tickit_sales_redshift ALTER COLUMN eventid TYPE float;
ALTER TABLE tickit_sales_redshift ALTER COLUMN qtysold TYPE float;

-- Can not cannot rename dependent column.
ALTER TABLE target_schema.target_event_table RENAME COLUMN eventid TO renamed_eventid;
ALTER TABLE tickit_event_redshift RENAME COLUMN eventid TO renamed_eventid;
ALTER TABLE tickit_sales_redshift RENAME COLUMN eventid TO renamed_eventid;
ALTER TABLE tickit_sales_redshift RENAME COLUMN qtysold TO renamed_qtysold;

-- Can not drop dependent column.
ALTER TABLE target_schema.target_event_table DROP COLUMN eventid CASCADE;
ALTER TABLE tickit_event_redshift DROP COLUMN eventid CASCADE;
ALTER TABLE tickit_sales_redshift DROP COLUMN eventid CASCADE;
ALTER TABLE tickit_sales_redshift DROP COLUMN qtysold CASCADE;

-- Can not drop lookup table.
DROP TABLE tickit_sales_redshift CASCADE;

-- Change session to security administrator bob.
SET SESSION AUTHORIZATION bob;

DROP RLS POLICY policy_concerts;
DROP RLS POLICY IF EXISTS policy_events;

ALTER TABLE tickit_category_redshift ROW LEVEL SECURITY OFF;

RESET SESSION AUTHORIZATION;

-- Drop users and roles.
DROP USER bob;
DROP USER alice;
DROP USER joe;
DROP USER molly;
DROP USER bruce;
DROP ROLE analyst;
DROP ROLE consumer;
DROP ROLE auditor FORCE;
DROP ROLE dbadmin FORCE;
```

# 메타데이터 보안
<a name="t_metadata_security"></a>

Amazon Redshift의 행 수준 보안과 마찬가지로 메타데이터 보안을 사용하면 메타데이터를 보다 세밀하게 제어할 수 있습니다. 프로비저닝된 클러스터 또는 서버리스 작업 그룹에 메타데이터 보안이 활성화된 경우 사용자는 보기 액세스 권한이 있는 객체의 메타데이터를 볼 수 있습니다. 메타데이터 보안을 사용하면 필요에 따라 가시성을 구분할 수 있습니다. 예를 들어 단일 데이터 웨어하우스를 사용하여 모든 데이터 스토리지를 중앙 집중화할 수 있습니다. 그러나 여러 섹터에 데이터를 저장하는 경우 보안 관리가 번거로울 수 있습니다. 메타데이터 보안을 활성화하면 가시성을 구성할 수 있습니다. 한 섹터의 사용자는 자신의 객체에 대해 더 큰 가시성을 가지는 동시에 다른 섹터 사용자에게는 보기 액세스를 제한할 수 있습니다. 메타데이터 보안은 스키마, 테이블, 뷰, 구체화된 뷰, 저장 프로시저, 사용자 정의 함수 및 기계 학습 모델과 같은 모든 객체 유형을 지원합니다.

사용자는 다음과 같은 상황에서 객체의 메타데이터를 볼 수 있습니다.
+ 사용자에게 객체 액세스 권한이 부여된 경우
+ 사용자가 속한 그룹 또는 역할에 객체 액세스 권한이 부여된 경우
+ 객체는 공개됩니다(퍼블릭).
+ 사용자는 데이터베이스 객체의 소유자입니다.

메타데이터 보안을 활성화하려면 [ALTER SYSTEM](https://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_SYSTEM.html) 명령을 사용합니다. 다음은 ALTER SYSTEM 명령을 메타데이터 보안과 함께 사용하는 방법을 나타내는 구문입니다.

```
ALTER SYSTEM SET metadata_security=[true|t|on|false|f|off];
```

메타데이터 보안을 활성화하면 필요한 권한을 가진 모든 사용자가 액세스 권한이 있는 객체의 관련 메타데이터를 볼 수 있습니다. 특정 사용자만 메타데이터 보안을 볼 수 있게 하려면 역할에 `ACCESS CATALOG` 권한을 부여한 다음 사용자에게 역할을 할당하세요. 역할을 사용하여 보안을 강화하는 방법에 대한 자세한 내용은 [역할 기반 액세스 제어](https://docs.aws.amazon.com/redshift/latest/dg/t_Roles.html)를 참조하세요.

다음 예시는 역할에 `ACCESS CATALOG` 권한을 부여한 다음 사용자에게 역할을 할당하는 방법을 보여줍니다. 권한을 부여하는 방법에 대한 자세한 내용은 [GRANT](https://docs.aws.amazon.com/redshift/latest/dg/r_GRANT.html) 명령을 참조하세요

```
CREATE ROLE sample_metadata_viewer;

GRANT ACCESS CATALOG TO ROLE sample_metadata_viewer;

GRANT ROLE sample_metadata_viewer to salesadmin;
```

이미 정의된 역할을 사용하려는 경우 [시스템 정의 역할](https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html)인 `operator`, `secadmin`, `dba`, `superuser`가 모두 객체 메타데이터를 보는 데 필요한 권한이 있습니다. 기본적으로 슈퍼 사용자는 전체 카탈로그를 볼 수 있습니다.

```
GRANT ROLE operator to sample_user;
```

역할을 사용하여 메타데이터 보안을 제어하는 경우 역할 기반 액세스 제어와 함께 제공되는 모든 시스템 뷰 및 기능에 액세스할 수 있습니다. 예를 들어, [SVV\$1ROLES](https://docs.aws.amazon.com/redshift/latest/dg/r_SVV_ROLES.html) 뷰를 쿼리하여 모든 역할을 확인할 수 있습니다. 사용자가 역할 또는 그룹의 구성원인지 확인하려면 [USER\$1IS\$1MEMBER\$1OF](https://docs.aws.amazon.com/redshift/latest/dg/r_USER_IS_MEMBER_OF.html) 함수를 사용하세요. SVV 뷰의 전체 목록은 [SVV 메타데이터 뷰](https://docs.aws.amazon.com/redshift/latest/dg/svv_views.html)를 참조하세요. 시스템 정보 함수 목록은 [시스템 정보 함수](https://docs.aws.amazon.com/redshift/latest/dg/r_System_information_functions.html)를 참조하세요.

# 동적 데이터 마스킹
<a name="t_ddm"></a>

**참고**  
Amazon Redshift는 민감한 메타데이터의 노출을 방지하기 위해 Data Catalog 뷰에 대한 쿼리 정보를 로깅할 때 특정 시스템 테이블 열을 자동으로 마스킹합니다. 자세한 내용은 *Amazon Redshift 관리 안내서*의 [보안 로깅](https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing-secure-logging.html)을 참조하세요.

Amazon Redshift에서 동적 데이터 마스킹(DDM)을 사용하면 데이터 웨어하우스의 민감한 데이터를 보호할 수 있습니다. Amazon Redshift가 데이터베이스에서 데이터를 변환하지 않고 쿼리 시 민감한 데이터를 사용자에게 표시하는 방식을 조작할 수 있습니다. 지정된 사용자 또는 역할에 사용자 지정 난독화 규칙을 적용하는 마스킹 정책을 통해 데이터에 대한 액세스를 제어합니다. 이렇게 하면 기본 데이터를 변경하거나 SQL 쿼리를 편집하지 않고도 변화하는 개인 정보 보호 요구 사항에 대응할 수 있습니다.

동적 데이터 마스킹 정책은 지정된 형식과 일치하는 데이터를 숨기거나 난독화하거나 익명화합니다. 테이블에 첨부하면 마스킹 표현식이 하나 이상의 해당 열에 적용됩니다. 마스킹 정책을 추가로 수정하여 특정 사용자 또는 [역할 기반 액세스 제어(RBAC)](t_Roles.md)로 생성할 수 있는 사용자 정의 역할에만 적용할 수 있습니다. 또한 마스킹 정책을 생성할 때 조건부 열을 사용하여 셀 수준에서 DDM을 적용할 수 있습니다. 조건부 마스킹에 대한 자세한 설명은 [조건부 동적 데이터 마스킹](t_ddm-conditional.md) 섹션을 참조하세요.

난독화 수준이 다른 여러 마스킹 정책을 테이블의 동일한 열에 적용하고 다른 역할에 할당할 수 있습니다. 하나의 열에 다른 정책을 적용하는 다른 역할이 있는 경우 충돌을 방지하기 위해 각 응용 프로그램에 대한 우선 순위를 설정할 수 있습니다. 이러한 방식으로 지정된 사용자 또는 역할이 액세스할 수 있는 데이터를 제어할 수 있습니다. DDM 정책은 데이터를 부분적으로 또는 완전히 수정하거나 SQL, Python 또는 AWS Lambda로 작성된 사용자 정의 함수를 사용하여 데이터를 해시할 수 있습니다. 해시를 사용하여 데이터를 마스킹하면 잠재적으로 민감한 정보에 액세스하지 않고도 이 데이터에 조인을 적용할 수 있습니다.

# 동적 데이터 마스킹 정책 관리용 SQL 명령
<a name="r_ddm-procedures"></a>

다음 작업을 수행하여 동적 데이터 마스킹 정책을 생성, 연결, 분리 및 삭제할 수 있습니다.
+ DDM 정책을 만들려면 [마스킹 정책 생성](r_CREATE_MASKING_POLICY.md) 명령을 사용합니다.

  다음은 SHA-2 해시함수를 이용하여 마스킹 정책을 생성한 예이다.

  ```
  CREATE MASKING POLICY hash_credit 
  WITH (credit_card varchar(256)) 
  USING (sha2(credit_card + 'testSalt', 256));
  ```
+ 기존 DDM 정책을 변경하려면 [마스킹 정책 변경](r_ALTER_MASKING_POLICY.md) 명령을 사용합니다.

  다음은 기존 마스킹 정책을 변경하는 예제입니다.

  ```
  ALTER MASKING POLICY hash_credit
  USING (sha2(credit_card + 'otherTestSalt', 256));
  ```
+ 테이블에 대한 DDM 정책을 하나 이상의 사용자 또는 역할에 연결하려면 [마스킹 정책 연결](r_ATTACH_MASKING_POLICY.md) 명령을 사용합니다.

  다음은 마스킹 정책을 열/역할 쌍에 연결하는 예제입니다.

  ```
   ATTACH MASKING POLICY hash_credit 
  ON credit_cards (credit_card) 
  TO ROLE science_role 
  PRIORITY 30;
  ```

  PRIORITY 절은 여러 정책이 동일한 열에 첨부될 때 사용자 세션에 적용되는 마스킹 정책을 결정합니다. 예를 들어 앞의 예에서 사용자가 동일한 신용 카드 열에 우선 순위가 20인 다른 마스킹 정책을 연결한 경우 science\$1role의 정책이 우선 순위가 30보다 높으므로 적용됩니다.
+ 하나 이상의 사용자 또는 역할에서 테이블의 DDM 정책을 분리하려면 DETACH [마스킹 정책 분리](r_DETACH_MASKING_POLICY.md) 명령을 사용합니다.

  다음은 마스킹 정책을 열/역할 쌍에서 분리하는 예제입니다.

  ```
  DETACH MASKING POLICY hash_credit 
  ON credit_cards(credit_card) 
  FROM ROLE science_role;
  ```
+ 모든 데이터베이스에서 DDM 정책을 삭제하려면 [마스킹 정책 삭제](r_DROP_MASKING_POLICY.md) 명령을 사용하세요.

  다음은 모든 데이터베이스에서 마스킹 정책을 삭제하는 예제입니다.

  ```
  DROP MASKING POLICY hash_credit;  
  ```

# 동적 데이터 마스킹 정책 계층 구조
<a name="t_ddm-hierarchy"></a>

마스킹 정책을 여러 개 연결할 때는 다음 사항을 고려하세요.
+ 여러 마스킹 정책을 단일 열에 연결할 수 있습니다.
+ 쿼리에 여러 마스킹 정책을 적용할 경우 각 열에 첨부된 가장 높은 우선 순위의 정책이 적용됩니다. 다음 예제를 살펴보세요.

  ```
  ATTACH MASKING POLICY partial_hash
  ON credit_cards(address, credit_card)
  TO ROLE analytics_role 
  PRIORITY 20;
  
  ATTACH MASKING POLICY full_hash
  ON credit_cards(credit_card, ssn)
  TO ROLE auditor_role 
  PRIORITY 30;
  
  SELECT address, credit_card, ssn
  FROM credit_cards;
  ```

  SELECT 문을 실행할 때 분석 및 감사자 역할을 모두 가진 사용자는 `partial_hash` 마스킹 정책이 적용된 주소 열을 보게 됩니다. 신용카드 열에서 `full_hash` 정책의 우선순위가 더 높기 때문에 `full_hash` 마스킹 정책이 적용된 신용카드 및 SSN 열이 표시됩니다.
+  마스킹 정책을 연결할 때 우선 순위를 지정하지 않으면 기본 우선 순위는 0입니다.
+ 우선 순위가 동일한 동일한 열에 두 개의 정책을 연결할 수 없습니다.
+ 사용자와 열 또는 역할과 열의 동일한 조합에 두 개의 정책을 연결할 수 없습니다.
+ 동일한 사용자 또는 역할에 연결된 상태에서 동일한 SUPER 경로를 따라 여러 마스킹 정책을 적용할 경우 우선순위가 가장 높은 첨부 파일만 적용됩니다. 다음 예제를 살펴보세요.

  첫 번째 예는 동일한 경로에 연결된 두 개의 마스킹 정책을 보여 주며 우선순위가 더 높은 정책이 적용됩니다.

  ```
  ATTACH MASKING POLICY hide_name
  ON employees(col_person.name)
  TO PUBLIC
  PRIORITY 20;
  
  ATTACH MASKING POLICY hide_last_name
  ON employees(col_person.name.last)
  TO PUBLIC
  PRIORITY 30;
  
  --Only the hide_last_name policy takes effect.
  SELECT employees.col_person.name FROM employees;
  ```

  두 번째 예에서는 정책 간 충돌 없이 동일한 SUPER 객체의 서로 다른 경로에 연결된 두 마스킹 정책을 보여줍니다. 두 첨부 파일이 동시에 적용됩니다.

  ```
  ATTACH MASKING POLICY hide_first_name
  ON employees(col_person.name.first)
  TO PUBLIC
  PRIORITY 20;
  
  ATTACH MASKING POLICY hide_last_name
  ON employees(col_person.name.last)
  TO PUBLIC
  PRIORITY 20;
  
  --Both col_person.name.first and col_person.name.last are masked.
  SELECT employees.col_person.name FROM employees;
  ```

주어진 사용자와 열 또는 역할과 열 조합에 적용되는 마스킹 정책을 확인하기 위해 [https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html](https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html) 역할이 있는 사용자는 [SVV\$1ATTACHED\$1MASKING\$1POLICY](r_SVV_ATTACHED_MASKING_POLICY.md) 시스템 뷰에서 열/역할 또는 열/사용자 쌍을 조회할 수 있습니다. 자세한 내용은 [동적 데이터 마스킹 시스템 뷰](r_ddm-svv.md) 섹션을 참조하세요.

# SUPER 데이터 유형 경로와 함께 동적 데이터 마스킹 사용
<a name="t_ddm-super"></a>

 Amazon Redshift는 동적 데이터 마스킹 정책을 SUPER 유형 열의 경로에 연결하는 것을 지원합니다. SUPER 데이터 형식에 대한 자세한 내용은 [Amazon Redshift의 반정형 데이터](super-overview.md) 섹션을 참조하세요.

SUPER 유형 열의 경로에 마스킹 정책을 연결할 때는 다음 사항을 고려하세요.
+ 마스킹 정책을 열의 경로에 연결하는 경우 해당 열을 SUPER 데이터 유형으로 정의해야 합니다. SUPER 경로의 **스칼라 값에만 마스킹 정책을 적용할 수 있습니다. 복잡한 구조나 배열에는 마스킹 정책을 적용할 수 없습니다.
+ SUPER 경로가 충돌하지 않는 한 단일 SUPER 열의 여러 스칼라 값에 서로 다른 마스킹 정책을 적용할 수 있습니다. 예를 들어 SUPER 경로 `a.b` 및 `a.b.c`는 `a.b`가 `a.b.c`의 상위 구조로 동일한 경로에 있기 때문에 충돌이 발생합니다. SUPER 경로 `a.b.c` 및 `a.b.d`는 충돌하지 않습니다.
+ Amazon Redshift는 사용자 쿼리 런타임 시 정책이 적용되기 전까지는 마스킹 정책이 연결된 경로가 데이터에 있고 예상 유형인지 확인할 수 없습니다. 예를 들어, INT 값이 포함된 SUPER 경로에 TEXT 값을 마스킹하는 마스킹 정책을 연결하면 Amazon Redshift는 해당 경로에 있는 값의 유형을 캐스팅하려고 시도합니다.

  이러한 상황에서 런타임 시 Amazon Redshift의 동작은 SUPER 객체를 쿼리하기 위한 구성 설정에 따라 달라집니다. 기본적으로 Amazon Redshift는 lax 모드이며 지정된 SUPER 경로에서 누락된 경로와 잘못된 캐스트를 `NULL`로 해석합니다. SUPER와 관련한 구성 설정에 대한 자세한 내용은 [SUPER 구성](super-configurations.md) 섹션을 참조하세요.
+ SUPER는 스키마가 없는 유형입니다. 즉, Amazon Redshift는 지정된 SUPER 경로에서 값의 존재를 확인할 수 없습니다. 존재하지 않는 SUPER 경로에 마스킹 정책을 연결하고 Amazon Redshift가 lax 모드인 경우 Amazon Redshift는 경로를 `NULL` 값으로 해석합니다. SUPER 열 경로에 마스킹 정책을 연결할 때는 SUPER 객체의 예상 형식과 이러한 객체에 예상치 못한 속성이 있을 가능성을 고려하는 것이 좋습니다. SUPER 열에 예상치 못한 스키마가 있다고 생각되면 마스킹 정책을 SUPER 열에 직접 연결하는 것을 고려해 보세요. SUPER 유형 정보 함수를 사용하여 속성 및 유형을 확인하고 값을 마스킹하는 데 `OBJECT_TRANSFORM`을 사용할 수 있습니다. SUPER 유형 정보 함수에 대한 자세한 내용은 [SUPER 형식 정보 함수](c_Type_Info_Functions.md) 섹션을 참조하세요.

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

**SUPER 경로에 마스킹 정책 연결**  
다음 예에서는 여러 마스킹 정책을 한 열의 여러 SUPER 유형 경로에 연결합니다.

```
CREATE TABLE employees (
    col_person SUPER
);

INSERT INTO employees
VALUES
    (
        json_parse('
            {
                "name": {
                    "first": "John",
                    "last": "Doe"
                },
                "age": 25,
                "ssn": "111-22-3333",
                "company": "Company Inc."
            }
        ')
    ),
    (
        json_parse('
            {
                "name": {
                    "first": "Jane",
                    "last": "Appleseed"
                },
                "age": 34,
                "ssn": "444-55-7777",
                "company": "Organization Org."
            }
        ')
    )
;
GRANT ALL ON ALL TABLES IN SCHEMA "public" TO PUBLIC;

-- Create the masking policies.

-- This policy converts the given name to all uppercase letters.
CREATE MASKING POLICY mask_first_name
WITH(first_name TEXT)
USING ( UPPER(first_name) );

-- This policy replaces the given name with the fixed string 'XXXX'.
CREATE MASKING POLICY mask_last_name
WITH(last_name TEXT)
USING ( 'XXXX'::TEXT );

-- This policy rounds down the given age to the nearest 10.
CREATE MASKING POLICY mask_age
WITH(age INT)
USING ( (FLOOR(age::FLOAT / 10) * 10)::INT );

-- This policy converts the first five digits of the given SSN to 'XXX-XX'.
CREATE MASKING POLICY mask_ssn
WITH(ssn TEXT)
USING ( 'XXX-XX-'::TEXT || SUBSTRING(ssn::TEXT FROM 8 FOR 4) );

-- Attach the masking policies to the employees table.
ATTACH MASKING POLICY mask_first_name
ON employees(col_person.name.first)
TO PUBLIC;

ATTACH MASKING POLICY mask_last_name
ON employees(col_person.name.last)
TO PUBLIC;

ATTACH MASKING POLICY mask_age
ON employees(col_person.age)
TO PUBLIC;

ATTACH MASKING POLICY mask_ssn
ON employees(col_person.ssn)
TO PUBLIC;

-- Verify that your masking policies are attached.
SELECT
    policy_name,
    TABLE_NAME,
    priority,
    input_columns,
    output_columns
FROM
    svv_attached_masking_policy;

   policy_name   | table_name | priority |           input_columns           |          output_columns
-----------------+------------+----------+-----------------------------------+-----------------------------------
 mask_age        | employees  |        0 | ["col_person.\"age\""]            | ["col_person.\"age\""]
 mask_first_name | employees  |        0 | ["col_person.\"name\".\"first\""] | ["col_person.\"name\".\"first\""]
 mask_last_name  | employees  |        0 | ["col_person.\"name\".\"last\""]  | ["col_person.\"name\".\"last\""]
 mask_ssn        | employees  |        0 | ["col_person.\"ssn\""]            | ["col_person.\"ssn\""]
(4 rows)

-- Observe the masking policies taking effect.
SELECT col_person FROM employees ORDER BY col_person.age;

-- This result is formatted for ease of reading.
         col_person
--------------------------------
{
    "name": {
        "first": "JOHN",
        "last": "XXXX"
    },
    "age": 20,
    "ssn": "XXX-XX-3333",
    "company": "Company Inc."
}
{
    "name": {
        "first": "JANE",
        "last": "XXXX"
    },
    "age": 30,
    "ssn": "XXX-XX-7777",
    "company": "Organization Org."
}
```

다음은 SUPER 경로에 잘못된 마스킹 정책을 첨부한 몇 가지 예입니다.

```
-- This attachment fails because there is already a policy
-- with equal priority attached to employees.name.last, which is
-- on the same SUPER path as employees.name.
ATTACH MASKING POLICY mask_ssn
ON employees(col_person.name)
TO PUBLIC;
ERROR:  DDM policy "mask_last_name" is already attached on relation "employees" column "col_person."name"."last"" with same priority
               
-- Create a masking policy that masks DATETIME objects.
CREATE MASKING POLICY mask_date
WITH(INPUT DATETIME)
USING ( INPUT );
               
-- This attachment fails because SUPER type columns can't contain DATETIME objects.
ATTACH MASKING POLICY mask_date
ON employees(col_person.company)
TO PUBLIC;
ERROR:  cannot attach masking policy for output of type "timestamp without time zone" to column "col_person."company"" of type "super
```

다음은 마스킹 정책을 존재하지 않는 SUPER 경로에 연결하는 예입니다. 기본적으로 Amazon Redshift는 경로를 `NULL`로 해석합니다.

```
ATTACH MASKING POLICY mask_first_name
ON employees(col_person.not_exists)
TO PUBLIC;

SELECT col_person FROM employees LIMIT 1;

-- This result is formatted for ease of reading.
         col_person
-----------------------------------
{
    "name": {
        "first": "JOHN",
        "last": "XXXX"
    },
    "age": 20,
    "ssn": "XXX-XX-3333",
    "company": "Company Inc.",
    "not_exists": null
}
```

# 조건부 동적 데이터 마스킹
<a name="t_ddm-conditional"></a>

마스킹 표현식에서 조건식을 사용하여 마스킹 정책을 생성하여 셀 수준에서 데이터를 마스킹할 수 있습니다. 예를 들어 해당 행에 있는 다른 열의 값에 따라 다른 마스크를 값에 적용하는 마스킹 정책을 만들 수 있습니다.

다음은 조건부 데이터 마스킹을 사용하여 사기와 관련된 신용 카드 번호를 부분적으로 수정하고 다른 모든 신용 카드 번호를 완전히 숨기는 마스킹 정책을 만들고 첨부하는 예입니다. 이 예제를 실행하려면 수퍼유저이거나 [https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html](https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html) 역할이 있어야 합니다.

```
--Create an analyst role.
CREATE ROLE analyst;

--Create a credit card table. The table contains an is_fraud boolean column,
--which is TRUE if the credit card number in that row was involved in a fraudulent transaction.
CREATE TABLE credit_cards (id INT, is_fraud BOOLEAN, credit_card_number VARCHAR(16));

--Create a function that partially redacts credit card numbers.
CREATE FUNCTION REDACT_CREDIT_CARD (credit_card VARCHAR(16))
RETURNS VARCHAR(16) IMMUTABLE
AS $$
    import re
    regexp = re.compile("^([0-9]{6})[0-9]{5,6}([0-9]{4})")
 
    match = regexp.search(credit_card)
    if match != None:
        first = match.group(1)
        last = match.group(2)
    else:
        first = "000000"
        last = "0000"
    
    return "{}XXXXX{}".format(first, last)
$$ LANGUAGE plpythonu;

--Create a masking policy that partially redacts credit card numbers if the is_fraud value for that row is TRUE,
--and otherwise blanks out the credit card number completely.
CREATE MASKING POLICY card_number_conditional_mask
    WITH (fraudulent BOOLEAN, pan varchar(16)) 
    USING (CASE WHEN fraudulent THEN REDACT_CREDIT_CARD(pan)
                ELSE Null
           END);

--Attach the masking policy to the credit_cards/analyst table/role pair. 
ATTACH MASKING POLICY card_number_conditional_mask ON credit_cards (credit_card_number)
 USING (is_fraud, credit_card_number)
 TO ROLE analyst PRIORITY 100;
```

# 동적 데이터 마스킹 시스템 뷰
<a name="r_ddm-svv"></a>

수퍼유저, `sys:operator` 역할이 있는 사용자, ACCESS SYSTEM TABLE 권한이 있는 사용자는 다음과 같은 DDM 관련 시스템 뷰에 액세스할 수 있습니다.
+  [SVV\$1MASKING\$1POLICY](r_SVV_MASKING_POLICY.md) 

   SVV\$1MASKING\$1POLICY를 사용하여 클러스터 또는 작업 그룹에 생성된 모든 마스킹 정책을 볼 수 있습니다.
+  [SVV\$1ATTACHED\$1MASKING\$1POLICY](r_SVV_ATTACHED_MASKING_POLICY.md) 

  SVV\$1ATTACHED\$1MASKING\$1POLICY를 사용하여 현재 연결된 데이터베이스에 정책이 연결된 모든 관계 및 사용자 또는 역할을 봅니다.
+  [SYS\$1APPLIED\$1MASKING\$1POLICY\$1LOG](SYS_APPLIED_MASKING_POLICY_LOG.md) 

  SYS\$1APPLIED\$1MASKING\$1POLICY\$1LOG를 사용하여 DDM로 보호되는 관계를 참조하는 쿼리에서 마스킹 정책의 적용을 추적합니다.

다음은 시스템 뷰를 사용하여 찾을 수 있는 정보의 몇 가지 예제입니다.

```
--Select all policies associated with specific users, as opposed to roles
SELECT policy_name,
       schema_name,
       table_name,
       grantee
FROM svv_attached_masking_policy
WHERE grantee_type = 'user';     

--Select all policies attached to a specific user
SELECT policy_name,
       schema_name,
       table_name,
       grantee
FROM svv_attached_masking_policy
WHERE grantee = 'target_grantee_name'            
            
--Select all policies attached to a given table
SELECT policy_name,
       schema_name,
       table_name,
       grantee
FROM svv_attached_masking_policy
WHERE table_name = 'target_table_name'
      AND schema_name = 'target_schema_name';            
            
--Select the highest priority policy attachment for a given role
SELECT samp.policy_name,
       samp.priority,
       samp.grantee,
       smp.policy_expression
FROM svv_masking_policy AS smp
JOIN svv_attached_masking_policy AS samp
    ON samp.policy_name = smp.policy_name
WHERE
    samp.grantee_type = 'role' AND
    samp.policy_name = mask_get_policy_for_role_on_column(
        'target_schema_name', 
        'target_table_name', 
        'target_column_name', 
        'target_role_name')
ORDER BY samp.priority desc
LIMIT 1;         

--See which policy a specific user will see on a specific column in a given relation
SELECT samp.policy_name,
       samp.priority,
       samp.grantee,
       smp.policy_expression
FROM svv_masking_policy AS smp
JOIN svv_attached_masking_policy AS samp
    ON samp.policy_name = smp.policy_name
WHERE
    samp.grantee_type = 'role' AND
    samp.policy_name = mask_get_policy_for_user_on_column(
        'target_schema_name',
        'target_table_name',
        'target_column_name',
        'target_user_name')
ORDER BY samp.priority desc; 
         
 --Select all policies attached to a given relation.
SELECT policy_name,
schema_name,
relation_name,
database_name
FROM sys_applied_masking_policy_log
WHERE relation_name = 'relation_name'
AND schema_name = 'schema_name';
```

# 동적 데이터 마스킹 사용 시 고려 사항
<a name="t_ddm-considerations"></a>

동적 데이터 마스킹을 사용할 때 다음 사항을 고려하세요.
+  뷰와 같은 테이블에서 생성된 객체를 쿼리할 때 사용자는 객체를 생성한 사용자의 정책이 아닌 자신의 마스킹 정책에 따라 결과를 보게 됩니다. 예를 들어 secadmin이 생성한 뷰를 쿼리하는 분석가 역할을 가진 사용자는 분석가 역할에 연결된 마스킹 정책이 있는 결과를 볼 수 있습니다.
+  EXPLAIN 명령이 잠재적으로 중요한 마스킹 정책 필터를 노출하지 않도록 하기 위해 SYS\$1EXPLAIN\$1DDM 권한이 있는 사용자만 EXPLAIN 출력에 적용된 마스킹 정책을 볼 수 있습니다. 사용자에게는 기본적으로 SYS\$1EXPLAIN\$1DDM 권한이 없습니다.

  다음은 역할에 권한을 부여할 때 사용하는 구문입니다.

  ```
  GRANT EXPLAIN MASKING TO ROLE rolename
  ```

   EXPLAIN 명령에 대한 자세한 내용은 [EXPLAIN](r_EXPLAIN.md) 섹션을 참조하세요.
+  역할이 다른 사용자는 사용된 필터 조건 또는 조인 조건에 따라 다른 결과를 볼 수 있습니다. 예를 들어 명령을 실행하는 사용자에게 해당 열을 난독화하는 마스킹 정책이 적용된 경우 특정 열 값을 사용하여 테이블에서 SELECT 명령을 실행하면 실패합니다.
+  DDM 정책은 조건자 작업 또는 예측보다 먼저 적용되어야 합니다. 마스킹 정책에는 다음이 포함될 수 있습니다.
  + 값을 null로 변환하는 것과 같은 저비용 상수 연산
  + HMAC 해싱과 같은 중간 비용 연산
  + 외부 Lambda 사용자 정의 함수 호출과 같은 고비용 연산

  따라서 가능하면 간단한 마스킹 표현식을 사용하는 것이 좋습니다.
+  행 수준 보안 정책이 있는 역할에 DDM 정책을 사용할 수 있지만 RLS 정책은 DDM보다 먼저 적용됩니다. 동적 데이터 마스킹 표현식은 RLS로 보호된 행을 읽을 수 없습니다. RLS에 대한 자세한 내용은 [행 수준 보안](t_rls.md) 섹션을 참조하세요.
+  [COPY](r_COPY.md) 명령을 사용하여 Parquet에서 보호된 대상 테이블로 복사할 때는 COPY 문에 열을 명시적으로 지정해야 합니다. COPY를 사용한 열 매핑에 대한 자세한 내용은 [열 매핑 옵션](copy-parameters-column-mapping.md) 섹션을 참조하세요.
+  DDM 정책은 다음 관계에 연결될 수 없습니다.
  +  시스템 테이블 및 카탈로그 
  +  외부 테이블 
  +  데이터 공유 테이블
  +  교차 데이터베이스 관계 
  +  임시 테이블 
  +  상관관계가 있는 쿼리 
+  DDM 정책에는 조회 테이블이 포함될 수 있습니다. 조회 테이블은 USING 절에 있을 수 있습니다. 다음 관계 유형은 조회 테이블로 사용할 수 없습니다.
  +  시스템 테이블 및 카탈로그 
  +  외부 테이블 
  +  데이터 공유 테이블 
  +  뷰, 구체화된 뷰 및 지연 바인딩 뷰 
  +  교차 데이터베이스 관계 
  +  임시 테이블 
  +  상관관계가 있는 쿼리 

  다음은 마스킹 정책을 조회 테이블에 연결하는 예제입니다.

  ```
  --Create a masking policy referencing a lookup table
  CREATE MASKING POLICY lookup_mask_credit_card WITH (credit_card TEXT) USING (
    CASE
      WHEN
        credit_card IN (SELECT credit_card_lookup FROM credit_cards_lookup)      
      THEN '000000XXXX0000'
      ELSE REDACT_CREDIT_CARD(credit_card)
      END
    ); 
    
  --Provides access to the lookup table via a policy attached to a role
  GRANT SELECT ON TABLE credit_cards_lookup TO MASKING POLICY lookup_mask_credit_card;
  ```
+  대상 열의 유형 및 크기와 호환되지 않는 출력을 생성하는 마스킹 정책을 연결할 수 없습니다. 예를 들어 12자 길이의 문자열을 VARCHAR(10) 열에 출력하는 마스킹 정책을 연결할 수 없습니다. Amazon Redshift Redshift는 다음 예외를 지원합니다.
  +  입력 유형이 INTN인 마스킹 정책은 M < N인 한 크기가 INTM인 정책에 연결할 수 있습니다. 예를 들어 BIGINT(INT8) 입력 정책은 smallint(INT4) 열에 연결할 수 있습니다.
  +  입력 유형이 NUMERIC 또는 DECIMAL인 마스킹 정책은 항상 FLOAT 열에 연결할 수 있습니다.
+ DDM 정책은 데이터 공유와 함께 사용할 수 없습니다. 데이터 공유의 데이터 생산자가 데이터 공유의 테이블에 DDM 정책을 연결하면, 테이블을 쿼리하려는 데이터 소비자의 사용자는 해당 테이블에 액세스할 수 없게 됩니다. 생산자측 클러스터 또는 네임스페이스에서 데이터 공유에 관계를 추가하려고 하면 다음 오류와 함께 작업이 실패합니다.

  ```
  <ddm_protected_relation> or a relation dependent on it is protected by a masking policy and cannot be added to a datashare
  ```

  마스킹 정책을 생산자측의 관계에 연결하고 해당 관계가 이미 데이터 공유에 포함된 경우 소비자측에서 관계를 쿼리하려고 하면 다음 오류와 함께 작업이 실패합니다.

  ```
  cross-cluster query of the masked relation <ddm_protected_relation> is not supported.
  ```

  MASKING OFF FOR DATASHARES 파라미터와 함께 ALTER TABLE 명령을 사용하여 데이터 공유에 대한 DDM을 끌 수 있습니다. 자세한 내용은 [ALTER TABLE](r_ALTER_TABLE.md) 섹션을 참조하세요.
+ 다음 구성 옵션의 값이 세션의 기본값과 일치하지 않으면 DDM 정책을 첨부한 관계를 쿼리할 수 없습니다.
  +  `enable_case_sensitive_super_attribute` 
  +  `enable_case_sensitive_identifier` 
  +  `downcase_delimited_identifier` 

  DDM 정책이 첨부된 관계를 쿼리하려고 할 때 "대/소문자 구분이 기본값과 다른 DDM 보호 관계에서 세션 수준 구성을 지원하지 않습니다."라는 메시지가 표시되면 세션의 구성 옵션을 재설정하는 것이 좋습니다.
+  프로비저닝된 클러스터 또는 서버리스 네임스페이스에 동적 데이터 마스킹 정책이 있는 경우 일반 사용자에게는 다음 명령이 차단됩니다.

  ```
  ALTER <current_user> SET enable_case_sensitive_super_attribute/enable_case_sensitive_identifier/downcase_delimited_identifier
  ```

  DDM 정책을 만들 때 일반 사용자의 기본 구성 옵션 설정을 정책을 만들 당시의 세션의 구성 옵션 설정과 일치하도록 변경하는 것이 좋습니다. 슈퍼유저 및 ALTER USER 권한이 있는 사용자는 파라미터 그룹 설정 또는 ALTER USER 명령을 사용하여 이 작업을 수행할 수 있습니다. 파라미터 그룹에 대한 자세한 내용은 **Amazon Redshift 관리 안내서의 [Amazon Redshift 파라미터 그룹](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-parameter-groups.html)을 참조하세요. ALTER USER 명령에 대한 자세한 내용은 [ALTER USER](r_ALTER_USER.md) 섹션을 참조하세요.
+ DDM 정책이 연결된 뷰와 지연 바인딩 뷰는 일반 사용자가 [CREATE VIEW](r_CREATE_VIEW.md) 명령을 사용하여 교체할 수 없습니다. DDM 정책이 연결된 뷰 또는 LBV를 바꾸려면 먼저 연결된 DDM 정책을 분리하고 뷰 또는 LBV를 교체한 다음, 정책을 다시 연결합니다. 슈퍼 사용자 및 `sys:secadmin` 권한이 있는 사용자는 정책을 분리하지 않고도 DDM 정책이 연결된 뷰 또는 LBV에 CREATE VIEW를 사용할 수 있습니다.
+ DDM 정책이 연결된 뷰는 시스템 테이블과 뷰를 참조할 수 없습니다. 지연 바인딩 뷰는 시스템 테이블 및 뷰를 참조할 수 있습니다.
+ DDM 정책이 연결된 지연 바인딩 뷰는 데이터 레이크의 중첩된 데이터(예: JSON 문서)를 참조할 수 없습니다.
+  지연 바인딩 뷰를 참조하는 뷰가 있는 경우 해당 지연 바인딩 뷰에는 DDM 정책을 연결할 수 없습니다.
+  지연 바인딩 뷰에 연결된 DDM 정책은 열 이름을 기준으로 첨부됩니다. 쿼리 시 Amazon Redshift는 지연 바인딩 뷰에 연결된 모든 마스킹 정책이 성공적으로 적용되었는지, 그리고 지연 바인딩 뷰의 출력 열 유형이 연결된 마스킹 정책의 유형과 일치하는지 확인합니다. 검증이 실패하면 Amazon Redshift가 쿼리에 대한 오류를 반환합니다.
+ DDM 정책을 생성할 때 사용자 지정된 세션 컨텍스트 변수를 사용할 수 있습니다. 다음 예제에서는 DDM 정책의 세션 컨텍스트 변수를 설정합니다.

  ```
  -- Set a customized context variable.
  SELECT set_config('app.city', 'XXXX', FALSE);
  
  -- Create a MASKING policy using current_setting() to get the value of a customized context variable.
  CREATE MASKING POLICY city_mask
  WITH (city VARCHAR(30))
  USING (current_setting('app.city')::VARCHAR(30));
  
  -- Attach the policy on the target table to one or more roles.
  ATTACH MASKING POLICY city_mask 
  ON tickit_users_redshift(city) 
  TO ROLE analyst, ROLE dbadmin;
  ```

  사용자 지정 세션 컨텍스트 변수를 설정 및 검색하는 방법을 자세히 알아보려면 [SET](r_SET.md), [SET\$1CONFIG](r_SET_CONFIG.md), [SHOW](r_SHOW.md), [CURRENT\$1SETTING](r_CURRENT_SETTING.md), [reset](r_RESET.md) 섹션으로 이동하세요. 일반적인 서버 구성 수정 방법을 자세히 알아보려면 [서버 구성 수정](cm_chap_ConfigurationRef.md#t_Modifying_the_default_settings) 섹션으로 이동하세요.
**중요**  
 DDM 정책 내에서 세션 컨텍스트 변수를 사용하는 경우 보안 정책은 정책을 간접 호출하는 사용자 또는 역할에 따라 달라집니다. DDM 정책에서 세션 컨텍스트 변수를 사용할 때는 보안 취약성이 발생하지 않도록 주의하세요.

# 동적 데이터 마스킹 엔드 투 엔드 예제
<a name="ddm-example"></a>

다음은 마스킹 정책을 생성하고 열에 연결하는 방법을 보여주는 종합 예제입니다. 이러한 정책을 통해 사용자는 역할에 연결된 정책의 난독화 정도에 따라 열에 액세스하고 다른 값을 볼 수 있습니다. 이 예제를 실행하려면 수퍼유저이거나 [https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html](https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html) 역할이 있어야 합니다.

## 마스킹 정책 생성
<a name="ddm-example-create"></a>

먼저 테이블을 만들고 신용 카드 값으로 채웁니다.

```
--create the table         
CREATE TABLE credit_cards (
  customer_id INT,
  credit_card TEXT
);

--populate the table with sample values
INSERT INTO credit_cards
VALUES
  (100, '4532993817514842'),
  (100, '4716002041425888'),
  (102, '5243112427642649'),
  (102, '6011720771834675'),
  (102, '6011378662059710'),
  (103, '373611968625635')
;

--run GRANT to grant permission to use the SELECT statement on the table
GRANT SELECT ON credit_cards TO PUBLIC;

--create two users
CREATE USER regular_user WITH PASSWORD '1234Test!';

CREATE USER analytics_user WITH PASSWORD '1234Test!';

--create the analytics_role role and grant it to analytics_user
--regular_user does not have a role
CREATE ROLE analytics_role;

GRANT ROLE analytics_role TO analytics_user;
```

다음으로 분석 역할에 적용할 마스킹 정책을 생성합니다.

```
--create a masking policy that fully masks the credit card number
CREATE MASKING POLICY mask_credit_card_full
WITH (credit_card VARCHAR(256))
USING ('000000XXXX0000'::TEXT);

--create a user-defined function that partially obfuscates credit card data
CREATE FUNCTION REDACT_CREDIT_CARD (credit_card TEXT)
RETURNS TEXT IMMUTABLE
AS $$
    import re
    regexp = re.compile("^([0-9]{6})[0-9]{5,6}([0-9]{4})")
 
    match = regexp.search(credit_card)
    if match != None:
        first = match.group(1)
        last = match.group(2)
    else:
        first = "000000"
        last = "0000"
    
    return "{}XXXXX{}".format(first, last)
$$ LANGUAGE plpythonu;

--create a masking policy that applies the REDACT_CREDIT_CARD function
CREATE MASKING POLICY mask_credit_card_partial
WITH (credit_card VARCHAR(256))
USING (REDACT_CREDIT_CARD(credit_card));

--confirm the masking policies using the associated system views
SELECT * FROM svv_masking_policy;

SELECT * FROM svv_attached_masking_policy;
```

## 마스킹 정책 연결
<a name="ddm-example-attach"></a>

마스킹 정책을 신용 카드 테이블에 연결합니다.

```
--attach mask_credit_card_full to the credit card table as the default policy
--all users will see this masking policy unless a higher priority masking policy is attached to them or their role
ATTACH MASKING POLICY mask_credit_card_full
ON credit_cards(credit_card)
TO PUBLIC;

--attach mask_credit_card_partial to the analytics role
--users with the analytics role can see partial credit card information
ATTACH MASKING POLICY mask_credit_card_partial
ON credit_cards(credit_card)
TO ROLE analytics_role
PRIORITY 10;

--confirm the masking policies are applied to the table and role in the associated system view
SELECT * FROM svv_attached_masking_policy;

--confirm the full masking policy is in place for normal users by selecting from the credit card table as regular_user
SET SESSION AUTHORIZATION regular_user;

SELECT * FROM credit_cards;

--confirm the partial masking policy is in place for users with the analytics role by selecting from the credit card table as analytics_user
SET SESSION AUTHORIZATION analytics_user;

SELECT * FROM credit_cards;
```

## 마스킹 정책 변경
<a name="ddm-example-alter"></a>

다음 섹션은 동적 데이터 마스킹 정책을 변경하는 방법을 설명합니다.

```
--reset session authorization to the default
RESET SESSION AUTHORIZATION;

--alter the mask_credit_card_full policy
ALTER MASKING POLICY mask_credit_card_full
USING ('00000000000000'::TEXT);	
	
--confirm the full masking policy is in place after altering the policy, and that results are altered from '000000XXXX0000' to '00000000000000'
SELECT * FROM credit_cards;
```

## 마스킹 정책 분리 및 삭제
<a name="ddm-example-detach"></a>

다음 섹션에서는 테이블에서 모든 동적 데이터 마스킹 정책을 제거하여 마스킹 정책을 분리 및 삭제하는 방법을 보여줍니다.

```
--reset session authorization to the default
RESET SESSION AUTHORIZATION;

--detach both masking policies from the credit_cards table
DETACH MASKING POLICY mask_credit_card_full 
ON credit_cards(credit_card) 
FROM PUBLIC;

DETACH MASKING POLICY mask_credit_card_partial 
ON credit_cards(credit_card) 
FROM ROLE analytics_role;

--drop both masking policies
DROP MASKING POLICY mask_credit_card_full;

DROP MASKING POLICY mask_credit_card_partial;
```

# 범위가 지정된 권한
<a name="t_scoped-permissions"></a>

범위가 지정된 권한을 사용하면 데이터베이스 또는 스키마 내 특정 유형의 모든 객체에 대한 권한을 사용자 또는 역할에 부여할 수 있습니다. 범위가 지정된 권한이 있는 사용자와 역할은 데이터베이스 또는 스키마 내의 모든 현재 및 미래 객체에 대한 지정된 권한을 갖습니다.

[SVV\$1DATABASE\$1PRIVILEGES](r_SVV_DATABASE_PRIVILEGES.md)에서 데이터베이스 수준 범위 지정 권한의 범위를 볼 수 있습니다. [SVV\$1SCHEMA\$1PRIVILEGES](r_SVV_SCHEMA_PRIVILEGES.md)에서 스키마 수준 범위 지정 권한의 범위를 볼 수 있습니다.

 범위가 지정된 권한 적용에 대한 자세한 내용은 [GRANT](r_GRANT.md) 및 [REVOKE](r_REVOKE.md) 섹션을 참조하세요.

# 범위가 지정된 권한 사용 시 고려 사항
<a name="t_scoped-permissions-considerations"></a>

범위가 지정된 권한을 사용할 때 다음 사항을 고려하세요.
+ 범위가 지정된 권한을 사용하여 지정된 사용자 또는 역할에게 데이터베이스 또는 스키마 범위에 대한 권한을 부여하거나 취소할 수 있습니다.
+ 범위가 지정된 권한을 사용자 그룹에는 부여할 수 없습니다.
+ 범위가 지정된 권한을 부여하거나 취소하면 범위 내 모든 현재 및 미래 객체에 대한 권한이 변경됩니다.
+ 범위가 지정된 권한과 객체 수준 권한은 서로 독립적으로 작동합니다. 예를 들어 사용자는 다음 두 경우 모두에서 테이블에 대한 권한을 유지합니다.
  + 사용자에게 schema1.table1 테이블에 대한 SELECT 권한과 schema1에 대한 SELECT 범위 지정 권한이 부여됩니다. 그런 다음 사용자에게 schema1 스키마의 모든 테이블에 대해 SELECT가 취소됩니다. 사용자에게 schema1.table1에 대한 SELECT가 유지됩니다.
  + 사용자에게 schema1.table1 테이블에 대한 SELECT 권한과 schema1에 대한 SELECT 범위 지정 권한이 부여됩니다. 그런 다음 사용자에게 schema1.table1에 대해 SELECT가 취소됩니다. 사용자에게 schema1.table1에 대한 SELECT가 유지됩니다.
+ 범위가 지정된 권한을 부여하거나 취소하려면 다음 기준 중 하나를 충족해야 합니다.
  + 슈퍼 사용자
  + 해당 권한에 대한 권한 부여 옵션이 있는 사용자 권한 부여 옵션에 대한 자세한 내용은 [GRANT](r_GRANT.md)의 WITH GRANT OPTION 파라미터를 참조하세요.
+ 범위가 지정된 권한은 연결된 데이터베이스의 객체 또는 데이터 공유에서 가져온 데이터베이스에만 부여하거나 취소할 수 있습니다.
+ 범위가 지정된 권한을 사용하여 데이터 공유에서 만든 데이터베이스에 기본 권한을 설정할 수 있습니다. 공유 데이터베이스에 대해 범위가 지정된 권한이 부여된 소비자 측 데이터 공유 사용자는 생산자 측에서 데이터 공유에 추가하는 모든 새 객체에 대해 해당 권한을 자동으로 얻게 됩니다.
+ 생산자는 스키마 내 객체에 대한 범위가 지정된 권한을 데이터 공유에 부여할 수 있습니다. (미리 보기) 