2026년 10월 05일 | DBMS Error 가이드
이 글에서 다루는 내용
01007 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
01007 privilege not granted 는?
PostgreSQL 에러 코드 01007 (privilege_not_granted) 은 특정 권한을 다른 사용자나 롤(Role)에게 부여(GRANT)하려 했으나, 해당 권한을 실제로 전달할 수 있는 위임 권한(GRANT OPTION) 이 없을 때 발생하는 경고성 에러입니다. 이 에러는 트랜잭션을 중단시키는 치명적인 오류(ERROR)가 아닌 경고(WARNING) 수준으로 분류되기 때문에, 실제 운영 환경에서 조용히 지나칠 수 있어 더욱 주의가 필요합니다. 일반적으로 복잡한 롤 계층 구조를 가진 시스템이나, 권한 위임 정책이 명확하지 않은 환경에서 자주 나타납니다.
주요 발생 원인
- GRANT OPTION 없이 권한 재위임 시도
가장 흔한 원인입니다. PostgreSQL에서 특정 사용자가 다른 사용자에게 권한을 부여하려면, 자신이 해당 권한을 WITH GRANT OPTION과 함께 받았어야 합니다. 예를 들어, user_a가 SELECT 권한을 WITH GRANT OPTION 없이 부여받은 상태에서 user_b에게 같은 권한을 넘기려 하면 01007 경고가 발생합니다. 이 경우 실제 권한 이전이 이루어지지 않으므로, 애플리케이션에서 해당 사용자를 통해 권한을 전달하는 로직이 있다면 반드시 점검해야 합니다.
- 존재하지 않거나 이미 부여된 권한을 GRANT할 때
대상 객체(테이블, 시퀀스, 함수 등)에 대해 현재 세션의 사용자가 소유하지 않거나, 슈퍼유저가 아닌 상태에서 권한 부여를 시도할 때 발생합니다. 또한 이미 동일한 권한이 부여되어 있는 상태에서 GRANT를 재실행하면, PostgreSQL은 에러 대신 이 경고를 발생시키며 작업을 무시합니다. 이는 자동화된 배포 스크립트나 마이그레이션 도구에서 멱등성(idempotency)을 고려하지 않았을 때 자주 나타납니다.
- 롤 계층 구조에서 간접 권한의 재위임 시도
PostgreSQL의 롤 기반 접근 제어(RBAC)에서는 롤 A가 롤 B를 멤버로 포함하고, 롤 B가 특정 테이블에 대한 권한을 가질 때, 롤 A의 멤버가 그 권한을 직접 제3의 사용자에게 GRANT할 수 없습니다. 간접적으로 상속받은 권한은 WITH GRANT OPTION이 명시적으로 설정되어 있지 않으면 재위임이 불가능합니다. 이 구조적 특성을 이해하지 못하고 권한 스크립트를 작성하면 01007 경고가 반복적으로 발생하게 됩니다.
해결 방법
원인 1: GRANT OPTION 부여
권한을 재위임해야 하는 사용자에게 WITH GRANT OPTION을 포함하여 권한을 부여합니다.
-- 잘못된 방식: GRANT OPTION 없이 부여
GRANT SELECT ON TABLE orders TO user_a;
-- user_a가 다시 user_b에게 부여 시도 → 01007 경고 발생
-- (user_a 세션에서 실행)
GRANT SELECT ON TABLE orders TO user_b; -- WARNING: 01007
-- 올바른 방식: 슈퍼유저 또는 테이블 소유자가 GRANT OPTION 포함하여 부여
GRANT SELECT ON TABLE orders TO user_a WITH GRANT OPTION;
-- 이제 user_a 세션에서 정상적으로 위임 가능
-- (user_a 세션에서 실행)
GRANT SELECT ON TABLE orders TO user_b; -- 성공
원인 2: 현재 권한 상태 확인 후 중복 GRANT 방지
권한 부여 전에 이미 해당 권한이 존재하는지 먼저 확인합니다.
-- 특정 테이블에 대한 권한 현황 조회
SELECT grantee, table_name, privilege_type, is_grantable
FROM information_schema.role_table_grants
WHERE table_name = 'orders'
AND grantee = 'user_b';
-- 권한이 없을 때만 부여하는 조건부 처리 (DO 블록 활용)
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1
FROM information_schema.role_table_grants
WHERE table_name = 'orders'
AND grantee = 'user_b'
AND privilege_type = 'SELECT'
) THEN
EXECUTE 'GRANT SELECT ON TABLE orders TO user_b';
RAISE NOTICE 'Privilege granted successfully.';
ELSE
RAISE NOTICE 'Privilege already exists, skipping.';
END IF;
END;
$$;
원인 3: 롤 계층 구조 재설계
간접 상속 대신 명시적인 권한 부여 체계를 구성합니다.
-- 문제 상황: role_manager가 role_staff의 권한을 재위임하려 함
CREATE ROLE role_staff;
CREATE ROLE role_manager;
GRANT role_staff TO role_manager; -- role_manager는 role_staff 멤버
GRANT SELECT ON TABLE salary TO role_staff;
-- role_manager 세션에서 third_user에게 위임 시도 → 01007 발생
GRANT SELECT ON TABLE salary TO third_user; -- WARNING
-- 해결: 권한을 직접 role_manager에게 부여하고 GRANT OPTION 포함
GRANT SELECT ON TABLE salary TO role_manager WITH GRANT OPTION;
-- 이제 role_manager는 다른 사용자에게 직접 권한 위임 가능
-- (role_manager 세션에서 또는 슈퍼유저가 대신 실행)
GRANT SELECT ON TABLE salary TO third_user; -- 성공
-- 현재 롤 계층 및 권한 위임 가능 여부 확인
SELECT rolname, member, admin_option
FROM pg_auth_members
JOIN pg_roles ON pg_roles.oid = pg_auth_members.roleid
WHERE member = (SELECT oid FROM pg_roles WHERE rolname = 'role_manager');
권한 전체 감사 쿼리
-- 테이블별 권한 및 GRANT OPTION 보유 현황 전체 조회
SELECT
t.table_schema,
t.table_name,
g.grantee,
g.privilege_type,
g.is_grantable
FROM information_schema.tables t
JOIN information_schema.role_table_grants g
ON t.table_name = g.table_name
AND t.table_schema = g.table_schema
WHERE t.table_schema NOT IN ('information_schema', 'pg_catalog')
ORDER BY t.table_schema, t.table_name, g.grantee;
예방 방법
- 권한 부여 정책을 문서화하고 전용 관리 롤을 운영하세요
권한 부여와 위임은 반드시 전담 DBA 롤 또는 권한 관리 롤(예: role_grant_admin)을 통해서만 이루어지도록 정책을 수립하세요. 이 롤에만 WITH GRANT OPTION을 부여하고, 일반 사용자나 애플리케이션 롤은 이 체계를 통해 권한을 받도록 구성하면 01007 경고의 대부분을 사전에 차단할 수 있습니다. 또한 권한 변경 이력을 PostgreSQL의 감사 로그(pgaudit 확장 등)로 추적하면 문제 발생 시 빠른 원인 파악이 가능합니다.
- 배포 스크립트에 멱등성 체크를 반드시 포함하세요
CI/CD 파이프라인이나 마이그레이션 도구(Flyway, Liquibase 등)를 사용할 때, GRANT 구문을 실행하기 전에 반드시 현재 권한 상태를 조회하는 로직을 포함하세요. 앞서 소개한 DO $$...$$ 블록 패턴이나, information_schema.role_table_grants 뷰를 활용한 사전 검사를 자동화하면 중복 권한 부여로 인한 01007 경고를 완전히 제거할 수 있습니다.
관련 에러
- 42501 (insufficient_privilege): 권한 자체가 없어 쿼리 실행이 거부될 때 발생하는 에러로, 01007이 경고로 조용히 지나갔을 경우 후속으로 발생할 수 있습니다.
- 01006 (privilege_not_revoked): 권한 회수(REVOKE) 시 해당 권한이 존재하지 않을 때 발생하는 유사한 경고 코드입니다. GRANT/REVOKE 짝으로 함께 관리해야 합니다.
- 0LP01 (invalid_grant_operation): 잘못된 객체 유형이나 범위에 대해 GRANT를 시도할 때 발생하며, 권한 관련 에러군에서 함께 점검해야 할 코드입니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.