시작하기
이 가이드는 OZero Security 설치부터 첫 번째 보안 기능 적용까지 단계별로 안내합니다. 보안 전문 지식이 없어도 약 3분이면 기본 설정을 완료할 수 있습니다.
개요
OZero Security는 일반 해킹 툴이 접근하기 어려운 Native C++ 레이어에서 보안 로직을 실행하여 Unity 게임을 보호합니다. Unity 에디터 내 대시보드에서 모듈을 활성화하는 것만으로 핵심 보호 기능이 동작합니다. 씬 설정이나 별도 코드 작성은 필요하지 않습니다.
- 빌드 무결성 검사 (앱 변조 탐지)
- 스피드핵 및 타임핵 탐지
- 메모리 인젝션 모니터링
- 암호화된 인게임 변수 타입 (Secure Types)
- 암호화된 세이브 파일 및 PlayerPrefs
- 활성화된 탐지기는 SDK 시작 시 자동으로 준비됩니다. 씬에 별도 오브젝트를 배치하거나 반복 초기화 코드를 작성할 필요가 없습니다.
- 보안 설정은 빌드 과정에서 보호되어 일반 플레이어 배포물에 평문 설정이 노출되지 않습니다.
- Native C++ 런타임 가드가 관리형 Unity 코드 바깥에서 추가 검증 계층을 제공합니다.
- 탐지 결과는 콜백, 로그, Pro 텔레메트리에서 확인할 수 있어 테스트와 운영 중 원인을 추적하기 쉽습니다.
1
패키지 임포트
Unity 에디터를 열고 OZero Security 패키지를 임포트합니다. Unity Package Manager를 통하거나 .unitypackage 파일을 더블클릭하여 임포트할 수 있습니다.
Import Unity Package 다이얼로그가 나타나면 모든 항목이 체크된 상태로 Import를 클릭하세요. 필요한 스크립트, 네이티브 플러그인, 에디터 도구가 자동으로 추가됩니다.
2
대시보드 열기
임포트가 완료되면 Unity 메뉴바에서 Config Dashboard를 엽니다:
Config Dashboard가 열리면 이 화면에서 프리셋, 보안 모듈, 라이선스, 빌드 무결성 설정을 한 번에 관리할 수 있습니다. Project 창에서 파일을 직접 찾아 수정할 필요는 없습니다.
Unity 에디터 메뉴 설명
OZeroSDK > Security 메뉴에는 SDK 설정과 진단 명령이 모여 있습니다. 보안 프리셋은 상단 메뉴가 아니라 Config & Dashboard에서 적용하도록 설계되어 있어, 저장 전에 변경될 설정을 확인할 수 있습니다.
| 메뉴 | 역할 | 사용 시점 |
|---|---|---|
| OZeroSDK > Security > Config & Dashboard | 메인 OZeroSecurityConfig 에셋을 열거나 생성합니다. | 프리셋 적용, 모듈 활성화, 대응 정책 설정, 빌드 무결성 설정 확인을 가장 먼저 여기서 진행합니다. |
| OZeroSDK > Security > License > Settings | OZeroLicenseConfig를 열거나 생성합니다. | Standard, Plus, Pro 라이선스 설정, 서버 엔드포인트, 텔레메트리 옵션을 입력할 때 사용합니다. |
| OZeroSDK > Security > Tools > Check Setup | 프로젝트와 릴리스 설정에서 자주 발생하는 문제를 에디터에서 진단합니다. | 패키지 임포트 직후, 릴리스 빌드 전, 또는 모듈 동작이 예상과 다를 때 실행합니다. |
| OZeroSDK > Security > Tools > Check Integrity Manifest | OZero 무결성 매니페스트를 열고 디코딩된 내용을 확인합니다. | 빌드 무결성 문제를 조사하거나 고객지원 중 매니페스트 내용을 확인할 때 사용합니다. |
| OZeroSDK > Security > Tools > Bake Security Config Blob | 보호된 보안 설정 blob을 StreamingAssets에 다시 생성합니다. | 고급 디버깅 또는 CI 흐름에서 사용합니다. 일반 플레이어 빌드에서는 자동으로 bake됩니다. |
| OZeroSDK > Security > Tools > Bake Assembly Hash | 가장 최근 빌드 결과물 기준으로 oz_ahash.bin을 다시 생성합니다. | 전체 빌드 파이프라인을 다시 돌리지 않고 코드만 재빌드한 경우에만 사용합니다. |
| OZeroSDK > Security > Tools > Keystore SHA Extractor | Android keystore에서 SHA-1, SHA-256 지문을 추출합니다. | Build Integrity의 Android 서명 지문 값을 채울 때 사용합니다. |
| OZeroSDK > Security > Tools > Add Debug SHA Key to Config | Android debug keystore를 찾아 SHA-256 지문을 config에 추가합니다. | 로컬 Android 디버그 빌드에서만 사용합니다. 릴리스 빌드는 릴리스 서명 키 지문을 사용해야 합니다. |
| OZeroSDK > Security > Tools > Steam Anti-Piracy > Scan Steam Redistributable | PC 빌드 또는 플러그인 폴더에서 Steam redistributable 파일과 알려진 emulator artifact를 스캔합니다. | Steam 릴리스 패키징 전이나 의심스러운 Steam 파일 포함 여부를 점검할 때 사용합니다. |
| OZeroSDK > Security > Tools > Check Time.timeScale Usage | OZero 시간 보호와 충돌할 수 있는 직접 Time.timeScale 수정 코드를 스캔합니다. | 릴리스 전 또는 Speed & Time Hack 모듈이 프로젝트 측 time-scale 정책 문제를 보고할 때 실행합니다. |
3
모듈 활성화
대시보드 안에서 보안 모듈 목록과 토글 스위치를 확인할 수 있습니다. 사용하려는 모듈을 활성화하세요. 아래는 권장 시작 구성입니다.
보안 프리셋 선택
먼저 프리셋을 선택한 뒤, 프로젝트에 맞춰 개별 모듈만 조정하세요. 일반적인 라이브 게임은 Standard부터 시작하는 것을 권장합니다. 보호 수준, 성능, 오탐 가능성의 균형이 가장 좋습니다.
| 프리셋 | 권장 사용처 | 적용 정책 요약 |
|---|---|---|
| Low | 프로토타입, 개발 빌드, 초기 QA | 가벼운 핵심 검사만 유지합니다. 테스트 환경이 너무 일찍 차단되지 않도록 플랫폼 네이티브 검사와 강제 종료 정책을 완화합니다. |
| Standard | 대부분의 출시 게임에 권장되는 기본값 | 핵심 보호 세트, 시작 시 검증, 런타임 재검증, 에뮬레이터 검사, 권장 IL2CPP 파일 커버리지를 켭니다. 호환성과 보호 수준의 균형을 맞춘 구성입니다. |
| Strict | 고위험 라이브 서비스, PvP, 경쟁형 빌드 | 가장 넓은 커버리지를 적용하고 더 많은 실패를 치명적 위반으로 처리합니다. 플랫폼, 서명, 스토어 배포 흐름을 충분히 테스트한 뒤 적용하세요. |
| 모듈 | 기능 설명 | 권장 여부 |
|---|---|---|
| Build Integrity Validator | 앱 바이너리 변조 여부 탐지 | 권장 |
| Speed Hack Detector | 시간 조작 치트 탐지 | 권장 |
| Injection Detector | 메모리 후킹 툴 모니터링 | 권장 |
| Install Source Validator | 불법 APK 차단 (Android 전용) | 선택 |
대시보드에서 사용할 모듈을 켜고 OZeroSecurityConfig 에셋을 저장하면 됩니다. 플레이어가 시작될 때 SDK가 활성화된 모듈을 자동으로 준비합니다.
라이선스 모델 — Standard / Plus / Pro
OZero Security는 Standard, Plus, Pro 세 가지 티어로 제공됩니다. Standard는 서버 연동 없이 로컬 보호 기능을 사용합니다. Plus는 프로젝트별 Native Variant 패키지와 매니페스트 / Bundle ID 바인딩을 추가합니다. Pro는 Plus 구성을 포함하고 텔레메트리, 서명된 서버 시간, 원격 정책, 서버 검증, 기기 한도 같은 운영 기능을 제공합니다.
| 항목 | Standard | Plus | Pro |
|---|---|---|---|
| 라이선스 키 | — (없음) | OZ-PLS-XXXX ×6 |
OZ-PRO-XXXX ×6 |
| 부팅 시 네트워크 | 필요 없음 — 오프라인 실행 가능 | 런타임 서버 불필요 — 포털에서 Variant 다운로드만 진행 | 디바이스당 POST /v1/activate 1회 후 캐시 |
| 10개 보호 모듈 | 10개 보호 모듈 전체 활성화 | 10개 전체 (로컬 보호 모듈은 Standard와 동일) | 10개 전체 (Standard와 동일) |
| 네이티브 Variant | 공용 네이티브 모듈 | 앱별 Variant + 매니페스트 바인딩 | 포함 |
| 클라우드 텔레메트리 | 전송하지 않음 | 꺼짐 (서버리스) | 켜짐 — 위협 이벤트를 /v1/telemetry로 전송 |
| 서명된 시간 (시계 조작 방지) | 꺼짐 — WebTime은 HTTPS HEAD만 사용 |
꺼짐 — Standard와 동일 | 켜짐 — 서명된 /v1/time 응답 사용 |
| 디바이스당 한도 | 무제한 (키 없음, 강제 없음) | 프로젝트 귀속 라이선스, 런타임 기기 한도 없음 | 기본 5대 / 조정 가능 |
| 소스 코드 접근 | 관리형 C#만 | 관리형 C#만 | 관리형 C#만 |
OZeroLicenseConfig 기반 서버 기능을 더합니다.
Plus / Pro 라이선스 키 등록
Standard 티어는 별도 설정이 필요 없습니다. Plus 또는 Pro는 ScriptableObject 에셋 1개를 추가하고 구매 후 받은 키를 붙여 넣습니다. Plus 키는 프로젝트별 Variant 검증과 포털 다운로드에 사용되고, Pro 키는 런타임 서버 활성화에도 사용됩니다.
1. 설정 에셋 생성
Config Dashboard (메뉴: OZeroSDK → Security → Config Dashboard)를 열고 License & Server 섹션에서 Create OZeroLicenseConfig 버튼을 클릭합니다. 에셋이 자동으로 올바른 Resources/ 폴더에 생성되므로 수동으로 이동할 필요가 없습니다.
Assets → Create → OZero → License Config로 수동 생성도 가능합니다. 단, 에셋이 Resources/ 폴더 아래에 있고 이름이 정확히 OZeroLicenseConfig(대소문자 구분)인지 직접 확인해야 합니다.
2. Inspector 필드 채우기
| 필드 | 필수 여부 | 설명 |
|---|---|---|
| tier | 모든 티어 | 드롭다운에서 Standard, Plus, Pro 중 하나를 선택합니다. Standard는 기본 네이티브 모듈을 사용합니다. Plus는 프로젝트에 연결된 Variant manifest가 필요합니다. Pro는 Plus 기능에 서버 운영 기능을 더합니다. |
| licenseKey | Plus / Pro | 이메일로 받은 키입니다. Plus 키는 OZ-PLS-..., Pro 키는 OZ-PRO-... 형식을 사용합니다. 키를 비워 두면 Plus 또는 Pro를 선택해도 서버 기능은 사용하지 않고 Standard와 같은 방식으로 실행됩니다. |
| appIdentifier | 자동 전송 | SDK는 활성화 시 Unity의 Application.identifier를 appIdentifier로 전송합니다. 서버는 이 값을 라이선스에 등록된 번들 / 패키지 id와 비교하므로, Player Settings의 Identifier가 발급된 키와 일치해야 합니다. |
| serverBaseUrl | Plus / Pro | 기본 https://api.ozero.security — OZero 지원팀이 별도 엔드포인트를 안내한 경우가 아니면 그대로 두세요. 릴리스 빌드에서는 반드시 HTTPS여야 하며, trailing slash는 자동으로 제거됩니다. |
| serverPublicKeyHex | Plus / Pro | OZero 라이선스 서버 응답의 서명을 확인하는 공개키입니다. 구매 이메일에 포함된 64자리 hex 값을 그대로 붙여 넣으세요. 출시 빌드에서는 이 값을 비워 두지 않는 것을 권장합니다. |
| tokenTtlSeconds | 선택 | 오프라인 상태에서 캐시된 활성화 결과를 신뢰하는 시간(초). 기본 604800 (7일). 만료 후에도 SDK는 계속 동작하지만, 다음 성공 활성화까지 서버 전용 기능(텔레메트리 / signed time)이 꺼집니다. |
| offlineProPolicyMode | Plus / Pro | 디바이스가 오프라인일 때 서명된 Pro 포털 차단 정책을 어떻게 적용할지 정합니다. 권장값은 ApplyCachedBlockPolicies입니다. RequireFreshPolicy는 정책이 오래되면 거부해야 하는 온라인 전용 게임에만 사용하세요. IgnoreCachedBlockPolicies는 특수한 테스트 상황을 위한 옵션이며 라이브 빌드에는 권장하지 않습니다. |
| activationTimeoutSeconds | 선택 | /v1/activate 응답을 기다리는 최대 시간(초)입니다. 이 시간을 초과하면 SDK는 저장된 활성화 정보를 사용하거나 Standard 방식으로 계속 실행합니다. 기본값은 6.0초입니다. |
| enableLog | 선택 | true이면 라이선스 캐시 사용, 활성화 성공, 타임아웃, 서명 불일치 같은 흐름을 OZeroSecLog로 기록합니다. 출시 빌드에서 로그를 줄이고 싶다면 끄세요. |
3. 빌드 & 검증
코드 변경은 필요 없습니다. 앱이 시작되면 SDK가 OZeroLicenseConfig 에셋을 자동으로 읽습니다. 첫 실행 후 Player 로그에서 [OZeroLicense] activated; tier=pro caps=5 같은 줄을 확인하세요. Pro로 설정했는데 Standard 모드로 실행된다는 로그가 보이면 에셋이 Resources/ 폴더 아래에 있고 이름이 정확히 OZeroLicenseConfig인지 확인하세요.
서버 활성화 흐름
활성화는 앱 시작 시 백그라운드에서 진행됩니다. 서버 응답이 늦거나 일시적으로 실패해도 씬 로드를 막지 않고, 저장된 활성화 정보가 있으면 그 값을 사용합니다.
부팅 시퀀스
- SDK는 앱 시작 시 라이선스 런타임을 자동 초기화합니다.
- Standard와 Plus는 런타임 서버 호출 없이 계속 진행됩니다.
- Pro는 백그라운드에서 가벼운 활성화 요청을 보냅니다.
- 활성화에 성공하면 텔레메트리, signed time, attestation 같은 Pro 서버 기능이 사용 가능해집니다.
- 활성화 실패, 만료, 타임아웃이 발생해도 플레이어에게 오류를 표시하지 않고 Standard 모드로 계속 실행됩니다.
네트워크에 흐르는 데이터
활성화 요청은 작은 JSON POST입니다. 필수 필드는 licenseKey, deviceId, sdkVersion, platform입니다. appIdentifier, companyName, productName, webglOrigin은 Unity에서 비어 있지 않은 값을 제공할 때만 추가됩니다. 기기 식별자 소스는 OZeroLicenseRuntime.DeviceIdProvider로 오버라이드할 수 있습니다.
POST https://api.ozero.security/v1/activate
Content-Type: application/json
{
"licenseKey": "OZ-PRO-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX",
"deviceId": "<DeviceIdProvider result; default SystemInfo.deviceUniqueIdentifier>",
"sdkVersion": "<OZeroSdkVersion.ManagedVersion>",
"platform": "<android | ios | windows | macos | linux | webgl | ...>",
"appIdentifier": "<Application.identifier>",
"companyName": "<Application.companyName>",
"productName": "<Application.productName>",
"webglOrigin": "<WebGL origin only>"
}
서버는 서명된 토큰, 결정된 티어, 사용할 수 있는 기능 목록, 만료 시각을 JSON으로 반환합니다. SDK는 설정된 공개키로 응답 서명을 확인한 뒤에만 Pro 기능을 활성화합니다.
서버 기능을 사용할 수 없을 때
서버 점검, 네트워크 타임아웃, 라이선스 만료/정지/폐기, Bundle ID 불일치는 곧바로 해킹으로 판단하지 않습니다. 이 경우 Pro 전용 기능만 비활성화하고 기본 보호 기능은 계속 실행합니다. 반대로 빌드 불일치, 차단된 빌드, 인젝션, 디버거처럼 변조가 명확한 상황은 설정된 대응 정책을 따릅니다.
await OZeroLicenseRuntime.Initialize();를 호출하고 OZeroLicenseRuntime.Entitlement?.cachedAtMillis를 살펴보세요. 최근 몇 초 이내 값이면 서버가 방금 응답한 것이고, 더 오래된 값이면 캐시 기반으로 동작 중입니다.
오프라인 동작
OZero는 네트워크 상태와 무관하게 플레이어가 항상 게임을 실행할 수 있도록 설계되었습니다. 정확한 동작은 티어에 따라 다릅니다:
Standard — 항상 오프라인
Standard는 서버 활성화나 텔레메트리 전송 없이 로컬 보호 기능만 실행합니다. 네트워크가 없어도 게임은 그대로 시작되며, Pro 전용 기능만 사용되지 않습니다.
Pro — TTL 내 오프라인 가능
지정 디바이스에서 /v1/activate가 처음 성공한 후, Pro 활성화 정보는 PlayerPrefs에 저장됩니다(기기 바인딩 키로 암호화 — 아래 캐시 보안 참조). 이후 실행에서는 네트워크 호출이 시작되기 전에 저장된 활성화 정보를 읽으므로, 플레이어가 오프라인이어도 SDK는 어떤 티어이고 어떤 Pro 기능이 사용 가능한지 알 수 있습니다.
저장된 Pro 활성화 정보는 활성화 시점에 기록된 cachedAtMillis로부터 tokenTtlSeconds 동안 신뢰됩니다. 기본 7일(604800)입니다. 그동안 계속 오프라인 상태로 시간이 지나면 저장된 정보는 폐기되고, 다음 온라인 활성화가 성공할 때까지 SDK는 Standard 수준으로 동작합니다. 디텍터는 계속 동작하며, 텔레메트리 전송과 signed-time 검증만 꺼집니다.
Pro — 서명된 오프라인 차단 정책
서버 장애 시 기본 보호로 계속 실행되는 것과, 포털에서 명시적으로 차단한 빌드를 허용하는 것은 다릅니다. Pro 활성화가 성공하면 서버는 현재 차단 정책을 서명된 형태로 내려주고, SDK는 이를 별도로 저장합니다.
권장값인 ApplyCachedBlockPolicies 모드에서는 서명된 정책이 유효한 동안 플레이어가 비행기 모드로 실행하더라도 차단된 manifest hash, SDK 버전, 앱 버전이 Build Integrity에서 계속 거부됩니다. 정책은 서명 토큰 TTL을 따르므로 포털에서 차단 규칙을 바꾼 뒤에는 한 번의 온라인 활성화가 필요합니다.
| 상태 | 디텍터 | 텔레메트리 | Signed Time |
|---|---|---|---|
| 온라인, 방금 활성화 | 10개 모두 On | On | On |
| 오프라인, 캐시 < TTL | 10개 모두 On | 큐 (다음 온라인 시 전송) | WebTime HTTPS HEAD 사용 |
| 오프라인, 캐시 > TTL | 10개 모두 On | Off (강등) | Off (강등) |
| 캐시 없음 (첫 실행 + 오프라인) | 10개 모두 On | 첫 온라인 실행까지 Off | 첫 온라인 실행까지 Off |
트러블슈팅
모든 라이선스 이벤트는 기본적으로 Unity의 Debug.Log로 라우팅되는 OZeroSecLog를 통해 기록됩니다 (OZeroSecurityConfig에서 설정 가능). Player 로그를 [OZeroLicense] 접두사로 필터링하여 부팅 시점의 결정을 확인하고, [OZeroTelemetry]로 리포터를 확인하세요. 일반적인 증상과 해결책:
| 증상 (로그 라인) | 예상 원인 | 확인할 사항 |
|---|---|---|
[OZeroLicense] Standard / serverless mode. |
에셋 누락 또는 tier=Standard 또는 빈 키 | OZeroLicenseConfig.asset이 Resources/ 폴더 아래에 있고 이름이 정확히 OZeroLicenseConfig이며 tier=Pro이고 비어 있지 않은 licenseKey를 가지고 있는지 확인하세요. |
/v1/activate failed: 401: invalid_key |
키 오타 또는 잘못된 티어 접두사 | 원본 구매 이메일에서 키를 다시 붙여넣으세요. 형식은 대소문자를 구분하며, 대시가 포함되어야 하고, 접두사는 OZ-PRO-여야 합니다. |
/v1/activate failed: 403: bundle_mismatch |
appIdentifier 불일치 |
서버 측 라이선스 기록은 키를 특정 번들 / 패키지 id에 바인딩합니다. Player Settings의 Application.identifier가 라이선스에 등록된 id와 일치하는지 확인하세요. |
activation token signature verification failed |
잘못된 serverPublicKeyHex 또는 MITM |
에셋의 hex 문자열을 구매 이메일의 표준 공개키와 비교하세요 — 64개의 hex 문자가 한 글자도 빠짐없이 일치해야 합니다. 정확한데도 계속 실패한다면 기업 프록시/MITM 어플라이언스를 의심하고 직접 모바일 데이터 연결을 시도해 보세요. |
/v1/activate timed out |
네트워크 지연 / 방화벽 | SDK는 자동으로 저장된 활성화 정보를 사용합니다. 첫 실행이거나 저장된 정보가 없을 때만 문제가 됩니다. 기기가 https://api.ozero.security/health에 도달할 수 있는지 확인하세요. 지연이 심한 지역에서 운영하는 경우 activationTimeoutSeconds를 늘리세요. |
cached activation past TTL; clearing. |
플레이어 오프라인 > TTL | 정상입니다. 디텍터는 계속 작동합니다; 다음 온라인 실행까지 텔레메트리 / signed-time은 꺼집니다. 사용자가 7일 이상 오프라인으로 플레이하는 경우가 많다면 tokenTtlSeconds를 늘리세요. |
cache hit; tier=pro on a different machine than expected |
디바이스 지문 변경 | SystemInfo.deviceUniqueIdentifier가 변경되면(일부 Android ROM / OS 초기화), 저장된 활성화 정보를 읽을 수 없어 SDK가 다시 활성화를 시도합니다. 사용자 조치는 필요 없습니다. 다음 온라인 실행 시 복구됩니다. |
enableLog를 꺼 두는 것을 권장합니다. 개발 로그에는 티어, 기능 상태, 탐지 흐름 일부가 남을 수 있어 QA에는 유용하지만, 일반 사용자 배포에는 필요하지 않습니다.
프로젝트 설정
개별 보안 모듈을 조정하기 전에, 네이티브 플러그인과 스토어 빌드, 플랫폼 검증에 영향을 주는 Unity Player Settings를 먼저 확인하세요.
최소 빌드 타겟
| 플랫폼 | 최소 타겟 | 설명 |
|---|---|---|
| iOS | 12.0+ |
iOS 빌드에서는 Project Settings > Player > iOS > Target minimum iOS Version을 12.0 이상으로 설정하세요. OZero는 이 PlayerSettings 값을 강제로 덮어쓰지 않으므로, 앱의 지원 정책에 맞춰 유지하면 됩니다. |
| Android | API 21+ |
Android 빌드는 Project Settings > Player > Android > Minimum API Level을 Android 5.0 Lollipop (API level 21) 이상으로 설정하세요. 스토어 릴리스 빌드는 IL2CPP와 ARM64 사용을 권장합니다. |
릴리스 빌드의 IL2CPP와 Managed Stripping
Android, iOS, standalone 릴리스 빌드에서는 Unity가 지원하는 경우 IL2CPP를 우선 사용하세요. IL2CPP가 역분석을 불가능하게 만드는 것은 아니지만, 평문 managed metadata 노출을 줄이고 OZero의 native 무결성 검사가 더 강한 릴리스 기준에서 동작하게 해 줍니다.
Project Settings > Player > Other Settings > Scripting Backend를 IL2CPP로 설정하세요. 릴리스 빌드의 Managed Stripping Level은 Low 또는 Medium부터 적용하고, 대상 기기에서 클린 실행 스모크 테스트를 진행하세요. reflection, serialization, Addressables, 서드파티 SDK 흐름을 검증하기 전에는 더 강한 stripping 단계로 바로 올리지 마세요.
Android ProGuard / R8 설정
OZero Security는 별도의 Java SDK 패키지를 요구하지 않습니다. 다만 Android 릴리스 빌드에서 Minify, ProGuard, R8을 활성화했다면 Unity Java 브리지와 프로젝트에서 사용하는 커스텀 Android 브리지 클래스를 보존해야 합니다. 그래야 패키지 정보, 설치 출처, APK 서명 인증서 검사, 부트 에셋 로딩에 필요한 JNI 호출이 난독화 이후에도 안정적으로 동작합니다.
proguard-user.txt에 추가하세요. Minify를 사용하지 않는 경우 별도 ProGuard 설정은 필요하지 않습니다.
# OZero Security - Unity Android ProGuard/R8 keep rules
-keep class com.unity3d.player.UnityPlayer { *; }
-keep class com.unity3d.player.UnityPlayerActivity { *; }
-keep class com.unity3d.player.UnityPlayerGameActivity { *; }
-keep class com.unity3d.player.UnityPlayerForActivityOrService { *; }
-keepattributes *Annotation*,InnerClasses,EnclosingMethod,Signature
# If your game adds custom Java/Kotlin bridge classes that OZero or your code
# calls through AndroidJavaClass / AndroidJavaObject, keep those classes too.
# Replace the package below with your own bridge package.
# -keep class com.yourcompany.yourgame.bridge.** { *; }
libOZeroSecurity.so를 이름 변경, 삭제, 재패키징하지 마세요. 플러그인은Assets/OZeroSDK/Plugins/Android/arm64-v8a아래에 유지하고, 32비트 빌드를 배포한다면armeabi-v7a도 함께 유지하세요.- Build Integrity > Check Platform Native와 Android SHA Keys를 사용하는 경우, Minify/R8 적용 후 최종 서명된 APK 또는 AAB로 반드시 테스트하세요. 디버그 키스토어 지문과 릴리스 키스토어 지문은 서로 다릅니다.
- Minify를 켠 뒤에만 Android 로그에서 JNI 조회 실패, 설치 출처 감지 실패, APK 서명 검사 결과 비어 있음이 보인다면 먼저 커스텀 브리지 keep 규칙을 확인하세요.
- 스토어 배포용 빌드는 IL2CPP, 릴리스 서명,
Android Sha Keys에 등록된 예상 Android SHA-256 지문, 그리고 최소 한 대 이상의 실제 기기 클린 실행 테스트를 기준으로 검증하세요.
5
OZeroSecurityConfig 설정
OZeroSecurityConfig ScriptableObject 에셋은 패키지 임포트 시 포함됩니다. Project 창에서 선택하여 모든 보안 모듈 설정을 확인하고 조정하세요. 런타임에서는 OZeroSecurityConfig.Instance로 접근합니다.
Common Setting
모든 모듈에 전역으로 적용되는 최상위 필드입니다.
| 필드 | Type | 기본값 | 설명 |
|---|---|---|---|
| developerSecret | string | — | 암호화 키 도출에 사용되는 고유 패스프레이즈입니다. 게임에 고유한 값으로 설정하고 비밀로 유지하세요. 출시 후 변경 시 기존 세이브 데이터를 읽을 수 없게 됩니다. |
| enableLog | bool | false | Enable Debug Logs를 켜면 SDK 초기화, 설정 로딩, 라이선스/텔레메트리 흐름, 탐지 이벤트 같은 내부 상태를 Unity Console과 Player 로그에 출력합니다. 개발/QA 단계에서 원인 파악에 유용하지만 탐지 흐름과 모듈 상태가 노출될 수 있으므로 운영 빌드에서는 끄는 것을 권장합니다. |
| enableFailureDiagnostics | bool | false | Enable Failure Diagnostics를 켜면 보안 위반이 발생했을 때 로컬 진단 파일을 Application.persistentDataPath에 저장합니다. 파일에는 모듈명, 해시, 기기 상태, 설치 패키지명, 런타임 설정 일부가 포함될 수 있으므로 QA나 고객 지원 세션에서만 켜는 것을 권장합니다.플랫폼별 기본 저장 위치:
|
Developer Secret을 설정하세요. 기본값을 사용하지 말고 출시 후에는 변경하지 마세요.
Global Threat Response
보안 위협이 확인되었을 때 게임이 어떻게 반응할지 정합니다. 테스트 중에는 콜백과 로그를 먼저 확인하고, 실제 배포 빌드에서는 플레이어에게 안내할 시간과 종료 정책을 프로젝트 운영 방식에 맞춰 선택하세요.
| 필드 | Type | 기본값 | 설명 |
|---|---|---|---|
| forceQuitOnDetection | bool | true | forceQuitOnDetection은 확정 위협이 감지되었을 때 SDK가 게임을 자동 종료할지 결정합니다. 끄면 콜백과 로그만 확인할 수 있어 QA에는 편하지만, 실제 배포 빌드에서는 우회된 클라이언트가 계속 실행될 수 있으므로 신중하게 선택하세요. |
| fatalCallbackGraceSeconds | float | 10 | fatalCallbackGraceSeconds는 위협 감지 후 게임 쪽 보안 콜백이 플레이어 안내 UI를 보여줄 수 있는 최대 시간입니다. 기본값은 10초입니다. 0으로 설정하면 안내 시간을 두지 않고 즉시 종료하는 이전 방식으로 동작합니다. |
빌드 무결성 검증기 설정
수정된 게임 파일, 디버거 연결, 비정상적인 실행 환경을 감지하는 빌드 무결성 검사기를 구성합니다.
| 필드 | Type | 기본값 | 설명 |
|---|---|---|---|
| Activate Build Integrity | checkbox | On | Build Integrity 모듈을 활성화합니다. |
| validateOnStartup | bool | true | 게임 실행 즉시 빌드 무결성 검사를 실행합니다. |
| validateInEditor | bool | false | Unity 에디터에서도 검증을 실행합니다(테스트용으로 유용하지만 일반 개발 중에는 끄는 것을 권장). |
| enablePeriodicValidation | bool | true | 게임 실행 중에도 무결성 검증을 반복합니다. 시작 시 1회 검증만으로 충분한 빌드가 아니라면 켜두는 것을 권장합니다. |
| periodicCheckInterval | float | 300 s | 게임 실행 중 주기적인 보안 검사가 실행되는 간격(초)입니다. |
| periodicCheckJitterPercent | float | 35% | 검증 주기에 무작위 변화를 더해 검사 타이밍을 예측하기 어렵게 합니다. 구체적인 주기와 범위는 공개 문서에서 안내하지 않으며, 기본값 사용을 권장합니다. |
| timingAnomalyConsecutiveRequired | int | 7 | 타이밍 기반 이상 신호가 몇 번 누적되어야 디버거 타이밍 드리프트로 판단할지 정합니다. 강한 디버거 신호는 즉시 실패할 수 있습니다. |
| timingAnomalyWindowSeconds | float | 900 s | 타이밍 기반 이상 신호를 누적하는 시간 창입니다. 길수록 관대하고, Strict는 더 짧은 창을 사용합니다. |
| timingAnomalyFrameHitchSuppressionSeconds | float | 20 s | 씬 로딩, 셰이더 컴파일, GC, OS 스케줄링 지연처럼 큰 프레임 히치가 발생한 뒤 일정 시간 동안 타이밍 기반 디버거 검사를 완화합니다. |
| checkAssemblyHash | bool | true | 빌드 무결성 검사의 일환으로 컴파일된 DLL 어셈블리의 해시를 검증합니다. |
| checkDebugger | bool | true | 런타임에 디버거가 프로세스에 연결되어 있는지 탐지합니다. |
| failOnDebugBuild | bool | false | Unity 디버그 빌드를 위반으로 간주합니다(릴리스 빌드에서 권장). |
| checkPlatformNative | bool | true | 에뮬레이터나 비정상적인 환경에서 실행 중인 징후를 확인합니다. |
| failIfManifestMissing | bool | true | oz_manifest.ozero 파일이 없거나 읽을 수 없으면 위반으로 처리합니다. 출시 빌드에서는 이 값을 켜 두어 매니페스트가 빠진 빌드가 배포되지 않도록 하세요. |
| failIfAssemblyHashBlobMissing | bool | true | 매니페스트에 번들된 어셈블리 해시 블롭이 없을 경우 위반으로 처리합니다. |
| requireCodeSignature (Windows) | bool | false | 메인 실행 파일이 코드 서명되어 있어야 합니다. Windows 전용. |
| blockVirtualMachine (Windows) | bool | false | 가상 머신 내부에서 게임 실행을 차단합니다. Windows 전용. |
| blockHyperV (Windows) | bool | false | Hyper-V VMBus 신호를 차단합니다. WSL2, Docker Desktop, Windows Sandbox 사용자도 막힐 수 있으므로 통제된 환경에서만 신중히 사용하세요. |
| blockNetworkProxies (Windows) | bool | false | 네트워크 프록시, 패킷 검사, 트래픽 분석 도구로 의심되는 실행 신호를 감지합니다. 경쟁형 빌드에서 사용하되 오탐 가능성을 테스트하세요. |
| blockReverseEngineeringTools (Windows) | bool | false | 역공학 또는 디버깅 도구로 의심되는 실행 신호를 감지합니다. 개발/QA 환경과 라이브 환경을 분리해 검증하세요. |
| blockSystemMonitorTools (Windows) | bool | false | 프로세스/시스템 모니터링 도구로 의심되는 실행 신호를 감지합니다. 일반 사용자 환경에서 오탐 가능성을 고려하세요. |
| il2cppHashGameAssembly | bool | true | Windows IL2CPP 빌드의 GameAssembly.dll을 해시 검증합니다. IL2CPP 파일 보호의 최소 권장 항목입니다. |
| il2cppHashGlobalGameManagers | bool | true | IL2CPP 매니페스트 검증 범위에 globalgamemanagers를 추가합니다. |
| il2cppHashSharedAssets | bool | true | IL2CPP 검증 범위에 sharedassets* 파일을 추가합니다. |
| il2cppHashSceneFiles | bool | true | IL2CPP 검증 범위에 level* 같은 Unity 씬 파일을 추가합니다. |
| il2cppHashResourcesAssets | bool | false | IL2CPP 검증 범위에 resources.assets를 추가합니다. Strict 모드에 유용하지만 패치 흐름을 먼저 테스트하세요. |
| il2cppAdditionalWatchedFiles | List<string> | — | 프로젝트가 별도 네이티브 페이로드를 포함하는 경우, 추가로 감시할 Windows IL2CPP 출력 파일을 지정합니다. |
| blockEmulator (Android) | bool | true | Android 전용입니다. 에뮬레이터 또는 미지원 런타임 신호를 무결성 위반으로 취급합니다. QA/에뮬레이터 테스트 중에는 완화하고, 프로덕션 빌드에서는 더 엄격한 정책을 권장합니다. |
| blockSystemRwMount (Android) | bool | true | Android 전용입니다. 시스템 파티션이 쓰기 가능하거나 root 계열 mount 상태가 보이면 무결성 위반으로 처리합니다. |
| androidShaKeys | List<string> | — | 기대되는 APK 서명 인증서의 SHA-256 지문 목록. 설치된 APK가 이 키 중 하나로 서명되지 않았다면 검증에 실패합니다(Android 전용). |
| expectedBundleIds (iOS) | List<string> | — | 허용할 iOS Bundle ID 목록입니다. 비워두면 Bundle ID 검사를 건너뜁니다. |
| excludedAssemblies | List<string> | — | 해시 검증에서 제외할 어셈블리 이름 목록(.dll 확장자 제외). 런타임에 변경되는 어셈블리(예: 생성된 코드)에 사용하세요. |
| checkIntegrityWithServer (Pro) | bool | false | Pro 서버 Attestation을 켭니다. 클라이언트가 nonce를 요청하고 무결성 증거를 제출한 뒤, 게임 서버 또는 OZero 서버가 검증할 수 있는 서명된 OZA 토큰을 받습니다. 서버에서는 nonce를 manifest hash, platform, SDK version, 앱 식별 정보와 함께 묶어 재사용/증거 바꿔치기를 줄입니다. |
| enableManagedVerification (Pro) | bool | false | 자체 게임 서버가 없는 팀을 위한 위임 검증 옵션입니다. 발급된 OZA 토큰을 OZero 서버가 다시 검증하고 허용/경고/차단 결과와 짧은 세션을 반환합니다. SDK는 세션이 만료되기 전에 자동으로 재검증을 시도합니다. checkIntegrityWithServer가 켜져 있어야 합니다. |
| requireManagedVerification (Pro) | bool | false | 켜면 위임 검증 네트워크 실패도 검증 실패로 처리합니다. 일반적으로는 꺼두고 기본(Standard) 보호로 자동 전환되게 두는 것을 권장합니다. |
| attestRefreshLeadSeconds (Pro) | float | 300 s | OZA 토큰 만료 전에 몇 초 먼저 갱신을 시도할지 정합니다. 0이면 만료 전 선갱신을 사용하지 않습니다. |
| attestRefreshCooldownSeconds (Pro) | float | 30 s | Attestation 갱신 시도 사이의 최소 대기 시간입니다. |
| manifestSigningPublicKey | string | — | requireManifestSignature가 활성화된 경우, 매니페스트 서명 검증에 사용되는 RSA 공개키(PEM). |
| requireManifestSignature | bool | false | 무결성 매니페스트 자체가 manifestSigningPublicKey로 서명되었는지 검증합니다. |
| manifestSigningPrivateKeyPath | string | OZeroSigningKeys | 빌드 시 manifest 서명에 사용할 private key PEM 경로입니다. Editor 전용이며 플레이어 빌드에는 포함되지 않습니다. |
Events
| Event | Description |
|---|---|
| OnValidationPassed | 로컬 무결성 검사가 위반 없이 완료되었을 때 발생합니다. Pro 서버 검증(attestation)은 아직 진행 중일 수 있습니다. |
| OnAttestationPassed | Pro OZA 검증(attestation) 토큰이 실제 발급된 뒤에만 발생합니다. 게임 서버 로그인, PvP, 랭킹, 재화 흐름은 이 이벤트 또는 AttestationToken.IsValid(nowMillis)로 검사해 통과한 경우에만 진행하세요. |
| OnValidationFailed | 무결성 검사가 위반을 감지했을 때 발생합니다. 글로벌 onHackDetected 이벤트도 ModulationType.BuildIntegrity와 함께 트리거됩니다. |
RSA 서명 키 생성 (빌드 무결성)
빌드 무결성을 활성화하고 Require Manifest Signature를 켠 경우, OZero는 공개키 기반 서명으로 무결성 매니페스트가 바뀌지 않았는지 확인합니다. 릴리스 빌드를 만들기 전에 Unity 에디터에서 키 쌍을 반드시 생성하세요.
빌드 시점에 OZero는 개인 키로 어셈블리 매니페스트를 서명하고 그 결과 서명을 빌드에 포함시킵니다. 런타임에는 OZeroSecurityConfig에 저장된 공개 키로 서명을 검증합니다. 서명이 일치하지 않으면 — 즉 매니페스트 또는 바이너리가 변조된 경우 — 게임은 이를 변조로 간주하고 Response Settings에 따라 대응합니다.
키 쌍 생성하기
- Unity 에디터에서 Project 창의
OZeroSecurityConfig를 선택합니다. - 인스펙터에서 Build Integrity 섹션을 펼칩니다.
- Require Manifest Signature 체크박스를 활성화합니다.
- Generate Key Pair 버튼을 클릭합니다.
- OZero가 서명 키 쌍을 생성합니다. 공개 키는
OZeroSecurityConfig에 저장되고, 개인 키는 다음 경로에 저장됩니다:[ProjectRoot]/OZeroSigningKeys/manifest_private_key.pem - 개인 키 위치를 보여주는 확인 대화상자가 나타납니다. OK를 클릭하여 닫습니다.
- 개인 키 파일은 Unity가 빌드에 포함시키지 않도록
Assets/폴더 외부에 저장됩니다. 절대로Assets/안으로 이동하지 마세요. OZeroSigningKeys/를 즉시.gitignore에 추가하세요. 개인 키를 버전 관리에 커밋하는 것은 심각한 보안 위험입니다.- 개인 키를 안전한 오프라인 장소(암호화된 USB 드라이브, 패스워드 매니저 등)에 백업하세요. 이 파일을 가진 사람은 누구든 유효한 매니페스트를 위조할 수 있습니다.
- 개인 키를 분실한 경우 새 키 쌍을 생성해야 합니다. 새 공개 키는 다음 빌드에 자동으로 포함됩니다. 기존에 출시된 빌드는 모두 새 공개 키로 매니페스트 검증에 실패하므로 업데이트를 배포해야 합니다.
사용자 지정 개인 키 경로 (CI/CD & 팀 환경)
인스펙터의 Manifest Signing — Editor Only 아래에 있는 Manifest Signing Private Key Path 필드에서 개인 키의 대체 위치를 지정할 수 있습니다. 다음 두 가지 상황에서 유용합니다:
- CI/CD 파이프라인 — 개인 키를 CI 시크릿으로 저장하고 빌드 시에 경로를 주입하면 빌드 머신이 키를 영구적으로 디스크에 보관하지 않아도 됩니다.
- 팀 환경 — 키를 공유 보안 서버나 시크릿 매니저에 보관하고 필드를 마운트 경로로 지정합니다. 릴리스 빌드를 실행하는 팀원만 접근 권한을 가지면 됩니다.
기존 키 쌍 유효성 검사
디스크의 개인 키와 OZeroSecurityConfig에 저장된 공개 키가 일치하는지 확인하려면 Validate Key Pair 버튼을 클릭하세요. OZero가 개인 키로 소규모 테스트 페이로드에 서명하고 공개 키로 검증합니다. 일치하면 성공 메시지가 표시되고, 일치하지 않으면 새 쌍을 생성해야 합니다.
- 개인 키를 분실하거나 유출된 경우.
- Validate Key Pair에서 불일치를 보고하는 경우(키가 동기화되지 않음).
- 예정된 보안 정책의 일환으로 의도적으로 키를 교체하는 경우.
재생성 후에는 새 공개 키가 다음 빌드에 자동으로 포함됩니다. 기존에 출시된 빌드는 새 공개 키로 매니페스트 검증에 실패하므로 업데이트를 배포해야 합니다.
듀얼 핑거프린트 무중단 키 회전
Generate Key Pair 버튼을 누르면 공개 키가 OZeroSecurityConfig에 저장되고, 같은 키를 식별하는 fingerprint가 OZeroManifestTrustAnchor.cs에도 기록됩니다. 런타임에는 이 두 값이 맞는지 확인한 뒤 매니페스트 서명을 검증합니다. 값이 서로 맞지 않으면 매니페스트를 신뢰하지 않습니다.
OZeroManifestTrustAnchor.cs에는 현재 사용할 키 fingerprint와, 키 회전 기간에만 임시로 허용할 이전 키 fingerprint를 기록할 수 있습니다. 평소에는 현재 키만 사용하고, 새 키로 교체할 때만 이전 키 슬롯을 잠시 채워 둡니다. 이렇게 하면 새 빌드를 배포하는 동안 기존 빌드 사용자가 갑자기 매니페스트 검증에 실패하는 일을 줄일 수 있습니다.
키 회전 절차
- 현재 fingerprint를 백업합니다.
Assets/OZeroSDK/Scripts/Security/BuildIntegirity/OZeroManifestTrustAnchor.cs를 열어ExpectedPublicKeyFingerprintHex값을 복사해 둡니다. - 이전 키 슬롯에 등록합니다. 같은 파일의
PreviousPublicKeyFingerprintHex에 1단계에서 복사한 값을 붙여 넣고 저장합니다. - 새 키 쌍을 생성합니다.
OZeroSecurityConfig인스펙터에서 Generate Key Pair를 클릭하고 재생성 확인창에서 진행합니다. 새 공개 키와 새 fingerprint가 자동으로 갱신됩니다. - 새 릴리스 빌드를 배포합니다. 새 매니페스트는 새 개인 키로 서명됩니다.
- 업데이트 전환 기간을 둡니다. 기존 빌드와 새 빌드가 함께 쓰이는 기간에는 이전 키도 허용해야 합니다. 라이브 게임에서는 보통 1~4주 정도를 기준으로 잡습니다.
- 이전 키 슬롯을 비웁니다. 옛 빌드 사용량이 충분히 낮아진 뒤
PreviousPublicKeyFingerprintHex = ""로 되돌리고 한 번 더 릴리스하면 회전이 완료됩니다.
라이브 서비스에서는 모든 사용자가 동시에 새 버전으로 이동하지 않습니다. 이전 키 슬롯을 잠시 유지하면 기존 빌드와 새 빌드가 함께 있는 동안 매니페스트 검증 실패를 줄일 수 있습니다. 충분한 전환 기간이 지난 뒤 이전 키 슬롯을 비우면 됩니다.
트러블슈팅
대부분의 키 관련 오류는 개인 키, OZeroSecurityConfig의 공개 키, OZeroManifestTrustAnchor의 fingerprint가 서로 맞지 않을 때 발생합니다. 아래 항목을 순서대로 확인하세요.
ExpectedPublicKeyFingerprintHex가 비어 있을 수 있습니다. 해결: Unity 에디터에서 Generate Key Pair를 한 번 실행한 뒤 클린 빌드하세요. 값이 이미 채워져 있는데도 실패한다면 이전 빌드 산출물이 남아 있을 수 있으므로 빌드 폴더를 비우고 다시 빌드하세요.
OZeroSecurityConfig.Integrity.ManifestSigningPublicKey가 비어 있을 때 발생합니다. 해결: 인스펙터에서 OZeroSecurityConfig를 열고 Build Integrity 섹션의 Generate Key Pair를 클릭한 뒤 다시 빌드하세요.
OZeroSecurityConfig의 공개 키와 코드에 기록된 fingerprint가 맞지 않을 때 발생합니다. 해결: Unity 에디터에서 Tools → OZero → Validate Manifest Signing Keys를 실행하세요. 도구가 불일치를 보고하면 Generate Key Pair로 새 키 쌍을 발급한 뒤 다시 빌드하세요. 배포된 빌드에서 이 메시지가 보이면 APK 또는 실행 파일이 재패키징되었는지도 확인해야 합니다.
새 키를 배포하기 전에 이전 fingerprint를 PreviousPublicKeyFingerprintHex에 등록하지 않았을 가능성이 큽니다. 해결: 이전 fingerprint를 Previous 슬롯에 넣은 핫픽스 빌드를 배포하고, 충분한 전환 기간이 지난 뒤 Previous 슬롯을 비우세요.
CI 머신에 OZeroSigningKeys/manifest_private_key.pem이 없을 때 발생합니다. 해결: 개인 키를 CI Secret에 보관하고, Unity 빌드 직전에 같은 경로로 복원하세요. 또는 OZeroSecurityConfig의 Manifest Signing Private Key Path에 CI에서 접근 가능한 보안 경로를 지정하세요. 모든 릴리스 빌드 머신은 같은 개인 키를 사용해야 합니다.
설치 출처 설정
게임이 승인된 스토어 또는 경로에서 설치된 경우에만 실행되도록 제한합니다. 사이드로드 또는 재패키징된 APK 방지에 유용합니다.
| 필드 | Type | 기본값 | 설명 |
|---|---|---|---|
| Activate Install Source | bool | true | Install Source 모듈을 활성화합니다. |
| allowGooglePlayStore | bool | true | Google Play 스토어를 통한 설치를 허용합니다. |
| allowSamsungGalaxyStore | bool | false | Samsung Galaxy Store를 통한 설치를 허용합니다. |
| allowAmazonAppstore | bool | false | Amazon Appstore를 통한 설치를 허용합니다. |
| allowHuaweiAppGallery | bool | false | Huawei AppGallery를 통한 설치를 허용합니다. |
| allowOneStore | bool | false | 원스토어(한국)를 통한 설치를 허용합니다. |
| allowXiaomiGetApps | bool | false | Xiaomi GetApps를 통한 설치를 허용합니다. |
| allowOppoAppMarket | bool | false | OPPO App Market를 통한 설치를 허용합니다. |
| allowVivoAppStore | bool | false | Vivo App Store를 통한 설치를 허용합니다. |
| allowADB | bool | false | ADB(Android Debug Bridge)를 통한 설치를 허용합니다. 내부 테스트 용도에서만 활성화하세요. |
| allowDetectionFailed | bool | false | Android installer package 조회나 JNI 호출이 실패했을 때 게임 실행을 허용합니다. 릴리스 빌드에서는 꺼두는 것을 권장합니다. |
| allowUnknownSources | bool | false | 기본 목록이나 커스텀 허용 목록에 없는 설치 출처를 허용합니다. 지역 스토어 대응이 필요할 때만 테스트 후 사용하세요. |
| enableServerSync (Pro) | bool | false | 감지된 installer package를 OZero 서버로 보내 allowlist 검증과 감사 로그를 수행합니다. Pro 전용입니다. |
| customAuthorizedPackages | List<string> | — | 추가로 허용할 설치자 패키지 이름 (예: com.yourcompany.launcher). |
| reportViolationToCallback | bool | true | 허용되지 않은 설치 출처가 감지되면 서버로 리포트를 전송합니다. |
| logRawInstallerPackage | bool | true | 원본 설치자 패키지 이름을 콘솔에 로그로 출력합니다. 커스텀 스토어의 올바른 패키지 이름을 식별할 때 개발 단계에서 유용합니다. |
Steam Anti-Piracy 설정
Steam으로 배포되는 PC 빌드에서 Steam 실행 경로, App ID, 권한 상태, 릴리스 설정을 확인합니다. Standard는 로컬 검증이며, Steam 서버를 통한 더 강한 소유권 검증은 Pro의 서버 Steam Attestation에서 제공합니다.
| 필드 | Type | 기본값 | 설명 |
|---|---|---|---|
| Activate Steam Anti-Piracy | checkbox | Off | Steam Anti-Piracy 활성화 체크박스입니다. Steam App ID와 배포 방식이 프로젝트마다 다르므로 기본값은 Off입니다. 먼저 관찰/QA 모드에서 상태를 확인한 뒤 출시 빌드 정책을 강화하세요. |
| expectedSteamAppId | int | 0 | 프로젝트의 Steam App ID입니다. 개발 확인용 AppID 480을 사용했다면 출시 전 반드시 실제 App ID로 바꾸세요. |
| requireSteamLaunch | bool | true | 게임이 실행 파일 직접 실행이 아니라 Steam을 통해 시작되었는지 확인합니다. 개발 중 직접 실행 테스트와 릴리스 정책을 구분하세요. |
| requireSteamApiInit | bool | true | Steam API 초기화 성공 여부를 확인합니다. 로컬 개발 실행에서는 Steamworks 설정에 따라 실패할 수 있으므로, 최종 판정은 실제 Steam 배포 경로에서 확인하세요. |
| requireSubscribedCurrentApp | bool | true | 현재 Steam 계정이 앱을 소유하거나 사용 권한을 가지고 있는지 확인합니다. 이 항목은 로컬 검증이며, 서버 측 소유권 검증은 Pro에서 수행합니다. |
| requiredDlcAppIds | List<int> | — | 보호할 DLC 흐름에서 소유가 필요한 DLC App ID 목록입니다. |
| blockSteamAppIdTxtInRelease | bool | true | 릴리스 빌드에 개발용 steam_appid.txt가 남아 있으면 실패 처리합니다. 이 파일은 로컬 개발 확인용이며 고객에게 배포하지 마세요. |
| validateSteamApiDllHash | bool | false | Steam API DLL 해시를 알려진 SHA-256 값과 비교해 검증합니다. |
| allowFamilySharing / allowFreeWeekend / allowTimedTrial | bool | true | Steam 가족 공유, 무료 주말, 시간 제한 체험 권한 상태를 허용할지 제어합니다. |
| enableServerSteamAttestation (Pro) | bool | false | Pro 전용입니다. Steam 권한 증거를 OZero 서버로 제출해 클라이언트 로컬 결과보다 강한 서버 측 소유권 검증을 수행합니다. |
디바이스 바인딩 설정
하드웨어 지문을 사용해 게임 계정을 최초 기기에 바인딩합니다. 다른 하드웨어로의 계정 이전을 감지합니다.
상용 운영 목적
기기 바인딩은 Pro 운영 레이어로 가장 유용합니다. 라이선스를 서버에 등록된 하드웨어 지문과 연결해 위험 기기를 격리하고, 단순 라이선스 공유 비용을 높이며, 정상적인 기기 변경을 전체 라이선스 차단 없이 지원할 수 있습니다.
반복 위험 기기 차단
SpeedHack, Injection, Install Source, Build Integrity 같은 보안 이벤트 증거를 확인한 뒤 사용하세요. 차단된 기기는 다음 활성화, 등록, 검증(verify), 정책(policy) 체크에서 DEVICE_BLOCKED를 받습니다.
정상 유저 리셋 지원
휴대폰 교체, OS 재설치, 하드웨어 교체, 정상 환경 변경 후 지문 불일치가 발생한 경우 Reset Token을 사용합니다. 토큰은 5분 유효, 1회용이며 정확한 라이선스와 기기에 묶입니다.
기기 슬롯 통제
Pro 라이선스에서는 maxDevices로 등록 가능한 활성 서버 지문 수를 제한합니다. 차단된 지문은 신뢰 가능한 재사용 슬롯이 아니므로, 리셋 또는 삭제는 고객지원 검증 후 사용하세요.
Reset Token 고객지원 흐름
- 일반 고객지원 절차에 따라 플레이어 계정과 리셋 사유를 확인합니다.
- Customer Portal → Device Binding에서 대상 기기를 찾고 Reset Token을 발급합니다.
- 토큰은 인증된 고객지원 채널로만 전달합니다. 장기간 남는 공개 채팅이나 스크린샷에 보관하지 마세요.
- 게임 또는 고객지원 UI는 토큰을
OZeroDeviceBindingDetector.Instance?.ClearStoredFingerprint(token.Trim())에 전달해야 합니다. - SDK가 토큰을 소비한 뒤 앱을 재시작하거나 보호 초기화 흐름에 다시 진입하면 현재 하드웨어 지문이 다시 등록됩니다.
| 필드 | Type | 기본값 | 설명 |
|---|---|---|---|
| Activate Device Binding | bool | true | Device Binding 모듈을 활성화합니다. |
| hardwareChangeTolerance | int (0–3) | 1 | 위반을 트리거하기 전에 허용되는 하드웨어 구성요소 변경 횟수. 0 = 엄격(변경 불가), 3 = 관대(주요 하드웨어 교체). 1은 사소한 OS 또는 펌웨어 업데이트를 허용하는 수준입니다. |
| storageKey | string | "ozero_dfp" | 암호화된 디바이스 지문이 저장되는 PlayerPrefs 키. 게임 내 기존 키와 충돌하는 경우에만 변경하세요. |
| enableServerSync | bool | false | 서버 사이드 검증을 위해 디바이스 지문을 백엔드 서버와 동기화합니다. |
| maxDevices (Pro) | int | 0 | 의도한 서버사이드 기기 한도를 문서화하는 값입니다. 실제 한도는 서버 라이선스 기록에서 강제되므로 이 로컬 값만 바꿔도 운영 한도가 올라가지는 않습니다. |
스피드핵 감지기 설정
Unity Time.realtimeSinceStartup를 네이티브 플랫폼 타이머 및 선택적으로 신뢰할 수 있는 웹 시간 소스와 비교하여 타임 스케일 조작(스피드핵)을 감지합니다.
| 필드 | Type | 기본값 | 설명 |
|---|---|---|---|
| Activate Speed & Time Hack | bool | true | Speed Hack Detector 모듈을 활성화합니다. |
| autoStart | bool | true | 게임 실행 시 자동으로 감지를 시작합니다. 비활성화할 경우 OZeroSpeedHackDetector.StartDetection()으로 수동 시작해야 합니다. |
| checkInterval | float | 1.0 s | 감지기가 타이머를 샘플링하고 비교하는 주기(초). |
| requiredDetections | int | 3 | 위반이 트리거되기 전에 필요한 연속 이상 샘플 수. 불안정한 기기에서의 오탐을 줄이려면 값을 높이세요. |
| ratioTolerance | float | 0.15 | Unity 시간과 네이티브 타이머의 흐름이 비정상적으로 벌어지는지 확인하는 허용 범위입니다. 기본값을 먼저 사용하고, 실제 게임 환경에서 오탐 여부를 확인한 뒤 조정하세요. |
| maxAllowedRatio | float | 4.0 | 정상 범위를 크게 벗어난 시간 흐름을 빠르게 감지하기 위한 상한값입니다. 일반적으로 기본값을 유지하세요. |
| detectSlowHack | bool | true | 속도 증가뿐 아니라 시간을 느리게 만드는 도구(1.0 - 허용오차 미만의 비율)도 함께 감지합니다. |
| enableTimeScaleDetection | bool | true | 메모리 에디터 등에 의해 프로그래밍적으로 설정된 비정상 Time.timeScale 값을 감지합니다. |
| hackDetectMultiplier | float | 1.3 | 강한 의심 신호를 더 빠르게 집계하기 위한 보정값입니다. 값이 낮을수록 민감해질 수 있으므로 QA 후 조정하세요. |
| enableThreadTimerCheck | bool | true | 백그라운드 스레드 타이머를 추가 기준 클록으로 사용하여, 메인 스레드만 영향을 주는 해킹을 더 어렵게 만듭니다. |
| useWebTimeValidation | bool | false | webTimeUrl에서 주기적으로 현재 시각을 가져와 기기 시계와 비교하여, 기기 수준의 시간 조작을 감지합니다. |
| webTimeUrl | string | — | 신뢰할 수 있는 시간 API 엔드포인트 URL (Unix 타임스탬프 또는 RFC 2616 Date 헤더 반환 필수). useWebTimeValidation 활성화 시 필수입니다. |
| webSyncInterval | float | 15 s | 웹 타임 서버와 동기화하는 주기(초). |
| webRatioTolerance | float | 0.15 | 기기 시간과 웹 서버 시간의 차이를 판단하는 허용 범위입니다. 네트워크 지연과 지역 환경을 고려해 기본값부터 검증하세요. |
| timeOffsetTolerance | float | 60 s | 위반 트리거 전에 허용되는 기기와 웹 서버 간 절대 시계 오프셋(초). |
| focusIgnoreTime | float | 4 s | 앱이 포커스를 다시 획득한 직후 무시할 시간(초). OS가 앱을 일시 정지시킬 때 발생하는 오탐을 방지합니다. |
| loadingGraceTime | float | 6 s | 앱 시작 또는 씬 로딩처럼 정상적으로 지연이 생길 수 있는 구간에서 오탐을 줄이기 위한 초기 완충 시간입니다. |
| lagSpikeIgnore | float | 0.5 s | 프레임 델타가 이 값을 초과하는 샘플은 폐기됩니다(시간 조작이 아닌 실제 랙 스파이크로 간주). |
| buildFailIfTimeScaleTampered | bool | true | 보호 대상 코드가 정책 밖에서 Time.timeScale을 변경하는 것으로 보이면 빌드/검증 단계에서 실패하게 하는 가드입니다. |
| timeScaleTamperExemptions | List<string> | — | 일시정지나 불릿타임처럼 의도적으로 Time.timeScale을 바꾸는 클래스/메서드 패턴을 예외로 등록합니다. |
| webTimeUrls | string[] | — | 신뢰할 시간 엔드포인트를 여러 개 지정할 수 있습니다. 여러 응답 성공을 요구해 웹 시간 신뢰도를 높입니다. |
| minSuccessfulEndpoints | int | 2 | 여러 웹 시간 엔드포인트를 사용할 때 성공해야 하는 최소 응답 수입니다. |
| maxConsecutiveFailures | int | 6 | 웹 시간 조회 실패가 몇 번 연속 발생하면 unavailable 정책을 적용할지 정합니다. |
| onWebTimeUnavailable | enum | WarnOnly | 신뢰할 웹 시간에 접근하지 못할 때 적용할 정책입니다. 네트워크 상황을 테스트한 뒤 엄격한 모드로 올리세요. |
| detectTimeHack | bool | true | 속도 비율 검사 외에 기기 시계와 웹 시간 조작 검사를 켭니다. |
| webSyncJitterPercent | float | 20% | 웹 시간 동기화 주기에 무작위 편차를 더해 조회 시점을 예측하기 어렵게 합니다. |
| sustainedLagThreshold | float | 0.15 | 반복되는 느린 프레임을 치트 증거가 아니라 지속 lag로 분류하기 위한 기준입니다. |
| sustainedLagGraceDuration | float | 3 s | 지속적인 렉이나 로딩 지연으로 판단되는 동안 오탐을 줄이기 위한 완충 시간입니다. |
| overloadStrictMultiplier | int | 3 | 반복적인 비정상 타이밍 조건 이후 overload 처리 기준을 더 엄격하게 적용하는 배수입니다. |
| enableRemoteSpeedHackConfig (Pro) | bool | false | Pro 서버 정책으로 Speed & Time Hack 임계값 일부를 원격에서 조정할 수 있습니다. |
| remoteSpeedHackConfigInterval | float | 300 s | 원격 Speed & Time Hack 설정을 새로 받아오는 주기입니다. |
| enableSignedServerTime (Pro) | bool | false | 사용 가능한 경우 서명된 서버 시간을 사용해 unsigned 응답 위조를 방지합니다. |
Time.timeScale 대신 OZeroTime.timeScale 사용
Speed & Time Hack 모듈이 활성화된 상태에서 Time.timeScale을 직접 수정하면 외부 시간 조작과 비슷한 신호로 보일 수 있습니다. 일시정지, 슬로우 모션, 컷신 속도 제어, 빠른 진행, 디버그 속도 조절처럼 게임이 의도적으로 속도를 바꿀 때는 OZeroTime.timeScale을 사용하세요.
OZeroTime.timeScale은 요청된 값을 OZero detector로 전달해 detector의 예상 game-time scale을 갱신한 뒤 Unity time scale을 안전하게 적용합니다. 이를 통해 SDK는 정상적인 게임플레이 속도 변경과 의심스러운 런타임 변조를 구분할 수 있습니다.
using OZeroSDK.Security;
// Correct: the detector knows this is an intentional game-side change.
OZeroTime.timeScale = 0.5f;
// Avoid: this bypasses OZero's expected time-scale tracking.
Time.timeScale = 0.5f;
TimeScaleTamperExemptions는 작게 유지하세요. 직접 Time.timeScale 접근이 불가피한 검토된 adapter script에만 사용하고, 그 외에는 OZeroTime.timeScale을 우선 사용하세요.
장시간 로딩 시 Watchdog 의도치 않은 종료 방지하기
OZero의 네이티브 Watchdog은 Unity 메인 스레드가 정상적으로 살아 있는지 주기적인 heartbeat로 확인합니다. 릴리스 빌드에서는 비-Android 플랫폼은 약 6초, Android는 시작 유예 이후 약 10초 동안 heartbeat가 들어오지 않으면 앱이 멈춘 것으로 판단하고 설정된 대응 정책에 따라 종료할 수 있습니다.
대형 씬 로딩, 동기식 에셋 압축 해제, 셰이더 warmup, Addressables 준비처럼 메인 스레드가 의도적으로 몇 초 이상 막히는 정상 작업에서도 이 상황이 발생할 수 있습니다.
이런 신뢰 가능한 로딩 구간은 OZeroWatchdog.BeginLoadingGrace(maxGraceMs)로 감싸세요. 로딩이 시작될 때 grace가 시작되고, scope가 dispose되거나 End()가 호출되는 순간 즉시 종료되므로 실제 로딩 시간을 미리 정확히 알 필요가 없습니다.
using OZeroSDK.Security;
using UnityEngine.SceneManagement;
public void LoadLargeScene()
{
using (OZeroWatchdog.BeginLoadingGrace(60000))
{
SceneManager.LoadScene("Battle", LoadSceneMode.Single);
// Grace ends as soon as the using scope exits.
}
}
public void WarmUpLargeAssets()
{
OZeroWatchdog.RunWithLoadingGrace(() =>
{
BuildLargeRuntimeCache();
}, 60000);
}
Loading Grace는 Watchdog deadline만 제한적으로 유예합니다. 보안 감시를 우회하거나 앱을 계속 켜두기 위한 무한 루프/keep-alive 용도로 오용해서는 안 됩니다.
하나의 큰 블로킹 작업이 최대 grace window를 넘을 수 있다면, 작업을 여러 개의 작은 단위(chunk)로 나누어 차례대로 처리하세요.
또는 Unity의 async/await, Coroutine 같은 비동기 로딩 흐름을 사용해 메인 스레드가 완전히 멈춰 있지 않도록 구현하세요.
Physics Hack Detector
OZeroPhysicsHackDetector는 각 플레이어 오브젝트마다 독립적인 감지 임계값이 필요한 멀티플레이어/MMORPG 게임을 위해 설계됐습니다. 플레이어 프리팹에 직접 컴포넌트를 추가하고 Inspector에서 오브젝트별로 설정을 구성하세요. 스폰 로직에서 Initialize(playerId)를 호출하여 감지를 활성화하세요.| 필드 | Type | 기본값 | 설명 |
|---|---|---|---|
| maxAllowedSpeed | float | 15 u/s | 허용되는 최대 이동 속도(Unity 유닛/초). 게임에서 허용되는 최대 정당 플레이어 속도에 맞춰 튜닝하세요. |
| distanceTolerance | float | 2.0 u | 네트워크 지연 또는 물리 부정확성을 보정하기 위한 추가 거리 허용값. |
| obstacleLayer | LayerMask | — | 벽과 장애물을 나타내는 레이어 마스크. 라인캐스트로 월핵을 감지하는 데 사용됩니다. |
| checkInterval | float | 0.05 s | 물리 검증기가 플레이어 위치와 속도를 샘플링하는 주기(초). |
| maxDeltaTimeCap | float | 0.1 s | 거리 계산에 사용되는 델타 타임의 상한. 랙 스파이크에 의해 부정 텔레포트가 가려지는 현상을 방지합니다. |
Injection Detector 설정
어셈블리 인젝션, DLL 하이재킹, IL2CPP 패칭 등 무단 코드 인젝션을 감지합니다.
| 필드 | Type | 기본값 | 설명 |
|---|---|---|---|
| Activate Injection & Hooking | checkbox | On | Code Injection Detector 모듈을 활성화합니다. 감지 로직은 전적으로 Native C++ 레이어에서 동작하며 추가 설정이 필요 없습니다. |
| enableServerWhitelist (Pro) | bool | false | 승인된 오버레이나 파트너 모듈을 허용할 수 있도록 서버에서 신뢰 모듈 목록을 내려받습니다. |
| serverWhitelistRefreshInterval | float | 0 s | 서버 관리 whitelist 정책 갱신 주기입니다. 0이면 시작 또는 정책 초기화 시점에만 갱신합니다. |
| requireSignerForNativeWhitelist | bool | false | 네이티브 whitelist 항목에 파일 해시뿐 아니라 서명자 식별 정보도 요구합니다. 더 강하지만 깨끗한 모듈 서명 데이터가 필요합니다. |
| enableRemoteInjectionConfig (Pro) | bool | true | Pro 서버 정책으로 Injection 검사 임계값과 검사 구성을 원격에서 조정할 수 있습니다. |
| remoteInjectionConfigInterval | float | 300 s | 원격 Injection 정책을 새로 받아오는 주기입니다. |
| enableWindowsModuleIdentityScan | bool | true | 로드된 Windows 네이티브 모듈을 스캔하고 해시/서명자 정보를 신뢰 정책과 비교합니다. |
| scanIntervalSeconds | float | 1 s | Injection 검사의 기본 실행 주기입니다. |
| windowsModuleIdentityScanIntervalSeconds | float | 5 s | 상대적으로 무거운 Windows 모듈 식별 스캔의 별도 주기입니다. |
| scanJitterPercent | float | 20% | 검사 주기에 무작위 편차를 더해 검사 시점을 예측하기 어렵게 합니다. |
| enableExecutablePrivateMemoryScan | bool | true | Injected shellcode나 런타임 patcher가 자주 사용하는 실행 가능한 private memory 영역을 감지합니다. |
| enableInlineHookScan | bool | false | 알려진 코드 진입점의 의심스러운 inline patch를 감지합니다. Strict 모드에서 호환성 테스트 후 켜는 항목입니다. |
| enableThreadStartAddressScan | bool | true | 스레드 시작 주소가 신뢰 모듈 밖의 의심스러운 위치인지 확인합니다. |
| enableExternalProcessHandleScan | bool | true | 외부 프로세스가 게임 프로세스에 의심스러운 handle을 들고 있는지 감지합니다. |
| detectionConfidenceThreshold | int | 70 | 여러 Injection 신호를 종합했을 때 위반으로 확정하기 위한 최소 신뢰 점수입니다. |
| enableWebRuntimeTamperScan (WebGL) | bool | true | WebGL 전용의 가벼운 브라우저 변조 검사입니다. Native C++ 보호가 아니므로 보조 신호로만 사용하세요. |
| WebGL probes | bools | true | WebGL 빌드에서 DevTools, 시계 조작, 네트워크 후킹, WASM 후킹, 저장소 후킹, 암호화 API 후킹 검사를 제어합니다. |
PlayerPrefs 암호화
Unity의 PlayerPrefs에 저장되는 데이터(설정, 사용자 환경설정 등)를 보호하려면 PlayerPrefs를 OZeroSafePlayerPrefs로 교체하세요. API는 동일합니다.
using OZeroSDK.Security;
// Save a value
OZeroSafePlayerPrefs.SetInt("score", 4200);
OZeroSafePlayerPrefs.SetFloat("volume", 0.8f);
OZeroSafePlayerPrefs.SetString("username", "Hero");
// Read a value
int score = OZeroSafePlayerPrefs.GetInt("score", 0);
float volume = OZeroSafePlayerPrefs.GetFloat("volume", 1.0f);
string username = OZeroSafePlayerPrefs.GetString("username", "");
세이브 파일 암호화
세이브 파일을 암호화하려면 File.ReadAllText / File.WriteAllText 대신 OZeroSV_File을 사용하세요. 파일은 쓸 때 자동으로 암호화되고 읽을 때 복호화됩니다. 로드 시 변조 여부도 검사합니다.
using OZeroSDK.Security;
string path = Application.persistentDataPath + "/save.json";
// Write encrypted file
OZeroSV_File.WriteAllText(path, jsonString);
// Read and decrypt file
string json = OZeroSV_File.ReadAllText(path);
developerSecret을 변경하지 마세요. developerSecret은 OZeroSafePlayerPrefs와 OZeroSV_File 데이터를 보호하는 기준값 중 하나입니다. 출시 후 이 값을 바꾸면 기존 버전에서 저장한 보호 데이터가 열리지 않을 수 있습니다.
4
인게임 변수 보호 (Secure Types)
Secure Types는 일반 C# 변수 타입을 암호화된 타입으로 대체합니다. 값이 Native C++ 힙에 저장되어 Cheat Engine 같은 도구로는 메모리를 스캔해도 찾을 수 없습니다. 타입 이름만 바꾸면 되고 나머지 코드는 그대로 동작합니다.
예시 코드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OZeroSDK.Security;
public class PlayerStats : MonoBehaviour
{
[SerializeField] OZeroSV_Int Gold = 5000;
[SerializeField] OZeroSV_Float Speed = 3.5f;
[SerializeField] OZeroSV_Int HP = 1000;
}
지원 타입
| 기존 | OZero 적용 후 |
|---|---|
| int | OZeroSV_Int |
| long | OZeroSV_Int64 |
| uint | OZeroSV_UInt |
| ulong | OZeroSV_UInt64 |
| short | OZeroSV_Short |
| ushort | OZeroSV_UShort |
| byte | OZeroSV_Byte |
| float | OZeroSV_Float |
| double | OZeroSV_Double |
| decimal | OZeroSV_Decimal |
| bool | OZeroSV_Bool |
| string | OZeroSV_String |
| Vector2 | OZeroSV_Vector2 |
| Vector3 | OZeroSV_Vector3 |
| byte[] | OZeroSV_Buffer |
7
보안 이벤트 처리 (선택)
기본적으로 OZero는 위협을 감지하면 설정된 대응 정책에 따라 앱을 종료하거나 로그만 남깁니다. 직접 경고 화면을 표시하거나, 자체 서버 로그를 보내거나, 종료 직전 저장 처리를 해야 한다면 콜백을 등록할 수 있습니다. 콜백은 OZeroSecurityEvent를 통해 변조 타입, 중단 코드, 메시지 키, 상세 메시지, 종료 예정 여부를 함께 전달합니다.
using UnityEngine;
using OZeroSDK.Security;
public class SecurityHandler : MonoBehaviour
{
void OnEnable()
{
// RegisterUserCallback runs on the user chain only.
// The built-in default handler runs independently and cannot be silenced.
OZeroSecurityManager.Instance.RegisterUserCallback(OnThreatDetected);
}
void OnDisable()
{
OZeroSecurityManager.Instance.UnregisterUserCallback(OnThreatDetected);
}
void OnThreatDetected(OZeroSecurityEvent evt)
{
// evt contains Type, AbortCode, AbortCodeHex, MessageKey, Message, and WillAbort.
Debug.LogWarning(
$"OZero threat: {evt.Type} {evt.AbortCodeHex} {evt.Message}");
switch (evt.Type)
{
case ModulationType.SpeedHack:
// e.g. kick the player, show warning, report to server
break;
case ModulationType.BuildIntegrity:
// evt.WillAbort is usually true for fatal build integrity violations.
break;
case ModulationType.Injection:
break;
}
if (evt.WillAbort)
{
// Last chance to flush your own analytics or save state.
}
}
}
OZeroSecurityEvent, ModulationType, OZeroAbortCode의 전체 목록은 API 레퍼런스에 문서화되어 있습니다.
evt.WillAbort가 true이면 현재 대응 정책상 콜백 이후 앱이 종료됩니다. 이때는 자체 analytics flush나 저장 처리만 짧게 수행하세요.
위협이 감지되면 OZero는 먼저 SDK 기본 대응 정책을 적용하고, 프로젝트에서 등록한 콜백과 인스펙터 이벤트에도 같은 보안 이벤트를 전달합니다. 직접 경고 화면을 띄우거나 서버 로그를 남기고 싶다면 콜백을 등록하세요. 앱 종료 여부는 Config Dashboard의 Response 설정과 evt.WillAbort 값으로 확인할 수 있습니다.
다음 단계
이제 OZero의 핵심 보호 기능이 실행 중입니다. API 레퍼런스에서 모든 클래스, 메서드, 설정 옵션을 자세히 확인해 보세요.