소셜 로그인 3종 출시 런북 — Google·Apple 활성화
Apple·Google·Kakao 3종 로그인을 production에서 정상 작동시키기 위한 실행 런북이다. 코드는 3종 모두 구현되어 있으므로(social-auth.md), 이 문서는 남은 외부 설정과 게시 절차를 순서대로 실행하는 데만 집중한다.
역할 표기: [오너] = 외부 콘솔 계정 권한이 필요해 오너가 직접 실행, [세션] = Claude 세션이 PR로 실행하고 검증.
순서 게이트
아래 순서는 뒤바꾸면 안 된다. 근거: 개인정보처리방침 v3 게시·시행 전에 Supabase에서 Google/Apple provider를 활성화하면, UI 버튼이 없어도 authorize 엔드포인트가 공개적으로 동작해 방침이 커버하지 않는 수집 경로가 열린다. 반대로 app-config gate를 provider 설정 전에 열면 미구성 provider 버튼이 사용자에게 노출된다.
Phase 0 [세션] v3 문서·도구 PR 발행 → [오너] 내용 검토 → 머지 = 게시
Phase 1 [오너] Google Cloud / Apple Developer 콘솔 준비 (게시 후 언제든, 활성화 제외)
Phase 2 [세션] 동의 버전 전환 (registry v3 + DB 마이그레이션) (시행일 이후)
Phase 3 [오너] Supabase provider 활성화 + Allow manual linking
Phase 4 [세션] 기계 검증 (프로브 3종 PASS) → app-config gate 3종 전환 PR
Phase 5 [오너] 실계정 최종 확인 체크리스트완주 판정 = Phase 4의 기계 검증 전부 그린 그리고 Phase 5의 오너 확인 완료.
공통 값
모든 콘솔 절차에서 아래 값을 그대로 사용한다.
| 항목 | 값 |
|---|---|
| Supabase OAuth callback (외부 provider에 등록할 유일한 redirect URI) | https://kobxeylancdimqhfkbnl.supabase.co/auth/v1/callback |
| 서비스 도메인 | www.barbelic.com |
| Supabase redirect allowlist (이미 등록돼 있어야 함) | https://www.barbelic.com/** · http://127.0.0.1:5173/** · barbelic://auth/callback** |
| iOS 번들 ID (기존) | com.dekerd.barbelic |
Phase 0 — v3 문서 게시 [오너 검토 → 머지]
- [ ] PR에 포함된
public/legal/terms-v3.html·public/legal/privacy-v3.html내용을 검토한다. 시행일은 2026-08-28로 초안 작성했다(약관 제3조의 "시행 7일 전 고지" 관례 기준). 바꾸려면 머지 전에 두 HTML과src/react/legalDocuments.ts의effectiveOn을 함께 바꾼다. 게시(머지) 후에는 불변 문서라 수정할 수 없다. - [ ] 외부 법적 검토 권장: 초안은 법률 자문 없이 작성됐다. 특히 기존 이용자 재동의 필요 여부는 법령 해석 사항이다. 초안은 "신규 수집은 해당 로그인 방식을 쓰는 이용자에게만 발생"하는 구조라 기존 이용자 재동의 없이 고지로 충분하다는 전제를 깔았고, 그래서 기존 이용자를 막는 재동의 UI는 만들지 않는다(현행 코드도 온보딩 완료자를 다시 온보딩으로 보내지 않는다).
- [ ] 머지하면 Vercel 배포로
/legal/terms-v3.html·/legal/privacy-v3.html이 공개된다. 완료 확인: 두 URL이 200으로 열리고 문서 버전 v3가 보인다. - [ ] (권장) 서비스 공지 채널이 있다면 개정 예고를 게시한다.
Phase 1 — 외부 콘솔 준비 [오너]
Supabase에 값을 입력하는 단계(활성화)는 Phase 3다. 여기서는 자격증명 준비까지만 한다. 만든 값은 Phase 3까지 안전한 곳(비밀 관리자)에 보관한다.
1a. Google Cloud Console
https://console.cloud.google.com
- [ ] 프로젝트 선택 또는 신규 생성 (예:
barbelic). - [ ] APIs & Services > OAuth consent screen:
- [ ] User Type = External.
- [ ] App name =
Barbelic, User support email·Developer contact = 운영 이메일. - [ ] Authorized domains에
barbelic.com과supabase.co추가 (redirect URI가 supabase.co라서 요구될 수 있다). - [ ] Scopes는 기본(비민감)만 —
openid,email,profile. 민감/제한 scope를 추가하지 않는다(추가하면 Google 검증 심사가 필요해진다). - [ ] Publishing status를 In production으로 전환한다. Testing 상태로 두면 등록한 테스트 계정만 로그인되는 함정이 있다.
- [ ] APIs & Services > Credentials > Create Credentials > OAuth client ID:
- [ ] Application type = Web application, 이름 예:
barbelic-supabase. - [ ] Authorized redirect URIs = 위 공통 값의 Supabase callback 하나만. (Authorized JavaScript origins는 비워도 된다 — 서버 교환 흐름이라 불필요.)
- [ ] 생성된 Client ID / Client secret을 보관한다.
- [ ] Application type = Web application, 이름 예:
완료 확인: Client ID가 *.apps.googleusercontent.com 형태로 발급됨.
1b. Apple Developer
https://developer.apple.com/account (유료 멤버십 필요)
[ ] Certificates, Identifiers & Profiles > Identifiers에서 App ID
com.dekerd.barbelic이 있는지 확인하고, 없으면 생성한다. 해당 App ID의 Capabilities에 Sign in with Apple을 체크해 둔다.[ ] Identifiers > (+) > Services IDs로 새 Services ID를 만든다:
- [ ] Identifier =
com.dekerd.barbelic.web(권장 — 번들 ID와 달라야 한다), Description =Barbelic web login. - [ ] 생성 후 그 Services ID를 열어 Sign in with Apple > Configure:
- [ ] Primary App ID =
com.dekerd.barbelic. - [ ] Domains and Subdomains =
kobxeylancdimqhfkbnl.supabase.co. - [ ] Return URLs = 위 공통 값의 Supabase callback.
- [ ] Primary App ID =
- [ ] Identifier =
[ ] **Keys > (+)**로 Sign in with Apple 키를 만든다 (Primary App ID 선택).
- [ ]
.p8키 파일을 내려받아 보관한다 — 한 번만 받을 수 있다. - [ ] Key ID(키 상세 화면)와 Team ID(계정 우상단 Membership)를 기록한다.
- [ ]
[ ] client secret(JWT)을 생성한다:
bashnode scripts/generate-apple-client-secret.mjs --key AuthKey_XXXXXXXXXX.p8 --team-id <TEAM_ID> --key-id <KEY_ID> --client-id com.dekerd.barbelic.web- [ ] 출력 첫 줄(JWT)을 보관하고, 함께 출력된 만료일을 아래 rotation 표와 운영 캘린더에 기록한다.
완료 확인: Services ID가 Return URL 검증을 통과해 저장되고, JWT가 eyJ... 3-토막 형태로 생성됨.
Phase 2 — 동의 버전 전환 [세션]
원칙은 시행일(2026-08-28) 이후 실행이나, 오너 결정(2026-08-21)으로 게시 직후 전환했다. 근거: 신규 가입자는 게시된 v3에 직접 동의하고 들어오므로 동의 공백이 없고, 시행일은 법정 기한이 아니라 약관 제3조의 자체 7일 예고 관례였다. 형식상 "시행일 전 전환" 흠결은 오너 재량으로 수용.
- [ ]
CURRENT_LEGAL_DOCUMENT_VERSIONS를{ terms: "v3", privacy: "v3" }로 전환. - [ ]
onboarding_consent_requirements()를 v3 요구로 교체하는 DB 마이그레이션 (착수 전 타임스탬프를 HQ에 신고, schema.sql verbatim append + suffix 계약 테스트 갱신 절차 포함). - [ ] 관련 계약 테스트(
tests/react/appContainer.test.mjs의 현행 버전 단언 등) 갱신. - [ ] Production DB 적용 +
check:remote-schemaEXIT=0 확인.
완료 확인: 신규 가입 온보딩이 v3 문서에 동의를 요구한다. 기존 사용자는 차단되지 않는다(온보딩 완료 판정은 동의 버전과 무관 — 실측 확인됨).
Phase 3 — Supabase provider 활성화 [오너]
https://supabase.com/dashboard → 프로젝트 kobxeylancdimqhfkbnl → Authentication
- [ ] Sign In / Providers > Google: Enable 켜고 Phase 1a의 Client ID / Client secret 입력, 저장.
- [ ] Sign In / Providers > Apple: Enable 켜고 Client IDs =
com.dekerd.barbelic.web, com.dekerd.barbelic(웹 Services ID + iOS 번들 ID — iOS 네이티브 Sign in with Apple의 identity token audience가 번들 ID라서 둘 다 필요, 아래 "iOS 네이티브 Sign in with Apple" 절), Secret Key = Phase 1b의 JWT 입력, 저장. - [ ] Kakao가 여전히 Enabled인지 함께 확인.
- [ ] Authentication > General(또는 Settings)에서 Allow manual linking이 켜져 있는지 확인 — 계정 연결(로그인 연결) 기능의 전제 조건.
- [ ] URL Configuration: Site URL =
https://www.barbelic.com, redirect allowlist가 공통 값 표와 일치하는지 확인.
완료 확인 (오너 또는 세션, 자격증명 불필요):
node scripts/check-social-provider-config.mjs3종 모두 PASS가 나와야 한다. FAIL이면 해당 provider의 콘솔 값을 재확인한다. (2026-08-21 실측: Allow manual linking·Site URL·allowlist는 이미 정상, Kakao PASS — 남은 것은 Google/Apple 입력·Enable뿐.)
Phase 4 — gate 전환과 기계 검증 [세션]
- [ ] 프로브 3종 PASS 재확인(위 명령).
- [ ] PR:
app-config.js의socialAuthProviders를["kakao", "google", "apple"]로 전환 + 계약 테스트 (tests/auth/socialOAuthProviders.test.mjs등) 갱신 + external-auth 스모크에 provider 설정 도달성 검사 편입 (check-social-provider-config.mjs --gated— gate가 노출하는 provider가 Supabase에서도 활성화돼 있어야 한다는 불변식을 CASE-003 앞에서 검사). PR은 Phase 3 전에 미리 준비할 수 있으나 머지는 프로브 3종 PASS 뒤에만 한다 — 순서 게이트(미구성 provider 버튼 노출 금지). - [ ] 머지·배포 후 production 로그인 화면에 버튼 3종이 노출되는지 확인.
Phase 5 — 실계정 최종 확인 [오너]
실계정 OAuth는 자동화로 대체할 수 없다. 각 항목을 실제 계정으로 확인한다.
| # | 시나리오 | Kakao | Apple | |
|---|---|---|---|---|
| 1 | 신규 가입(해당 provider를 처음 쓰는 계정) → 온보딩 → v3 동의 → 홈 진입 | ☐ | ☐ | ☐ |
| 2 | 로그아웃 후 같은 provider로 재로그인 → 같은 데이터 보임 | ☐ | ☐ | ☐ |
| 3 | 한 계정으로 로그인 → 내 정보 > 로그인 연결에서 다른 provider 연결 → 로그아웃 → 연결한 provider로 로그인 → 같은 운동 데이터 진입 | ☐ | ☐ | ☐ |
| 4 | 로그인·연결 callback URL에 token 없이 code만 있는지(주소창 확인) | ☐ | ☐ | ☐ |
| 5 | iOS 앱에서 로그인/취소/앱 복귀 동작 | ☐ | ☐ | ☐ |
추가 확인: Apple 신규 가입 시 "이메일 가리기"를 선택해 relay 이메일로도 가입이 정상 동작하는지 1회 확인(권장).
문제 발견 시 해당 provider만 gate에서 되돌리는 최소 롤백이 가능하다 (socialAuthProviders에서 제거 — Supabase 비활성화보다 안전하고 빠르다).
Phase 5 발견 사항 (2026-08-22 오너 실계정 확인 중)
- 미확인 계정의 Kakao identity가 Google 로그인 때 제거됨. 오너 계정은 2026-05 생성 당시 Kakao가 검증 이메일을 주지 않아 Supabase 기준 "이메일 미확인" 상태였다(
auth.users.emailNULL). 같은 이메일의 Google(검증됨)로 로그인하자 Supabase Auth가 자동 연결 뒤 계정 선점 방어 규칙 (createAccountFromExternalIdentity→!user.IsConfirmed()→RemoveUnconfirmedIdentities)으로 미확인 identity(Kakao)를 삭제했다. 같은 계정(데이터 그대로)이라 피해는 없고, 복구 = 로그인 연결 > 카카오 (manual linking). 재연결된 identity는 검증 이메일을 들고 왔고 계정이 확인됨 상태가 되어 재발하지 않는다. 검증 이메일로 가입한 보통 Kakao 계정에는 해당 없음. 재연결 전 Kakao로 새로 로그인하면 빈 계정이 새로 생기니 주의. - iOS 계정 연결 완료 후 WebView가 앱 진입으로 리셋됨(재부팅처럼 보임). 네이티브
nativeAuthComplete처리가 sign-in/link를 구분하지 않고reloadHomeAfterNativeAuthCompletion()을 호출했다. 수정: 주입 스크립트가action을 함께 보내고 link면 리셋을 건너뛴다(iOS 빌드 배포 필요, 웹 무변경). - Apple "이메일 가리기"는 끌 수 없다(플랫폼 보장·심사 지침 4.8). 릴레이 주소는 검증된 고유 이메일이고 계정 식별은 Apple
sub라 재로그인은 같은 계정으로 들어온다. 기존 Kakao/Google 계정과는 이메일이 달라 자동 연결이 안 되므로 "로그인 연결"이 해답. 자동 연결 규칙(Supabase): 새 provider의 검증된 이메일이 기존 어느 identity의 이메일이든(또는users.email) 같으면 그 계정에 붙는다 — Kakao a + 연결된 Google b 계정에 Apple이 a나 b 이메일을 공유하면 같은 계정, 릴레이/제3의 이메일이면 새 계정.
iOS 네이티브 Sign in with Apple (2026-08-22 도입, 맥북 절차)
iOS 앱의 Apple 로그인은 Supabase authorize 웹 페이지 대신 시스템 시트 (ASAuthorizationController)를 쓴다. 코드는 레포에 있고(MainViewController.swift, App/App.entitlements, CODE_SIGN_ENTITLEMENTS), 기기 반영에는 아래가 필요하다. Apple 계정 연결과 Kakao·Google은 종전 ASWebAuthenticationSession 그대로다.
- [ ] [오너, Supabase] Authentication > Providers > Apple > Client IDs를
com.dekerd.barbelic.web, com.dekerd.barbelic으로 저장(번들 ID 추가). 네이티브 identity token의 audience가 번들 ID라 없으면 "audience mismatch"로 실패한다. 확인: Management APIconfig/auth의external_apple_client_id에 둘 다 포함. - [ ] [오너, 맥북 Xcode]
ios/App/App.xcworkspace열기 → App target > Signing & Capabilities에 Sign in with Apple이 보이는지 확인(entitlements가 레포에 있으므로 자동 표시; 안 보이면 + Capability로 추가 — 같은 entitlements 파일에 기록된다). Automatic signing이 App ID(com.dekerd.barbelic, Phase 1b에서 capability 켬)에 맞춰 프로필을 갱신한다. - [ ] [오너, 맥북] 실기기 빌드 → 로그아웃 상태에서 "Apple로 시작" → 시스템 시트 (Face ID/암호) → 홈 진입. 취소 시 "로그인이 취소되었습니다." 토스트. 내 정보 > 로그인 연결 > Apple은 종전처럼 웹 시트가 뜬다(의도).
- [ ] [오너, 맥북] TestFlight/App Store 업로드. 이 빌드에는 #574(연결 후 WebView 리셋 제거)도 같이 실린다.
동작 요약: 네이티브가 무작위 nonce(32바이트 hex)를 만들고 SHA-256 hex를 요청 nonce에 넣는다 → Apple이 identity token 반환 → barbelic:native-auth 이벤트 detail { provider: "apple", idToken, nonce(원문) } → 웹 completeNativeSocialLogin → signInWithIdToken({ provider: "apple", token, nonce }) → 세션 저장 → 완료 이벤트 → 네이티브가 앱 진입으로 리셋(로그인 경로 공통). 토큰은 로그·커스텀 스킴에 싣지 않는다.
Apple client secret rotation (반복 운영 절차)
Apple secret은 최대 6개월짜리 JWT라 만료 전 재발급이 필수다. 만료를 넘기면 Apple 로그인·연결이 전부 실패한다.
재발급 절차 (5분, 배포 불필요):
- 보관 중인
.p8키로 Phase 1b의 생성 명령을 다시 실행한다 (.p8·Key ID·Team ID는 재사용, 새 JWT만 생성된다). - Supabase Dashboard > Authentication > Providers > Apple의 Secret Key를 새 JWT로 교체하고 저장한다.
node scripts/check-social-provider-config.mjs apple로 PASS 확인.- 아래 표와 운영 캘린더에 새 만료일을 기록한다 (만료 2주 전 알림 권장).
.p8 키 자체를 분실했으면 Apple Developer > Keys에서 새 키를 만들어 (새 Key ID) 같은 절차를 밟는다 — 기존 키 revoke는 새 secret 적용 확인 후에.
| 발급일 | 만료일 | 실행자 | 비고 |
|---|---|---|---|
| 2026-08-21 | 2027-02-17 (2주 전 알림: 2027-02-03) | 오너 | 최초 발급. Key ID BB47KJ2BXP, Services ID com.dekerd.barbelic.web |
이력
- 2026-08-21: 최초 작성 (소셜 로그인 3종 완주 트랙). 코드 현황과 정책 원칙은
social-auth.md가 정본이고, 이 문서는 실행 절차만 담는다. - 2026-08-21: Phase 4 PR — gate 3종 전환 + 스모크
--gated프로브 편입. Phase 3 실측 주석(manual linking 기정상) 추가. - 2026-08-22: Phase 3 오너 활성화 → #547 머지·배포 → Phase 5 실계정 확인 중 발견 사항 3건 기록 + iOS 연결 완료 후 WebView 리셋 제거(iOS 빌드 필요).
- 2026-08-22: iOS 네이티브 Sign in with Apple 도입(로그인만, 연결은 웹 유지) — Phase 3 Apple Client IDs에 번들 ID 추가 + 맥북 절차 신설.