[오늘가챠] 프론트-DB 직결 시대의 필수 보안: Supabase RLS 적용기

2026. 7. 25. 16:24·◈ Yermi Project/오늘가챠🃏
728x90
반응형
BaaS(Backend as a Service)의 등장으로 프론트엔드에서 API를 거치지 않고 DB를 직접 쿼리하는 일이 잦아졌습니다. 이는 개발 속도를 비약적으로 높여주지만, 자칫하면 대형 보안 사고로 이어질 수 있습니다. 이를 방어하기 위해 Supabase의 핵심 기능인 RLS(Row Level Security)를 적극 활용한 경험을 공유합니다.

RLS(Row Level Security) 동작 원리


1. BaaS의 편리함 이면에 숨겨진 보안 취약점

'오늘가챠' 앱에서는 유저가 카드를 뽑으면 cards 테이블에 데이터가 저장됩니다.
만약 프론트엔드 클라이언트가 Supabase anon 키(익명 접속용 퍼블릭 키)를 이용해 직접 DB 쿼리를 날린다면 어떨까요?

// 프론트엔드에서 직접 DB를 찌르는 코드 (위험함)
const { data } = await supabase.from('cards').select('*')

 

악의적인 해커가 개발자 도구(Network 탭)에서 anon 키를 빼내어, 남의 user_id를 넣고 쿼리를 조작한다면 타인의 인벤토리를 들여다보거나 카드를 삭제해버릴 수 있습니다. 기존 백엔드(Spring)에서는 아래처럼 매번 권한 검증 로직을 짜야 했습니다.

// PhotoService.java — 기존의 수동 권한 검증 코드
public Photo getOwnedPhoto(Long userId, Long photoId) {
    Photo up = photoMapper.findById(photoId);
    if (up == null) throw new IllegalArgumentException("업로드를 찾을 수 없습니다.");
    if (!up.getUserId().equals(userId)) throw new SecurityException("권한이 없습니다.");
    return up;
}

2. RLS(Row Level Security)란?

PostgreSQL 9.5부터 도입된 RLS는 애플리케이션 코드가 아닌 데이터베이스 엔진 레벨에서 특정 유저가 테이블의 '어떤 행(Row)'에 접근할 수 있는지 권한을 제어하는 기능입니다.

Supabase는 자체 구축한 Auth(인증) 시스템의 JWT 토큰과 이 RLS를 기가 막히게 연동해 두었습니다.

3. RLS 정책(Policy) 작성 실전

Supabase 대시보드(SQL Editor)를 통해 cards 테이블에 다음과 같은 정책을 선언했습니다.

-- 1. 카드 조회 정책: 오직 자신이 뽑은 카드만 볼 수 있다.
CREATE POLICY "View own cards" 
ON cards FOR SELECT 
USING (auth.uid() = user_id);

-- 2. 카드 추가 정책: 카드 뽑기 성공 시 자기 계정에만 저장 가능.
CREATE POLICY "Insert own cards" 
ON cards FOR INSERT 
WITH CHECK (auth.uid() = user_id);

-- 3. 사진 조회 정책: 공개(public) 사진은 모두가 볼 수 있지만,
--    비공개(private) 사진은 소유자만 볼 수 있다.
CREATE POLICY "View photos" 
ON photos FOR SELECT 
USING (
  status = 'public' 
  OR auth.uid() = user_id
);

동작 원리

  1. 프론트엔드나 백엔드에서 Supabase로 요청을 보낼 때, 헤더에 유저가 로그인하며 발급받은 JWT(Authorization: Bearer <token>)를 담아 보냅니다.
  2. DB 엔진 내부에서 이 토큰을 파싱해 auth.uid() 함수를 통해 요청자의 고유 UUID를 알아냅니다.
  3. 쿼리에 명시적 WHERE 절이 없더라도, DB가 알아서 자신이 소유한 행(Row)만 필터링하여 응답을 내려주거나 접근을 차단합니다.
[요청 흐름]
프론트엔드 → JWT 토큰 포함 요청 → Supabase PostgREST
         → auth.uid() 추출 → RLS 정책 자동 적용
         → "WHERE user_id = '추출된_UUID'" 자동 주입
         → 안전한 결과만 반환

실제 프로젝트의 테이블 스키마와 RLS의 연계

-- photos 테이블은 user_id를 FK로 가지며, RLS가 이 컬럼을 기준으로 필터링
CREATE TABLE IF NOT EXISTS photos (
    id            BIGSERIAL PRIMARY KEY,
    user_id       BIGINT       NOT NULL REFERENCES users(id),
    image_url     VARCHAR(500) NOT NULL,
    status        VARCHAR(10)  NOT NULL DEFAULT 'DRAFT',
    -- ...
);

-- cards 테이블도 동일하게 user_id 기반 RLS 적용
CREATE TABLE IF NOT EXISTS cards (
    id          BIGSERIAL PRIMARY KEY,
    user_id     BIGINT    NOT NULL REFERENCES users(id),
    photo_id    BIGINT    NOT NULL REFERENCES photos(id),
    -- ...
);

4. 마무리

RLS를 적용함으로써, 백엔드 서버에서 길고 장황하게 작성해야 했던 유저 권한 검증 로직이 통째로 삭제되었습니다. 프론트엔드-BaaS 직결 아키텍처를 사용할 때 발생할 수 있는 보안 취약점을 DB 엔진 층에서 가장 안전하고 우아하게 틀어막은 베스트 프랙티스입니다.
728x90
반응형
'◈ Yermi Project/오늘가챠🃏' 카테고리의 다른 글
  • [오늘가챠] 앱 생태계를 지켜라: dHash와 SHA-256을 활용한 이미지 중복 방어
  • [오늘가챠] 생성형 AI의 도입: Gemini 2.0 Flash와 안전장치
  • [오늘가챠] 서버리스 DB의 한계 극복: Supabase 커넥션 풀 고갈 해결
  • [오늘가챠] 비용 0원 무중단 배포 파이프라인 구축기 (Vercel + Render)
