개념 설명

인증과 RLS가 뭔가요? 화면은 열어도 데이터는 잠그는 법

읽는 데 약 7분#RLS#개념#입문

이 글의 독자AI가 만들어준 로그인 화면 뒤에서 데이터가 실제로 잠겨 있는지 궁금한 사람

시리즈 · AI 자동화 개념 사전 12편 중 9번째, 펼쳐서 보기
  1. API가 뭔가요? 분식집 주문지 한 장이면 이해됩니다
  2. 웹훅이 뭔가요? 웨이팅 번호표 한 장이면 이해됩니다
  3. 서버가 뭔가요? 나 대신 켜져 있는 컴퓨터 이야기
  4. 터미널이 뭔가요? 안내판 없는 관계자 출입구 하나면 이해됩니다
  5. MCP, 에이전트, 컨텍스트, 스킬, 시크릿: 헷갈리는 AI 자동화 용어 5개 한 번에
  6. 클로드 용어 정리: 프로젝트, 아티팩트, 코워크, 예약 작업까지 한 번에
  7. 데이터베이스가 뭔가요? 표는 같아도 잠그는 방식이 다릅니다
  8. Supabase가 뭔가요? 표, 인증, 자동 실행을 한 곳에서
  9. 인증과 RLS가 뭔가요? 화면은 열어도 데이터는 잠그는 법
  10. Apps Script가 뭔가요? 구글 서버에 내 코드를 올려두는 일입니다
  11. Playwright가 뭔가요? AI가 크롬 창을 저절로 여는 이유
  12. Aside가 뭔가요? 내 로그인 그대로 AI가 클릭하는 에이전트 브라우저

한줄 요약: 화면은 누구에게나 열어둬도, 그 안의 데이터는 사람마다 다르게 보여야 할 때가 있습니다. 이때 열쇠가 두 개 필요합니다. 지금 요청한 사람이 누구인지 확인하는 것이 인증(Auth)이고, 확인된 사람마다 볼 수 있는 행(줄)을 데이터베이스 안에서 제한하는 규칙이 RLS입니다. 이 글은 실제로 anon 키 하나로 표를 읽고 써 본 기록으로 이 둘이 각각 언제, 어떻게 작동하는지 보여줍니다.

목차

  1. 화면은 공개, 데이터는 잠급니다
  2. 인증과 RLS는 서로 다른 일을 합니다
  3. 안 열어둔 표는 조용히 비고, 잘못된 쓰기는 시끄럽게 막힙니다
  4. anon 키 화면에서 확인하는 법
  5. 승인 버튼 하나가 여는 위험
  6. 되고 나서 조심할 것

AI에게 “로그인 기능을 만들어줘”라고 시키면 화면은 금방 나옵니다. 아이디와 비밀번호를 넣고 들어가면 내 이름이 뜨고, 로그아웃하면 다시 로그인 화면으로 돌아갑니다. 여기까지만 보면 다 된 것 같습니다.

그런데 데이터베이스 표 안을 들여다보면 사정이 다릅니다. 로그인 화면 뒤에서 정작 표는 누가 봐도 다 보이거나, 반대로 로그인한 사람조차 아무것도 못 보는 두 경우가 다 생깁니다. 화면의 잠금과 데이터의 잠금이 서로 다른 자리에 있기 때문입니다. 이 글은 그 두 자리를 나눠서 짚고, 실제로 표를 anon 키 하나로 읽고 써 본 기록으로 무엇이 어떻게 막히는지 보여줍니다. 이 글 하나만 읽어도 인증과 RLS가 각각 무엇을 하는지, 그리고 왜 함께 있어야 하는지 알 수 있습니다.

1. 화면은 공개, 데이터는 잠급니다

로그인 화면을 만드는 이유는 화면을 숨기기 위해서가 아닙니다. 화면 자체는 누구나 열 수 있어도 됩니다. 대신 그 화면이 보여주는 데이터가 사람마다 달라야 합니다. 예를 들어 연차 신청 화면이라면, 화면 자체는 누구나 접속할 수 있어도 신청 내역은 본인 것만 보여야 합니다.

