Skip to content

apps-in-toss-community/sdk-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

160 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sdk-example

한국어 · English

@apps-in-toss/web-framework SDK의 모든 public API를 인터랙티브하게 테스트할 수 있는 레퍼런스 앱.

  • 앱인토스에 배포된 실제 앱으로 네이티브 환경에서 API 동작을 직접 확인할 수 있다.
  • 일반 웹 브라우저에서도 @ait-co/devtools의 mock 레이어로 토스 앱 없이 개발/테스트할 수 있다.
  • 앱 코드 자체가 SDK 사용 예제로 동작한다.

지원 SDK 도메인 (18개)

경로 도메인 설명 API 수
/auth Auth appLogin, getAnonymousKey 등 5
/navigation Navigation closeView, openURL, share 등 10
/environment Environment getPlatformOS, getNetworkStatus 등 14
/permissions Permissions getPermission, openPermissionDialog 등 3
/storage Storage setItem, getItem, removeItem, saveBase64Data 등 5
/location Location getCurrentLocation, startUpdateLocation 2
/camera Camera & Photos openCamera, fetchAlbumPhotos, fetchAlbumItems 3
/contacts Contacts fetchContacts 1
/clipboard Clipboard getClipboardText, setClipboardText 2
/haptic Haptic generateHapticFeedback 1
/iap IAP 상품 조회, 구매, 주문 관리 8
/ads Ads GoogleAdMob, TossAds, FullScreenAd 10
/game Game 게임센터, 프로모션, contactsViral 6
/analytics Analytics screen, impression, click, eventLog 4
/partner Partner addAccessoryButton, removeAccessoryButton 2
/events Events graniteEvent, tdsEvent, onVisibilityChangedByTransparentServiceWeb, appsInTossEvent 4
/payment Payment 토스페이 정기결제창 — wrappedToken으로 사용자 인증 (실제 결제는 서버) 1
/notification Notification 푸시 알림 동의 — newAgreement/alreadyAgreed/agreementRejected 3-way 결과 1

기술 스택

  • React 19 + TypeScript (strict)
  • Vite 6 + Tailwind CSS v4
  • react-router-dom v7
  • @apps-in-toss/web-framework (dev 환경에서 @ait-co/devtools mock으로 swap)

시작하기

pnpm install
pnpm dev        # Vite dev 서버 → http://localhost:5173
pnpm dev:phone  # = AIT_TUNNEL=1 pnpm dev — Cloudflare quick tunnel + ASCII QR

pnpm dev:phone은 dev 서버를 Cloudflare quick tunnel(*.trycloudflare.com)로 노출하고 QR을 출력한다. 폰에서 https://devtools.aitc.dev/launcher/를 한 번 열어 홈 화면에 추가한 뒤 QR을 스캔하면 미니앱을 풀스크린으로 확인할 수 있다. cloudflared는 첫 실행 시 한 번 다운로드되어 캐시된다.

개발 중에는 @ait-co/devtools의 unplugin이 @apps-in-toss/web-framework import를 mock으로 자동 대체해준다. 토스 앱 없이 브라우저에서 바로 확인 가능하다.

명령어

