Apple In-App Purchase (IAP) 이해와 구현

JaeEun Lee·2025년 3월 6일

iOS

목록 보기
2/4

Apple IAP(In-App Purchase)란?

Apple의 In-App Purchase(IAP)는 iOS/macOS/tvOS 앱에서 디지털 상품 및 서비스를 구매할 수 있도록 하는 결제 시스템입니다.
앱 내에서 구매, 복원, 구독, 관리 등을 처리할 수 있으며, Apple의 StoreKit 프레임워크를 사용하여 구현합니다.

IAP 개발자의 주요 관점

  1. IAP의 주요 개념
  • 제품(Product): 사용자가 구매할 수 있는 디지털 아이템 (SKProduct)
  • 결제 요청(Purchase Request): 사용자가 구매 버튼을 눌렀을 때의 요청 (SKPayment)
  • 트랜잭션(Transaction): 결제 프로세스 내에서 발생하는 단위 (SKPaymentTransaction)
  • 영수증(Receipt): Apple이 발행하는 구매 인증 정보 (receiptBase64)
  • 복원(Restore): 사용자가 이전에 구매한 아이템을 다시 다운로드 (restoreCompletedTransactions)

IAP의 주요 흐름

1. 앱 실행 시 제품 목록을 불러오기 (SKProductsRequest)

사용자가 구매할 수 있는 상품 목록을 불러오는 단계입니다.

func fetchProducts() {
    let productIdentifiers: Set<String> = ["com.example.product1", "com.example.product2"]
    let request = SKProductsRequest(productIdentifiers: productIdentifiers)
    request.delegate = self
    request.start()
}

2. 사용자 구매 요청 (SKPaymentQueue)

사용자가 구매 버튼을 누르면 Apple의 SKPaymentQueue에 결제 요청을 추가합니다.

func purchase(product: SKProduct) {
    let payment = SKPayment(product: product)
    SKPaymentQueue.default().add(payment)
}

3. 결제 완료 처리 (paymentQueue(_:updatedTransactions:))

결제가 승인되면 Apple이 paymentQueue(_:updatedTransactions:) 콜백을 호출합니다.

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    for transaction in transactions {
        switch transaction.transactionState {
        case .purchased:
            completeTransaction(transaction)
        case .failed:
            failTransaction(transaction)
        case .restored:
            restoreTransaction(transaction)
        default:
            break
        }
    }
}

4. 구매 복원 (restoreCompletedTransactions())

이전에 구매한 아이템을 복원하려면 restoreCompletedTransactions()를 호출해야 합니다.

func restorePurchases() {
    SKPaymentQueue.default().restoreCompletedTransactions()
}

5. 영수증 검증 (서버 검증)

Apple이 제공하는 영수증(receiptBase64)을 활용하여 결제가 정상적인지 확인해야 합니다.

func getReceiptBase64() -> String? {
    guard let url = Bundle.main.appStoreReceiptURL,
          let data = try? Data(contentsOf: url) else { return nil }
    return data.base64EncodedString()
}

IAP 개발 시 주의할 점

결제 트랜잭션을 반드시 finishTransaction()으로 종료해야 함

finishTransaction()을 호출하지 않으면 트랜잭션이 계속 남아 있어서 앱이 실행될 때마다 중복 처리될 수 있음.

func completeTransaction(_ transaction: SKPaymentTransaction) {
    // 구매 완료 로직 처리
    SKPaymentQueue.default().finishTransaction(transaction) // ✅ 반드시 호출해야 함!
}

restoreCompletedTransactions()는 비소비형 & 구독 상품에만 해당

restoreCompletedTransactions()는 소비형 상품에는 적용되지 않음.
구독형 상품(예: 월정액 서비스) 또는 비소비형 상품(예: 광고 제거)에서만 사용할 것.

영수증 검증을 서버에서 수행해야 안전

클라이언트에서 직접 검증하면 보안에 취약 → 해킹 툴을 사용하면 결제를 우회할 수도 있음.
Apple 서버에서 영수증 검증을 수행하는 것이 보안적으로 더 안전함.

let receipt = getReceiptBase64()
let request = [
    "receipt-data": receipt!,
    "password": "YOUR_SHARED_SECRET"
]

처리과정

sequenceDiagram
    participant User
    participant App_Client as App (Client)
    participant StoreKit as Apple StoreKit
    participant App_Server as App Server (Validation)
    participant Apple_Receipt as Apple Receipt Server

    User ->> App_Client: 1. 사용자 구매 요청
    App_Client ->> StoreKit: 2. StoreKit에 결제 요청
    StoreKit ->> App_Client: 3. 결제 승인
    App_Client ->> StoreKit: 4. 트랜잭션 생성 및 완료 확인
    App_Client ->> App_Server: 5. 영수증을 서버로 전송
    App_Server ->> Apple_Receipt: 6. Apple 서버에서 영수증 검증
    Apple_Receipt ->> App_Server: 7. 검증 결과 반환
    App_Server ->> App_Client: 8. 앱에서 결제 완료 처리
    App_Client ->> User: 9. 사용자에게 결제 완료 UI 표시

요약

  • IAP는 SKPaymentQueue, SKProductsRequest, SKPaymentTransaction 등을 활용하여 구매를 관리해야 함.
  • 결제 트랜잭션을 반드시 finishTransaction()으로 종료해야 중복 처리를 방지 가능.
  • 보안 강화를 위해 영수증 검증은 Apple 서버에서 수행하는 것이 가장 안전함.
profile
공업철학프로그래머

0개의 댓글