행 필터란?
행 필터(Row Filter) 는 테이블의 데이터를 조회할 때 사용자에 따라 보이는 행을 동적으로 제한 하는 기능입니다. 원본 데이터를 변경하지 않고, SQL 함수를 통해 조회 시점에 필터가 자동 적용됩니다.💡 왜 필요한가요? 같은 테이블이라도 서울 지역 담당자는 서울 데이터만, 부산 지역 담당자는 부산 데이터만 봐야 하는 경우가 있습니다. 뷰를 만들어 분리할 수도 있지만, 담당자가 늘어날 때마다 뷰를 추가해야 하므로 관리가 어렵습니다. 행 필터를 사용하면 하나의 테이블에 하나의 정책 으로 해결할 수 있습니다.
이 기능의 기본 개념은 권한 관리의 “행 수준 보안” 섹션에서 소개했습니다. 이 문서에서는 다양한 시나리오와 고급 패턴을 상세히 다룹니다.
동작 원리
행 필터는 SQL 함수 로 구현됩니다. 이 함수는 각 행에 대해TRUE 또는 FALSE를 반환하며, TRUE인 행만 사용자에게 보입니다.
필터 함수에서 사용하는 주요 함수
| 함수 | 설명 | 예시 |
|---|---|---|
| IS_ACCOUNT_GROUP_MEMBER() | 현재 사용자가 특정 그룹의 멤버인지 확인합니다 | IS_ACCOUNT_GROUP_MEMBER('admin') |
| CURRENT_USER() | 현재 로그인한 사용자의 이메일을 반환합니다 | CURRENT_USER() = 'alice@corp.com' |
| IS_MEMBER() | Workspace 로컬 그룹 멤버 여부를 확인합니다 | IS_MEMBER('ws_admins') |
기본 설정 방법
단계 1: 필터 함수 생성
단계 2: 테이블에 행 필터 적용
단계 3: 동작 확인
행 필터 제거
시나리오별 예제
시나리오 1: 부서별 데이터 접근 제어
시나리오 2: 본인 데이터만 조회 (CURRENT_USER 활용)
시나리오 3: 날짜 기반 접근 제어
시나리오 4: 다중 컬럼 기반 필터
주의사항 및 제한
| 항목 | 설명 |
|---|---|
| 테이블당 하나 | 하나의 테이블에 하나의 행 필터만 적용할 수 있습니다 |
| 성능 영향 | 복잡한 필터 함수는 쿼리 성능에 영향을 줄 수 있습니다 |
| 뷰 전파 | 행 필터가 적용된 테이블을 참조하는 뷰에도 필터가 자동 적용됩니다 |
| 소유자 면제 | 테이블 소유자(OWNER)에게는 행 필터가 적용되지 않습니다 |
| EXPLAIN 노출 | EXPLAIN 실행 시 필터 로직이 표시될 수 있으므로, 민감한 정책은 주의가 필요합니다 |
| Managed Table만 | 외부 테이블(External Table)에는 행 필터를 적용할 수 없습니다 |
모범 사례
| 원칙 | 설명 |
|---|---|
| 전용 스키마 | 필터 함수를 production.policies 같은 전용 스키마에 모아 관리합니다 |
| 관리자 예외 | 모든 필터에 IS_ACCOUNT_GROUP_MEMBER('admin') 조건을 포함합니다 |
| 테스트 우선 | 프로덕션 적용 전 dev 환경에서 충분히 테스트합니다 |
| 문서화 | 각 필터 함수에 COMMENT로 목적과 대상을 명시합니다 |
| 성능 최적화 | 필터 조건이 단순할수록 쿼리 성능이 좋습니다 |
현업 사례: 다국적 기업에서 리전별 데이터 격리를 Row Filter로 구현
🔥 GDPR, 개인정보보호법 등 규제를 다루는 프로젝트에서 자주 등장하는 패턴입니다.글로벌 기업에서 “한국 팀은 한국 고객 데이터만, EU 팀은 EU 고객 데이터만 볼 수 있어야 합니다”라는 요구사항은 매우 흔합니다. 뷰를 리전별로 만들면 리전이 추가될 때마다 뷰를 추가해야 합니다. Row Filter를 사용하면 하나의 테이블에 하나의 정책 으로 해결됩니다.
실제 구현 사례
구현 후 실제 동작 확인
성능 영향: 필터 함수가 모든 쿼리에 추가됩니다
⚠️ 많은 팀이 간과하는 부분입니다. Row Filter는 해당 테이블에 대한 모든 쿼리 에 자동으로 WHERE 조건이 추가되는 것과 같습니다. 이것이 성능에 미치는 영향을 반드시 이해해야 합니다.
성능 테스트 실측 결과
성능 최적화 규칙
| 규칙 | 설명 | 성능 영향 |
|---|---|---|
| 필터 함수를 단순하게 | IS_ACCOUNT_GROUP_MEMBER() + 간단한 비교만 사용 | 최소 |
| 서브쿼리 피하기 | 필터 함수 내에서 다른 테이블을 조회하지 마세요 | 치명적 |
| IN 절 값 제한 | IN 절의 값이 50개 이상이면 매핑 테이블로 분리 | 중간 |
| 파티션 컬럼 활용 | 필터 조건이 파티션 컬럼과 일치하면 파티션 프루닝 적용 | 최적 |
복잡한 필터 로직의 디버깅 전략
Row Filter가 적용된 테이블에서 “왜 이 데이터가 안 보이죠?”라는 질문은 현업에서 매우 자주 발생합니다. 디버깅이 까다로운 이유는 필터가 투명하게 적용되어 사용자가 필터의 존재를 모르는 경우 가 많기 때문입니다.디버깅 체크리스트
흔한 디버깅 시나리오
| 증상 | 원인 | 해결 |
|---|---|---|
| ”아무 데이터도 안 보여요” | 필터 조건에 해당하는 그룹에 속하지 않음 | 사용자를 올바른 그룹에 추가 |
| ”어제까지 보이던 데이터가 안 보여요” | 그룹 멤버십이 변경됨 (SCIM 동기화 이슈 등) | IdP에서 그룹 멤버십 확인 |
| ”집계 결과가 다른 팀과 안 맞아요” | 각 팀이 서로 다른 리전 데이터를 보고 있음 | 필터가 적용된다는 사실을 공유 |
| ”EXPLAIN에서 필터 조건이 보여요” | EXPLAIN은 필터 로직을 노출함 | 보안 민감 정책은 EXPLAIN 권한 제한 고려 |
테스트 환경에서의 필터 검증 패턴
💡 현업 팁: Row Filter를 적용할 때는 반드시 각 그룹별 테스트 계정 을 준비하세요. “admin으로 로그인하면 다 보이니까 괜찮겠지”는 가장 위험한 생각입니다. 실제 일반 사용자의 관점에서 데이터가 올바르게 필터링되는지 확인해야 합니다. 그리고 필터 함수를 변경할 때는 dev 환경에서 먼저 테스트 한 후 production에 적용하는 프로세스를 반드시 지켜야 합니다.
정리
| 핵심 개념 | 설명 |
|---|---|
| Row Filter | SQL 함수로 사용자별 행 접근을 동적으로 제어합니다 |
| 필터 함수 | RETURNS BOOLEAN 함수로, TRUE인 행만 조회됩니다 |
| IS_ACCOUNT_GROUP_MEMBER | 그룹 기반 조건 분기의 핵심 함수입니다 |
| CURRENT_USER | 현재 사용자 기반 필터링에 사용합니다 |
| 테이블당 1개 | 행 필터는 테이블당 하나만 적용할 수 있습니다 |