lifecarelog
백엔드

Supabase RLS 두고 서버에서 권한을 한 번 더 검증하는 이유

RLS는 마지막 방어선으로 남기고, 분기가 많은 인가 로직은 단위테스트 가능한 서버 코드로 옮기는 백엔드 설계 정리.

6분 읽기

Supabase로 백엔드를 만들면 RLS 정책 하나로 권한 문제가 끝난 것처럼 느껴져요. 저도 처음엔 그렇게 믿었어요. 그런데 "총무만 회비를 수정할 수 있다"는 규칙을 RLS에 넣고 나서, 이 규칙이 제대로 동작하는지 확인하려면 매번 DB를 띄워야 한다는 걸 알게 됐어요. 혹시 비슷한 경험 없으신가요?

RLS는 최종 경계, 업무 규칙은 아니에요

RLS(Row Level Security)는 "이 행을 이 사용자가 볼 수 있나"를 DB가 마지막에 한 번 걸러주는 장치예요. auth.uid()와 소유자 컬럼을 비교하는 정책 한 줄이면 다른 사람 데이터가 새는 사고를 막아줘요.

문제는 그 위에 분기가 붙을 때예요. 소유자는 수정 가능, 매니저는 특정 컬럼만, 일반 멤버는 읽기만. 이런 규칙이 3가지만 되어도 SQL 정책은 서브쿼리와 CASE로 길어지고, 실패했을 때 왜 막혔는지 로그도 남지 않아요.

RLS 정책(DB 최종 경계, 검증엔 DB 필요) vs 서버 인가 코드(분기·로그·단위테스트 가능)

단위테스트가 안 되는 게 진짜 이유예요

RLS 정책은 함수가 아니라 DB 설정이에요. 그래서 "매니저가 회비 금액을 바꾸려 하면 거절"이라는 케이스를 검증하려면 실제 Postgres에 사용자 3명을 만들고 JWT를 바꿔 끼우며 쿼리를 날려야 해요. 로컬에서 돌려 보니 케이스 4개 확인하는 데 매번 수십 초가 걸렸고, CI에서는 DB 컨테이너부터 띄워야 했어요.

같은 규칙을 서버 코드로 옮기면 이렇게 돼요.

type Role = "owner" | "manager" | "member";
 
export function canEditFee(role: Role, field: string) {
  if (role === "owner") return true;
  if (role === "manager") return field === "memo";
  return false;
}

이 함수는 DB 없이 테스트할 수 있어요. 직접 만들어 보니 케이스 4개짜리 테스트 파일이 1초 안에 끝났고, 규칙이 바뀌면 테스트가 먼저 빨간불을 켜줬어요.

두 겹으로 두는 구조

요청서버에서 auth.getUser()로 사용자 확인인가 함수로 분기 판정DB 쿼리(RLS가 마지막에 한 번 더 확인)

순서는 이래요.

  1. 서버(Route Handler나 API)에서 세션으로 사용자를 확인해요. 클라이언트가 보낸 userId는 믿지 않아요.
  2. 인가 함수로 "이 사용자가 이 작업을 할 수 있나"를 판정하고, 거절이면 403과 사유를 로그에 남겨요.
  3. 통과한 요청만 DB로 가고, RLS는 "소유자 또는 같은 모임 멤버"처럼 단순한 정책으로 마지막 경계만 지켜요.

RLS를 없애는 게 아니에요. 서버 코드에 버그가 생겨 검증을 건너뛰어도, 남의 모임 데이터는 DB가 막아줘요. 반대로 RLS만 믿으면 "왜 안 되죠?"라는 질문에 답할 로그가 없어요.

적용해 보면서 정한 기준

플랜비(plan-b)의 회비·출전 로테이션처럼 총무·매니저·멤버 역할이 세 겹으로 나뉘는 도메인을 놓고 기준을 세 줄로 정리했어요.

  • RLS에는 테넌트 격리만 남겨요. 정책 조건이 2개를 넘으면 서버로 옮길 신호예요.
  • 인가 함수는 순수 함수로 두고, 입력은 세션에서 나온 사용자와 역할만 받아요.
  • 거절 사유는 코드 하나로 남겨요. 문의가 왔을 때 로그 한 줄로 원인을 찾을 수 있어요.

테스트해 보면 RLS 정책은 짧아지고, 규칙 변경은 테스트 파일 수정으로 끝나요. 혼자 운영하면서 가장 아꼈던 건 "DB 켜고 확인하는 시간"이었어요.

권한 규칙이 길어지기 시작했다면, RLS를 늘리기보다 함수 하나를 먼저 만들어 보세요. 마지막 경계는 DB가, 판단은 코드가 맡는 쪽이 훨씬 편해요.

#Supabase#RLS#인가

라이프케어로그 서비스가 궁금하신가요?

AI 기반 건강·일정·재활 관리 앱을 직접 써보세요.

서비스 살펴보기

관련 글

댓글

아직 댓글이 없어요. 첫 댓글을 남겨주세요.