주요 컨텐츠로 이동

행 수준 보안이란 무엇인가요?

작성자: Databricks 직원

  • 행 수준 보안(Row-level security)은 사용자 ID, 역할 또는 세션 컨텍스트를 기준으로 테이블 데이터를 필터링하여, 각 사용자가 대시보드, 노트북, API 및 기타 도구 전체에서 액세스 권한이 있는 행만 볼 수 있도록 보장합니다.
  • 효과적인 RLS는 명확한 액세스 로직, 신뢰할 수 있는 키 열, 읽기 및 쓰기 작업에 대한 별도의 제어에 의존하며, 여러 사용자 역할에 대한 테스트를 통해 지원됩니다.
  • RLS는 그 자체만으로는 민감한 열이나 집계 결과를 보호하지 않으므로, 테이블 권한, 열 수준 보안, 데이터 마스킹, 감사 로깅과 함께 계층화된 거버넌스의 일부로 구성할 때 가장 효과적입니다.

행 수준 보안(RLS)은 사용자의 신원, 역할 또는 세션 컨텍스트를 기반으로 사용자가 읽거나 변경할 수 있는 테이블의 행을 제한하는 데이터베이스 액세스 제어 기능입니다.

RLS는 전체 테이블이나 특정 열에 대한 액세스를 제한하는 대신 데이터를 행 단위로 필터링합니다. 데이터베이스 엔진이 쿼리 실행 시 필터를 자동으로 적용하므로, 사용자가 어떤 도구를 사용하여 데이터에 액세스하든 동일한 규칙이 적용됩니다.

RLS는 다음과 같은 세분화된 액세스 제어(fine-grained access control)의 일부입니다.

  • 열 수준 보안
  • 데이터 마스킹
  • 테이블 수준 권한 부여

예를 들어, 영업 사원은 회사의 주문 테이블을 쿼리할 때 테이블에 모든 지역의 데이터가 포함되어 있더라도 자신이 배정된 지역의 주문만 볼 수 있습니다. 사용자는 일반적인 SELECT 문을 작성하고, 엔진은 해당 사용자가 볼 수 있도록 허용된 행만 반환합니다.

이제 RLS는 멀티 테넌트 SaaS, 지역별 데이터 격리 및 규정 준수 사용 사례의 핵심 구성 요소입니다. 이 문서에서는 RLS의 작동 방식, 유용한 부분, 한계점, 그리고 Databricks 플랫폼에서 작동하는 방식에 대해 설명합니다.

행 수준 보안은 어떻게 작동하나요?

행 수준 보안은 흔히 정책(policy) 또는 조건자(predicate)라고 불리는 필터 규칙을 테이블에 적용하여 작동합니다. 사용자가 쿼리를 실행하면 데이터베이스 엔진이 해당 필터를 자동으로 적용하여 사용자가 볼 수 있도록 허용된 행만 반환합니다.

실제로 RLS는 보통 다음 세 단계로 작동합니다.

  1. 사용자가 쿼리를 실행합니다: 사용자는 보안 필터를 직접 추가하지 않고 표준 쿼리를 작성합니다.
  2. 데이터베이스가 사용자의 신원을 확인합니다: 엔진은 CURRENT_USER과 같은 내장 함수, 애플리케이션에서 설정한 세션 변수 또는 사용자 및 그룹을 허용된 데이터에 연결하는 매핑 테이블을 통해 사용자를 평가합니다.
  3. 엔진이 결과를 필터링합니다: RLS 조건자는 사용자가 볼 수 있는 행에 대해 TRUE을 반환하고, 그 외의 모든 행에 대해 FALSE을 반환합니다. 조건자를 통과한 행만 반환됩니다.

데이터베이스 레이어에서 강제가 적용되므로 BI 대시보드, 노트북, 애드혹 SQL, API 및 타사 도구를 포함한 모든 액세스 경로에 동일한 규칙이 일관되게 적용됩니다. 이러한 일관성이 바로 RLS를 강력하게 만드는 이유입니다. 즉, 하나의 규칙이 모든 곳에 적용되고 엔진에 의해 강제됩니다.