예르미(yermi)
예르미(yermi)
끊임없이 제 자신을 계발하는 개발자입니다👨🏻‍💻
  • 예르미(yermi)
    예르미의 코딩노트
    예르미(yermi)
  • 전체
    오늘
    어제
    • 분류 전체보기 (1025) N
      • ◎ Java (133)
        • Java☕ (93)
        • JSP📋 (26)
        • Applet🧳 (6)
        • Interview👨🏻‍🏫 (8)
      • ◎ JavaScript (48)
        • JavaScript🦎 (25)
        • jQuery🌊 (8)
        • React🌐 (2)
        • Vue.js🔰 (6)
        • Node.js🫒 (3)
        • Google App Script🐑 (4)
      • ◎ HTML5+CSS3 (17)
        • HTML5📝 (8)
        • CSS3🎨 (9)
      • ──────────── (0)
      • ▣ Framework (67)
        • Spring🍃 (36)
        • Spring Boot🍀 (12)
        • Bootstrap💜 (3)
        • Selenium🌕 (6)
        • MyBatis🐣 (10)
      • ▣ Tools (47)
        • API🎯 (18)
        • Library🎲 (15)
        • JitPack🚀 (3)
        • Jenkins👨🏻 (7)
        • Thymeleaf🌿 (4)
      • ▣ Server (30)
        • Apache Tomcat🐱 (14)
        • Apache HTTP Server🛡️ (1)
        • Nginx🧶 (7)
        • OracleXE💿 (4)
        • VisualSVN📡 (4)
      • ▣ Infra & DevOps (20) N
        • LGTM Stack🔭 (5)
        • Kafka🐦‍🔥 (0)
        • Kubernetes🚢 (9) N
        • KubeCon Japan 2026⚓ (6)
      • ▣ OS : 운영체제 (18)
        • cmd : 명령프롬프트💻 (10)
        • Linux🐧 (8)
      • ▣ SQL : Database (56)
        • Oracle SQL🏮 (26)
        • PL SQL💾 (9)
        • MySQL🐬 (6)
        • MariaDB🦦 (6)
        • H2 Database🔠 (3)
        • SQL 실전문제🐌 (6)
      • ────────── (0)
      • ◈ Human Project (86)
        • Mini : Library Service📚 (15)
        • 화면 설계 [HTML]🐯 (10)
        • 서버 프로그램 구현🦁 (15)
        • Team : 여수어때🛫 (19)
        • Custom : Student🏫 (9)
        • Custom : Board📖 (18)
      • ◈ Yermi Project (49)
        • 조사모아(Josa-moa)📬 (5)
        • Riddle-Game🧩 (6)
        • 맛있을 지도🍚 (2)
        • 어디 가! 박대리!🙋🏻‍♂️ (5)
        • 조크베어🐻‍❄️ (4)
        • Looks Like Thirty🦉 (2)
        • Toy Project💎 (12)
        • 오픈소스 파헤치기🪐 (5)
        • 오늘가챠🃏 (8)
      • ◈ Refactoring (15)
        • Mini : Library Service📚 (8)
        • 서버 프로그램 구현🦁 (1)
        • Team : 여수어때🛫 (0)
        • 쿼리 튜닝일지🔧 (6)
      • ◈ Coding Test (80)
        • 백준(BOJ)👨🏻‍💻 (71)
        • 프로그래머스😎 (2)
        • 코드트리🌳 (7)
      • ◈ Study (129)
        • 기초튼튼 개발지식🥔 (25)
        • HTTP 웹 지식💡 (4)
        • 클린코드(Clean Code)🩺 (1)
        • 디자인패턴(GoF)🥞 (12)
        • 알고리즘(Algorithm)🎡 (14)
        • 다이어그램(Diagram)📈 (4)
        • 파이썬(Python)🐍 (16)
        • 에러노트(Error Note)🧱 (34)
        • 웹 보안(Web Security)🔐 (11)
        • 인공지능 AI🛸 (8)
      • ◈ 공부모임 (57)
        • 혼공학습단⏰ (18)
        • 코드트리 챌린지👊🏻 (2)
        • 개발도서 100독👟 (8)
        • 나는 리뷰어다🌾 (17)
        • 국가기술자격 서포터즈🌻 (12)
      • ◈ 자격증 공부 (48)
        • 정보처리기사🔱 (16)
        • 정보처리산업기사🔅 (9)
        • 정보보안기사⚜️ (11)
        • 컴퓨터활용능력 1급📼 (12)
      • ─────────── (0)
      • ◐ 기타 (124)
        • 알아두면 좋은 팁(tip)✨ (46)
        • 개발자의 일상🎈 (55)
        • 개발도서 서평🔍 (10)
        • 개발관련 세미나🎤 (2)
        • 블로그 꾸미기🎀 (9)
        • 사도신경 프로젝트🎚️ (2)
  • 인기 글

  • 최근 댓글

  • 반응형
    250x250
  • 태그

    자바스크립트
    코딩
    백준 티어
    Project
    Error Note
    CSS
    Oracle
    일상
    BOJ
    Database
    spring
    Java
    코딩 테스트
    javascript
    jsp
    SQL
    백준
    꿀팁
    프로그래밍
    spring boot
  • hELLO· Designed By정상우.v4.10.3
예르미(yermi)
[오늘가챠] 프론트-DB 직결 시대의 필수 보안: Supabase RLS 적용기
상단으로

티스토리툴바