qcoding

[Flutter게임개발] Supabase 리더보드 구현: RPC, RLS, 로컬 fallback 본문

Flutter 게임개발 (인디게임)

[Flutter게임개발] Supabase 리더보드 구현: RPC, RLS, 로컬 fallback

Qcoding 2026. 4. 29. 23:13
반응형

Supabase 리더보드는 Flutter 게임에서 빠르게 온라인 기록 시스템을 붙이는 좋은 방법입니다. MBTI 히어로는 RPC 함수로 점수를 제출하고, 네트워크 실패 시 로컬 리더보드로 fallback하는 구조를 사용했습니다.

Supabase 초기화는 어떻게 안전하게 처리하나요?

Web과 앱에서 환경값이 없을 수 있으므로, 설정이 없으면 온라인 기능만 비활성화합니다.

class SupabaseBootstrap {
  static bool get isConfigured =>
      _supabaseUrl.isNotEmpty && _supabaseAnonKey.isNotEmpty;

  static Future<bool> initializeIfConfigured() async {
    if (!isConfigured) return false;
    try {
      await Supabase.initialize(
        url: _supabaseUrl,
        anonKey: _supabaseAnonKey,
      ).timeout(const Duration(seconds: 5));
      return true;
    } catch (_) {
      return false;
    }
  }
}

리더보드 제출은 왜 RPC로 감싸나요?

클라이언트가 테이블에 직접 insert하도록 열어두면 검증 책임이 분산됩니다. RPC 함수에 닉네임 길이, 점수 범위, 중복 닉네임 처리 같은 규칙을 모아두면 보안과 유지보수가 쉬워집니다.

RLS는 어떤 정책으로 시작했나요?

create table if not exists public.leaderboard_entries (
  id bigint generated always as identity primary key,
  nickname text not null,
  nickname_normalized text not null,
  character text not null,
  companion text not null,
  wave integer not null,
  score integer not null,
  created_at timestamptz not null default timezone('utc', now())
);

alter table public.leaderboard_entries enable row level security;
grant select on public.leaderboard_entries to anon;

읽기는 anon에게 허용하고, 쓰기는 RPC execute로 제한하는 구조가 초반 운영에 적합합니다. 게임 클라이언트가 필요한 최소 권한만 갖게 됩니다.

네트워크 실패 시 UX는 어떻게 지키나요?

온라인 제출이 실패해도 플레이어 기록을 버리지 않고 로컬 저장으로 넘깁니다. 실패 이유는 network, config, duplicate처럼 분류해 UI에서 다른 메시지를 줄 수 있습니다.


MBTI 히어로는 지금 바로 플레이할 수 있습니다.

 

MBTI 히어로: 직장인 생존기

직장에서 살아남는 2D 생존 액션 게임. MBTI 캐릭터와 함께 웨이브를 돌파하세요.

mbti-hero.web.app

 

반응형
Comments