한국어 · English
@apps-in-toss/web-framework SDK의 모든 public API를 인터랙티브하게 테스트할 수 있는 레퍼런스 앱.
- 앱인토스에 배포된 실제 앱으로 네이티브 환경에서 API 동작을 직접 확인할 수 있다.
- 일반 웹 브라우저에서도
@ait-co/devtools의 mock 레이어로 토스 앱 없이 개발/테스트할 수 있다. - 앱 코드 자체가 SDK 사용 예제로 동작한다.
| 경로 | 도메인 | 설명 | 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/devtoolsmock으로 swap)
pnpm install
pnpm dev # Vite dev 서버 → http://localhost:5173
pnpm dev:phone # = AIT_TUNNEL=1 pnpm dev — Cloudflare quick tunnel + ASCII QRpnpm 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: [] 배열에 검색 키워드를 채우면 된다.
AuthPage의 "OIDC bridge demo" 섹션은 oidc-bridge의 커뮤니티 공용 인스턴스(https://oidc-bridge.aitc.dev)를 호출한다. 별도 환경 변수나 설정 없이 바로 동작.
self-host 인스턴스를 가리키게 하려면 src/components/OidcBridgeSection.tsx의 OIDC_BRIDGE_BASE_URL 상수를 수정한다.
v* 형식의 git tag를 push하면 .github/workflows/deploy-ait.yml이 자동으로:
.ait번들을 빌드 (pnpm bundle:ait=tsc -b && vite build && ait build)aitcc app deploy로aitc-sdk-example(miniAppId31146, workspace3095)에 업로드 — Deploy Key는 GitHub secretAITCC_API_KEY로 주입- 반환된
intoss-private://URL을 QR PNG로 렌더 - 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다.
-
에이전트의
devtools-mcp기동 — AI host(~/.mcp.json)에 등록된devtools-mcp가 Chii 서버 + Cloudflare quick tunnel을 띄우고wss://relay URL과 secret token을 출력한다. -
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> -
에이전트 관측 —
devtools-mcp도구(list_pages,list_console_messages,call_sdk등)로 미니앱 상태를 조회하고 SDK API를 구동한다.
token이 없으면 quick tunnel URL이 노출돼도 attach가 거부된다. relay는 stateless이고 서버 영구 저장이 없다.
선택 사항이지만 권장. clone 후 다음 한 줄로 표준 pre-commit hook(스테이지된 파일에 biome check 실행)을 활성화한다:
git config core.hooksPath .githookspush 전에 빠른 피드백을 주기 위한 개발자 편의 장치다. 실제 강제 계층은 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 참고.
각 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);
}}
/>@ait-co/polyfill이 노출하는 표준 Web API와 SDK 호출을 한 카드 안에서 토글로 비교 실행할 때 사용. 같은 동작을 두 경로로 번갈아 호출하며 결과를 옆에 두고 비교할 수 있다 (SDK ↔ Polyfill 결과는 모드별로 보존). 카드를 두 개로 나란히 두는 paired-card 패턴(Location, Navigation, Environment)과 토글 패턴(Clipboard, Haptic)이 공존하며, 페이지 성격에 맞춰 둘 중 하나를 고른다.
여러 API를 순서대로 호출하는 다단계 플로우를 스텝 UI로 표현. IAP의 "상품조회 → 구매 → 주문관리", Ads의 "load → show" 등에 사용.
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.tsx가public/og/<slug>.png19장(home + 18 그룹)을 생성한다. PNG는 commit 대상. - 라우트별 HTML:
pnpm build마지막 단계의scripts/build-route-html.ts가dist/index.html을 읽어dist/<slug>/index.html을 만들면서og:title/og:description/og:image/twitter:*메타와<title>을 그룹별로 치환한다. 같은 JS bundle을 모든 HTML이 공유하므로 SPA는 정상 동작하고, 크롤러(JS 미실행)는 정적 메타만 본다. - 수정 흐름: 메타·문구를 바꾸려면
manifest.ts→ 디자인을 바꾸려면template.tsx→pnpm build→public/og/의 PNG diff 리뷰. 새 도메인 그룹 추가 시manifest.ts에 엔트리 한 줄만 추가하면 된다.
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등)의 ApiCarddescription/label/placeholderprops 추출은 follow-up. HomePage.tsx의domains배열의name/description은scripts/sync-readme-domains.ts가 정규식으로 파싱하므로 string 리터럴을 유지한다 (i18n lookup 거치지 않음).ApiCard의nameprop은 SDK 메서드명(예:appLogin)이고 crosslink/README 매칭의 기준이라 i18n 미경유.
- 빌드 타임 검증:
src/__typecheck.ts가@apps-in-toss/web-framework의 모든 public export를 import한다. 새 export가 추가되었는데 파일에 누락되면pnpm typecheck실패. - CI 감지:
.github/workflows/check-sdk-update.yml이 매주 월요일에 SDK/devtools 새 버전을 감지하고 typecheck 실패 시 이슈를 자동 생성한다.
@apps-in-toss/web-framework— 원본 SDK@ait-co/devtools— mock 라이브러리, unplugin
커뮤니티 오픈소스 프로젝트입니다.