이 통합 아키텍처는 여러 핵심 구성 요소로 이루어져 있습니다.
구매 시작 (HTML & Stimulus)
사용자는 HTML 페이월의 버튼을 통해 구매를 시작합니다. 이 버튼은 Stimulus 컨트롤러(bridge--paywall)를 트리거하며, productId와 userId를 데이터 속성으로 전달합니다. Stimulus 컨트롤러는 이 데이터를 추출하여 iOS 브릿지 컴포넌트로 메시지를 전송합니다.
iOS 구매 처리 (Swift & StoreKit)
iOS의 PaywallComponent는 브릿지로부터 메시지를 수신합니다. 메시지에 포함된 productId와 userId를 사용하여 StoreKit에서 해당 제품을 조회하고, appAccountToken 옵션에 userId를 포함하여 구매를 시작합니다. 이 appAccountToken은 Apple이 거래 관련 모든 웹훅에서 다시 반환하는 고유 식별자로, 사용자-구매 연동의 핵심입니다.
Apple 웹훅 처리 (Rails)
구매가 성공적으로 완료되면 Apple은 서명된 JWS(JSON Web Signature)를 Rails 서버로 POST합니다. AppStoreWebhooksController는 이 페이로드를 디코딩하여 signedTransactionInfo에서 appAccountToken을 추출하고, 이를 통해 해당 사용자를 식별합니다. notificationType에 따라 사용자의 구독 정보를 업데이트(예: SUBSCRIBED 시 product_id, expires_at, status 업데이트)합니다.
UI 실시간 업데이트 (Turbo Streams)
Subscription 모델은 구독 정보가 성공적으로 저장되고 활성화될 때 after_commit 콜백을 통해 broadcast_update를 실행합니다. 이는 Turbo::StreamsChannel.broadcast_replace_to를 사용하여 사용자에게 특정 target(paywall)을 paywalls/success 부분 템플릿으로 교체하도록 지시하여 UI를 실시간으로 업데이트합니다.
주요 이점
-
유연한 페이월 디자인: Rails에서 페이월을 설계하고 반복하며, 앱 스토어 바이너리 제출 없이 가격 실험 및 재설계가 가능합니다.
-
중앙 집중식 구독 데이터: 구독 데이터가 Apple 서버가 아닌 Rails 데이터베이스에 저장되어
user.subscribed?와 같은 일반적인 로직을 사용할 수 있습니다. -
항상 동기화된 데이터: 웹훅 수신을 통해 사용자가 앱을 다시 열지 않아도 구독 데이터가 항상 동기화됩니다. 이는 앱 내 구독 시 웹에서도 즉시 접근 권한을 부여하는 데 유용합니다.
이러한 복잡한 과정은 PurchaseKit과 같은 솔루션으로 추상화될 수 있지만, 이 문서는 그 내부 동작 방식을 이해하는 데 필요한 심층적인 지식을 제공합니다.