본문으로 건너뛰기
9.1 사용자·역할·GRANT/REVOKE

9.1 사용자·역할·GRANT/REVOKE

PostgreSQL은 “user"와 “group"을 구분하지 않고 모두 역할(role)이라는 하나의 개념으로 다룹니다. 역할에 비밀번호·로그인 권한·다른 역할 멤버십·객체 권한이 붙습니다. GRANT/REVOKE로 세밀하게 부여·회수합니다.

역할의 두 얼굴

속성의미
LOGIN클라이언트가 직접 접속 가능. 보통 “사용자"라고 부르는 역할
NOLOGIN (기본)접속 불가. 보통 “그룹"으로 쓰임
SUPERUSER모든 권한 (위험)
CREATEDB데이터베이스 만들기
CREATEROLE역할 만들기·관리
REPLICATION복제 연결 가능
BYPASSRLSRLS 정책 무시
INHERIT (기본)멤버십을 통해 권한 상속
PASSWORD '...'비밀번호
VALID UNTIL '...'만료 시점
-- 그룹 역할
CREATE ROLE app_readers NOLOGIN;
CREATE ROLE app_writers NOLOGIN;

-- 사람 사용자
CREATE ROLE alice LOGIN PASSWORD 'secret' VALID UNTIL '2027-01-01';
GRANT app_readers, app_writers TO alice;

-- 애플리케이션 사용자
CREATE ROLE svc_app LOGIN PASSWORD 'secret_app';
GRANT app_writers TO svc_app;

권한 객체

PostgreSQL이 권한을 갖는 객체:

객체권한 예시
DatabaseCONNECT, CREATE, TEMPORARY
SchemaUSAGE, CREATE
Table / View / Materialized ViewSELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER
ColumnSELECT, INSERT, UPDATE, REFERENCES
SequenceUSAGE, SELECT, UPDATE
Function / ProcedureEXECUTE
Type / DomainUSAGE
Foreign Data WrapperUSAGE
TablespaceCREATE

GRANT / REVOKE

-- 스키마 접근
GRANT USAGE ON SCHEMA app TO app_readers, app_writers;

-- 읽기 전용
GRANT SELECT ON ALL TABLES IN SCHEMA app TO app_readers;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA app TO app_readers;

-- 쓰기
GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA app TO app_writers;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA app TO app_writers;

-- 회수
REVOKE INSERT, UPDATE, DELETE ON app.orders FROM app_writers;

ALL TABLES IN SCHEMA는 현재 존재하는 테이블만. 새로 만들어지는 테이블에 자동 적용하려면 default privileges.

ALTER DEFAULT PRIVILEGES

새로 만드는 객체에 적용될 기본 권한을 미리 정의합니다.

-- alice가 app 스키마에 만들 미래 테이블은 자동으로 app_readers에 SELECT 부여
ALTER DEFAULT PRIVILEGES
  FOR ROLE alice
  IN SCHEMA app
  GRANT SELECT ON TABLES TO app_readers;

운영의 핵심 패턴 — 그룹 역할 + default privileges로 신규 객체도 자동 권한 부여.

PUBLIC

PUBLIC은 모든 역할에 부여되는 가상의 역할. 위험합니다.

-- 모든 사용자가 어느 DB에든 접속 가능 (위험)
GRANT CONNECT ON DATABASE app_main TO PUBLIC;

-- 보안 강화: PUBLIC의 CONNECT를 회수
REVOKE CONNECT ON DATABASE app_main FROM PUBLIC;

기본 클러스터에서 PUBLIC이 갖는 권한:

  • template1·새 DB의 public 스키마에 CREATE, USAGE (PG 14까지)
  • PG 15+부터 public 스키마의 CREATE가 PUBLIC에서 회수 — 보안 개선
  • 일부 시스템 함수 EXECUTE

운영 표준: 새 클러스터에서 PUBLIC의 불필요한 권한은 모두 REVOKE.

역할 멤버십 (그룹·역할 상속)

GRANT app_readers TO alice;        -- alice가 app_readers 멤버
GRANT app_readers TO alice WITH ADMIN OPTION;  -- alice가 다른 사람에게도 부여 가능

-- 현재 사용자가 갖는 역할
SELECT * FROM pg_roles WHERE rolname = current_user;

기본 동작 (INHERIT):

  • alice가 app_readers의 권한을 자동으로 가짐
  • 별도 SET ROLE 불필요

NOINHERIT 역할은 명시적 SET ROLE app_readers가 필요합니다. PostgreSQL 16에서 멤버십에 WITH SET FALSE 같은 세부 옵션이 추가됐습니다.

