[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CBH2E4JC0EJTYVX28T0W5M":3,"skill-same:01M6CBH2E4JC0EJTYVX28T0W5M":54},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":21,"frontMatter":22,"refName":23,"commitSha":24,"skillDirectory":25,"forksCount":13,"repositoryHtmlUrl":26,"repositoryHomepageUrl":6,"ownerHtmlUrl":27,"ownerBlogUrl":6,"ownerDescription":28,"updatedAt":29,"install":30,"resources":43},"01M6CBH2E4JC0EJTYVX28T0W5M","36-account-login-gpgs",null,"devwinsoft\u002Fdevian","devwinsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F22570160?v=4","01M6C6RR8W05NH8NPKQNCE3Q72","maoshy","01M6C6RRDJ5TJJCZXRTY801YDH",0,"MIT","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian-unity\u002F50-mobile-package\u002F20-account-system\u002F36-account-login-gpgs\u002FSKILL.md",[],[18],"36 account login gpgs","2026-11-10 10:12:30",false,"# 36-account-login-gpgs — AccountLoginGpgs (Sign-in + Cloud Save)\n\n\n## 범위\n- Google Play Games Services(GPGS) **v2** 기반 (assembly: `Google.Play.Games`):\n  - Sign-in (`Action\u003CSignInStatus>`)\n  - Saved Games(Cloud Save) Load\u002FSave\u002FDelete\n  - RequestServerSideAccess (`Action\u003CAuthResponse>`)\n- 기존 중복 로직을 신규 `AccountLoginGpgs`로 점진 치환한다.\n- GPGS v1 (`GooglePlayGames` assembly)은 지원하지 않는다.\n\n\n## Implementation Location (3-path mirror)\n- UPM (정본): `framework-cs\u002Fupm\u002Fcom.devian.foundation\u002FSamples~\u002FMobilePackage\u002FRuntime\u002FAccount\u002FAccountLoginGpgs.cs`\n- Packages (sync): `framework-cs\u002Fapps\u002FUnityExample\u002FPackages\u002Fcom.devian.foundation\u002FSamples~\u002FMobilePackage\u002FRuntime\u002FAccount\u002FAccountLoginGpgs.cs`\n- Assets\u002FSamples (import): `framework-cs\u002Fapps\u002FUnityExample\u002FAssets\u002FSamples\u002FDevian Samples\u002F{version}\u002FMobilePackage\u002FRuntime\u002FAccount\u002FAccountLoginGpgs.cs`\n\n\n## 핵심 정책\n- **GPGS v2 전용** — `Google.Play.Games` 어셈블리만 참조한다.\n- GPGS 플러그인이 없는 환경에서도 컴파일 가능해야 한다(Reflection 기반).\n- Android 런타임 외에서는 `NotAvailable`로 안전하게 처리한다.\n- 인증 시도 순서: `Authenticate`(silent) 우선, 실패 시 `ManuallyAuthenticate`(UI) fallback.\n- AccountManager 로그인 경로에서는 `RequestServerSideAccess` auth code가 필수다. auth code가 비어 있으면 성공으로 처리하지 않고 실패로 반환한다.\n- 구매 진입 자동보정 경로에서는 `GetServerAuthCodeCredentialSilentAsync`(silent-only, UI 없음)를 사용한다.\n- 기존 기능(1) AccountManager의 GPGS auth code 획득, (2) SaveCloudClientGoogle의 Saved Games 호출을 `AccountLoginGpgs`로 모은다.\n- 완료 후 기존 분산 로직은 삭제(리팩터링)한다.\n\n\n## 사용 예시\n\n\n### 1) 백엔드 로그인\u002F계정 연결(서버 Auth Code 기반) — AccountManager에서 호출\n```csharp\n\u002F\u002F before: AccountManager 내부에서 Reflection으로 auth code 획득\n\u002F\u002F after: AccountLoginGpgs.Instance.GetServerAuthCodeCredentialAsync(ct)\n\nvar credResult = await AccountLoginGpgs.Instance.GetServerAuthCodeCredentialAsync(ct);\nif (credResult.IsFailure) return CoreResult\u003CLoginCredential>.Failure(credResult.Error!);\n\n\u002F\u002F LoginCredential.ServerAuthCode를 사용해 백엔드 sign-in\u002Flink 로직 진행(구현체는 프로젝트 선택)\n```\n\n\n### 2) Cloud Save — SaveCloudManager\u002FSaveCloudClientGoogle 내부에서 호출\n```csharp\nawait AccountLoginGpgs.Instance.SignInIfNeededAsync(ct);\n\nvar (result, payload) = await AccountLoginGpgs.Instance.LoadAsync(slot, ct);\nif (result == SaveCloudResult.Success) { \u002F* payload 사용 *\u002F }\n\nawait AccountLoginGpgs.Instance.SaveAsync(slot, payload, ct);\n```\n\n\n## 체크리스트(DoD)\n\n- UPM\u002FExample 경로에 동일한 AccountLoginGpgs.cs 존재\n- AccountManager의 Google credential 획득 로직이 AccountLoginGpgs 호출로 치환됨\n- SaveCloudClientGoogle의 Saved Games 핵심 로직이 AccountLoginGpgs 호출로 치환됨(중복 로직 삭제)\n- 빌드 컴파일 에러 없음(플러그인 미설치 환경에서도 컴파일)\n",{},"main","8cb5bd877a3a7004867d2f55697cb9e4ff2f1734","skills\u002Fdevian-unity\u002F50-mobile-package\u002F20-account-system\u002F36-account-login-gpgs","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian","https:\u002F\u002Fgithub.com\u002Fdevwinsoft","Kim Hyong Joon","2026-04-12 18:44:10",{"source":7,"skillName":5,"commands":31,"prompt":41,"zipAvailable":42},[32,35,38],{"tool":33,"command":34},"npx","npx skills add devwinsoft\u002Fdevian --skill 36-account-login-gpgs",{"tool":36,"command":37},"bunx","bunx skills add devwinsoft\u002Fdevian --skill 36-account-login-gpgs",{"tool":39,"command":40},"pnpm","pnpm dlx skills add devwinsoft\u002Fdevian --skill 36-account-login-gpgs","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian-unity\u002F50-mobile-package\u002F20-account-system\u002F36-account-login-gpgs\u002FSKILL.md",true,[44,50],{"path":45,"resourceType":46,"resourceTypeDesc":47,"sizeBytes":48,"sourceHtmlUrl":49},"DEEPENING.md","REFERENCE","参考文档",3599,"https:\u002F\u002Fgithub.com\u002Fmalinskibeniamin\u002Fskills\u002Fblob\u002Fmain\u002Fcodebase-design\u002FDEEPENING.md",{"path":51,"resourceType":46,"resourceTypeDesc":47,"sizeBytes":52,"sourceHtmlUrl":53},"DESIGN-IT-TWICE.md",2884,"https:\u002F\u002Fgithub.com\u002Fmalinskibeniamin\u002Fskills\u002Fblob\u002Fmain\u002Fcodebase-design\u002FDESIGN-IT-TWICE.md",[55,61,69,77,86,93],{"skillNo":56,"name":57,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":58,"categories":59,"keywords":60,"publishedAt":19},"01M6CBX3K2JJV38ANHVGCAT8A0","devian","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002FSKILL.md",[],[57],{"skillNo":62,"name":63,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":66,"publishedAt":19},"01M6CBX210BFMM8AMN770J9WY8","90-project-archive","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F90-project-archive\u002FSKILL.md",[],[67,68],"archive","90 project archive",{"skillNo":70,"name":71,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":74,"publishedAt":19},"01M6CBWZSGRR9R3YJZB3177667","30-env-management","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F30-env-management\u002FSKILL.md",[],[75,76],"management","30 env management",{"skillNo":78,"name":79,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":82,"publishedAt":19},"01M6CBWYD3TGWBQV7V35551THF","19-page-push-send","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F19-page-push-send\u002FSKILL.md",[],[83,84,85],"push","page","19 page push send",{"skillNo":87,"name":88,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":89,"categories":90,"keywords":91,"publishedAt":19},"01M6CBWWRQ05A7604GHJKTPJTF","18-page-savedata","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F18-page-savedata\u002FSKILL.md",[],[84,92],"18 page savedata",{"skillNo":94,"name":95,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":98,"publishedAt":19},"01M6CBWVH4S2VF1V7B2GBTESCT","17-page-deobfuscate","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F17-page-deobfuscate\u002FSKILL.md",[],[84,99],"17 page deobfuscate"]