9.1 사용자·역할·GRANT/REVOKE
PostgreSQL은 “user"와 “group"을 구분하지 않고 모두 역할(role)이라는 하나의 개념으로 다룹니다. 역할에 비밀번호·로그인 권한·다른 역할 멤버십·객체 권한이 붙습니다. GRANT/REVOKE로 세밀하게 부여·회수합니다.
역할의 두 얼굴
| 속성 | 의미 |
|---|---|
LOGIN | 클라이언트가 직접 접속 가능. 보통 “사용자"라고 부르는 역할 |
NOLOGIN (기본) | 접속 불가. 보통 “그룹"으로 쓰임 |
SUPERUSER | 모든 권한 (위험) |
CREATEDB | 데이터베이스 만들기 |
CREATEROLE | 역할 만들기·관리 |
REPLICATION | 복제 연결 가능 |
BYPASSRLS | RLS 정책 무시 |
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이 권한을 갖는 객체:
| 객체 | 권한 예시 |
|---|---|
| Database | CONNECT, CREATE, TEMPORARY |
| Schema | USAGE, CREATE |
| Table / View / Materialized View | SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER |
| Column | SELECT, INSERT, UPDATE, REFERENCES |
| Sequence | USAGE, SELECT, UPDATE |
| Function / Procedure | EXECUTE |
| Type / Domain | USAGE |
| Foreign Data Wrapper | USAGE |
| Tablespace | CREATE |
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_monitor | pg_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 채널 |
GRANT 후 REVOKE 안 함 | 권한 누적, 감사 어려움 |
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 — 를 봅니다.