PC용 Play Integrity를 사용하면 게임 이벤트와 서버 요청이 정품 PC 기기의 PC용 Google Play Games 정품 인스턴스에서 비롯되는지 확인할 수 있습니다. 잠재적으로 위험한 기기와 알 수 없는 에뮬레이터를 감지하여 게임의 백엔드 서버가 적절한 조치를 취해 부정행위, 무단 액세스, 사기성 트래픽, 악용을 방지할 수 있습니다.
자격 요건
- SDK 설정을 완료합니다.
- Integrity API 보안 고려사항을 검토합니다.
- Integrity API 서비스 약관 및 데이터 처리 정보를 읽고 이해합니다.
- Google Cloud 콘솔에서 Cloud 프로젝트를 만들거나 PC용 Play Integrity와 함께 사용할 기존 Cloud 프로젝트를 선택합니다. API 및 서비스 로 이동하여 Google Play Integrity API를 사용 설정합니다.
- 하루에 10, 000건 이상의 PC용 Play Integrity 요청을 할 것으로 예상되는 경우 일일 최대 요청 수를 늘려 달라고 요청해야 합니다.
1단계: 게임에서 PC용 Play Integrity를 사용하는 방법 결정
PC용 Play Integrity를 호출하여 환경에 관한 무결성 확인 결과를 가져올 시점을 결정합니다. 예를 들어 게임이 열릴 때, 플레이어가 로그인할 때 또는 플레이어가 멀티플레이어 게임에 참여할 때 확인 결과를 요청할 수 있습니다. 그런 다음 다양한 무결성 응답을 처리하는 방법을 결정합니다. 예를 들어 다음과 같은 작업을 할 수 있습니다.
- 강제 조치 없이 응답을 수집하고 데이터를 내부적으로 분석하여 악용의 유용한 신호인지 파악합니다.
- 응답을 수집하고 백엔드 서버에 로직을 구현하여 무결성 확인 결과를 통과한 기기가 게임을 정상적으로 플레이하도록 허용하는 동시에 의심스러운 환경에서 발생하는 트래픽에 대한 액세스를 차단하거나 거부합니다.
- 응답을 수집하고 백엔드에 로직을 구현하여 무결성 검사를 통과한 기기의 플레이어를 함께 매칭하는 동시에 의심스러운 환경에서 발생하는 트래픽을 함께 매칭합니다.
2단계: 게임에서 무결성 토큰 요청
PC용 Play Integrity 준비
PC용 Play Integrity를 준비 (또는 '준비')합니다. 이렇게 하면 무결성 확인 결과 요청을 할 때 중요한 경로의 지연 시간을 줄이기 위해 Google Play에서 기기의 부분 증명 정보를 스마트하게 캐시할 수 있습니다. 게임이 열리자마자 비동기식으로 이 작업을 실행하여 필요할 때 주문형 무결성 요청을 할 수 있습니다.
void PrepareIntegrityToken( const PrepareIntegrityTokenParams & params, PrepareIntegrityTokenContinuation continuation )
성공하면 무결성 토큰을 요청하는 데 사용해야 하는 RequestTokenData가 포함된 PrepareIntegrityTokenResultValue로 연속이 호출됩니다. 이 데이터는 메모리에 캐시되어야 하며 애플리케이션 세션 기간 동안 RequestIntegrityToken 호출을 위해 재사용되어야 합니다.
애플리케이션에서 무결성 확인 결과를 완전히 다시 평가해야 한다고 판단하는 경우에만 PrepareIntegrityToken 호출이 이루어져야 합니다.
| 세부정보 | |
|---|---|
| 매개변수 | params: Google Cloud 프로젝트 번호가 포함된 매개변수입니다. continuation: 무결성 토큰 제공자를 반환하는 비동기 콜백입니다. |
PrepareIntegrityToken 작업을 호출하는 방법을 보여주는 코드 스니펫은 다음과 같이 제공됩니다.
google::play::integrity::IntegrityClient client_;
google::play::integrity::PrepareIntegrityTokenResult
IntegrityInterface::PrepareIntegrityToken(int64_t cloud_project_number) {
google::play::integrity::PrepareIntegrityTokenParams params;
params.cloud_project_number = cloud_project_number;
auto promise = std::make_shared<
std::promise<google::play::integrity::PrepareIntegrityTokenResult>>();
client_.PrepareIntegrityToken(
params,
[promise](
google::play::integrity::PrepareIntegrityTokenResult result) {
promise->set_value(std::move(result));
});
return promise->get_future().get();
}
무결성 토큰 요청
무결성 토큰은 게임에서 기기가 무단 변경되지 않았음을 확인할 수 있는 메커니즘입니다. 게임에서 진짜인지 확인하려는 서버 요청을 실행할 때마다 무결성 토큰을 요청하고 복호화 및 확인을 위해 게임의 백엔드 서버로 전송할 수 있습니다.
PC용 Play Integrity API로 앱에서 사용자 작업을 확인할 때 RequestIntegrityTokenParams::request_hash 필드를 사용하여 조작 공격을 완화할 수 있습니다. 예를 들어 플레이어의 점수를 게임의 백엔드 서버에 보고하려고 할 때 서버는 프록시 서버에서 이 점수가 조작되지 않았는지 확인하려고 합니다. PC용 Play Integrity는 서명된 무결성 응답 내에서 이 필드에 설정된 값을 반환할 수 있습니다. requestHash가 없으면 무결성 토큰은 기기에만 바인딩되고 특정 요청에는 바인딩되지 않으므로 공격이 발생할 수 있습니다.
void RequestIntegrityToken( const RequestIntegrityTokenParams & params, RequestIntegrityTokenContinuation continuation )
공격 가능성을 완화하려면 무결성 확인 결과를 요청할 때 다음 단계를 따르세요.
- 발생하는 사용자 작업 또는 서버 요청에서 모든 관련 요청 매개변수 (예: 안정적인 요청 직렬화의 SHA256)의 다이제스트를 계산합니다.
- RequestIntegrityTokenParams::request_hash 필드를 다이제스트로 설정합니다.
| 세부정보 | |
|---|---|
| 매개변수 | params: 준비된 RequestTokenData 및 무결성 검사 요청 해시가 포함된 매개변수입니다. continuation: 데이터를 반환하는 비동기 콜백입니다. |
RequestIntegrityToken 작업을 호출하는 방법을 보여주는 코드 스니펫은 다음과 같이 제공됩니다.
absl::StatusOr<google::play::integrity::RequestIntegrityTokenResult>
IntegrityInterface::RequestIntegrityToken(
const google::play::integrity::PrepareIntegrityTokenResult&
prepare_integrity_token_result,
const std::string& request_hash) {
// Check if the prepare_integrity_token_result is OK
if (!prepare_integrity_token_result.ok()) {
return absl::FailedPreconditionError(
absl::StrCat("PrepareIntegrityTokenResult is not OK. Error code: ",
prepare_integrity_token_result.error_code));
}
google::play::integrity::RequestIntegrityTokenParams params{
.request_token_data =
prepare_integrity_token_result.request_token_data,
.request_hash = request_hash};
auto promise = std::make_shared<std::promise<
google::play::integrity::RequestIntegrityTokenResult>>();
client_.RequestIntegrityToken(
params,
[promise](google::play::integrity::RequestIntegrityTokenResult result) {
promise->set_value(std::move(result));
});
return promise->get_future().get();
}
3단계: 게임의 백엔드 서버에서 무결성 토큰 복호화 및 확인
무결성 토큰 복호화
무결성 확인 결과를 요청하면 Play Integrity API가 암호화된 응답 토큰을 제공합니다. 기기 무결성 확인 결과를 가져오려면 Google 서버에서 무결성 토큰을 복호화해야 합니다.
- 서비스 계정을 앱에 연결된 Google Cloud 프로젝트 내에서 만듭니다.
앱 서버에서 playintegrity 범위를 사용하여 서비스 계정 사용자 인증 정보로부터 액세스 토큰을 가져오고 다음과 같이 요청합니다.
playintegrity.googleapis.com/v1/<var>PACKAGE_NAME</var>:decodePcIntegrityToken -d \ '{ "integrity_token": "<var>INTEGRITY_TOKEN</var>" }'JSON 응답을 읽습니다.
결과 페이로드는 개발자가 제공한 정보와 함께 무결성 확인 결과 및 세부정보가 포함된 일반 텍스트 토큰입니다. 복호화된 무결성 토큰은 다음과 같습니다.
{
"requestDetails": {
"requestPackageName": "com.your.package.name",
"requestTime": "2025-08-29T13:10:37.285Z",
"requestHash": "your_request_hash_string"
},
"deviceIntegrity": {
"deviceRecognitionVerdict": [
"MEETS_PC_INTEGRITY"
]
},
"accountDetails": {
"appLicensingVerdict": "LICENSED"
}
}
무결성 토큰 확인
디코딩된 무결성 토큰의 requestDetails 필드에는 requestHash에 개발자가 제공한 정보를 비롯하여 요청에 관한 정보가 포함됩니다.
requestHash 및 packageName 필드는 원래 요청의 필드와 일치해야 합니다. 따라서 requestPackageName과 requestHash가 다음 코드 스니펫과 같이 원래 요청에서 전송된 것과 일치하는지 확인하여 JSON 페이로드의 requestDetails 부분을 확인합니다.
const auto& request_details = json_payload["requestDetails"];
if (request_details.value("requestPackageName", "") != <YOUR_PACKAGE_NAME>) {
// Don't trust the verdicts.
}
// Check for the existence of the request_hash.
// If you set a request hash in the request and it's not present, you shouldn't
// trust the verdicts.
if (!request_details.contains("requestHash")) {
// Don't trust the verdicts.
}
// The requestHash from request_details needs to match the request hash your
// app provided.
if (request_details.value("requestHash", "") != <PROVIDED_REQUEST_HASH>) {
// Don't trust the verdicts.
}
// You can read the rest of payload's fields.
4단계: 무결성 확인 결과에 따라 취할 조치 결정
deviceIntegrity 필드에는 단일 값인 deviceRecognitionVerdict가 포함될 수 있습니다. 이 값을 사용하여 게임이 Play 무결성 검사를 통과하는 PC에서 실행 중인지 여부를 확인할 수 있습니다 (MEETS_PC_INTEGRITY 응답). accountDetails 필드에는 단일 값인 appLicensingVerdict가 포함됩니다. 이 값을 사용하여 사용자가 Play에서 라이선스를 받았는지 여부를 확인할 수 있습니다. 게임의 백엔드 서버는 이 정보를 수집하고 이를 사용하여 게임 이벤트 진행 허용 또는 위험한 트래픽에 대한 액세스 거부와 같이 게임에서 취해야 하는 조치를 결정할 수 있습니다.
"deviceIntegrity": {
"deviceRecognitionVerdict": ["MEETS_PC_INTEGRITY"]
}
"accountDetails": {
"appLicensingVerdict": "LICENSED"
}
기기 무결성 확인 결과
deviceRecognitionVerdict는 다음 값을 보유할 수 있습니다.
MEETS_PC_INTEGRITY- 게임이 기기 내 무단 변경이 감지되지 않은 정품 PC 환경에서 실행 중입니다.
- 비어 있음 (빈 값)
- 게임이 공격(예: API 후킹)이나 시스템 손상(예: 무단 변경된 Google 데스크톱 서비스 버전이 실행되는 기기) 징후가 있는 기기에서 실행되거나, 앱이 Google Play 무결성 검사를 통과하지 못한 에뮬레이터와 같은 실제 기기에서 실행되지 않습니다.
계정 세부정보 확인 결과
appLicensingVerdict는 다음 값을 보유할 수 있습니다.
LICENSED- 사용자에게 앱 사용 권한이 있습니다. 즉, 사용자가 기기의 Google Play에서 앱을 설치했거나 업데이트했습니다.
UNLICENSED- 사용자에게 앱 사용 권한이 없습니다. 예를 들어 사용자가 앱을 사이드로드하거나 Google Play에서 앱을 획득하지 않은 경우에 이러한 상황이 발생합니다.
UNEVALUATED- 필요한 요구사항을 충족하지 못하여 라이선스 세부정보가 평가되지 않았습니다.
이러한 상황은 다음과 같은 여러 가지 이유로 발생할 수 있습니다.
- 기기를 충분히 신뢰할 수 없습니다.
- 기기에 설치된 앱 버전을 Google Play에서 알 수 없습니다.
- 사용자가 Google Play에 로그인하지 않았습니다.
5단계: 오류 코드 처리
게임에서 PC용 Play Integrity 요청을 하고 호출이 실패하면 게임에서 오류 코드를 수신합니다. 이러한 오류는 네트워크 연결 불량과 같은 환경 문제, API 통합 문제, 악의적인 활동 및 활성 공격 등 다양한 이유로 발생할 수 있습니다.
재시도 가능한 오류 코드
이러한 오류의 원인은 일시적인 조건으로 인해 발생할 수 있으므로 지수 백오프 전략을 사용하여 호출을 다시 시도해야 합니다.
| IntegrityError | 오류 설명 | 오류 코드 |
|---|---|---|
kNetworkError |
기기의 네트워크 연결 문제입니다. | 5 |
kTooManyRequests |
기기에서 요청이 너무 많습니다. | 6 |
kClientTransientError |
클라이언트의 일시적인 문제입니다. | 7 |
재시도 전략에 관한 자세한 권장사항은 여기를 참고하세요.
재시도할 수 없는 오류 코드
이 경우에는 자동 재시도가 도움이 되지 않습니다. 단, 사용자가 문제의 원인이 된 조건을 해결한다면 수동 재시도가 도움이 될 수 있습니다.
| IntegrityError | 오류 설명 | 오류 코드 | 권장 조치 |
|---|---|---|---|
kError |
SDK 작업 중 치명적인 오류가 발생했습니다. | 1 | 다시 시도하기 전에 API 구현을 확인하세요. |
kCloudProjectNumberIsInvalid |
Cloud 프로젝트 번호가 잘못되었습니다. | 2 | Google Cloud 콘솔에서 클라우드 프로젝트 번호가 올바르게 구성되어 있고 올바른 클라우드 프로젝트 번호로 요청이 이루어지는지 확인합니다. |
kRequestHashTooLong |
요청 해시가 너무 깁니다. | 3 | 생성된 요청 해시가 너무 깁니다. 500자 미만인지 확인합니다. |
kNoValidPreparedTokenFound |
토큰 요청을 하기 전에 준비된 토큰이 없습니다. | 4 | [RequestIntegrityToken][request-integrity-token] 호출을 하기 전에 [PrepareIntegrityToken][prepare-token] 작업을 호출합니다. |
kSdkRuntimeUpdateRequired |
Play for Native SDK를 업데이트해야 합니다. | 8 | 기기의 Google Play 서비스 클라이언트가 최신 상태이고 최신 버전의 Play for Native PC SDK를 사용하고 있는지 확인합니다. |
앱 내에서 다양한 Play Integrity API 응답 테스트
Play Integrity API가 앱과 상호작용하는 방식을 평가하는 테스트를 만들 수 있습니다.
사용자의 이메일 주소로 Google 그룹을 하나 이상 설정합니다. Google Play 서버에서 앱에 표시할 무결성 확인 결과 또는 오류 코드를 선택할 수 있습니다. 이렇게 하면 앱이 가능한 모든 응답과 오류에 어떻게 반응하는지 테스트할 수 있습니다.
여기에서 티켓을 만들고 어떤 Google 그룹에 어떤 API 응답이 표시되는지 보고합니다. 각 그룹은 다음 선택사항 중 하나를 수신하도록 할당됩니다.
기기 무결성 확인 결과가 실패하면 라이선스 확인 결과는 항상 UNEVALUATED를 반환합니다.라이선스 확인 결과 통과 라이선스 확인 결과 실패 라이선스 확인 결과를 평가할 수 없음 기기 무결성 통과 ALLOWLIST_CONFIG_MEETS_PC_INTEGRITY_LICENSEDALLOWLIST_CONFIG_MEETS_PC_INTEGRITY_UNLICENSEDALLOWLIST_CONFIG_MEETS_PC_INTEGRITY_LICENSING_UNEVALUATED기기 무결성 실패 해당 사항 없음 해당 사항 없음 ALLOWLIST_CONFIG_NO_PC_INTEGRITY_LICENSING_UNEVALUATED요청이 처리되고 테스트 사용자가 테스트를 위해 미리 정의된 무결성 확인 결과를 수신할 수 있도록 허용 목록에 추가되면 알림이 전송됩니다.