
Kim JeongHyeonFrontend Focused Fullstack Developer
Supabase RLS의 기본 개념부터 흔한 실수, 디버깅 방법까지 실전 가이드.
RLS(Row Level Security)는 데이터베이스 레벨에서 접근을 제어합니다. API 키가 노출되어도 데이터가 안전합니다.
Supabase의 anon 키는 클라이언트에 노출됩니다. RLS가 없으면 누구나 모든 데이터를 읽고 쓸 수 있습니다:
// 누군가 DevTools에서 이렇게 하면?
const { data } = await supabase.from("users").select("*");
// → 모든 유저 정보 유출!-- 1. RLS 활성화
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- 2. 공개 읽기 (published만)
CREATE POLICY "Public read"
ON posts FOR SELECT
USING (published = true);
-- 3. 인증된 유저만 쓰기
CREATE POLICY "Auth write"
ON posts FOR INSERT
WITH CHECK (auth.uid() IS NOT NULL);
-- 4. 작성자만 수정
CREATE POLICY "Owner update"
ON posts FOR UPDATE
USING (author_id = auth.uid());-- auth.uid(): 현재 로그인한 유저의 UUID
-- auth.jwt(): 전체 JWT 클레임 (role, email 등)
CREATE POLICY "Admin full access"
ON posts FOR ALL
USING (auth.jwt() ->> 'role' = 'admin');-- 이것만으로는 쓰기가 전부 차단됨
CREATE POLICY "Read" ON posts FOR SELECT USING (true);
-- INSERT, UPDATE, DELETE 정책도 필요// 절대 하지 마세요!
const supabase = createClient(url, serviceRoleKey); // RLS 무시service_role 키는 서버 사이드(API Route)에서만 사용하세요.
posts와 comments를 JOIN할 때, 두 테이블 모두 RLS 정책이 필요합니다.
-- 특정 유저로 정책 테스트
SET request.jwt.claim.sub = 'user-uuid-here';
SELECT * FROM posts; -- RLS가 적용된 결과 확인