# 접근 규칙 (RLS)

가장 자주 틀리는 곳이에요. **오류 없이 빈 목록이 돌아와서** 틀린 줄 몰라요.

## 반드시 알아야 하는 것

새 표는 접근 규칙이 **켜진 채** 만들어지고 규칙은 **하나도 없어요**.
규칙이 없으면 아무에게도 보이지 않아요. 오류가 아니라 빈 배열이 돌아와요.

```sql
create table notes (id uuid primary key default gen_random_uuid(), body text);
-- 지금 공개 키로 select 하면: []  (오류 아님)
```

## 역할 이름

프로젝트마다 달라요. 고정된 `anon`/`authenticated`가 아니에요.
`list_policies`가 그 프로젝트의 실제 역할 이름 세 개를 알려줘요.

| 역할 | 누구 |
|---|---|
| `<ref>_anon` | 로그인하지 않은 사람 |
| `<ref>_authenticated` | 로그인한 사람 |
| `<ref>_service_role` | 서버. 규칙을 통째로 우회해요 |

**Supabase에서 쓰던 SQL은 그대로 실행돼요(Supabase 이름 변환).** run_sql, query_sql, apply_migrations, 콘솔 SQL 편집기, `oneend db push`에서
`public.`, `auth.`, `storage.`는 `app_<ref>.`, `auth_<ref>.`, `stor_<ref>.`로, `to`/`from` 뒤의 `anon`, `authenticated`, `service_role`은 이 프로젝트의 역할로 바꿔 실행해요.
이름을 가리키는 문자열(`'public.orders'::regclass`, `to_regclass('public.orders')`, `'public'::regnamespace`)의 스키마도 바꿔요.
바꾼 내용은 응답의 `translated`에 있어요. 그 밖의 문자열·주석과 직접 연결(psql)은 바꾸지 않아요.
모든 실행은 search_path가 `app_<ref>, auth_<ref>, public, extensions`인 채로 돌아서, 스키마를 붙이지 않은 `create table orders`·`'orders'::regclass`도 이 프로젝트의 것을 가리켜요.

## 흔한 규칙 세 가지

```sql
-- 누구나 읽을 수 있게
create policy "public read" on notes for select to <ref>_anon using (true);

-- 로그인한 본인 것만
create policy "own rows" on notes for all to <ref>_authenticated
  using (user_id = auth_<ref>.uid());

-- 로그인한 사람이 쓰되, 남의 이름으로는 못 쓰게
create policy "insert own" on notes for insert to <ref>_authenticated
  with check (user_id = auth_<ref>.uid());
```

`using`은 읽을 때, `with check`는 쓸 때 봐요. insert에 `using`만 걸면 아무도 못 써요.

## 확인하는 법

`list_policies`로 규칙을 보고, `read_rows`로 공개 키로 실제로 보이는지 확인하세요.
표나 규칙을 바꾼 뒤에는 `get_advisors`로 RLS가 꺼진 표, 누구나 쓸 수 있는 규칙 같은 문제를 확인하세요.

앱이 시작할 때마다 실행하는 SQL(Figma Make의 kv_store 같은)에서는 인덱스에 이름을 붙이고 `if not exists`를 쓰세요: `create index if not exists kv_store_x_key_idx on kv_store_x (key text_pattern_ops);`. 이름 없는 `create index on …`은 실행할 때마다 `_idx1`, `_idx2`… 같은 인덱스를 하나 더 만들고, 쓰기마다 그 모두를 갱신해요. `get_advisors`의 duplicate_index가 하나만 남기는 `drop index`를 함께 줘요.

규칙을 만들었는데도 비어 있으면 대개 역할 이름이 틀린 거예요.

---

https://end.blackall.ai/docs/access-rules?lang=ko
