출시 전 IAP 연동 테스트 중, 전형적이지만 매우 헷갈리는 문제를 만났습니다.
- 사용자가 “구매 계속”을 누름
- 버튼이 “처리 중”으로 바뀜
- 몇 초 뒤 다시 “구매 계속”으로 돌아감
- App Store 구매 확인 팝업이 뜨지 않음
이 글에서는 실제 추적 경로, 핵심 로그, 근본 원인, 그리고 출시 전 바로 적용 가능한 수정 전략을 정리합니다.
1. 문제 증상
구매 페이지의 상품 목록은 정상 로드됐지만, 구매 버튼을 누른 뒤:
purchase()가 호출됨- 시스템 팝업이 나타나지 않음
- UI가 결국 미구매 상태로 복귀함
처음에는 “구매 플로우가 시작조차 안 된 것”처럼 보였지만, 로그는 다른 사실을 보여줬습니다.
2. 1차 점검: 구매 체인이 실제로 동작하는지 확인
구매 플로우의 핵심 지점에 로그를 촘촘히 추가했습니다.
- 버튼 클릭 파라미터
purchaseSelectedProduct()진입 및guard분기product.purchase()호출 전/후Transaction.updatesrefreshEntitlements()Transaction.currentEntitlementsTransaction.latest(for:)
결과:
purchase()는.success반환- 트랜잭션 검증 성공,
transaction.finish()도 실행됨 - 하지만
entitledIDs는 계속 비어 있음
즉, **문제는 “구매가 시작되지 않음”이 아니라 “구매 후 권한이 인식되지 않음”**이었습니다.
3. 심화 분석에서 나온 결정적 사실
로그를 더 보강하자 결정적인 신호가 나왔습니다.
Transaction.currentEntitlements반복 수가0Transaction.latest(for: monthly)에는 유효 기록이 있으나 이미 만료됨- 더 중요한 점: 구매 전
Transaction.unfinished에 오래된 트랜잭션이 존재 - 이번
purchase()가 새 인터랙티브 구매가 아니라 오래된 체인의 트랜잭션을 반환
이게 “팝업이 안 뜨는” 이유를 설명합니다.
- StoreKit이 먼저 처리 가능한 오래된 트랜잭션(unfinished / 과거 체인)을 반환
- 코드가 이를
finish()처리 - 요청은 “성공”처럼 보이지만 사용자가 기대하는 새 구매 확인 경로로는 가지 않음
4. 근본 원인 요약
단일 원인이 아니라 두 요인이 겹친 문제였습니다.
- unfinished transaction이 구매 플로우를 간섭
- sandbox 구독 체인이 만료 상태 (latest transaction이 있어도 active entitlement가 아닐 수 있음)
최종적으로는 “팝업 없음 + 성공처럼 보임 + 권한 비어 있음”으로 나타났습니다.
5. 수정 전략 (실무에서 효과 확인)
5.1 구매 전 unfinished 트랜잭션 선제 정리
앱 시작 시점과 구매 버튼 클릭 전 Transaction.unfinished 를 순회하고, verified transaction에 finish() 를 실행해 오래된 트랜잭션이 새 구매 흐름을 가로채지 못하게 합니다.
5.2 진단 로그 유지 및 강화 (출시 전 권장)
출시 전까지 유지할 핵심 로그:
unfinished transaction스냅샷subscription status(state, renewal info)currentEntitlements반복 개수latest(for:)의 transaction/expiration 정보
5.3 권한 판정 “이중 경로” 적용 (선택 강화)
일부 환경에서 currentEntitlements 가 잠시 비는 경우, latest(for:) 를 fallback으로 활용할 수 있습니다(단, active 상태 검증은 필수).
6. 출시 전 IAP 체크리스트
- 테스트마다 Sandbox 계정의 구독 상태(만료 여부) 확인
- 핵심 경로에서
unfinished개수 로깅 - “첫 구매 / 만료 후 재구독 / 복원 구매” 3가지 시나리오 테스트
currentEntitlements와latest일치 여부 확인- “팝업이 안 뜸” 발생 시, 먼저 오래된 트랜잭션 경로 적중 여부 확인
7. 결론
“구매를 눌렀는데 팝업이 안 뜸”은 UI 문제나 호출 타이밍 문제만은 아닙니다.
StoreKit 2에서는 트랜잭션 상태, unfinished 큐, 구독 라이프사이클이 최종 동작에 직접 영향을 줍니다.
출시 전에 이 로그와 정리 루틴을 갖춰두면, 운영 환경에서 재현 어려운 IAP 이슈를 크게 줄일 수 있습니다.