Google Play 변경 사항 및 Epic 합의: 제3자 모바일 결제(Third-Party Mobile Billing) 아키텍처 설계
모든 모바일 게임 개발자는 월간 수익 대시보드를 보며 마진을 즉시 증발시키는 30%의 플랫폼 수수료에 눈살을 찌푸린 적이 있을 것입니다. 수년 동안 Android 개발자들은 경직된 생태계에 갇혀 있었습니다. 세계 최대의 모바일 스토어에 게임을 출시하려면 해당 스토어의 전용 빌링 시스템을 사용해야 했고, 마이크로트랜잭션 수익의 상당 부분을 포기해야 했으며, 모든 엔タイトル먼트(Entitlement) 아키텍처를 특정 API에 맞춰 구축해야 했습니다.
그 시대가 공식적으로 끝나가고 있습니다. google play changes epic settlement로 인해 도입된 조건을 완전히 활용하려면 개발자는 백엔드 인프라를 근본적으로 재고해야 합니다.
최근 Epic Games와 Google 간의 법적 분쟁이 마무리되면서 법원이 명령한 변경 사항으로 인해 Android 생태계가 활짝 열렸습니다. 이제 개발자는 플레이어를 외부 Payment Gateway로 유도하여 의무적인 30% 세금을 회피할 수 있으며, Google Play 내에서 직접 호스팅되는 대체 앱 스토어를 통해 배포할 수도 있습니다.
하지만 이러한 새로운 재정적 자유에는 막대한 기술적 비용이 따릅니다. Google Play Billing을 포기하면 해당 시스템이 제공하던 자동 Receipt Validation, 오프라인 캐싱, 중앙 집중식 엔タイトル먼트 추적 기능을 잃게 됩니다. 이제 여러 Payment Gateway에 걸쳐 플레이어의 구매를 안전하게 관리하는 책임은 전적으로 개발자에게 있습니다.
이 글에서는 이러한 변화가 기술적으로 미치는 영향과, 사기를 방지하고 월드 상태를 동기화된 상태로 유지하는 안전한 스토어 불가지론적(Store-Agnostic) 빌링 백엔드를 설계하는 방법을 심층적으로 살펴봅니다.
Epic vs. Google 합의의 기술적 영향
코드를 살펴보기 전에, 법원의 가처분 명령(2024년 11월부터 2027년 11월까지 유효)이 게임 아키텍처에 구체적으로 어떤 변화를 주는지 이해해야 합니다.
1. 외부 결제 라우팅의 합법화
Google은 더 이상 구매 완료를 위해 플레이어를 웹 브라우저로 유도하는 링크가 포함되어 있다는 이유로 게임을 차단할 수 없습니다. 즉, Stripe, Xsolla 또는 PayPal과 같은 결제 서비스 제공업체를 통합할 수 있음을 의미합니다. 이러한 업체들은 일반적으로 트랜잭션당 약 2.9%~5%와 소액의 고정 수수료를 부과합니다. 마이크로트랜잭션으로 월 50,000달러의 수익을 올리는 미드코어 인디 게임의 경우, 30%의 플랫폼 수수료에서 벗어나면 매달 약 12,500달러를 절약할 수 있습니다.
2. 사이드로딩(Sideloading) 및 제3자 스토어
이제 대체 앱 스토어를 Google Play Store를 통해 직접 배포할 수 있으며, Google이 기기 제조사에 Google Play만 독점적으로 사전 설치하도록 대가를 지불하는 것이 금지됩니다. 플레이어는 동일한 Android 기기에서 게임을 플레이하면서도 Epic Games Store, Amazon Appstore 또는 커스텀 퍼블리셔 런처에서 게임을 다운로드할 수 있게 됩니다.
3. 단일 소스 엔タイトル먼트의 종말
과거에는 게임 클라이언트가 단순히 Google Play Billing Library에 "이 사용자가 프리미엄 배틀 패스를 소유하고 있습니까?"라고 쿼리하기만 하면 되었습니다. 대답이 "예"라면 콘텐츠를 잠금 해제했습니다.
이제 플레이어는 PC에서 Stripe 결제 링크를 통해 배틀 패스를 구매하고, 대체 Android 스토어에서 다운로드한 게임에 로그인하여 콘텐츠가 있기를 기대할 수 있습니다. 클라이언트 사이드 검증(Client-side validation)은 공식적으로 끝났습니다. 백엔드가 모든 플레이어 인벤토리의 유일한 진실의 원천(Single Source of Truth)이 되는 Server-authoritative 아키텍처로 이동해야 합니다.
스토어 불가지론적 엔タイトル먼트 백엔드 설계
여러 Payment Gateway를 지원하려면 백엔드에 금융 트랜잭션과 게임 내 엔タイトル먼트를 분리하는 견고한 데이터베이스 스키마가 필요합니다.
플레이어의 인벤토리를 특정 스토어의 영수증 ID에 직접 연결하지 마세요. 대신 중간 트랜잭션 테이블을 사용하십시오.
권장 데이터베이스 스키마
이를 수동으로 구축하려면 관계형 데이터베이스(예: PostgreSQL)에 세 개의 핵심 테이블이 필요합니다.
Users: 핵심 플레이어 프로필.Transactions: 금융 이벤트를 기록합니다.GatewayProvider(예: "Stripe", "Google", "Xsolla"),GatewayTransactionId,Amount,Currency,Status(Pending, Completed, Refunded)를 포함합니다.Entitlements: 사용자가 소유한 실제 게임 내 아이템입니다.UserId,ItemId,AcquiredViaTransactionId,RevokedAt을 포함합니다.
구매가 발생하면 Payment Gateway는 Webhook을 통해 서버에 알림을 보냅니다. 서버는 Webhook을 확인하고 Transactions 테이블에 Completed 레코드를 생성한 다음, 해당 아이템을 Entitlements 테이블에 삽입합니다.
안전한 서버 사이드 Webhook 검증 구현
이 새로운 아키텍처에서 가장 중요한 부분은 Webhook 핸들러입니다. 플레이어를 제3자 결제 페이지로 유도하는 경우, 결제가 성공하면 해당 외부 제공업체가 백엔드로 HTTP POST 요청을 보냅니다.
사기꾼들은 보호되지 않은 Webhook 엔드포인트를 적극적으로 스캔합니다. 엔드포인트가 암호화 서명을 확인하지 않고 JSON 페이로드를 맹목적으로 수락하면, 공격자는 "결제 성공" 메시지를 위조하여 자신에게 무한한 프리미엄 재화를 부여할 것입니다.
다음은 Express.js를 사용한 프로덕션용 TypeScript 예제입니다. 이 스니펫은 Stripe Webhook 서명을 안전하게 검증하고, 멱등성(Idempotency)을 보장하며(Webhook이 두 번 실행되어도 플레이어에게 중복 과금되지 않도록 함), 플레이어의 데이터베이스를 업데이트하는 방법을 보여줍니다.
import express from 'express';
import crypto from 'crypto';
import { PrismaClient } from '@prisma/client';
const app = express();
const prisma = new PrismaClient();
const WEBHOOK_SECRET = process.env.PAYMENT_WEBHOOK_SECRET || '';
// We need the raw body to verify the cryptographic signature
app.post('/api/webhooks/billing', express.raw({ type: 'application/json' }), async (req, res) => {
const signature = req.headers['x-payment-signature'] as string;
const rawBody = req.body;
// 1. Cryptographic Signature Verification
const expectedSignature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(rawBody)
.digest('hex');
if (signature !== expectedSignature) {
console.error("Security Alert: Invalid webhook signature detected.");
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(rawBody.toString());
// 2. Process only successful payments
if (event.type === 'payment.success') {
const { transactionId, playerId, itemId } = event.data;
try {
// 3. Database Transaction with Idempotency Check
await prisma.$transaction(async (tx) => {
// Check if we already processed this transaction (Idempotency)
const existingTx = await tx.transaction.findUnique({
where: { gatewayTransactionId: transactionId }
});
if (existingTx) {
console.log(`Transaction ${transactionId} already processed. Skipping.`);
return;
}
// Log the financial transaction
const newTx = await tx.transaction.create({
data: {
gatewayTransactionId: transactionId,
provider: 'CustomStripeGateway',
status: 'COMPLETED',
playerId: playerId
}
});
// Grant the in-game entitlement
await tx.entitlement.create({
data: {
playerId: playerId,
itemId: itemId,
acquiredViaTransactionId: newTx.id
}
});
console.log(`Successfully granted item ${itemId} to player ${playerId}`);
});
return res.status(200).send('Webhook processed');
} catch (error) {
console.error("Database error during webhook processing:", error);
return res.status(500).send('Internal Server Error');
}
}
// Acknowledge other event types without crashing
return res.status(200).send('Event ignored');
});
페이로드 하드닝(Payload Hardening)의 중요성
위의 코드가 JSON으로 파싱하기 전에 요청의 정확한 바이트 스트림을 캡처하기 위해 express.raw()를 사용하는 방식에 주목하십시오. JSON 페이로드에 공백 하나만 잘못 들어가도 HMAC 해시가 일치하지 않게 됩니다.
이러한 엔드포인트를 보호하는 것은 선택이 아닙니다. 주요 업계 사고에서 보았듯이, 스푸핑된 HTTP 요청에 대해 백엔드를 강화하지 않는 것은 게임 경제를 망치는 확실한 방법입니다. 노출된 API가 어떻게 치명적인 익스플로잇으로 이어지는지에 대한 자세한 내용은 The Star Citizen Data Breach Explained Architecting Game Backends To Survive Compromises 분석을 읽어보시기 바랍니다.
실시간 동기화 문제 해결
백엔드 엔タイトル먼트 로직은 해결했지만, 이제 UX 문제에 직면하게 됩니다.
플레이어 흐름을 상상해 보십시오.
- 플레이어가 Android 게임에서 "1000 코인 구매"를 누릅니다.
- 게임은 기기의 웹 브라우저를 열어 커스텀 결제 페이지로 이동합니다.
- 플레이어는 신용카드로 구매를 완료합니다.
- Payment Gateway가 서버로 Webhook을 보냅니다.
- 플레이어는 게임 앱으로 돌아옵니다.
게임 클라이언트는 구매가 성공했는지 어떻게 알 수 있을까요? HTTP Polling(클라이언트가 3초마다 서버에 "구매했나요?"라고 묻는 방식)에 의존하면 기기 배터리가 소모되고 백엔드에 불필요한 요청이 쏟아지게 됩니다.
대신, 데이터베이스 트랜잭션이 커밋되는 정확한 밀리초에 백엔드에서 클라이언트로 업데이트된 인벤토리 상태를 푸시해야 합니다. 이를 위해서는 지속적인 양방향 연결이 필요합니다. 이 인프라를 처음부터 구축하려면 데이터베이스 이벤트를 수신하고 이를 활성 클라이언트 세션에 브로드캐스트하는 WebSocket 레이어를 구현해야 합니다.
이 아키텍처 구축에 어려움을 겪고 있다면 Ditch Http Polling An Unreal Engine Websockets Tutorial For Real Time Backends 가이드에서 실시간 푸시 알림 구현 방법을 배울 수 있습니다.
제3자 모바일 빌링을 위한 5가지 모범 사례
새로운 생태계 변화를 활용하기 위해 표준 Google Play Billing 라이브러리에서 게임을 마이그레이션하는 경우 다음 5가지 아키텍처 모범 사례를 준수하십시오.
- 엄격한 멱등성(Idempotency) 적용: 모바일 기기에서는 네트워크 타임아웃이 빈번하게 발생합니다. 서버 응답이 너무 오래 걸리면 Payment Gateway가 동일한 "성공" Webhook을 세 번 보낼 수 있습니다. 아이템을 지급하기 전에 항상 데이터베이스에서
TransactionId를 확인하여 플레이어에게 아이템이 실수로 중복 지급되지 않도록 하십시오. - 차지백(Chargeback) 취소 자동화: 제3자 빌링을 사용한다는 것은 차지백 및 환불 처리에 대한 책임이 개발자에게 있음을 의미합니다. Webhook 핸들러는
payment.refunded이벤트를 수신하고Entitlements테이블의 해당 행을 자동으로Revoked로 표시해야 합니다. 이를 생략하면 플레이어는 신용카드 결제를 취소하면서도 프리미엄 재화를 계속 보유할 수 있다는 사실을 알게 될 것입니다. - 클라이언트와 게이트웨이 분리: 게임 클라이언트는 Payment Gateway의 API와 직접 통신해서는 안 됩니다. 클라이언트는 백엔드에 결제 세션 토큰을 요청하고, 해당 토큰으로 웹 뷰를 열어야 하며, 실제 트랜잭션 검증은 백엔드에서 처리하도록 해야 합니다.
- 단계적 기능 축소(Graceful Degradation) 구현: 데이터베이스가 다운되더라도 게임은 여전히 플레이 가능해야 합니다. 암호화된 저장 파일을 사용하여 기기 로컬에 엔タイトル먼트를 캐싱하되, 플레이어가 프리미엄 재화를 사용하거나 멀티플레이어 매치에 참여하려고 할 때는 항상 서버 사이드의 진실과 대조하여 검증하십시오.
- 가상 재화 파이프라인 통합: 데이터베이스에 "Google 코인"과 "Stripe 코인"을 별도로 생성하지 마세요. 백엔드에서 모든 들어오는 법정 화폐 트랜잭션을 단일화된 가상 재화 ID에 매핑하여 게임 UI 로직에서 큰 혼란이 발생하는 것을 방지하십시오.
인프라 구축 vs 구매(Build vs. Buy) 현실 점검
Epic vs. Google 합의는 개발자 수익 측면에서 큰 승리이지만, 인프라 구축의 부담을 개발자의 어깨로 직접 옮깁니다.
가용성이 높고 스토어 불가지론적인 빌링 백엔드를 구축하려면 PostgreSQL 데이터베이스 설정, 멱등성 캐싱을 위한 Redis 구성, 보안 Webhook을 위한 SSL 인증서 관리, 실시간 클라이언트 업데이트를 위한 WebSocket 서버 유지가 필요합니다. 소규모 인디 팀에게 이는 최소 4~6주의 전담 백엔드 엔지니어링 시간이 소요되는 작업이며, 이 시간은 원래 게임을 재미있게 만드는 데 사용되어야 합니다.
이것이 바로 우리가 제거하는 아키텍처 마찰입니다. horizOn을 사용하면 이러한 복잡한 백엔드 서비스가 미리 구성된 상태로 제공됩니다. 당사 플랫폼은 서버 간 Webhook 검증을 안전하게 처리하고, 중복 트랜잭션을 방지하며, 플레이어 인벤토리를 실시간으로 자동 동기화하는 즉시 사용 가능한 스토어 불가지론적 엔タイトル먼트 시스템을 제공합니다. DevOps 엔지니어가 되지 않고도 제3자 빌링의 재정적 이점을 누릴 수 있습니다.
향후 전망
모바일 게임 생태계는 10년 만에 가장 중요한 구조적 변화를 겪고 있습니다. 마침내 폐쇄적인 정원이 무너지고 있으며, 백엔드 아키텍처를 플랫폼 불가지론적으로 적응시키는 개발자는 기존의 30% 플랫폼 세금을 피함으로써 막대한 재정적 보상을 얻게 될 것입니다.
그러나 이러한 자유에는 기술적 책임이 따릅니다. 클라이언트 사이드 권한(Client-side authority)은 더 이상 유효하지 않습니다. 멀티 스토어, 멀티 게이트웨이 세상에서 살아남으려면 백엔드를 절대적인 진실의 원천으로 취급해야 합니다.
수천 줄의 상용구 인프라 코드를 작성하지 않고도 멀티플레이어 백엔드를 확장하고 안전한 크로스 플랫폼 엔タイトル먼트를 구현할 준비가 되셨습니까? horizOn을 무료로 체험해 보시고, 서버 아키텍처는 저희에게 맡기고 게임 출시에만 집중하십시오.