logo
|
Blog

    [ 개인플젝 ] Supabase 이용하기

    RN개발자 혼자 프로젝트 완성하기 with Supabase
    김보람's avatar
    김보람
    Jan 11, 2026
    [ 개인플젝 ] Supabase 이용하기
    Contents
    Supabase 채택이유1. 앱 기능 요약2. 전체 DB 구조3. users 테이블4. seasons 테이블5. records 테이블

    Supabase 채택이유

    개인 프로젝트(운동 인증 앱)를 개발하면서 백엔드로 Firebase 대신 Supabase를 선택했다.

    사실 처음에는 익숙한 Firebase로 서버를 구성하고 싶었으나 개발 환경이 비교적 최신(macOS / Xcode)이다 보니 Firebase iOS SDK 및 일부 네이티브 모듈과의 버전 호환 이슈가 발생했다

    내가 실직전 회사에서 최대한 늦게 업데이트하는 이유이다…. ㅂㄷㅂㄷ

    무튼 환경 디버깅에 너무 많은 시간을 쏟지 않기 위해 차선책으로 비슷한 Supabase를 채택했다


    1. 앱 기능 요약

    이 프로젝트에서 구현한 핵심 기능은 다음과 같다.

    1. 유저는 앱 최초 진입 시 닉네임을 생성

    2. 로그인은 별도 회원가입 없이 익명 인증으로 처리

    3. 하나의 시즌 안에서

      • 하루에 한 번만 인증 가능

      • 인증 시 사진을 업로드

    4. 이번 시즌 기준으로

      • 연속 기록(streak)

      • 캘린더

      • 랭킹

    이 기능을 기준으로 필요한 테이블을 구성해야한다


    2. 전체 DB 구조

    users → 유저 기본 정보
    seasons → 시즌 정의 (운영자 관리)
    records → 유저의 인증 기록


    3. users 테이블

    • 유저 기본 정보

      Supabase Auth의 auth.uid()를 그대로 사용자 ID로 사용한다.

      create table users (
        id uuid primary key,
        nickname text not null,
        notification_enabled boolean default true,
        created_at timestamptz default now()
      );
    • 설계 포인트

      • id는 Supabase Auth의 UID

      • 닉네임은 앱 최초 진입(OOBE)에서 한 번 생성

      • 필요 시 언제든 수정 가능


    4. seasons 테이블

    • 시즌 정의 (운영자 === 내가 관리)

      시즌은 유저가 생성하지 않는다.
      운영자가 직접 관리하는 기준 데이터다.

      create table seasons (
        id uuid primary key default gen_random_uuid(),
        season_key text not null unique,       -- 예: '2026_01'
        start_date date not null,
        end_date date not null,
        is_current boolean default false,
        created_at timestamptz default now()
      );

      • Row Level Security (읽기 전용)

        alter table seasons enable row level security;
        
        create policy "anyone can read seasons"
        on seasons
        for select
        using (true);

      • 초기 시즌 데이터

        insert into seasons (season_key, start_date, end_date, is_current)
        values (
          '2026_01',
          '2026-01-01',
          '2026-03-31',
          true
        );

      • 설계 포인트

        • 시즌은 “2026년 첫 시즌” 같은 논리 단위

        • 앱에서는 항상 is_current = true인 시즌만 사용

        • 시즌 변경은 SQL로 한 번 실행하면 끝


    5. records 테이블

    • 인증 기록

      유저의 인증 기록을 저장하는 테이블이다.

      create table records (
        id uuid primary key default gen_random_uuid(),
      
        user_id uuid not null,
        season_id uuid not null,
      
        record_date date not null,       -- 인증 날짜
        record_month text not null,       -- '2026-01' (캘린더/집계용)
      
        image_url text not null,
      
        created_at timestamptz default now(),
      
        constraint fk_records_user
          foreign key (user_id)
          references users (id)
          on delete cascade,
      
        constraint fk_records_season
          foreign key (season_id)
          references seasons (id)
          on delete cascade,
      
        constraint unique_user_day
          unique (user_id, record_date)
      );

      • 하루 1회 인증 보장

        unique (user_id, record_date)
        
        // 중복 요청
        // 네트워크 지연
        // 클라이언트 버그
        // 를 DB 레벨에서 모두 방지

      • records 테이블 보안 (RLS)

        records는 절대 공개되면 안 되는 데이터다.

        alter table records enable row level security;
      • 기록 조회

        alter table records
        enable row level security;
        
        create policy "users can read records in current season"
        on records
        for select
        using (
          -- 본인 기록이거나
          auth.uid() = user_id
        
          OR
        
          -- 현재 시즌의 기록이면
          season_id = (
            select id
            from seasons
            where is_current = true
          )
        );
      • 본인 기록만 생성

        create policy "users can insert own records"
        on records
        for insert
        with check (auth.uid() = user_id);
      • 본인 기록만 삭제

        create policy "users can delete own records"
        on records
        for delete
        using (auth.uid() = user_id);

    Share article
    Contents
    Supabase 채택이유1. 앱 기능 요약2. 전체 DB 구조3. users 테이블4. seasons 테이블5. records 테이블

    김보람 | 930802qhfka@gmail.com

    RSS·Powered by Inblog