1. Pub/Sub 개념 설명
1.1 Pub/Sub이란 무엇인가?
Pub/Sub(Publish-Subscribe)은 비동기 메시징 서비스로, 발행자(Publisher)와 구독자(Subscriber)가 메시지를 주고받을 수 있도록 돕는 Google Cloud의 서비스다.
• 발행자(Publisher): 메시지를 특정 주제(Topic)에 게시
• 구독자(Subscriber): 해당 주제의 메시지를 구독하고 처리
이를 활용하면 시스템 간의 결합도를 낮추고, 실시간 데이터 처리를 간편하게 할 수 있다. 즉 웹훅으로 사용할 수 있다.
1.2 왜 구글 인앱 결제에서 Pub/Sub을 사용해야 할까?
구글 인앱 결제에서는 사용자가 구매, 구독 취소, 결제 실패 등의 이벤트를 발생시킨다.
하지만 클라이언트에서 직접 구매 상태를 확인하는 것은 보안상 위험할 수 있다.
Pub/Sub을 활용하면 결제 이벤트를 서버에서 안전하게 감지하고 처리할 수 있다.
1.3 구글 Play Billing 시스템과의 관계
Google Play Billing 시스템은 결제 이벤트가 발생하면 이를 Google Cloud Pub/Sub으로 전송할 수 있다.
• Play Console에서 Pub/Sub 주제를 설정하면 Google Play Billing이 자동으로 관련 메시지를 발행
• 구독된 서버에서 이를 감지하고 결제 처리 로직을 수행
2. Google Cloud Pub/Sub 설정하기
2.1 GCP에서 Pub/Sub 주제(Topic) 만들기
1. Google Cloud Console 접속
2. Pub/Sub → 주제(Topic) 만들기 클릭
3. 적절한 이름을 입력 (예: play-billing-topic)
4. 메시지 보안 강화를 위해 메시지 데이터 암호화(KMS) 옵션 선택 가능
2.2 구독(Subscription) 생성
1. 생성한 주제에서 “구독 만들기” 선택
2. 구독 방식 선택
• 푸시(Push) 방식: 메시지를 특정 엔드포인트(URL)로 전달
• 풀(Pull) 방식: 서버가 직접 메시지를 가져옴
3. Cloud Functions, Cloud Run 또는 서버 API와 연동할 경우 푸시 방식 권장
2.3 IAM 권한 설정
Pub/Sub을 활용하려면 Google Play Billing이 메시지를 발행할 수 있도록 권한을 부여해야 한다.
1. IAM & 관리자 → 역할 추가
2. service-<project-number>@gcp-sa-playbilling.iam.gserviceaccount.com 사용자 추가
3. Pub/Sub 게시자(Pub/Sub Publisher) 역할 할당
3. Google Play Console에서 Pub/Sub 연동하기
3.1 Google Play 결제 이벤트를 Pub/Sub에 연결하는 방법
1. Play Console 접속
2. “설정 → 개발자 계정 → API 접근 → Pub/Sub 설정” 이동
3. 방금 생성한 Pub/Sub 주제를 입력하고 저장
3.2 JSON 메시지 형식과 주요 필드
Cloud Pub/Sub 주제에 관한 각 게시에는 하나의 base64로 인코딩된 데이터 필드가 포함되어 있다.
{
"message": {
"attributes": {
"key": "value"
},
"data": "eyAidmVyc2lvbiI6IHN0cmluZywgInBhY2thZ2VOYW1lIjogc3RyaW5nLCAiZXZlbnRUaW1lTWlsbGlzIjogbG9uZywgIm9uZVRpbWVQcm9kdWN0Tm90aWZpY2F0aW9uIjogT25lVGltZVByb2R1Y3ROb3RpZmljYXRpb24sICJzdWJzY3JpcHRpb25Ob3RpZmljYXRpb24iOiBTdWJzY3JpcHRpb25Ob3RpZmljYXRpb24sICJ0ZXN0Tm90aWZpY2F0aW9uIjogVGVzdE5vdGlmaWNhdGlvbiB9",
"messageId": "136969346945"
},
"subscription": "projects/myproject/subscriptions/mysubscription"
}
base64로 인코딩된 데이터 필드를 디코딩하면 DeveloperNotification에 다음 필드가 포함된다.
{
"version": string,
"packageName": string,
"eventTimeMillis": long,
"oneTimeProductNotification": OneTimeProductNotification,
"subscriptionNotification": SubscriptionNotification,
"voidedPurchaseNotification": VoidedPurchaseNotification,
"testNotification": TestNotification
}
4. 서버에서 Pub/Sub 메시지 처리하기
4.1 서버에서 Pub/Sub 메시지 받는 방법
# views.py
@action(methods=["POST"], detail=False, serializer_class=GoogleWebhookHistorySerializer, permission_classes=[])
def webhook(self, request, *args, **kwargs):
return self._create(request, *args, **kwargs)
# serializer.py
class GoogleWebhookHistorySerializer(serializers.ModelSerializer):
message = serializers.DictField(label="메세지", write_only=True)
class Meta:
model = GoogleReceipt
fields = ["message"]
def validate(self, attrs):
str_bytes = base64.b64decode(attrs["message"]["data"])
base64_decode_dict = eval(str_bytes.decode("utf-8"))
if "voidedPurchaseNotification" not in base64_decode_dict.keys():
raise ValidationError({"nonField": ["취소 요청이 아닙니다."]})
attrs["notification_type"] = base64_decode_dict["voidedPurchaseNotification"]["productType"]
attrs["purchase_token"] = base64_decode_dict["voidedPurchaseNotification"]["purchaseToken"]
attrs["order_id"] = base64_decode_dict["voidedPurchaseNotification"]["orderId"]
Pub/Sub을 활용할 때 주의할 점
• 중복 메시지 처리: 메시지가 중복 전달될 수 있으므로 messageId를 기반으로 중복 제거
• 보안 강화: 푸시 방식 사용 시 검증된 IP에서만 요청을 허용
메세지가 수신되지 않을 때 IAM 권환 확인이 필요하다. (Pub/Sub Subscriber 역할 필요)
'django' 카테고리의 다른 글
운영 중인 서비스에서 DB 구조 변경하기 (feat. 기존 데이터 이관) (0) | 2025.02.23 |
---|---|
Django에서 API GateWay와 Dynamo DB를 이용한 채팅 (0) | 2025.02.12 |
Django 비동기 작업 추적 기능 개선 (0) | 2025.01.25 |
Django Admin 커스텀 (0) | 2022.11.22 |
Django ORM (0) | 2022.03.09 |