# Privy 이전

codemod로 import와 Provider 설정을 바꾸고, 미지원 API와 기존 이용자의 자산 이전을 처리합니다.

codemod가 Privy import와 Provider 설정을 바꿉니다. 이후 보고서에 나온 미지원 API를 수정하고 로그인과 결제를 확인합니다. `@shard-lab/nc-waas-react`는 Privy React SDK와 같은 이름, 같은 모양의 API이고, 서버와 wagmi도 같은 이름으로 있습니다. Privy 지갑 키는 옮기지 않습니다. 이용자는 같은 이메일로 로그인해서 새 Pouchi 지갑을 받습니다.

## 패키지 import

API 이름이 같아서 앱 코드의 import는 패키지 이름만 바뀝니다. codemod도 이 변경을 합니다.

```diff lang="tsx"
- import { PrivyProvider, usePrivy } from "@privy-io/react-auth";
+ import { PrivyProvider, usePrivy } from "@shard-lab/nc-waas-react";
```

Provider에는 `apiUrl`과 앱의 체인을 더하고, `appId`에 Pouchi 앱 ID를 넣습니다. [Provider 설정](#provider)

## 이전 순서

배포할 코드에 codemod를 적용하기 전에 옛 Privy 지갑 provider를 열 수 있는 이전용 빌드를 보존합니다. 이용자가 자산을 옮길 때는 그 provider로 서명해야 합니다. 이전 기간이 끝날 때까지 유지하세요. import를 바꾸는 것만으로 자산이 이동하지는 않습니다.

1. **codemod로 코드를 옮깁니다.** 먼저 dry run으로 바뀔 내용과 보고서를 보고, `--write`로 적용합니다.

```sh
# nc-waas 저장소 루트에서
node packages/pouchi-migrate/bin/pouchi-migrate.mjs /path/to/my-app --diff     # 아무것도 쓰지 않음
node packages/pouchi-migrate/bin/pouchi-migrate.mjs /path/to/my-app --write
```

codemod 패키지(`@shard-lab/pouchi-migrate`)는 배포 준비 중입니다. 지금은 nc-waas 저장소의 `packages/pouchi-migrate`에서 실행합니다. 저장소와 패키지 접근 권한이 없으면 [business@pouchi.app](mailto:business@pouchi.app)으로 요청하세요.

2. **앱을 설정합니다.** 앱 주소와 Privy에서 쓰던 로그인 수단을 Pouchi 앱 설정에 맞춥니다. [앱 설정](#tenant)

3. **env 값을 넣고 빌드합니다.** `NEXT_PUBLIC_POUCHI_TENANT_ID`, `NEXT_PUBLIC_POUCHI_API_URL` (Vite는 `VITE_`).

4. **보고서의 항목을 처리합니다.** 지원하지 않는 API는 파일:줄과 대안이 보고서에 있습니다. [지원 범위](#unsupported)

5. **이용자에게 안내합니다.** 같은 이메일로 로그인하면 새 지갑이 생기고, 옛 지갑의 자산은 이용자가 직접 옮깁니다. [기존 이용자](#users)

## codemod 변경 범위

| 대상 | 변경 |
| --- | --- |
| import | `@privy-io/react-auth` (`/solana`, `/smart-wallets`, `/extended-chains`, `/cards`, `/farcaster` 포함), `@privy-io/wagmi`, `@privy-io/server-auth`, `@privy-io/node`을 `@shard-lab/nc-waas-react`의 같은 하위 경로로. `require()`도 바꿈 |
| `PrivyProvider` | `apiUrl`과 `config.defaultChain`(앱의 체인, `marooTestnet`)을 더함. Pouchi에 없는 로그인 수단은 `loginMethods`에서 뺌 |
| env | `NEXT_PUBLIC_PRIVY_APP_ID`를 `NEXT_PUBLIC_POUCHI_TENANT_ID`로, `PRIVY_APP_ID`를 `POUCHI_TENANT_ID`로, `PRIVY_APP_SECRET`을 `POUCHI_TENANT_CREDENTIAL`로. 코드와 `.env*` 파일 모두 |
| `package.json` | Privy 패키지를 `@shard-lab/nc-waas-react` 하나로 |
| 개발용 프록시 | `--dev-proxy <API 주소>`를 주면 Next.js 앱의 `/v1`을 Pouchi API로 넘김 (로컬 개발 전용) |

보고서는 앱이 쓰는 Privy API마다 상태를 보여 줍니다. `ok`는 같은 동작, `different`는 동작하지만 차이가 있음, `refused`는 같은 이름으로 있어 컴파일되고 호출하면 EIP-1193 `4200`과 문서 링크로 거절, `missing`은 Pouchi에 없어 코드를 고쳐야 함입니다. `missing`이 있으면 종료 코드가 2입니다.

```text
REFUSED src/components/sections/fund-wallet.tsx:5:3  useFundWallet: compiles, rejects with 4200 when called. Instead: send funds to the wallet address (testnets: the faucet)  [/docs/privy-migration/#funding]
Compatibility score: 40%  Every import resolves.
```

## Provider 설정

```diff lang="tsx"
- import { PrivyProvider } from "@privy-io/react-auth";
+ import { PrivyProvider, marooTestnet } from "@shard-lab/nc-waas-react";

  <PrivyProvider
-   appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID!}
+   apiUrl={process.env.NEXT_PUBLIC_POUCHI_API_URL!}
+   appId={process.env.NEXT_PUBLIC_POUCHI_TENANT_ID!}
    config={{
+     defaultChain: marooTestnet,
      embeddedWallets: { ethereum: { createOnLogin: "users-without-wallets" } },
```

`appId`는 Pouchi 앱 ID입니다. 지갑은 앱의 체인 하나에만 있고, `supportedChains`의 다른 체인은 무시됩니다. `externalWallets`, `mfa`, `solana`, `fundingMethodConfig` 같은 Privy 설정은 받기만 하고 무시하며, codemod 보고서에 표시됩니다.

## 로그인 수단

| Privy | Pouchi |
| --- | --- |
| 이메일 (`useLoginWithEmail`, 모달) | 같음. 헤드리스 `sendCode`는 Pouchi 시트를 열고, 새 이용자는 그 시트에서 지갑 보호(PIN 또는 패스키)를 마침 |
| Google, Apple (`useLoginWithOAuth`) | 같음. 앱 설정에서 켜고 redirect URI를 등록해야 함. Kakao, Naver도 있음 |
| 패스키 (`useLoginWithPasskey`, `linkPasskey`) | 같음. 패스키만으로 가입(`useSignupWithPasskey`)은 거절: 이메일이나 소셜로 가입한 뒤 패스키를 더함 |
| SMS, 외부 지갑(SIWE, SIWS), Twitter, Discord, GitHub, Telegram, Farcaster, 게스트 | 없음. 같은 이름의 훅은 있고 호출하면 `4200`. 이 이용자들은 이메일이나 지원하는 소셜 계정으로 로그인 |
| `useOAuthTokens` | 콜백이 호출되지 않음. 마운트할 때 콘솔에 경고 |

## wagmi

`@privy-io/wagmi`의 `createConfig`, `WagmiProvider`, `useSetActiveWallet`이 같은 이름으로 `@shard-lab/nc-waas-react/wagmi`에 있습니다. `createConfig`는 임베디드 지갑 커넥터와 앱의 체인(첫 번째)을 더하고, `WagmiProvider`는 로그인하면 wagmi를 지갑에 연결하고 로그아웃하면 끊습니다. 그래서 `useAccount`, `useSignMessage`, `useSignTypedData`, `useSendTransaction` 같은 wagmi 훅이 그대로 Pouchi 지갑에서 동작합니다. `useSetActiveWallet`은 임베디드 지갑 하나만 고를 수 있습니다.

## 서버

```diff lang="ts"
- import { PrivyClient } from "@privy-io/server-auth";
+ import { PrivyClient } from "@shard-lab/nc-waas-react/server";

  const privy = new PrivyClient(process.env.POUCHI_TENANT_ID!, process.env.POUCHI_TENANT_CREDENTIAL);
  const claims = await privy.verifyAuthToken(accessToken);   // claims.userId, claims.walletAddress
```

| Privy | Pouchi |
| --- | --- |
| `verifyAuthToken`, `utils().auth().verifyAuthToken` | 같음. JWKS로 오프라인 검증, 비밀값 필요 없음. API 주소는 `POUCHI_API_URL` |
| `getUser(id)`, `getUser({ idToken })`, `users().get` | 지갑 주소와 ID를 돌려줌. 이메일은 없음(이메일이 필요하면 아래 조회). `idToken` 자리에는 access token |
| `getUserByEmail`, `getUserByWalletAddress` | 같은 이름으로 동작. 이 앱의 이용자만 찾고, 없으면 `null`. 이메일은 이메일 로그인과 비교(대소문자와 앞뒤 공백 무시). 소셜 계정의 이메일로는 찾지 않음. 이용자 ID, 이메일, 지갑 주소, 상태(`ACTIVE_UNPROTECTED` 포함), 가입 시각을 돌려줌 |
| `users().getByEmailAddress({ address })`, `users().getByWalletAddress({ address })` | 위와 같음. 없으면 Privy처럼 404 오류 |
| `getUserByPhoneNumber`, `getUserByCustomAuthId`, `getUsers`, `users().list` | 거절. 이 정보와 `user.id`의 연결은 앱 DB에 둠 |
| `importUser`, `users().create`, `deleteUser` | 거절. 이용자는 앱에서 가입하고 새 지갑을 받음 |

`appSecret` 자리에는 앱의 Client Credential을 `<credentialId>:<clientSecret>` 형태로 넣습니다(`wallets:read`). `getUser`와 이용자 조회에 필요합니다. 조회는 Credential마다 분당 횟수 제한이 있고(기본 120회, 넘으면 `429`), 모두 감사 로그에 남습니다.

### 웹훅

`verifyWebhook(payload, headers, secret)`과 `webhooks().verify(...)`는 Pouchi 웹훅(`x-waas-signature: sha256=<hex>`, `x-waas-event-id`)을 검증하고 이벤트를 돌려줍니다. Pouchi 이벤트 종류는 Privy와 다릅니다. Privy(Svix) 헤더만 있는 요청은 거절합니다.

### 서버 지갑

`walletApi`, `wallets()`, `policies()`, `keyQuorums()`, `useSigners`, `useAuthorizationSignature`는 모두 거절합니다. Pouchi는 서버에서 이용자 대신 서명하지 않습니다. 앱 안의 반복 승인은 [`useSessionApproval`](/docs/delegation/#앱-안-세션-키), 서버가 실행하는 결제는 [앱 서버가 실행하는 결제](/docs/delegation/#앱-서버-결제-권한)를 씁니다. 두 방식 모두 한도를 지갑 컨트랙트가 강제합니다.

## 지원 범위

| Privy API | 상태 | 대안 |
| --- | --- | --- |
| `usePrivy`, `useLogin`, `useLogout`, `useUser`, `useToken`, `getAccessToken`, `useModalStatus` | 지원 | `user.id`는 `did:nc-waas:<tenant>:<walletId>` |
| `useWallets`, `useCreateWallet` | 지원 | 현재 앱에서 이용자당 EVM 스마트 지갑 1개. `createAdditional`은 거절 |
| `useSendTransaction`, `useSendCalls`, `useSmartWallets`, `SmartWalletsProvider` | 지원 | ERC-4337. 가스비는 앱이 부담하며 이용자 지갑에서는 차감하지 않음 |
| `useSignMessage`, `useSignTypedData`, `toViemAccount` | 지원 | ERC-1271 (배포 전 지갑은 ERC-6492). 타입 데이터의 `chainId`는 앱의 체인 |
| `useLinkAccount`, `useLinkWithPasskey` | 지원 | 이메일, Google, Apple, Kakao, Naver, 패스키. 나머지는 `onError`로 거절 |
| `usePrivy().exportWallet` | 다르게 동작 | 키가 나뉘어 있어 내보내지 않음. 계정 복구 수단 안내 |
| `useSessionSigners`, `useSigners`, `useAuthorizationSignature` | 거절 (`NOT_SUPPORTED`) | 앱 안 반복 결제는 `useSessionApproval`, 서버 실행은 승인된 위임 결제 |
| `useIdentityToken` | 다르게 동작 | `identityToken`은 null. access token이 이용자를 증명 |
| `useSignTransaction`, `eth_sign` | 거절 | 스마트 지갑은 서명된 원시 트랜잭션이 없음. `sendTransaction` |
| `useFundWallet`, `useAddFunds`, `useFiatOnramp`, `useDepositAddress`, `/cards` | 거절 | 지갑 주소로 직접 입금 (테스트넷은 faucet) |
| `useImportWallet`, `setWalletPassword` | 거절 | 개인키를 받지 않음. 키는 처음부터 나뉘어 생성 |
| `useMfaEnrollment`, `useMfa` | 거절 | 승인에는 사용자 인증(패스키, PIN 등)을 사용 |
| `useCrossAppAccounts`, `@privy-io/cross-app-*` | 거절, 없음 | 앱마다 Pouchi로 로그인 |
| `/solana`, `/extended-chains`, `useLoginWithSiws` | 거절 | EVM 전용. 지갑 목록은 비어 있음 |
| `@privy-io/expo`, `@privy-io/js-sdk-core` | 없음 | React Native SDK는 아직 없음. 프레임워크 없이는 `@shard-lab/nc-waas-react/core` |

거절은 조용히 넘어가지 않습니다. 같은 이름과 타입이 있어 코드는 컴파일되고, 호출하면 `NcWaasError` (`code: "NOT_SUPPORTED"`, EIP-1193 `4200`)가 이유와 이 페이지의 링크를 담아 실패합니다.

## 앱 설정

```sh
node packages/pouchi-migrate/bin/pouchi-migrate.mjs tenant /path/to/my-app --tenant <앱 ID> --api-url <Pouchi API> --origin https://app.example.com
```

읽기만 합니다. 앱의 `loginMethods`를 Pouchi 로그인 수단에 맞춰 보여 주고, 앱 주소가 이미 허용됐는지(API의 CORS 응답) 확인하고, env 값과 할 일을 출력합니다. 적용은 Pouchi 콘솔의 설정 화면이나 개발자 MCP의 `set_app_origins`, `set_login_methods`로 합니다. [AI 개발 도구 연동](/docs/ai/)

| 할 일 | 어디서 |
| --- | --- |
| 앱 주소 등록 (CORS, 패스키) | 콘솔 설정 또는 `set_app_origins` |
| 이메일 로그인, Google, Apple 켜기 | 콘솔 설정 또는 `set_login_methods`. 소셜 로그인은 운영자가 먼저 제공자를 설정 |
| 가스 대납 한도 | 콘솔 또는 `set_sponsorship` |
| 서버의 `getUser`용 Client Credential (`wallets:read`) | 콘솔 |

## 기존 이용자

Privy 지갑 키는 옮기지 않습니다. Pouchi 키는 기기와 Pouchi가 함께 새로 만드는 분산 키라서 외부 개인키를 가져오지 않습니다. **지갑 주소가 바뀝니다.**

1. **같은 이메일로 로그인합니다.** 이용자는 Privy에서 쓰던 이메일(또는 Google, Apple)로 로그인하고, 첫 로그인 때 새 Pouchi 지갑을 받습니다. SMS나 외부 지갑으로만 로그인하던 이용자는 이메일을 먼저 등록하게 안내합니다.

2. **필요하면 두 계정을 연결합니다.** 같은 요청에 Privy 토큰과 Pouchi 토큰을 함께 보내고 서버에서 둘 다 검증한 뒤 연결합니다. 이메일이 같다는 이유만으로 연결하지 않습니다.

```ts
import { createNcWaasServerClient, linkPrivyUser } from "@shard-lab/nc-waas-react/server";

const privyClaims = await privyClient.verifyAuthToken(privyToken);     // Privy 서버 SDK (이전 기간 동안만)
const ncWaasClaims = await pouchi.verifyAuthToken(pouchiToken);
await db.userLinks.insert(linkPrivyUser({ privyClaims, ncWaasClaims, oldAddress }));
```

3. **자산은 이용자가 옮깁니다(선택).** 옛 Privy 지갑에서 새 Pouchi 주소로 보내는 보통의 전송이고, 이용자가 아직 Privy를 쓰는 앱 화면에서 직접 서명합니다. `AssetMigrationCard`가 토큰을 먼저, 네이티브 코인은 가스 여유분을 남기고 마지막에 보냅니다. 같은 체인에서 보내는 전송이며 브리지가 아닙니다. 현재 절차는 Maroo Testnet(450815)의 테스트 자산만 대상으로 합니다. 보내기 전에 두 지갑과 자산이 지원 체인에 있는지 확인하세요. 다른 체인에서 같은 주소로 보내도 Pouchi에서 쓸 수 있게 되지는 않습니다. 옛 Privy 지갑의 전송 가스비는 그 지갑에서 준비해야 합니다.

```tsx
import { AssetMigrationCard } from "@shard-lab/nc-waas-react";

const oldProvider = await privyWallet.getEthereumProvider();
<AssetMigrationCard oldProvider={oldProvider} tokens={[{ address: TOKEN, symbol: "tKRW", decimals: 18 }]} />
```

4. **주소에 묶인 데이터를 갱신합니다.** 앱 DB와 허용 목록이 새 주소를 가리키도록 갱신합니다. NFT 소유권은 지원 체인에서 별도로 전송해야 하며 DB 주소를 바꿔도 이동하지 않습니다. DeFi 포지션, 토큰 사용 승인과 ENS 이름은 자동으로 따라오지 않습니다.

5. **이전 기간이 끝나면 Privy SDK를 지웁니다.** 옮기지 않은 이용자에게는 Privy의 지갑 내보내기 안내를 남깁니다.

## 이전 후 확인

codemod를 적용하고 앱을 실행한 뒤 아래 순서로 확인합니다.

1. **로그인 버튼을 누릅니다.** Privy 모달 대신 Pouchi 로그인 시트가 열립니다.

2. **같은 이메일로 로그인합니다.** 처음이면 지갑 보호(PIN이나 패스키)를 설정하고 새 지갑 주소가 생깁니다.

3. **송금이나 서명을 한 번 실행합니다.** Pouchi 승인 화면이 열리고, 승인하면 기존 코드가 받던 값(`hash`, 서명)이 그대로 돌아옵니다.

## 자주 겪는 오류

| 증상 | 원인 | 해결 |
| --- | --- | --- |
| codemod가 종료 코드 2로 끝남 | 보고서에 `missing`(Pouchi에 없는 API)이 있어 타입 검사가 통과하지 않음 | 보고서의 파일:줄과 대안대로 코드를 고침. [지원 범위](#unsupported) |
| 호출하면 `NOT_SUPPORTED` (`rpcCode` 4200) | `useFundWallet`처럼 거절하는 API를 호출함 | 오류 메시지의 링크와 [지원 범위](#unsupported)의 대안을 씀 |
| `INVALID_PARAMS`: `NcWaasProvider needs chain (or config.defaultChain)` | 손으로 옮기면서 체인을 빠뜨림 | `config.defaultChain: marooTestnet`을 더함 |
| 브라우저 콘솔에 API 요청의 CORS 오류 | 앱 주소가 Pouchi 앱 설정의 허용 출처에 없음 | `pouchi-migrate tenant`로 허용 여부를 보고 콘솔이나 `set_app_origins`로 등록 |
| 서버의 `getUser`가 `NOT_SUPPORTED`: `this call needs a tenant Client Credential` | `appSecret` 자리에 Client Credential이 없음 | `POUCHI_TENANT_CREDENTIAL`에 `<credentialId>:<clientSecret>`을 넣음 (`wallets:read`) |
| 기존 이용자의 지갑 주소가 다름 | 정상. Privy 키는 옮기지 않아 새 지갑이 생김 | [기존 이용자](#users) 순서대로 계정 연결과 자산 이동을 안내 |

## 공식 예제 호환 점수

[privy-io/examples](https://github.com/privy-io/examples) 커밋 `95a0f6e`의 예제 전체에 같은 이전을 해 본 결과입니다. "기존 SDK"는 import 교체와 Provider 설정만 한 코드를 이번 작업 전 SDK로 타입 검사한 결과, "codemod 후"는 `pouchi-migrate --write` 결과를 지금 SDK로 타입 검사한 결과입니다(원본에 이미 있던 오류는 뺌). 점수는 예제가 쓰는 Privy API마다 같은 동작 1, 다르게 동작 0.75, 거절이나 없음 0으로 매긴 평균입니다. Privy 기능을 모두 보여 주는 스타터는 Solana, 충전, MFA 같은 화면이 많아 점수가 낮고, 실제 앱에 가까운 예제가 높습니다.

| 예제 | Privy 패키지 | 기존 SDK | codemod 후 | 빌드 | 실행 | 점수 | 남는 차이 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| privy-next-cards | react-auth | 실패 (오류 6) | 통과 | n/a | n/a | 89% | 카드 |
| privy-next-permissionless | react-auth | 실패 (오류 2) | 통과 | n/a | n/a | 88% | 없음 |
| privy-next-fiat-orchestration | node, react-auth | 실패 (오류 2) | 통과 | n/a | n/a | 84% | 서버 서명자 |
| privy-react-pwa | react-auth | 실패 (오류 3) | 통과 | n/a | n/a | 83% | 없음 |
| privy-next-fiat-onramp | react-auth, server-auth | 실패 (오류 1) | 통과 | 성공 | n/a | 81% | 이용자 삭제, Solana |
| privy-next-yield-demo | react-auth, server-auth | 실패 (오류 9) | 통과 | n/a | n/a | 77% | 서버 서명자, 일부 로그인 수단 |
| privy-next-tempo | node, react-auth | 실패 (오류 3) | 통과 | n/a | n/a | 67% | 전화번호로 이용자 조회, 이용자 생성, 일부 로그인 수단 |
| privy-react-whitelabel-starter | react-auth | 실패 (오류 46) | 통과 | 성공 | 라이브 | 56% | Solana, 일부 로그인 수단 |
| privy-next-cross-app-connect | cross-app-connect, react-auth | 통과 | 통과 (Privy 패키지 남음) | n/a | n/a | 50% | cross-app-connect (Privy 전용) |
| privy-next-solana | react-auth | 실패 (오류 2) | 통과 | n/a | n/a | 42% | Solana, 원시 트랜잭션 서명, 충전, 크로스 앱 계정 |
| privy-next-cross-app-provider | cross-app-provider, react-auth | 실패 (오류 2) | 통과 (Privy 패키지 남음) | n/a | n/a | 41% | cross-app-provider (Privy 전용), 서버 서명자, Solana, 충전 |
| privy-next-smart-wallets | react-auth | 실패 (오류 2) | 통과 | n/a | n/a | 41% | 서버 서명자, Solana, 원시 트랜잭션 서명, 충전 |
| privy-next-wagmi | react-auth, wagmi | 실패 (오류 7) | 통과 | 성공 | 라이브, 영상 | 40% | 서버 서명자, Solana, 원시 트랜잭션 서명, 충전 |
| privy-next-starter | react-auth | 통과 | 통과 | 성공 | n/a | 39% | 서버 서명자, Solana, 원시 트랜잭션 서명, 충전 |
| privy-react-starter | react-auth | 통과 | 통과 | 성공 | n/a | 39% | 서버 서명자, Solana, 원시 트랜잭션 서명, 충전 |
| privy-react-chrome-extension | react-auth | 통과 | 통과 | n/a | n/a | 39% | 서버 서명자, Solana, 원시 트랜잭션 서명, 충전 |
| privy-next-farcaster | react-auth | 실패 (오류 6) | 통과 | n/a | n/a | 39% | Farcaster, 서버 서명자, Solana, 충전 |
| privy-next-session-keys | react-auth | 실패 (오류 1) | 통과 | n/a | n/a | 39% | 서버 서명자, Solana, 원시 트랜잭션 서명, 충전 |
| privy-next-farcaster-mini-app | react-auth | 실패 (오류 1) | 통과 | n/a | n/a | 38% | Farcaster, 서버 서명자, Solana, 충전 |
| privy-next-funding | react-auth | 실패 (오류 4) | 통과 | n/a | n/a | 37% | 충전, 서버 서명자, Solana |
| privy-node-telegram-trading-bot | server-auth | 통과 | 통과 | n/a | n/a | 19% | 서버 지갑 |
| privy-node-starter | node | 실패 (오류 1) | 통과 | n/a | n/a | 13% | 서버 지갑 |
| privy-next-mpp-agent-demo | node | 실패 (오류 1) | 통과 | n/a | n/a | 11% | 서버 지갑 |
| privy-next-x402-agent-demo | node | 실패 (오류 1) | 실패 (오류 1) | n/a | n/a | 9% | node/x402 (Privy 전용), 서버 지갑 |
| privy-vanilla-starter | js-sdk-core | 통과 | 통과 (Privy 패키지 남음) | n/a | n/a | 0% | js-sdk-core (Privy 전용) |
| privy-expo-starter, privy-expo-bare-starter | expo | 대상 아님 | 대상 아님 | n/a | n/a | n/a | React Native |
| privy-flutter-starter, privy-swift-auth0 | 네이티브 | 대상 아님 | 대상 아님 | n/a | n/a | n/a | 웹 SDK 대상이 아님 |

웹과 서버 예제 25개 중 24개가 codemod 후 타입 검사를 통과합니다(기존 SDK로는 19개 실패). 그중 21개는 Privy 패키지가 하나도 남지 않습니다. 빌드는 다섯 개(`privy-next-starter`, `privy-next-wagmi`, `privy-react-starter`, `privy-react-whitelabel-starter`, `privy-next-fiat-onramp`) 모두 성공했고, wagmi와 whitelabel 예제는 로컬 Pouchi API와 Maroo Testnet에서 로그인, 서명, 송금까지 실제로 실행했습니다.

## 다음 단계

- [빠른 시작](/docs/quickstart/): 송금, 서버 검증, wagmi 연결
- [위임 결제](/docs/delegation/): Privy 서버 지갑 대신 쓰는 한도 승인
- [React SDK 레퍼런스](/docs/reference/react/): 주요 공개 API와 지원 상태
- [AI 개발 도구 연동](/docs/ai/): 코딩 에이전트에 이전 작업 맡기기