이 경계가 실제로 어디서 갈리는지는 3장의 실측 기록에서 그대로 드러납니다.

여기서 중요한 건 이 두 열쇠가 서로 다른 자리에서 일한다는 점입니다. 인증은 로그인 화면과 토큰 발급 쪽에서 일하고, RLS는 데이터베이스 안에서 일합니다. 로그인 화면만 잘 만들고 RLS를 켜지 않으면, 로그인 여부와 상관없이 표 전체가 그대로 열려 있습니다.

2. 인증과 RLS는 서로 다른 일을 합니다

Supabase 공식 문서는 인증과 RLS의 역할을 이렇게 나눕니다. 인증(Authentication)은 “지금 요청한 사람이 정말 그 사람이 맞는지 확인하는 것”이고, RLS는 확인된 사람이 어떤 자원에 접근할 수 있는지를 표 단위가 아니라 행 단위로 강제합니다. 공식 Auth 가이드에는 로그인 뒤 요청마다 따라붙는 신분증 같은 값(토큰)으로 신원을 확인하고, 그 신원을 RLS 규칙과 연결해 행 단위 접근을 제어한다고 설명되어 있습니다.

두 역할을 표로 나누면 이렇습니다.

구분 인증(Auth) RLS
확인하는 것 요청한 사람이 누구인지 그 사람이 볼 수 있는 행
일하는 자리 로그인 화면, 토큰 발급 데이터베이스 안 규칙
작동 방식 로그인 수단으로 신원 확인 조회마다 조건을 자동으로 추가
하나만 있으면 로그인은 되지만 표는 그대로 열림 로그인 없이는 모든 방문자가 같은 anon 역할, 행 조건은 걸 수 있어도 사람별 구분은 불가

RLS 공식 문서는 정책 하나를 “모든 조회에 붙는 WHERE절”에 비유합니다. 로그인한 사람이 누구인지와 상관없이, RLS를 켜두지 않은 표는 그 표에 접근 권한이 있는 누구에게나 읽고 쓰기가 그대로 열려 있다고도 밝히고 있습니다. 인증만으로는 이 문을 못 잠급니다. 인증은 문 앞에서 신분증을 확인할 뿐이고, 그 신분증을 보고 안쪽 서랍마다 열어줄지 말지 정하는 건 RLS의 일입니다.

이 말을 대시보드가 직접 문장으로 보여주는 화면이 있습니다.

Supabase Database Policies 화면. alert_log와 book_reviews 표 아래 각각 이 표에는 RLS 정책이 없어 Data API로 데이터가 반환되지 않는다는 문구와 아직 만든 정책이 없다는 안내, Disable RLS와 Create policy 버튼이 있다
Supabase Database > Policies 화면. alert_log, book_reviews 두 표 모두 정책이 하나도 없는 상태입니다.

3. 안 열어둔 표는 조용히 비고, 잘못된 쓰기는 시끄럽게 막힙니다

여기까지는 개념입니다. 실제로 로그인하지 않은 방문자용 키(anon 키)로 표를 읽고 써 보면, RLS가 막았을 때 신호가 어떻게 오는지가 읽기와 쓰기에서 완전히 다릅니다. 아래는 실제로 이 절차를 두 번 밟아본 기록입니다.

쓰기: 정책 없는 표에 anon 키로 새 행 넣기(insert)

  1. 요청 연차 신청 표에 새 행 추가 시도 RLS는 켜져 있고 anon에게 열린 정책은 없음
  2. 응답 HTTP 401, 정책 위반 오류 문구 그대로 출력 new row violates row-level security policy for table "leave_requests" (코드 42501)
  3. 알아차림 오류가 눈앞에 뜨는 즉시 원인 확인 가능 막혔다는 사실을 코드가 바로 알려줌

시끄럽게 막힘, 오류로 옴

읽기: 같은 표를 anon 키로 조회(select)

  1. 요청 같은 표에서 행 읽기 시도 RLS는 켜져 있고 anon에게 열린 정책은 없음
  2. 응답 HTTP 200, 빈 배열(결과 0건) 오류가 아니라 정상 응답 형태로 옴
  3. 알아차림 한참 뒤에야 알아챔 코드는 정상 작동, 화면에만 아무것도 안 뜸

조용히 비어버림, 에러 없이 0건

4. anon 키 화면에서 확인하는 법

인증이 실제로 무슨 일을 하는지부터 화면으로 확인하겠습니다. Supabase 대시보드의 Authentication > Users 화면에는 로그인한 사람의 목록이 그대로 나옵니다.

Supabase Authentication Users 화면. 사용자 한 명이 등록되어 있고 이메일은 vod-reader@example.com, Providers는 Email이다. UID는 블러 처리되어 있다
Supabase Authentication > Users 화면. 예시 계정 [email protected] 한 명이 등록되어 있습니다. UID는 가려 두었습니다.

anon 키가 실제로 어디에 있는지 눈으로 보면 감이 잡힙니다. Supabase 대시보드의 API Keys 화면에는 이렇게 나옵니다.

Supabase API Keys 설정 화면. Publishable key 항목 아래 이 키는 표에 RLS를 켜고 정책을 구성했다면 브라우저에서 써도 안전하다는 안내 문구가 있다
Supabase 프로젝트의 API Keys 화면. 공개용 키(Publishable, 예전 이름 anon) 아래 "RLS를 켜고 정책을 구성했다면 브라우저에서 안전하게 쓸 수 있다"는 안내가 그대로 적혀 있습니다.

이 키를 어디에 넣고 언제 서버 전용 키(secret, 예전 이름 service_role)를 따로 써야 하는지는 Supabase API 키 고르기 글에서 다룹니다. 이 글은 그 키 뒤에서 RLS가 실제로 무엇을 하는지에 집중합니다.

5. 승인 버튼 하나가 여는 위험

정책을 하나씩 늘리면 화면은 점점 편해집니다. 연차 신청 표에 읽기, 쓰기, 수정 정책을 각각 열어주고 직원 표에도 조회 정책을 하나 열어주면, 신청도, 승인도, 조회도 anon 키 하나로 전부 돌아갑니다. 실제로 신청(등록), 승인(수정), 조회를 이 방식으로 전부 확인했습니다.

6. 되고 나서 조심할 것

인증과 RLS를 둘 다 켜고 나면 화면은 그대로인데 동작은 사람마다 달라집니다. 로그인한 사람은 자기 신청만 보이고, 관리자로 확인된 사람만 승인 버튼이 통과됩니다. 여기까지 오면 잊기 쉬운 게 하나 있습니다. 정책을 새로 열 때마다 그 정책이 누구에게, 어떤 동작에 열리는지 한 번씩 확인하는 습관입니다. 읽기 정책 하나를 무심코 anon에게 열어주면, 화면에는 에러가 안 뜨니 문제가 있다는 사실 자체를 눈치채기 어렵습니다.

AI가 짜준 코드에 RLS 정책까지 같이 들어 있다면, 그 정책이 어떤 역할(anon인지, 로그인한 사용자 역할(authenticated)인지, 관리자인지 아닌지)에 어떤 동작(select, insert, update)을 열어주는지 한 줄씩 읽어보는 게 안전합니다. 코드가 잘 도는지와 데이터가 잠겨 있는지는 서로 다른 질문이고, 앞의 질문에 답이 됐다고 뒤의 질문에도 답이 된 게 아닙니다.

관련해서 API가 뭔가요?웹훅이 뭔가요?도 같은 시리즈로 함께 보면 좋습니다. 인증과 RLS로 데이터를 지킨 다음, 그 데이터를 주고받는 통로가 API와 웹훅입니다.

댓글

    핀번호는 내 댓글을 지울 때 필요합니다.

    뉴스레터

    새 글을 메일로 받아보세요

    AI 자동화 튜토리얼과 저자 코멘터리를 보냅니다. 스팸 없이, 새 글이 올라올 때만.

    구독하기 ›