8단계
8단계 — 행 수준 보안으로 DB 우회 경로 닫기
1회 조회
목차
API에서 WHERE user_id = ?를 넣어도 다른 SQL 경로나 SDK가 같은 검사를 빼먹을 수 있습니다. 행 수준 보안(RLS)은 데이터베이스가 현재 주체와 각 행을 비교해 마지막 접근 경계를 지키게 합니다.
역할과 정책을 분리한다
브라우저용 익명·인증 역할과 서버 전용 역할을 구분합니다. 사용자가 소유한 행은 JWT subject와 owner_id를 비교하고, 공용 읽기와 관리자 쓰기를 별도 정책으로 둡니다. USING은 기존 행을 볼 수 있는지, WITH CHECK는 새 결과 행이 허용되는지를 판정합니다.
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
CREATE POLICY documents_owner_read ON documents
FOR SELECT TO authenticated
USING (owner_id = auth.uid());
CREATE POLICY documents_owner_write ON documents
FOR INSERT TO authenticated
WITH CHECK (owner_id = auth.uid());
service role을 만능 열쇠로 쓰지 않는다
RLS를 우회하는 서버 키는 브라우저에 전달하지 않고 최소 서버 경계에서만 사용합니다. 관리자 UI가 권한을 검사해도 DB 정책을 true로 열어 두지 않습니다. 마이그레이션에는 정책 이름·대상 역할·명령·조건을 명시하고 운영 DB와 drift를 검사합니다.
완료 기준
- 소유자 A가 소유자 B의 행을 조회·수정하지 못한다.
- 익명·인증·관리·서버 역할별 정상과 거절 테스트가 있다.
- 직접 SQL과 SDK 경로에서도 같은 정책이 적용된다.
- 정책 변경은 migration과 운영 drift 검증으로 추적된다.
관련 용어: 행 수준 보안
이 글에서 만나는 용어
🎉 웹 보안의 기초 — JWT · OAuth · OWASP 완주를 축하해요
이어서 어떤 걸 배워 볼까요?