Supabase는 인증(Authentication)과 인가(Authorization)를 명확히 분리한다. 로그인에 성공했다고 해서 모든 데이터에 접근할 수 있는 것은 아니며, 실제 데이터 접근 여부는 RLS Policy가 결정한다. 이 두 개념의 차이를 이해하는 것이 Supabase 권한 설계의 출발점이다.
| 개념 | 질문 | Supabase 구현 |
|---|---|---|
| Authentication | 누구인가? | supabase.auth.signIn → JWT 발급 |
| Authorization | 무엇을 할 수 있는가? | RLS Policy → 행 단위 필터 |
RLS(Row Level Security): PostgreSQL이 제공하는 행 단위 접근 제어 기능. 테이블에 활성화하면 Policy 없이는 어떤 역할도 행을 읽거나 쓸 수 없다.
Supabase는 PostgreSQL 역할을 그대로 노출한다. 클라이언트 요청은 JWT 유무에 따라 두 가지 역할 중 하나로 실행된다.
클라이언트 요청
│
├─ JWT 없음 ──▶ anon 역할 (공개 읽기 등 제한된 권한)
│
└─ JWT 있음 ──▶ authenticated 역할 (로그인 사용자 기본 권한)
│
└─ JWT Claim에 custom role 포함 시
──▶ app_metadata.role 값으로 분기
anon: 익명 사용자용 PostgreSQL 역할. Supabase 프로젝트 생성 시 자동으로 만들어진다. authenticated: 유효한 JWT를 가진 사용자가 사용하는 역할.
RLS를 활성화한 뒤 Policy를 추가하지 않으면 해당 테이블은 완전히 잠긴다. 아래는 사용자가 자신의 행만 읽을 수 있도록 허용하는 Policy다.
-- 테이블 RLS 활성화
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- 본인 행만 SELECT 허용
CREATE POLICY "users can read own posts"
ON posts
FOR SELECT
USING (auth.uid() = user_id);
auth.uid는 Supabase가 제공하는 헬퍼 함수로, 현재 JWT에서 사용자 ID를 추출한다. Policy의 USING 절은 SELECT/DELETE에, WITH CHECK 절은 INSERT/UPDATE에 적용된다.
관리자(admin)처럼 특수 권한이 필요한 경우 JWT의 app_metadata에 역할을 저장하고 Policy에서 참조한다.
-- app_metadata.role이 'admin'인 사용자만 전체 읽기 허용
CREATE POLICY "admin full access"
ON posts
FOR ALL
USING (
(auth.jwt() -> 'app_metadata' ->> 'role') = 'admin'
);
app_metadata는 서버 측에서만 수정할 수 있으므로 클라이언트가 위조할 수 없다. 역할 부여는 Supabase Admin API 또는 Service Role Key를 사용하는 Edge Function에서 수행한다.
// Edge Function — 역할 부여 예시
const { error } = await supabaseAdmin.auth.admin.updateUserById(userId, {
app_metadata: { role: "admin" },
});
최소 권한 원칙을 기본으로 삼는다. RLS를 활성화한 뒤 필요한 작업에만 Policy를 추가하고, anon 역할에는 공개 데이터 읽기만 허용한다. Policy가 복잡해지면 PostgreSQL 함수로 추출해 재사용성을 높인다.
-- 재사용 가능한 역할 확인 함수
CREATE OR REPLACE FUNCTION is_admin()
RETURNS boolean AS $$
SELECT (auth.jwt() -> 'app_metadata' ->> 'role') = 'admin';
$$ LANGUAGE sql STABLE;
-- Policy에서 함수 참조
CREATE POLICY "admin only"
ON sensitive_table
FOR ALL
USING (is_admin());
STABLE: 동일 트랜잭션 내에서 같은 인자에 대해 동일한 결과를 반환함을 PostgreSQL에 알리는 함수 속성. 쿼리 최적화에 활용된다.