명령 설명
pnpm dev Vite dev 서버 기동
pnpm dev:phone AIT_TUNNEL=1 pnpm dev — Cloudflare quick tunnel로 dev 서버 노출 + QR 출력 (폰 실기 확인용)
pnpm build OG 이미지 생성(prebuild) + 타입 체크 + 프로덕션 빌드 + 라우트별 HTML 생성 → dist/
pnpm build:og OG 이미지(public/og/*.png)만 재생성
pnpm preview 빌드 결과 로컬 서빙
pnpm typecheck tsc --noEmit (SDK export 커버리지 검증 포함)
pnpm lint biome check .
pnpm lint:fix biome check --write .
pnpm format biome format --write .
pnpm test Vitest 컴포넌트 smoke 테스트 (jsdom)
pnpm test:watch Vitest watch 모드
pnpm test:e2e Playwright e2e (실제 브라우저, 별도 dev 서버 자동 기동)
pnpm scaffold:domain <name> 새 SDK 도메인 페이지 boilerplate 생성 (page + route + 카탈로그 entry)

새 도메인 추가

새 SDK 도메인을 dog-food하려면:

pnpm scaffold:domain analytics --label "Analytics" --description "사용자 이벤트 추적"
# → src/pages/AnalyticsPage.tsx 생성
# → src/App.tsx에 라우트 추가
# → src/pages/HomePage.tsx의 domains 카탈로그에 entry 추가

옵션: --label "Display", --group <core|permissions|commerce|telemetry|misc> (현재 HomePage entry 스키마에는 저장되지 않고 의도 메모용 — runtime 효과 없음), --description "...", --dry-run (변경 없이 plan만 출력). 같은 name으로 재실행하면 no-op이다.

생성 후 <Name>Page.tsx에 실제 ApiCard를 추가하고 HomePage.tsx entry의 apis: [] 배열에 검색 키워드를 채우면 된다.

OIDC bridge 데모

AuthPage의 "OIDC bridge demo" 섹션은 oidc-bridge의 커뮤니티 공용 인스턴스(https://oidc-bridge.aitc.dev)를 호출한다. 별도 환경 변수나 설정 없이 바로 동작.

self-host 인스턴스를 가리키게 하려면 src/components/OidcBridgeSection.tsxOIDC_BRIDGE_BASE_URL 상수를 수정한다.

배포

v* 형식의 git tag를 push하면 .github/workflows/deploy-ait.yml이 자동으로:

  1. .ait 번들을 빌드 (pnpm bundle:ait = tsc -b && vite build && ait build)
  2. aitcc app deployaitc-sdk-example(miniAppId 31146, workspace 3095)에 업로드 — Deploy Key는 GitHub secret AITCC_API_KEY로 주입
  3. 반환된 intoss-private:// URL을 QR PNG로 렌더
  4. URL · QR · .ait 번들을 GitHub Release에 첨부
git tag v0.1.5
git push origin v0.1.5

수동 트리거가 필요하면 Actions 탭에서 "Deploy .ait bundle" workflow를 workflow_dispatch로 실행하면서 기존 tag를 입력한다.

미니앱의 serviceStatus가 출시 review를 통과해 OPENED 등으로 전환되면, 토스 앱이 설치된 폰에서 Release 페이지의 intoss-private:// URL을 직접 열거나 QR을 카메라로 스캔하면 미니앱이 풀스크린으로 뜬다. 아직 PREPARE(review 통과 전)인 동안은 그 URL을 열어도 토스 앱이 번들을 로드하지 않으므로, _deploymentId + debug=1 + relay=<wss> 쿼리를 포함한 deep-link를 QR로 렌더해 폰 카메라로 스캔하면 PREPARE 상태에서도 cold-load된다.

Deploy Key는 앱인토스 콘솔의 "API 키" 기능으로 발급한다 (이 프로젝트에서는 노출 문구를 Deploy Key로 통일하지만, 콘솔 UI와 CLI flag(--api-key)는 그대로 유지). 만료 시 새 키를 발급해 secret 값만 교체하면 된다.

디버그 모드

폰에서 도는 번들에 AI 에이전트가 devtools-mcp로 read-only attach해, 사람이 화면을 지켜보지 않고도 회귀를 진단할 수 있다.

main.tsx에 있는 import '@ait-co/devtools/in-app/auto'; 한 줄이 CDP relay attach와 window.__sdk/__sdkCall SDK 브리지를 모두 담당한다. ?debug=1/?relay= URL 파라미터가 있거나 DEV 빌드에서만 활성화되고, 그 외 일반 production load에서는 dormant다.

  1. 에이전트의 devtools-mcp 기동 — AI host(~/.mcp.json)에 등록된 devtools-mcp가 Chii 서버 + Cloudflare quick tunnel을 띄우고 wss:// relay URL과 secret token을 출력한다.

  2. QR/deep-link로 진입_deploymentId + debug=1 + relay=<wss> + token=<secret>을 포함한 deep-link를 QR로 렌더해 폰 카메라로 스캔한다. 이 경로 하나로 PREPARE 상태의 번들도 cold-load + relay attach된다.

    intoss-private://aitc-sdk-example?_deploymentId=<id>&debug=1&relay=wss://<id>.trycloudflare.com&token=<secret>
    
  3. 에이전트 관측devtools-mcp 도구(list_pages, list_console_messages, call_sdk 등)로 미니앱 상태를 조회하고 SDK API를 구동한다.

token이 없으면 quick tunnel URL이 노출돼도 attach가 거부된다. relay는 stateless이고 서버 영구 저장이 없다.

Pre-commit hook

선택 사항이지만 권장. clone 후 다음 한 줄로 표준 pre-commit hook(스테이지된 파일에 biome check 실행)을 활성화한다:

git config core.hooksPath .githooks

push 전에 빠른 피드백을 주기 위한 개발자 편의 장치다. 실제 강제 계층은 CI(pnpm lint)이므로, hook을 활성화하지 않은 contributor도 PR 단계에서 lint 실패로 막힌다.

프로젝트 구조

src/
├── main.tsx               # 엔트리포인트 (@ait-co/polyfill/auto + @ait-co/devtools/in-app/auto)
├── App.tsx                # React Router 설정
├── __typecheck.ts         # SDK export 커버리지 컴파일 타임 검증
├── components/            # 공유 컴포넌트 (Layout, PageHeader, ApiCard, ...)
└── pages/                 # 18개 도메인 페이지

자세한 내부 구조와 개발 가이드는 CLAUDE.md 참고.

주요 컴포넌트

ApiCard<Params>

각 API 함수를 하나의 인터랙티브 카드로 표시. 제네릭 variadic tuple 타입으로 params 정의에서 execute 콜백의 파라미터 타입을 자동 추론한다.

<ApiCard
  name="Storage.setItem"
  description="값 저장"
  params={[
    { name: 'key', label: 'Key' },
    { name: 'value', label: 'Value' },
  ]}
  execute={async ({ key, value }) => {
    await Storage.setItem(key, value);
  }}
/>

PolyfillToggleCard

@ait-co/polyfill이 노출하는 표준 Web API와 SDK 호출을 한 카드 안에서 토글로 비교 실행할 때 사용. 같은 동작을 두 경로로 번갈아 호출하며 결과를 옆에 두고 비교할 수 있다 (SDK ↔ Polyfill 결과는 모드별로 보존). 카드를 두 개로 나란히 두는 paired-card 패턴(Location, Navigation, Environment)과 토글 패턴(Clipboard, Haptic)이 공존하며, 페이지 성격에 맞춰 둘 중 하나를 고른다.

WorkflowStepper

여러 API를 순서대로 호출하는 다단계 플로우를 스텝 UI로 표현. IAP의 "상품조회 → 구매 → 주문관리", Ads의 "load → show" 등에 사용.

OG 이미지

SPA 앱이지만 도메인 그룹 페이지(예: /iap, /permissions)를 SNS에 공유했을 때 그룹별 OG 이미지가 떨어지도록 정적 파이프라인을 둔다.

  • 소스: src/og/manifest.ts (라우트 ↔ OG 메타 single source of truth), src/og/template.tsx (satori JSX 템플릿).
  • 이미지 빌드: pnpm build:og 또는 pnpm build의 prebuild 단계에서 scripts/build-og-images.tsxpublic/og/<slug>.png 19장(home + 18 그룹)을 생성한다. PNG는 commit 대상.
  • 라우트별 HTML: pnpm build 마지막 단계의 scripts/build-route-html.tsdist/index.html을 읽어 dist/<slug>/index.html을 만들면서 og:title / og:description / og:image / twitter:* 메타와 <title>을 그룹별로 치환한다. 같은 JS bundle을 모든 HTML이 공유하므로 SPA는 정상 동작하고, 크롤러(JS 미실행)는 정적 메타만 본다.
  • 수정 흐름: 메타·문구를 바꾸려면 manifest.ts → 디자인을 바꾸려면 template.tsxpnpm buildpublic/og/의 PNG diff 리뷰. 새 도메인 그룹 추가 시 manifest.ts에 엔트리 한 줄만 추가하면 된다.

i18n

UI 카피의 primary locale은 ko (한국어). 모든 UI string은 src/i18n/ko.ts의 단일 record에서 lookup되며, 컴포넌트는 import { t } from '../i18n't('key') 또는 t('key', { name: value }) 로 호출한다.

  • 추가 의존성 없음 (react-i18next/FormatJS 등 미사용). 단순 record + {name} placeholder 치환.
  • en.ts는 현재 ko의 fallback re-export. 실제 영어 번역은 follow-up.
  • 컴포넌트 카피 추출은 공용 컴포넌트(ApiCard, HistoryLog, ResultView, PageHeader, ErrorBoundary, DemoBanner, PolyfillNotice, PolyfillToggleCard)와 HomePage까지 완료. 도메인 페이지(AuthPage, IAPPage 등)의 ApiCard description/label/placeholder props 추출은 follow-up.
  • HomePage.tsxdomains 배열의 name/descriptionscripts/sync-readme-domains.ts가 정규식으로 파싱하므로 string 리터럴을 유지한다 (i18n lookup 거치지 않음).
  • ApiCardname prop은 SDK 메서드명(예: appLogin)이고 crosslink/README 매칭의 기준이라 i18n 미경유.

SDK 업데이트 대응

  • 빌드 타임 검증: src/__typecheck.ts@apps-in-toss/web-framework의 모든 public export를 import한다. 새 export가 추가되었는데 파일에 누락되면 pnpm typecheck 실패.
  • CI 감지: .github/workflows/check-sdk-update.yml이 매주 월요일에 SDK/devtools 새 버전을 감지하고 typecheck 실패 시 이슈를 자동 생성한다.

관련 레포


커뮤니티 오픈소스 프로젝트입니다.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors