앱 매니페스트 레퍼런스
stripe-app.json 매니페스트 파일은 Stripe App의 중심 구성 파일입니다. 앱의 식별 정보, 권한, UI 뷰, 보안 정책, 설치 후 동작을 이 파일에서 선언합니다.
전체 매니페스트 예시
{ "id": "com.tajo.brevo-integration", "version": "1.2.0", "name": "Tajo for Brevo", "icon": "./assets/icon.png", "distribution_type": "public", "sandbox_install_compatible": true, "stripe_api_access_type": "oauth", "allowed_redirect_uris": [ "https://tajo.io/stripe/callback", "https://tajo.io/stripe/oauth/complete" ], "permissions": [ { "permission": "customer_read", "purpose": "Read customer profiles to sync with Brevo contacts" }, { "permission": "customer_write", "purpose": "Update customer metadata with Brevo sync status" }, { "permission": "charge_read", "purpose": "Access payment history for Brevo event tracking" }, { "permission": "product_read", "purpose": "Sync product catalog to Brevo for personalized campaigns" }, { "permission": "event_read", "purpose": "Subscribe to real-time events for Brevo automation triggers" }, { "permission": "invoice_read", "purpose": "Track invoice lifecycle events in Brevo" } ], "ui_extension": { "views": [ { "viewport": "stripe.dashboard.customer.detail", "component": "CustomerDetailView" }, { "viewport": "stripe.dashboard.customer.list", "component": "CustomerListView" }, { "viewport": "stripe.dashboard.home.overview", "component": "OverviewView" }, { "viewport": "stripe.dashboard.drawer.default", "component": "DrawerView" }, { "viewport": "stripe.dashboard.settings", "component": "SettingsView" }, { "viewport": "stripe.dashboard.onboarding", "component": "OnboardingView" } ], "content_security_policy": { "connect-src": [ "https://api.tajo.io", "https://api.brevo.com" ], "image-src": [ "https://cdn.tajo.io", "https://assets.brevo.com" ], "purpose": "Connect to Tajo API for data sync and Brevo API for contact management" } }, "post_install_action": { "type": "onboarding" }, "constants": { "API_BASE_URL": "https://api.tajo.io/v1", "SYNC_INTERVAL_SECONDS": "300" }}스키마 레퍼런스
최상위 필드
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
id | string | 예 | 역방향 도메인 표기법(슬러그 형식)으로 작성한 고유 앱 식별자 |
version | string | 예 | 시맨틱 버전 문자열(예: "1.2.0") |
name | string | 예 | 마켓플레이스에 표시되는 이름(최대 35자) |
icon | string | 예 | 앱 아이콘 파일의 상대 경로(300x300 PNG 또는 SVG) |
distribution_type | string | 예 | 마켓플레이스 배포는 "public", 내부 사용은 "private" |
sandbox_install_compatible | boolean | 아니요 | 샌드박스/테스트 모드에 앱을 설치할 수 있는지 여부 |
stripe_api_access_type | string | 아니요 | API 접근 방식: "oauth" 또는 "api_key" |
allowed_redirect_uris | string[] | 아니요 | 설치 플로에서 허용되는 OAuth 리디렉션 URI |
permissions | PermissionRequest[] | 예 | 권한 요청 배열 |
ui_extension | UIExtensionManifest | 아니요 | UI 확장 구성 |
post_install_action | PostInstallAction | 아니요 | 앱 설치 후 수행할 동작 |
constants | object | 아니요 | 런타임에 앱에서 접근할 수 있는 키-값 쌍 |
id
앱 식별자는 슬러그 형식의 문자열이며, 보통 역방향 도메인 표기법을 사용합니다.
"id": "com.tajo.brevo-integration"- 모든 Stripe Apps에서 전역적으로 고유해야 합니다
- 소문자, 숫자, 하이픈, 점만 사용합니다
- 앱을 생성한 뒤에는 변경할 수 없습니다
- 마켓플레이스에서 앱의 URL을 결정합니다
version
시맨틱 버저닝을 따릅니다.
"version": "1.2.0"- MAJOR: 호환성이 깨지는 변경 또는 대규모 기능 추가
- MINOR: 하위 호환되는 신규 기능
- PATCH: 버그 수정과 소규모 개선
- 업로드할 때마다 반드시 올려야 합니다
distribution_type
앱을 설치할 수 있는 대상을 제어합니다.
| 값 | 설명 |
|---|---|
"public" | Stripe App Marketplace에서 모든 사용자에게 공개됩니다 |
"private" | 본인의 Stripe 계정에서만 설치할 수 있습니다 |
stripe_api_access_type
앱이 Stripe API에 인증하는 방식을 결정합니다.
| 값 | 설명 |
|---|---|
"oauth" | 인증에 OAuth 2.0 플로를 사용합니다(공개 앱 권장) |
"api_key" | 제한된 API 키를 사용합니다(비공개 앱에 적합) |
PermissionRequest
각 권한 요청은 앱에 필요한 특정 Stripe API 권한을 선언합니다.
{ "permission": "customer_read", "purpose": "Read customer profiles to sync with Brevo contacts"}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
permission | string | 예 | 권한 식별자(권한 레퍼런스 참고) |
purpose | string | 예 | 이 권한이 필요한 이유에 대한 사람이 읽을 수 있는 설명 |
purpose 작성 지침:
- 판매자가 이해할 수 있도록 명확하고 구체적으로 설명합니다
- 권한이 무엇을 허용하는지가 아니라 무엇에 쓰이는지를 설명합니다
- 설명은 한 문장으로 간결하게 유지합니다
- 기술 전문 용어는 피합니다
UIExtensionManifest
앱의 UI 컴포넌트를 구성합니다.
{ "ui_extension": { "views": [...], "content_security_policy": {...} }}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
views | ViewManifest[] | 예 | 뷰 선언 배열 |
content_security_policy | CSPRequest | 아니요 | 외부 리소스에 대한 콘텐츠 보안 정책 |
ViewManifest
각 뷰는 React 컴포넌트를 Stripe 대시보드의 뷰포트에 매핑합니다.
{ "viewport": "stripe.dashboard.customer.detail", "component": "CustomerDetailView"}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
viewport | string | 예 | 이 뷰가 렌더링되는 대시보드 위치(뷰포트 레퍼런스 참고) |
component | string | 예 | 렌더링할 React 컴포넌트 이름(내보낸 컴포넌트 이름과 일치해야 함) |
하나의 앱에서 서로 다른 뷰포트에 여러 뷰를 선언할 수 있습니다.
"views": [ { "viewport": "stripe.dashboard.customer.detail", "component": "CustomerDetailView" }, { "viewport": "stripe.dashboard.payment.detail", "component": "PaymentDetailView" }, { "viewport": "stripe.dashboard.home.overview", "component": "OverviewView" }]CSPRequest
콘텐츠 보안 정책은 앱이 연결할 수 있는 외부 도메인을 제어합니다.
{ "content_security_policy": { "connect-src": [ "https://api.tajo.io", "https://api.brevo.com" ], "image-src": [ "https://cdn.tajo.io" ], "purpose": "Connect to Tajo API for data sync and load images from CDN" }}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
connect-src | string[] | 아니요 | 앱이 네트워크 요청을 보낼 수 있는 도메인 |
image-src | string[] | 아니요 | 앱이 이미지를 불러올 수 있는 도메인 |
purpose | string | 예 | 이러한 외부 연결이 필요한 이유에 대한 설명 |
Caution
앱이 실제로 연결해야 하는 도메인만 포함하세요. CSP 항목이 지나치게 많으면 추가 심사 대상이 될 수 있습니다.
PostInstallAction
사용자가 앱을 설치한 직후에 일어날 동작을 구성합니다.
{ "post_install_action": { "type": "onboarding" }}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type | string | 예 | 동작 유형(아래 참고) |
url | string | 조건부 | external 유형 동작에 사용할 URL |
동작 유형
| 유형 | 동작 |
|---|---|
"onboarding" | 대시보드에서 앱의 온보딩 뷰를 엽니다 |
"settings" | 대시보드에서 앱의 설정 뷰를 엽니다 |
"external" | 사용자를 외부 URL로 리디렉션합니다(url 필드 필요) |
예시:
// Open onboarding flow{ "post_install_action": { "type": "onboarding" }}
// Open settings page{ "post_install_action": { "type": "settings" }}
// Redirect to external setup{ "post_install_action": { "type": "external", "url": "https://app.tajo.io/stripe/setup" }}자세한 구현 패턴은 설치 후 동작 가이드를 참고하세요.
상수
앱 런타임에서 접근할 수 있는 정적 키-값 쌍을 정의합니다.
{ "constants": { "API_BASE_URL": "https://api.tajo.io/v1", "SYNC_INTERVAL_SECONDS": "300", "MAX_BATCH_SIZE": "100" }}- 모든 값은 문자열이어야 합니다
- 상수는 빌드 시점에 앱에 포함됩니다
- 환경마다 달라지는 구성값에 상수를 사용하세요
- 시크릿이나 API 키는 절대 상수로 저장하지 말고 Secret Store API를 사용하세요
앱 코드에서 상수에 접근하는 방법은 다음과 같습니다.
import { constants } from '@stripe/ui-extension-sdk/constants';
const apiUrl = constants.API_BASE_URL;개발용 확장 매니페스트
로컬 개발 중에는 추가 필드를 사용할 수 있습니다.
{ "id": "com.tajo.brevo-integration", "version": "0.1.0", "name": "Tajo for Brevo (Dev)", "icon": "./assets/icon-dev.png", "distribution_type": "private", "sandbox_install_compatible": true, "dev": { "hot_reload": true, "port": 4242 }}dev 섹션은 프로덕션 빌드와 앱 업로드 과정에서 제거됩니다. 로컬 개발 편의를 위한 설정에만 사용하세요.
검증
업로드하기 전에 매니페스트를 검증하세요.
# Validate manifest syntax and schemastripe apps validate
# Check for common issuesstripe apps check자주 발생하는 검증 오류는 다음과 같습니다.
| 오류 | 원인 | 해결 방법 |
|---|---|---|
Invalid permission | 알 수 없는 권한 식별자 | 권한 레퍼런스를 확인하세요 |
Invalid viewport | 알 수 없는 뷰포트 식별자 | 뷰포트 레퍼런스를 확인하세요 |
Missing purpose | purpose 필드가 없는 권한 | 각 권한에 purpose 문자열을 추가하세요 |
Invalid version | 시맨틱 버전이 아닌 문자열 | MAJOR.MINOR.PATCH 형식을 사용하세요 |
Icon not found | 아이콘 경로가 해석되지 않음 | 지정한 경로에 아이콘 파일이 있는지 확인하세요 |