2026년 10월 05일 | DBMS Error 가이드
이 글에서 다루는 내용
01006 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
01006 privilege not revoked 는?
PostgreSQL 에러 코드 01006은 SQLSTATE 01006, 즉 “privilege not revoked” 경고(Warning)입니다. 이 에러는 REVOKE 명령을 실행했을 때, 해당 권한이 실제로 존재하지 않아 취소되지 않은 경우 발생합니다. 엄밀히 말하면 에러(Error)가 아닌 경고(Warning) 수준이므로 쿼리 자체가 실패하지는 않지만, 권한 관리가 의도대로 이루어지지 않았음을 의미하기 때문에 실무에서는 반드시 주의를 기울여야 합니다.
주요 발생 원인
1. 존재하지 않는 권한을 REVOKE 시도
가장 흔한 원인입니다. 특정 사용자(Role)에게 부여된 적이 없는 권한을 취소하려 할 때 이 경고가 발생합니다. 예를 들어, user_a에게 INSERT 권한을 부여한 적이 없는데 REVOKE INSERT를 실행하면 PostgreSQL은 조용히 경고만 출력하고 넘어갑니다. 이 상황은 권한 관리 스크립트를 여러 환경(개발/스테이징/운영)에 동일하게 적용할 때 특히 자주 발생합니다.
2. 잘못된 GRANT OPTION 또는 권한 계층 문제
PostgreSQL에서는 권한을 부여할 때 WITH GRANT OPTION을 통해 다른 사용자에게 권한을 재부여할 수 있는 능력을 줄 수 있습니다. 이 경우, 중간 역할(Role)이 삭제되거나 권한 체인이 깨진 상태에서 REVOKE를 시도하면 01006 경고가 발생할 수 있습니다. 권한 계층 구조가 복잡할수록 이 문제가 발생할 가능성이 높아집니다.
3. 그룹 Role 또는 상속 구조에서의 권한 혼동
PostgreSQL은 역할 기반 접근 제어(RBAC)를 지원하며, 사용자는 여러 그룹 Role에 속할 수 있습니다. 개별 사용자에게 직접 부여되지 않고 그룹 Role을 통해 상속받은 권한을 직접 REVOKE하려 할 때 이 경고가 발생합니다. DBA가 개별 사용자 레벨에서 권한을 제거하려 하지만 실제로는 그룹 레벨에 권한이 존재하는 경우가 대표적입니다.
해결 방법
원인 1: 존재하지 않는 권한 REVOKE 시도 해결
먼저 해당 사용자에게 실제로 어떤 권한이 부여되어 있는지 확인합니다.
-- 특정 테이블에 대한 권한 현황 조회
SELECT grantee, table_name, privilege_type, is_grantable
FROM information_schema.role_table_grants
WHERE table_name = 'your_table_name'
AND grantee = 'target_user';
-- 스키마 레벨 권한 확인
SELECT nspname, acl.*
FROM pg_namespace,
aclexplode(nspacl) AS acl
WHERE nspname = 'your_schema_name';
권한이 존재하는지 확인 후 REVOKE를 실행합니다.
-- 권한 존재 여부 확인 후 안전하게 REVOKE
DO $$
DECLARE
v_count INT;
BEGIN
SELECT COUNT(*)
INTO v_count
FROM information_schema.role_table_grants
WHERE table_name = 'employees'
AND grantee = 'user_a'
AND privilege_type = 'INSERT';
IF v_count > 0 THEN
EXECUTE 'REVOKE INSERT ON employees FROM user_a';
RAISE NOTICE 'INSERT privilege revoked from user_a';
ELSE
RAISE NOTICE 'No INSERT privilege found for user_a, skipping REVOKE';
END IF;
END;
$$;
원인 2: GRANT OPTION 관련 문제 해결
-- 현재 권한 및 GRANT OPTION 상태 확인
SELECT grantor, grantee, privilege_type, is_grantable
FROM information_schema.role_table_grants
WHERE table_name = 'sensitive_data';
-- GRANT OPTION만 선택적으로 REVOKE
REVOKE GRANT OPTION FOR SELECT ON sensitive_data FROM intermediate_role;
-- CASCADE 옵션으로 하위 권한까지 함께 제거
REVOKE SELECT ON sensitive_data FROM intermediate_role CASCADE;
CASCADE 옵션을 사용하면 해당 Role이 다른 사용자에게 재부여한 권한도 함께 취소됩니다. 운영 환경에서는 CASCADE 사용 전 반드시 영향 범위를 사전에 확인하십시오.
원인 3: 그룹 Role 상속 권한 문제 해결
-- 특정 사용자의 Role 멤버십 확인
SELECT r.rolname AS role_name,
m.rolname AS member_name,
g.rolname AS granted_by
FROM pg_auth_members am
JOIN pg_roles r ON r.oid = am.roleid
JOIN pg_roles m ON m.oid = am.member
JOIN pg_roles g ON g.oid = am.grantor
WHERE m.rolname = 'target_user';
-- 그룹 Role 레벨에서 권한 제거
REVOKE SELECT ON TABLE orders FROM group_role_read;
-- 특정 사용자만 그룹에서 제외
REVOKE group_role_read FROM specific_user;
그룹 Role 구조 전체 권한을 확인하는 쿼리:
-- pg_default_acl 확인 (스키마 기본 권한)
SELECT pg_get_userbyid(defaclrole) AS role,
nspname AS schema,
defaclobjtype AS object_type,
aclexplode(defaclacl) AS acl_info
FROM pg_default_acl
JOIN pg_namespace ON pg_namespace.oid = pg_default_acl.defaclnamespace;
예방 방법
1. 권한 관리 스크립트에 사전 검증 로직 포함
운영 환경에서 권한 변경 스크립트를 실행하기 전, 반드시 현재 권한 상태를 조회하는 검증 단계를 포함하십시오. 아래와 같이 idempotent(멱등성)한 스크립트를 작성하면 동일한 스크립트를 여러 환경에 반복 적용하더라도 01006 경고를 방지할 수 있습니다.
-- 권한 부여 전 확인 후 조건부 실행
DO $$
BEGIN
-- 권한이 없을 때만 GRANT
IF NOT EXISTS (
SELECT 1 FROM information_schema.role_table_grants
WHERE grantee = 'app_user'
AND table_name = 'orders'
AND privilege_type = 'SELECT'
) THEN
GRANT SELECT ON orders TO app_user;
RAISE NOTICE 'GRANT executed';
ELSE
RAISE NOTICE 'Privilege already exists, skipping GRANT';
END IF;
END;
$$;
2. 정기적인 권한 감사(Audit) 체계 구축
PostgreSQL의 pg_roles, information_schema.role_table_grants, pg_default_acl 등을 활용한 정기 권한 감사 리포트를 구축하십시오. 최소 월 1회 이상 권한 현황을 스냅샷으로 기록하고, 변경 사항을 추적하면 불필요한 권한 누적과 잘못된 REVOKE 시도를 사전에 방지할 수 있습니다. 가능하다면 pgaudit 익스텐션을 도입하여 DDL 및 권한 변경 이력을 로그로 남기는 것을 강력히 권장합니다.
관련 에러
- 42501 (insufficient_privilege): 권한이 없는 상태에서 객체에 접근하려 할 때 발생하는 에러로, 01006과 함께 권한 관리 문제를 진단할 때 자주 등장합니다.
- 0LP01 (invalid_grant_operation): GRANT/REVOKE 명령 자체가 잘못된 구문이나 대상으로 실행될 때 발생합니다.
- 42000 (syntax_error_or_access_rule_violation): 접근 규칙 위반 관련 에러 클래스로, 권한 체계 전반의 문제를 포괄합니다.
- 01007 (privilege_not_granted): 01006의 반대 개념으로, 권한이 부여되지 않은 상태에서 관련 작업을 시도할 때 발생하는 경고입니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.