Supabase를 사용하다 보면 Row Level Security(RLS)를 켜놓은 상태에서 UPDATE 쿼리를 실행했는데도 다음과 같은 에러를 만날 수 있습니다:
ERROR: permission denied for table user_profiles
“분명히 Policy도 설정했는데 왜 안 되지?” 싶은 분들을 위해, 이 글에서는 이 에러의 근본 원인과 해결 방법을 예제로 함께 정리합니다.
문제 상황
시도한 쿼리
update public.user_profiles
set name = '테스트'
where id = 'e0804eda-xxxxx-xxxxx-xxxxxx-xxxx';
발생한 에러 로그
ERROR: permission denied for table user_profiles
이 에러는 단순히 RLS 정책이 없어서가 아닙니다. 오히려 RLS는 잘 설정되어 있었지만, PostgreSQL 권한(GRANT) 자체가 누락되어 있어서 발생하는 것입니다.
원인 분석: Supabase의 보안 구조
Supabase는 다음 두 단계를 거쳐 요청을 허용합니다:
1. PostgreSQL 권한 (GRANT)
• 역할(Role)이 테이블에 접근할 수 있는지
• 예: SELECT, INSERT, UPDATE, DELETE 권한을 가졌는가?
2. Row Level Security (RLS) 정책
• 해당 row에 접근 가능한 조건을 만족하는가?
• 예: 로그인한 사용자의 auth.uid()와 row의 id가 일치하는가?
즉, GRANT + RLS 둘 다 통과해야 UPDATE가 작동합니다.
해결 방법
테이블 권한 부여
GRANT UPDATE ON public.user_profiles TO authenticated;
필요에 따라 SELECT도 함께 부여합니다:
GRANT SELECT ON public.user_profiles TO authenticated;
RLS 활성화
ALTER TABLE public.user_profiles ENABLE ROW LEVEL SECURITY;
RLS 정책 작성
로그인한 사용자가 자신의 프로필만 수정 가능하게 만들기:
CREATE POLICY "Users can update their own profile"
ON public.user_profiles
FOR UPDATE
TO authenticated
USING (auth.uid() = id)
WITH CHECK (auth.uid() = id);
• USING: 해당 row를 조회할 수 있는 조건
• WITH CHECK: 해당 row를 수정할 수 있는 조건
최종 정리
설정항목 | 설명 | 예시 |
GRANT | 테이블에 대한 접근 권한 부여 | GRANT UPDATE ON ... TO authenticated |
RLS ENABLE | Row-Level Security 사용 설정 | ALTER TABLE ... ENABLE ROW LEVEL SECURITY |
POLICY | 행(row) 단위 조건 설정 | USING, WITH CHECK 조건 작성 |
결과: 정상 동작
위 설정이 완료되면, Supabase Auth를 통해 로그인한 사용자가 자신의 id를 가진 row에 대해 다음과 같은 쿼리를 정상적으로 실행할 수 있습니다.
update public.user_profiles
set name = '테스트'
where id = '로그인한_사용자의_id';
마무리
처음엔 "RLS 정책만 설정하면 된다"고 생각하기 쉽지만, Supabase는 PostgreSQL 위에서 작동하는 만큼 기본 권한 설정도 꼭 필요합니다. 앞으로는 permission denied 에러가 나면 다음 두 가지를 먼저 체크해보세요:
1. GRANT 권한이 있는가?
2. RLS Policy가 올바른가?
이 구조만 이해하면, Supabase의 보안 모델을 더 자신 있게 다룰 수 있을 거예요.
# 해피코딩!
'Supabase' 카테고리의 다른 글
[supabase] View에 RLS 적용 시키는 방법 (0) | 2025.03.08 |
---|---|
[supabase] Auth Hooking 을 이용한 그룹별 DB access 권한 제한 (0) | 2025.01.24 |
[supabase] postgres plv8 활성화 (0) | 2025.01.24 |
[Supabase] Edge function 만들기 (0) | 2024.12.11 |
[Flutter] supabase database 의 json 내부 query하기 (0) | 2024.09.19 |