대부분의 엔진은 읽기 측면과 쓰기 측면의 강제 적용을 구분하기도 합니다. 읽기 조건자는 SELECT 쿼리가 반환하는 내용을 제어합니다. 쓰기 조건자는 흔히 WITH CHECK 절을 사용하여 별도로 정의되며, 사용자가 삽입, 업데이트 또는 삭제할 수 있는 행을 제어합니다.

두 조건자는 같을 수도 있지만 반드시 같어야 하는 것은 아닙니다. 예를 들어, 사용자가 모든 지역의 행을 읽을 수는 있지만 자신의 지역에 대한 행만 삽입하도록 허용될 수 있습니다. 테이블이 쓰기 작업을 허용하는 경우 양쪽 모두를 정의하는 것이 중요합니다. 쓰기 검사를 건너뛰는 것은 프로덕션 환경에서 팀들이 RLS를 잘못 구성하는 가장 흔한 실수 중 하나이기 때문입니다.

행 수준 보안 vs. 열 수준 보안 및 기타 액세스 제어

RLS는 여러 세분화된 액세스 제어 기능 중 하나이며, 프로덕션 환경에서는 거의 항상 다른 제어 기능과 함께 사용됩니다. 아래 표는 각 제어 기능이 어떻게 적용되는지 보여줍니다.

제어 기능제한 대상일반적인 사용 사례
행 수준 보안(RLS)테이블의 특정 행사용자를 해당 지역, 테넌트 또는 부서로 제한
열 수준 보안(CLS)테이블의 특정 열분석가에게 급여, SSN 또는 PII 열 숨기기
객체 수준 보안(OLS)전체 테이블, 뷰 또는 측정값민감한 데이터 세트에 대한 액세스를 완전히 차단
데이터 마스킹열 내의 가시적인 값카드 번호의 마지막 4자리만 표시
GRANT / REVOKE테이블 수준 읽기/쓰기 권한테이블 전체에 대한 액세스 허용 또는 거부

이러한 제어 기능은 계층화되도록 설계되었습니다. 일반적인 설정에서는 테이블 수준 권한 부여를 사용하여 테이블에 액세스할 수 있는 사람을 제어하고, RLS를 사용하여 표시되는 행의 범위를 지정하며, 열 수준 보안 또는 데이터 마스킹을 사용하여 해당 행 내의 민감한 필드를 보호합니다. 이를 대체 가능한 메뉴가 아닌 스택으로 취급하면 거버넌스를 감사 가능하고 복원력 있게 만들 수 있습니다. 한 레이어의 잘못된 구성이 다른 레이어에 영향을 미치지 않습니다.

행 수준 보안의 일반적인 사용 사례

RLS는 공유 테이블 내에서 누가 무엇을 볼 수 있는지 강제하는 표준 방법으로, 지역, 테넌트 또는 분류와 같은 키 지정 열을 기준으로 사용자의 속성에 따라 행을 필터링합니다. 대부분의 팀은 하나의 데이터 세트가 서로 다른 가시성 규칙을 가진 여러 대상에게 서비스를 제공해야 할 때 이 기능을 사용합니다.

  • 멀티 테넌트 SaaS: tenant_id 열과 세션 컨텍스트를 사용하여 공유 테이블 내에서 각 고객의 데이터를 격리합니다. 이를 통해 테넌트당 하나의 스키마 또는 하나의 데이터베이스를 운영하는 비용을 방지하는 동시에 쿼리 실행 시 각 고객의 데이터를 완전히 분리할 수 있습니다.
  • 지역별 격리: 지리적 위치에 따라 기본 테이블을 분할하지 않고도 사용자가 자신의 국가 또는 지역에 대한 레코드만 볼 수 있도록 판매, HR 또는 주문 데이터를 제한합니다.
  • 부서별 액세스: 재무, 마케팅 및 운영 팀에 동일한 테이블에 대한 액세스 권한을 부여하되, 부서 또는 코스트 센터(cost-center) 열에 매핑된 서로 다른 행에 액세스하도록 합니다.
  • 규정 준수: 데이터 레지던시 규칙을 강제합니다. 예를 들어 GDPR에 따라 EU 레코드를 EU 기반 직원에게만 표시되도록 하거나 HIPAA, CCPA 또는 산업별 규정에 따라 보호되는 카테고리를 제한합니다.
  • 의료 및 임상 데이터: 임상의가 환자 테이블을 공유하면서 자신의 환자만 볼 수 있도록 하여 사일로 간에 레코드를 복제하지 않고도 HIPAA의 최소 필요 액세스 원칙을 지원합니다.
  • 파트너 및 공급업체 포털: 외부 파트너 간에 단일 데이터 세트를 공유하는 동시에 각 파트너가 자신의 레코드만 필터링하여 볼 수 있도록 하여, 하나의 단일 진실 공급원(source-of-truth) 테이블로 수십 개의 파트너용 뷰를 지원할 수 있습니다.

