PostgreSQL · 2026-02-18

PostgreSQL RLS 적용과 사례별 예제

PostgreSQL Row Level Security(RLS)의 기본 개념부터 정책 설계, 접근 제어 구현, 실무 예제와 적용 예시 모음

작성일 : 2026-02-18 ㆍ 작성자 : 관리자
post
목차

개요

Row Level Security(RLS)는 테이블의 행 단위로 접근을 통제하는 PostgreSQL 기능이다. 다중 테넌시 환경이나 민감한 데이터에서 유용하다. 이 글은 초심자도 이해할 수 있도록 개념 설명부터 설정 예제, 정책 설계 사례와 테스트 방법을 차근히 다룬다.

RLS 기본 개념

왜 RLS가 필요한가

애플리케이션 레벨에서 필터링을 해도 개발 실수로 데이터가 노출될 위험이 있다. RLS는 DB 레벨에서 보안을 강화한다. 권한을 가진 사용자만 특정 행을 조회·수정·삭제하도록 정책을 정의할 수 있다.

주요 용어

  • policy: 행 접근 규칙
  • role: PostgreSQL 사용자 또는 그룹
  • using / with check: select/insert/update 시 조건

기본 설정 절차

다음 순서로 진행하면 기본 RLS 준비가 완료된다.

  • 테이블 생성
  • RLS 활성화(ALTER TABLE ... ENABLE ROW LEVEL SECURITY)
  • 정책 생성(CREATE POLICY)
  • 권한 부여(GRANT)

간단한 예제: 테넌트 기반 접근 제어

테넌트별로 tenant_id 컬럼을 두고, 세션 설정으로 현재 테넌트를 지정하는 방식이 흔하다. 아래 예제는 tenant_id 컬럼을 통해 select/insert/update를 제한한다.

CREATE TABLE orders (
  id serial PRIMARY KEY,
  tenant_id int NOT NULL,
  owner_id int NOT NULL,
  amount numeric
);

-- RLS 활성화
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

-- 기본 policy: 세션 변수 current_tenant 에 맞는 행만 보기
CREATE POLICY tenant_isolation ON orders
  USING (tenant_id = current_setting('app.current_tenant')::int)
  WITH CHECK (tenant_id = current_setting('app.current_tenant')::int);

-- 권한 부여: 애플리케이션 역할에 대해 SELECT/INSERT/UPDATE 권한 부여
GRANT SELECT, INSERT, UPDATE, DELETE ON orders TO app_role;

세션에서 현재 테넌트를 설정한 뒤 접속하여 쿼리하면 해당 테넌트 행만 보인다.

-- 세션에서 현재 테넌트 지정
SET app.current_tenant = '42';
-- 이제 SELECT는 tenant_id = 42 인 행만 반환
SELECT * FROM orders;

정책 설계 사례

사례 1: 소유자 기반 접근 제어

사용자별로 owner_id가 일치하는 행만 수정·삭제하도록 할 때 유용하다. SELECT는 공용 정보로 허용하고 UPDATE/DELETE는 소유자만 가능하게 설정한다.

-- SELECT는 모두 허용, UPDATE/DELETE는 owner만
CREATE POLICY owner_select ON orders FOR SELECT USING (true);
CREATE POLICY owner_modify ON orders FOR UPDATE, DELETE
  USING (owner_id = current_setting('app.current_user_id')::int)
  WITH CHECK (owner_id = current_setting('app.current_user_id')::int);

사례 2: 관리자 예외 처리

관리자 역할은 모든 행에 접근해야 할 때가 있다. policy에 역할 조건을 추가하면 된다.

CREATE POLICY admins_full_access ON orders
  USING (
    current_setting('app.current_user_role', true) = 'admin'
    OR tenant_id = current_setting('app.current_tenant')::int
  );

테스트 방법과 유의사항

테스트 절차

  • 세션 변수로 사용자, 테넌트 값을 설정
  • 권한이 없는 사용자로 접속해 결과 확인
  • 관리자 예외, 조인 시 동작을 점검

주의할 점

  • DEFAULT ROLE 권한으로 우회할 수 있는지 확인
  • 테이블에 존재하지 않는 컬럼을 조건에 쓰면 정책이 예기치 않게 동작
  • 함수 사용 시 SECURITY DEFINER의 권한 상승 여부 검토

조인과 서브쿼리 처리

RLS는 각 테이블에 대해 정책을 적용한다. 따라서 조인 시 조인 대상 테이블의 정책도 만족해야 행이 반환된다. 복잡한 뷰나 서브쿼리에서는 성능 및 의도치 않은 필터링이 발생할 수 있어 주의가 필요하다.

트러블슈팅

대표적 문제와 해결

  • 쿼리가 빈 결과를 반환: 세션 변수 미설정 또는 정책 조건 불일치 확인
  • 관리자도 접근 불가: current_setting의 세컨드 인자(true)로 없을 때 기본값 처리 검토
  • 함수 내부에서 권한 상승: SECURITY DEFINER 사용 시 정책 우회 여부 확인

실무 적용 팁

전체 시스템에 RLS를 도입할 때는 단계적으로 적용한다. 먼저 읽기 정책을 적용하고, 로그 및 테스트를 통해 예상된 결과를 검증한 뒤 쓰기 정책을 도입한다. 또한 정책은 가능한 단순하게 유지하여 유지보수성을 높인다.

마무리

PostgreSQL RLS는 데이터베이스 수준에서 강력한 접근 제어를 제공한다. 이 글에서 다룬 postgres rls 설정 예제, row level security postgres 사용법, rls 정책 postgres 사례를 바탕으로 정책을 설계하면 안전한 다중 테넌시 및 사용자 권한 관리를 구현할 수 있다. 초기에는 작은 테이블부터 적용해 테스트를 충분히 수행하는 것을 권장한다.

postgresql postgres rls 설정 예제 row level security postgres 사용법 rls 정책 postgres 사례 postgresql rls 다중테넌시 보안 정책기반 접근제어 SQL 정책 예제