SET ROLE — 일시적 역할 전환

SET ROLE app_writers;
INSERT INTO app.orders VALUES (...);
RESET ROLE;

세션 중 다른 역할로 일시 전환. 객체 소유권·권한 위임 시나리오에 사용합니다.

객체 소유자

각 객체에는 owner가 있습니다. owner는:

  • DROP, ALTER, REINDEX, VACUUM, ANALYZE 가능
  • 다른 사용자에게 GRANT 가능
  • REASSIGN OWNED BY / DROP OWNED BY로 소유권 이전
-- 모든 객체를 다른 사용자에게
REASSIGN OWNED BY alice TO svc_app;

-- alice가 가진 모든 객체 + 권한 제거
DROP OWNED BY alice;
DROP ROLE alice;

사용자 삭제 전 표준 절차. 그냥 DROP ROLE alice는 다른 객체가 alice를 참조 중이면 실패.

흔한 권한 모델

1. 3-tier 역할 (그룹 + 사용자)

    flowchart TD
  G1["app_readers (그룹)"]
  G2["app_writers (그룹)"]
  G3["app_admins (그룹)"]
  U1["alice (사람)"]
  U2["bob (사람)"]
  U3["svc_app (앱)"]

  G1 --> U1
  G1 --> U2
  G1 --> U3
  G2 --> U2
  G2 --> U3
  G3 --> U1

  classDef group fill:#ede9fe,stroke:#6d28d9,color:#3b0764,stroke-width:2px
  classDef user fill:#d1fae5,stroke:#047857,color:#064e3b
  class G1,G2,G3 group
  class U1,U2,U3 user
  

권한은 그룹에 부여, 사용자는 그룹에 멤버로. 새 사람·새 앱은 그룹 가입만.

2. tenant 별 분리

테넌트마다 별 DB 또는 별 스키마. 각 테넌트의 역할은 자기 스키마만 USAGE.

3. 읽기 전용 슈퍼 사용자

분석·감사용. SUPERUSER 부여하면 데이터 손상 위험 — 읽기 전용 슈퍼 권한 역할은 사실상 만들기 어렵습니다.

대안:

-- 모든 스키마·테이블에 SELECT만
GRANT pg_read_all_data TO auditor;     -- PG 14+

PG 14+의 미리 정의된 역할:

역할권한
pg_read_all_data모든 데이터 SELECT
pg_write_all_data모든 데이터 INSERT/UPDATE/DELETE
pg_read_all_settings슈퍼유저 전용 GUC 읽기
pg_read_all_stats통계 뷰 전체
pg_stat_scan_tables통계 함수 호출
pg_monitorpg_read_all_stats + pg_read_all_settings
pg_signal_backend다른 세션 cancel/terminate
pg_use_reserved_connections슈퍼유저 예약 슬롯

pg_monitor는 모니터링 도구용 표준 역할.

권한 점검 SQL

-- 한 테이블의 권한
SELECT grantee, privilege_type
  FROM information_schema.table_privileges
 WHERE table_schema = 'app' AND table_name = 'orders';

-- 한 사용자가 갖는 권한
SELECT * FROM information_schema.role_table_grants
 WHERE grantee = 'alice';

-- 사용자가 어느 그룹의 멤버인지
SELECT r.rolname AS role, m.member::regrole AS member
  FROM pg_auth_members m
  JOIN pg_roles r ON m.roleid = r.oid;

운영 안티패턴

안티패턴문제
모든 앱이 postgres 슈퍼유저로 접속사고 시 피해 한계 없음
사용자에 직접 권한 부여인원 변경 시 권한 누락
비밀번호를 SQL 평문 로그에 남김\password 사용 또는 SCRAM 채널
GRANTREVOKE 안 함권한 누적, 감사 어려움
GRANT ALL PRIVILEGES 남발최소 권한 원칙 위배

정리

  • user vs group 구분 없음 — 모두 역할
  • 권한은 그룹 역할에 부여, 사용자는 그룹 멤버로
  • ALTER DEFAULT PRIVILEGES로 미래 객체에 자동 부여
  • PUBLIC의 불필요한 권한은 REVOKE
  • 사용자 삭제 전 REASSIGN OWNED BY 또는 DROP OWNED BY
  • PG 14+의 pg_monitor·pg_read_all_data 같은 미리 정의된 역할 활용

다음 절(9.2)에서는 누가 어떤 방식으로 접속 인증을 통과하는지 — pg_hba.conf — 를 봅니다.