행 수준 보안을 구현하는 방법: 4단계

일반적인 패턴은 플랫폼 전반에서 일관되며, 필요한 경우 벤더별 구문이 채워집니다.

  1. 필터 로직 식별: 사용자 ID, 그룹 멤버십, 지역, 테넌트 ID 또는 매핑 테이블 중 액세스를 결정하는 요소를 결정합니다. 필터 로직은 사용자가 쿼리 실행 시 제어하는 값이 아니라 세션 컨텍스트 또는 안정적인 조회에서 파생될 수 있어야 합니다.
  2. 키 지정 열 추가 또는 확인: 테이블에 tenant_id, region 또는 owner_id와 같이 필터가 사용할 수 있는 열이 있는지 확인합니다. 이러한 열이 아직 존재하지 않는 경우 정책이 적용되기 전에 백필을 계획하고, 조건자 비용을 낮게 유지하기 위해 열 인덱싱을 고려하세요.
  3. 정책 또는 행 필터 정의: 사용자가 볼 수 있도록 허용된 행에 대해 TRUE를 반환하는 조건자를 작성하고, 테이블이 쓰기를 허용하는 경우 쓰기에 대한 별도의 검사를 작성합니다. 가능한 경우 로직을 SQL로 유지하세요. 대부분의 엔진은 다른 언어로의 함수 호출보다 SQL 조건자를 더 잘 최적화합니다.
  4. 여러 사용자 신원으로 테스트: 서로 다른 역할로 쿼리를 실행하여 올바른 행이 나타나는지, 테넌트 간에 데이터가 유출되지 않는지 확인합니다. 부정 테스트(negative test)를 포함하세요. 일치하는 행이 없는 사용자는 오류가 아니라 빈 결과를 보아야 하며, 권한이 있는 사용자는 소유자 우회(owner-bypass) 동작을 확인하기 위해 별도로 테스트해야 합니다.
보고서

기업을 위한 에이전틱 AI 플레이북

행 수준 보안의 이점

액세스 로직을 데이터 레이어로 이동하면 여러 가지 실질적인 이점을 얻을 수 있습니다. 간단히 말해, 데이터를 다루는 모든 애플리케이션이 아니라 데이터베이스가 액세스의 단일 진실 공급원(source of truth)이 됩니다.

  • 중앙 집중식 로직: 액세스 규칙이 애플리케이션 코드나 BI 도구에 분산되지 않고 데이터와 함께 유지됩니다.
  • 일관된 강제 적용: 사용자가 노트북, 대시보드 또는 API 중 어디에서 쿼리하든 동일한 규칙이 적용됩니다.
  • 심층 방어: RLS는 애플리케이션 레이어 검사가 우회되거나 버그가 있는 경우 두 번째 보호 레이어를 추가합니다.
  • 더 간단한 애플리케이션 코드: 개발자가 모든 쿼리에 수동으로 WHERE 절을 추가할 필요가 없습니다.
  • 더 쉬운 감사: 규정 준수 팀은 여러 시스템에 걸쳐 액세스 로직을 추적하는 대신 하나의 정책만 검토하면 됩니다.
  • 새로운 도구의 신속한 온보딩: 새로운 BI 도구나 노트북 환경은 별도의 통합 작업 없이도 기존의 행 수준 규칙을 그대로 상속받습니다.

