여러 앱에서 하나의 Google 로그인을 공유하는 법 (Supabase + Flutter)

TL;DR

여러 앱이 같은 Supabase 프로젝트를 쓰면, 같은 Google 계정은 어느 앱에서 로그인해도 같은 유저가 돼요. Android 앱은 Google Cloud Console에 Android 클라이언트를 추가하고, Flutter 코드에서 Web Client ID를 serverClientId로 쓰면 돼요. Supabase Google Provider에는 Web Client ID가 들어가요. iOS 앱은 Supabase 문서대로 iOS Client ID도 Supabase의 Client IDs에 쉼표로 함께 넣어야 해요.


문제 상황

"Just Apps"라는 플랫폼을 만들고 있어요. Just QR, Just Notes 등 여러 앱을 하나의 계정 시스템으로 운영하고 싶어요. 백엔드는 Supabase, 프론트는 Flutter예요.

처음 든 의문은 이거였어요.

Supabase Google Provider에 Client ID를 하나밖에 못 넣는데, 앱이 여러 개면 어떻게 하지?

이 의문 때문에 signInWithOAuth(브라우저 방식)도 시도해 봤지만, 결국 원래 쓰던 방식(google_sign_in + signInWithIdToken)으로 돌아왔어요.

정정 (2026-10): Supabase Google Provider의 Client IDs 칸에는 여러 Client ID를 쉼표로 이어서 넣을 수 있어요. Web Client ID를 맨 앞에 두면 돼요.


Google OAuth Client의 구조

Google Cloud Console에서 OAuth 클라이언트를 만들 때 타입이 나뉘어요.

타입역할어디에 등록?
WebFlutter 코드의 serverClientId, Supabase 토큰 검증Supabase Provider에 등록 (맨 앞)
Android앱의 패키지명 + 서명(SHA-1) 확인Google Cloud Console
iOS앱의 번들 ID 확인Google Cloud Console + Supabase Client IDs

실제 구조

TEXT
Google Cloud 프로젝트 (Just Apps)
│
├── Web Client (1개)
│   └── Supabase Google Provider에 등록
│   └── 모든 앱의 Flutter 코드에서 serverClientId로 사용
│
├── Android Client - Just QR 디버그
│   └── 패키지명: com.justkihyun.justqr + 디버그 SHA-1
├── Android Client - Just QR 릴리즈
│   └── 패키지명: com.justkihyun.justqr + 릴리즈 SHA-1
├── Android Client - Just Notes 디버그
│   └── 패키지명: com.justkihyun.justnotes + 디버그 SHA-1
├── Android Client - Just Notes 릴리즈
│   └── 패키지명: com.justkihyun.justnotes + 릴리즈 SHA-1
│
├── iOS Client - Just QR
│   └── Bundle ID: com.justkihyun.justqr
└── iOS Client - Just Notes
    └── Bundle ID: com.justkihyun.justnotes

흐름

TEXT
[Flutter 앱]
    │
    ├── google_sign_in 패키지로 네이티브 Google 로그인
    │   (Google SDK가 앱의 패키지명 + SHA-1로 Android Client 매칭)
    │
    ├── idToken, accessToken 획득
    │
    └── Supabase signInWithIdToken() 호출
        (Supabase가 등록된 Client ID로 토큰 검증)
        │
        └── 동일한 Supabase 프로젝트 → 동일한 auth.users → 동일한 계정

앱이 달라도 같은 Google 계정으로 로그인하면 같은 Supabase 유저가 돼요. 모든 앱이 같은 Supabase 프로젝트를 쓰고, Google 계정이 같기 때문이에요.


새 앱을 추가할 때 할 일

  1. Google Cloud Console: Android/iOS 클라이언트 추가 (패키지명 + SHA-1 / Bundle ID)
  2. Flutter 코드: 같은 Web Client ID를 serverClientId로 사용
  3. Supabase: 같은 프로젝트 URL + anon key 연결
  4. iOS 앱이면: 새 iOS Client ID를 Supabase Client IDs에 쉼표로 추가

Android 앱만 추가한다면 Supabase 설정은 바꿀 게 없어요.


signInWithOAuth를 쓰지 않은 이유

브라우저 기반 OAuth 방식(signInWithOAuth)도 시도해 봤어요. 그때는 이런 제한 때문에 멀티앱 구조에 맞지 않는다고 판단했어요.

  • Supabase Site URL이 1개만 설정 가능
  • Redirect URLs에 커스텀 스킴(myapp://) 등록 불가

정정 (2026-10): 두 가지 모두 Supabase 문서와 달라요. Site URL은 redirectTo가 없을 때 쓰는 기본값이고, Additional Redirect URLs 허용 목록에는 여러 URL(와일드카드 포함)을 넣을 수 있어요. 커스텀 스킴도 넣을 수 있어요. Supabase의 Flutter 딥링크 예시가 io.supabase.flutterquickstart://login-callback을 등록하는 방식이에요. 그래서 signInWithOAuth로도 앱별 딥링크를 등록해 멀티앱을 구성할 수 있어요. 이 글에서는 네이티브 로그인 화면을 쓰는 google_sign_in + signInWithIdToken 방식을 썼어요.


흔한 질문

"앱마다 Supabase에 Client ID를 등록해야 하나요?"

Android 앱은 Flutter 코드에서 Web Client ID를 serverClientId로 쓰면, Supabase에는 Web Client ID만 있으면 돼요. Android 클라이언트는 Google Cloud Console에서 앱의 패키지명과 서명을 확인하는 데 쓰여요. iOS 앱은 Supabase 문서대로 iOS Client ID도 Client IDs에 함께 넣어요.

"ApiException: 10 에러가 나요"

대부분 지금 빌드에 쓴 서명의 SHA-1이 Google Cloud Console의 Android 클라이언트에 등록되지 않아서 나요. 디버그 빌드라면 keytool로 디버그 SHA-1을 확인하고 Android 클라이언트를 추가하면 돼요.

Bash
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android

정리

질문답
Supabase에 뭘 등록?Web Client ID (맨 앞) + iOS 앱이 있으면 iOS Client ID
앱마다 추가 설정?Google Cloud Console에 Android/iOS 클라이언트 추가
Supabase 설정 변경?Android 앱만 추가하면 없음, iOS 앱이면 Client IDs에 추가
계정 공유?같은 Supabase 프로젝트면 자동 공유
약관 동의 공유?user_agreements 같은 테이블을 공유하면 돼요