행 수준 보안의 한계와 위험성

RLS는 강력하지만, 팀에서 미리 대비해야 할 잘 알려진 함정들이 있습니다. 이러한 문제의 대부분은 프로덕션 단계나 감사 중에만 나타나므로 미리 알아두는 것이 좋습니다.

관리자 및 소유자 우회

많은 데이터베이스에서 테이블 소유자와 높은 권한을 가진 관리자는 기본적으로 RLS를 우회합니다. 예를 들어 PostgreSQL에서는 테이블 소유자에게 정책을 적용하려면 FORCE ROW LEVEL SECURITY 설정이 필요하며, 다른 엔진에도 유사한 설정이 존재합니다. 이는 감사에서 자주 지적되는 사항입니다. 구성에서 정책을 강제로 적용하도록 명시하지 않는 한, 권한이 있는 사용자는 모든 행을 볼 수 있다고 가정해야 합니다. 최종 승인하기 전에 일반 세션뿐만 아니라 권한이 있는 세션에서도 정책을 테스트해 보세요.

열 또는 요약 숨기기 불가

RLS는 행을 필터링하지만, 열을 숨기거나 집계 결과를 차단하지는 않습니다. RLS가 열 또는 집계 제한과 결합되지 않은 경우, 개별 EU 레코드를 볼 수 없도록 차단된 분석가도 필터링되지 않은 테이블에 대해 SELECT COUNT(*)을(를) 실행할 수 있습니다. 이러한 공백을 메우려면 RLS를 열 수준 보안 또는 데이터 마스킹과 결합하고, 가장 민감한 테이블에 대해서는 집계 쿼리 자체를 제어해야 하는지 검토하세요.

성능 오버헤드

모든 쿼리에 RLS 조건자가 적용되므로, 필터 로직이 복잡하거나 키 지정 열이 인덱싱되지 않은 경우 성능이 저하될 수 있습니다. 정책이 참조하는 열을 인덱싱하고 조건자를 최대한 단순하게 유지하세요. 필터 내부에서 서브쿼리나 매핑 테이블 조회를 사용하는 대신 간단한 CASE 표현식을 사용하는 것이 좋습니다. 엔진이 지원하는 경우, 사용자 대 행 매핑을 실시간으로 계산하는 대신 인덱싱이 잘 된 작은 테이블로 구체화(materialize)하세요.

디버깅의 복잡성

RLS로 인해 발생하는 빈 결과 세트는 '일치하는 데이터 없음'과 동일하게 보입니다. 누락된 행을 찾는 개발자들은 정책에 의해 필터링되었다는 사실을 깨닫기 전까지 몇 시간씩 허비하곤 합니다. 개발 중에 유효한 사용자 ID와 정책 버전을 로깅하고, 결과가 잘못되었을 때 엔지니어가 RLS의 활성화 여부를 확인할 수 있는 방법을 제공하며, 쉽게 찾을 수 있도록 테이블 스키마와 동일한 위치에 정책을 문서화하세요.

잘못 구성된 쓰기 규칙

RLS 정책에는 대개 두 가지 측면이 있습니다. 사용자가 읽을 수 있는 내용을 필터링하는 USING 절과 사용자가 삽입하거나 업데이트할 수 있는 내용을 제어하는 WITH CHECK 절입니다. 둘 중 하나만 정의하는 것은 흔히 하는 실수입니다. 쓰기 검사 없이 읽기 필터링만 적용하면 사용자가 소유해서는 안 되는 행을 삽입하거나 업데이트할 수 있게 됩니다. 테이블이 쓰기를 허용하는 경우 항상 두 가지를 모두 정의하고, 정책 검토의 일환으로 쓰기 측 테스트를 실행하세요.

Databricks 플랫폼의 행 수준 보안

Databricks 플랫폼에서 행 수준 보안은 데이터 및 AI를 위한 Databricks의 통합 거버넌스 계층인 Unity Catalog의 행 필터를 통해 처리됩니다. 패턴은 간단합니다. 특정 사용자가 볼 수 있는 행에 대해 true를 반환하는 SQL 사용자 정의 함수(UDF)를 정의한 다음, 이를 대상 테이블에 연결합니다. 필터는 쿼리 실행 시 자동으로 실행되며, 현재 사용자의 ID 또는 세션 컨텍스트를 사용하여 반환할 행을 결정합니다.

행 필터는 Databricks SQL, 노트북, 작업 및 연결된 BI 도구 전반에 걸쳐 일관되게 적용되므로 각 환경마다 별도의 커스텀 로직이 필요하지 않습니다. 행 필터는 열 마스크와 함께 작동하여 완전하고 미세한 수준의 액세스 제어(fine-grained access control)를 제공하며, 필터링된 테이블에 액세스하는 모든 쿼리는 Unity Catalog의 리니지 및 감사 로그에 기록됩니다. 따라서 거버넌스 및 보안 팀은 어떤 정책이 어떤 테이블에 적용되는지, 어떤 사용자가 무엇을 조회했는지 정확히 파악할 수 있습니다.

자주 묻는 질문

동적 행 수준 보안이란 무엇인가요? 동적 RLS는 현재 사용자의 ID 또는 세션 컨텍스트를 사용하여 쿼리 실행 시 액세스 규칙을 평가하므로, 동일한 정책이라도 사용자마다 다른 결과를 반환합니다. Databricks의 ABAC 정책, 행 필터, 동적 뷰를 포함하여 모든 최신 RLS 구현이 이 방식으로 작동합니다.

행 수준 보안과 열 수준 보안의 차이점은 무엇인가요? RLS는 사용자가 볼 수 있는 행을 제한하고, 열 수준 보안은 열을 제한하여 일반적으로 급여나 주민등록번호와 같은 민감한 필드를 숨기는 데 사용됩니다. 대부분의 프로덕션 배포에서는 두 가지를 함께 사용합니다.

행 수준 보안만으로 민감한 데이터를 보호하기에 충분한가요? 아닙니다. RLS는 행의 가시성을 처리하지만 열 값을 마스킹하거나, 집계 쿼리를 차단하거나, ID 및 액세스 관리를 대체하지는 않습니다. 심층 방어(defense-in-depth) 전략의 일환으로 열 수준 보안, 테이블 수준 권한 부여, 감사 로깅과 함께 사용하세요.

Databricks는 행 수준 보안을 어떻게 구현하나요? Unity Catalog를 통해 ABAC 정책, 테이블 수준 행 필터, 동적 뷰의 세 가지 옵션을 제공합니다. 대규모 거버넌스에는 ABAC가 권장되며, 보다 맞춤화된 요구사항에는 행 필터와 동적 뷰를 사용할 수 있습니다.

행 수준 보안이 쿼리 성능에 영향을 미치나요? 예, 하지만 일반적으로 영향은 관리 가능한 수준입니다. 정책 로직을 단순하게 유지하고, 정책이 참조하는 열을 인덱싱하며, Python UDF보다 SQL UDF를 사용하는 것이 좋습니다. 성능 저하를 조기에 발견할 수 있도록 정책 변경 전후에 쿼리 프로파일링을 수행하세요.

Databricks에서 미세한 수준의 액세스 제어 시작하기

행 수준 보안은 열, 마스킹, 리니지 및 감사까지 포괄하는 광범위한 거버넌스 모델의 일부로 사용할 때 가장 효과적입니다. Unity Catalog가 어떻게 Databricks 플랫폼에서 행 수준 보안, 열 마스킹, 통합 거버넌스를 함께 제공하는지 확인해 보세요.

(이 글은 AI의 도움을 받아 번역되었습니다. 원문이 궁금하시다면 여기를 클릭해 주세요)

최신 게시물을 이메일로 받아보세요

블로그를 구독하고 최신 게시물을 이메일로 받아보세요.