모바일 어트리뷰션 SDK의 주요 API 정의란 무엇인가요? 핵심 API 정의에는 (지연된 설치 컨텍스트를 검색하기 위해 최초 실행 온보딩 중에 주로 호출되는) getInstallParam과 (실행 시 실시간 유니버설 링크 페이로드를 가로채는) getWakeUpParams가 포함됩니다.
모바일 어트리뷰션 SDK의 API 정의는 메서드 시그니처, 입력 파라미터, 비동기 실행 규칙, 반환 데이터 스키마를 상세히 다루는 공식 사양입니다. 지연된 설치 쿼리 및 실시간 링크 인터셉션 API와 같은 콜백 함수를 표준화함으로써, API 정의는 모바일 애플리케이션이 Android 및 iOS 라이프사이클 이벤트 전반에 걸쳐 상황별 동적 파라미터를 안전하게 파싱할 수 있도록 지원합니다.
| 용어 | 정의 | 관련 엔티티 | 검색 의도 역할 |
|---|---|---|---|
| API 정의 | SDK 콜백 메서드와 데이터 모델을 개략적으로 설명하는 구조화된 사양. | SDK 메서드 시그니처 | 정보성 / 기술적 |
| 딥 링크 | 유니버설 링크 또는 스킴을 통해 사용자를 동적인 인앱 위치로 라우팅하는 기술. | 동적 라우팅 API | 기술적 / 정보성 |
| 추적 파라미터 | 추천 링크에 추가되어 SDK 콜백을 통해 반환되는 커스텀 키-값 쌍. | JSON 페이로드 스키마 | 기술적 / 정보성 |
어트리뷰션 SDK API 정의의 핵심 아키텍처 카테고리
SDK API 분류: 지연된 수집, 실시간 인터셉션, 이벤트 어트리뷰션
모바일 어트리뷰션 및 딥 링크 클라이언트 라이브러리는 사용자 라이프사이클의 서로 다른 단계를 처리하도록 설계된 애플리케이션 프로그래밍 인터페이스(API)를 제공합니다. 모놀리식 유틸리티 클래스로 작동하는 대신, 어트리뷰션 SDK는 프로그래밍 책임을 세 가지 주요 기능 범주로 나눕니다.
- 지연된 파라미터 수집 API: Android의
getInstallParam및 iOS의getInstallParmsCompleted같은 메서드는 주로 설치 후 애플리케이션의 초기 온보딩 중에 작동합니다. 임의의 웹 네비게이션 파라미터는 기본적으로 스토어 설치 경계를 넘어서 유지되지 않으므로, 지연된 API는 클라이언트측 캐시와 백엔드 어트리뷰션 엔드포인트를 쿼리하여 사전 설치 클릭에 바인딩된 컨텍스트 메타데이터(초대자 ID, 추천 토큰, 캠페인 파라미터 등)를 복구합니다. - 실시간 링크 인터셉션 API: Android의
handleDeepLink및 iOS의getWakeUpParams같은 메서드는 호스트 운영 체제에 이미 애플리케이션이 설치되어 있을 때 실행됩니다. 이 API들은 네이티브 시스템 프로토콜(특히 Apple 유니버설 링크, Android 앱 링크, 커스텀 URL 스킴)에 훅을 걸어 외부 웹 링크나 보조 애플리케이션이 앱 실행을 트리거할 때 실시간 URI 파라미터를 캡처합니다. - 설치 후 이벤트 어트리뷰션 API: Android의
saveEvent및 iOS의reportEffectPoint같은 클라이언트측 보고 메서드를 사용하면 클라이언트 애플리케이션이 다운스트림 사용자 마일스톤을 어트리뷰션 집계 서버로 다시 보고할 수 있습니다. 이러한 호출은 인앱 전환 액션을 이전 설치 파라미터와 바인딩하여 세밀한 마케팅 투자 수익률(ROAS) 감사, 코호트 리텐션 추적, 바이럴 루프 분석을 가능하게 합니다.

애플리케이션 콜드 스타트 스레드 차단을 방지하는 비동기 콜백의 역할
모바일 운영 체제는 애플리케이션 시작 시 엄격한 성능 임계값을 적용합니다. Android에서는 메인 스레드에서 동기식 네트워크 작업을 실행하면 NetworkOnMainThreadException이 발생하며, 디스크 I/O 차단을 포함한 장기적인 동기식 작업은 UI 스레드를 고착시켜 응답 없음(ANR) 오류를 유발할 수 있습니다. iOS에서는 운영 체제 감시(watchdog) 타이머가 초기화 중 메인 스레드를 장시간 차단하는 프로세스를 종료합니다.
어트리뷰션 SDK는 파라미터 검색 인터페이스를 비동기 콜백으로 구현하여 이 제약 조건을 완화합니다. 비동기 콜백 인터페이스를 사용하면 호출자가 네트워크 완료를 동기적으로 기다릴 필요 없이 검색 결과를 나중에 전달받을 수 있습니다. 개발자는 배포된 SDK 버전에 대한 시작 성능과 콜백 동작을 계속 검증해야 합니다.
비동기 콜백을 사용하면 네트워크 지연으로 인해 UI 스레드가 차단될 위험이 줄어들어, 애플리케이션이 콜드 스타트 중에 스플래시 뷰나 홈 인터페이스를 원활하게 렌더링할 수 있습니다.
클라이언트측 SDK API와 서버 간(S2S) 포스트백 인터페이스의 차이점
엔지니어링 팀은 간혹 클라이언트측 SDK API 정의와 서버 간(S2S) 포스트백 API를 혼동합니다. 두 인터페이스 모두 어트리뷰션 데이터를 처리하지만, 실행 컨텍스트, 보안 모델, 운영 목적은 근본적으로 다릅니다.
- 클라이언트측 SDK API: 모바일 바이너리 내에 직접 컴파일되며(예: CocoaPods 프레임워크 또는 Maven AAR 종속성을 통해), 네이티브 기기 기능과 상호 작용합니다. 애플리케이션 라이프사이클 알림을 수신하고, 들어오는 시스템 인텐트를 파싱하며, 구성 파일을 읽고, 동적 라우팅을 위해 애플리케이션 프리젠테이션 컨트롤러에 직접 메모리 객체를 제공합니다.
- 서버 간(S2S) 포스트백 인터페이스: 백엔드 서버 인프라 전반에서 완전히 실행되며, 어트리뷰션 플랫폼과 광고 네트워크 간에 전환 포스트백을 전송하는 HTTP REST 엔드포인트로 구성됩니다. 제공자에 따라 S2S 통신은 인증된 HTTPS 엔드포인트, 서명된 페이로드 토큰, 상호 TLS 또는 네트워크 액세스 Controls을 활용하여 클라이언트 기기 실행 상태와 독립적으로 무결성을 보장할 수 있습니다.
getInstallParam에서 지연된 딥 링크 쿼리 메커니즘이 작동하는 방식
지연된 어트리뷰션 윈도우: 최초 실행 시 캐시된 파라미터 검색
지연된 딥 리킹은 모바일 소프트웨어 배포의 근본적인 아키텍처 공백을 해결합니다. 표준 운영 체제 앱 스토어는 다운로드 및 설치 워크플로 전반에 걸쳐 임의의 URL 쿼리 스트링을 유지하지 않습니다. Google Play Install Referrer와 같은 플랫폼별 메커니즘은 스토어 다운로드를 통해 지원되는 캠페인 컨텍스트를 전달할 수 있지만, 일반적인 웹 쿼리 파라미터(예: https://example.com/invite?channelCode=affiliate_01&inviter_id=user_9876)는 앱 스토어 경계를 자동으로 넘지 못합니다.
이러한 단절을 메우기 위해 모바일 어트리뷰션 및 딥 링크 플랫폼인 OpoInstall은 사용자가 랜랜딩 페이지와 상호 작용할 때 컨텍스트 속성과 캠페인 파라미터를 캡처합니다. 사용자가 새로 설치한 애플리케이션을 실행하면 클라이언트 SDK가 초기화되고 어트리뷰션 클러스터와의 연결이 설정됩니다.
getInstallParam API는 이 지연된 어트리뷰션 윈도우를 쿼리하기 위한 프로그래밍 방식의 게이트웨이 역할을 합니다. 이 메서드를 호출하면 클라이언트 애플리케이션은 SDK에 최신 앱 인스턴스를 이전 웹 클릭 이벤트와 대조하도록 요청하고, 일치하는 파라미터를 애플리케이션 런타임으로 반환합니다.
개발자는 상세한 환경 설정 규칙 및 기본 파라미터 전송 아키텍처에 대해 OpoInstall SDK 통합 문서를 참고할 수 있습니다.
getInstallParam 분석: 파라미터 페이로드, 채널 코드, 상태 응답
지연된 설치 콜백에 의해 반환된 데이터 객체는 운영 상태 플래그와 함께 두 개의 개별 데이터 스트림을 캡슐화합니다.
- 커스텀 동적 파라미터 (
data): 원래 캠페인 링크에 전달된 개발자 정의 쿼리 스트링을 포함하는 구조화된 데이터 컨테이너입니다. 이 필드는 추천 할인 ID, 선호하는 사용자 로케일, 특정 콘텐츠 식별자와 같은 캠페인별 비즈니스 컨텍스트를 전달합니다. - 채널 식별 파라미터 (
channelCode): 존재하는 경우,channelCode는 마케팅 소스 또는 광고 네트워크 파트너를 나타내는 문자열 형태의 채널 식별자로 노출됩니다. 채널 링크가 연동되지 않은 유기적 설치의 경우, 플랫폼 SDK 바인딩에 따라 이 파라미터가 null 또는 빈 값으로 해결될 수 있습니다. - 운영 결과 및 오류: 고정된 범용 정수 코드에 의존하는 대신 오류 및 타임아웃은 플랫폼별 오류 모델(Android의
OpoError또는 iOS의 오류 콜백 등)을 통해 전달됩니다. 콜백은 네트워크 연결이 실패하거나 구성 불일치가 발생할 때 설명적인 오류 구조를 제공합니다.
타임아웃 상태 처리: 대기 주기 및 동적 재시도 플래그 이해
모바일 애플리케이션은 지하철 대중교통망이나 혼잡한 공용 Wi-Fi 액세스 포인트와 같이 저하된 연결 환경에서 자주 실행됩니다. SDK가 백엔드 어트리뷰션 클러스터에 즉시 도달할 수 없는 경우, 파라미터 가져오기 작업으로 인해 애플리케이션 로직이 중단되어선 안 됩니다.
배포된 SDK가 문서화된 콜백 또는 상태 모델을 통해 타임아웃 또는 검색 실패를 보고하는 경우, 시작 경로를 차단하지 않고 애플리케이션에서 정의한 재시도 정책을 사용하여 해당 결과를 처리하세요. 배포된 SDK 버전에 구성 가능한 타임아웃 파라미터나 메서드 오버로드가 문서화되어 있는 경우, 해당 버전별 인터페이스를 사용하고 범용 기본 타임아웃을 가정하지 마세요.
오류나 타임아웃 응답이 발생할 때 권장되는 엔지니어링 관행에는 가벼운 인메모리 플래그를 설정하고, 사용자가 등록 또는 결제 버튼 누르기와 같은 참여 네트워크 마일스톤에 도달했을 때 파라미터 인터페이스를 나중에 다시 쿼리하는 것이 포함됩니다.
getWakeUpParams에서의 실시간 딥 링크 리다이렉션 및 콜백 파싱
시스템 프로토콜을 통한 콜드 스타트 및 백그라운드 런칭 이벤트 가로채기
애플리케이션이 이미 사용자의 기기에 있는 경우, 외부 클릭은 스토어 설치 단계를 완전히 우회합니다. 최신 모바일 플랫폼은 전용 라우팅 표준(iOS의 유니버설 링크와 Android의 Android 앱 링크)을 사용하여 외부 브라우저에서 설치된 네이티브 애플리케이션으로 실행을 직접 전환합니다.
운영 체제는 특정 애플리케이션 델리게이트 메서드를 통해 이러한 런칭 이벤트를 디스패치합니다.
- iOS 라이프사이클: 최신 윈도우 아키텍처를 사용하는 애플리케이션의 경우, 유니버설 링크는
SceneDelegate내의scene:continueUserActivity:(또는 초기 씬 연결 중scene:willConnectToSession:options:)를 통해 도착합니다. 씬 델리게이트를 사용하지 않는 애플리케이션의 경우, 운영 체제는AppDelegate내의application:continueUserActivity:restorationHandler:를 통해 디스패치합니다. 커스텀 URL 스킴은application:openURL:options:또는scene:openURLContexts:를 호출합니다. AppDelegate에 표시된 SDK 포워딩 메서드는 씬이 활성화될 때 애플리케이션의 실제 UIScene 라이프사이클에 맞게 조정되어야 합니다. - Android 라이프사이클: 수신된 인텐트는 대상 Activity가 메모리에서 활성화되지 않은 경우
onCreate(Bundle)을 호출하고, Activity가singleTask또는singleTop런칭 모드 구성으로 작동하는 경우onNewIntent(Intent)를 호출합니다.
getWakeUpParams 콜백 API(및 그에 대응하는 Android의 handleDeepLink)는 이러한 운영 체제 라이프사이클 훅을 통해 전달된 동적 URI 파라미터를 수신, 검증, 해제하는 중앙 집중식 리스너 역할을 합니다.
유니버설 링크 및 URL 스킴 리다이렉션 중 getWakeUpParams 페이로드 파싱
시스템 런칭 이벤트를 가로채면 SDK는 들어오는 URL 스트링을 추출하고, URI로 인코딩된 쿼리 컴포넌트를 디코딩하며, 페이로드를 일관된 데이터 모델로 정규화합니다.
콜백 시그니처는 channelCode와 data 모두에 대한 액세스를 제공합니다. 예를 들어 https://app.example.com/shoes/running?promo_code=SUMMER20&item_id=sku_456으로 구조화된 이커머스 캠페인 링크가 앱 실행을 트리거하면, 콜백은 promo_code와 item_id를 추출하여 애플리케이션 프리젠테이션 로직에서 소비할 수 있도록 콜백 페이로드에 패키징합니다.
동적 인앱 씬 복원: JSON 페이로드 키를 대상 Activity/View Controller에 매핑
실시간 딥 리킹의 최종 운영 목표는 씬 복원입니다. 즉, 기본 홈 화면 랜딩 뷰를 완전히 우회하여 프로모션 링크가 참조하는 특정 상품, 프로필, 액티비티 화면으로 사용자를 직접 안내하는 것입니다.
신뢰할 수 있는 씬 복원을 달성하려면 애플리케이션 아키텍처 내에 결정론적 라우터를 구축해야 합니다.
- 1단계: 페이로드 키 추출: 콜백 리스너 내에서 애플리케이션은
target_screen또는resource_id와 같이 사전에 합의된 라우팅 키가 있는지data페이로드를 검사합니다. - 2단계: Null 및 타입 검증: 라우터는 값이 존재하고, 예상되는 원시 타입(primitive type)을 준수하며, 활성 애플리케이션 기능과 일치하는지 검증합니다.
- 3단계: 네비게이션 컨트롤러 실행: 애플리케이션은 현재 루트 네비게이션 계층 구조를 해결하고 적절한 대상 뷰 컨트롤러나 Activity 인텐트를 푸시하거나 표시합니다.
중복 런칭 라이프사이클 트리거에서의 멱등(Idempotent) 실행 보장
모바일 딥 리킹에서 흔히 발생하는 통합 함정은 중복 이벤트 디스패치입니다. Android에서는 화면 방향 변경 또는 구성 업데이트로 인해 기본 Activity가 다시 생성되면서 onCreate가 원래 런칭 Intent와 함께 다시 실행될 수 있습니다. iOS에서는 애플리케이션 포그라운드 상태 전환이 중복된 델리게이트 알림을 트리거할 수 있습니다.
중복된 뷰 전환이나 중복 분석 로깅을 방지하기 위해 애플리케이션 라우터는 멱등 실행을 강제해야 합니다. 개발자는 처리된 이벤트 식별자의 인메모리 기록이나 짧은 중복 제거 윈도우로 범위가 지정된 정규화된 페이로드 해시를 유지 관리해야 하며, 이미 완료된 네비게이션 이벤트와 시그니처가 일치하는 수신 페이로드는 폐기해야 합니다.
Android 및 iOS 통합을 위한 듀얼 플랫폼 메서드 시그니처

Android 메서드 시그니처: Kotlin ResultCallBack 및 Activity 라이프사이클 훅
Android 클라이언트 개발에서 어트리뷰션 SDK는 콜백 인터페이스를 중심으로 구조화된 비동기 인터페이스를 노출합니다. 호출 스레드를 차단하는 대신, 메서드 호출은 ResultCallBack<T>의 구현을 수락합니다.
개발자는 OpoInstall SDK 다운로드 패키지를 다운로드하여 네이티브 라이브러리 바이너리, Maven 배포판, ProGuard keep-rule 정의에 액세스할 수 있습니다.
주요 Android API 시그니처는 다음과 같습니다.
- 초기화:
OpoInstall.initialize(Application application) - 라이프사이클 시작:
OpoInstall.getInstance().start(Activity activity) - 지연된 파라미터 검색:
OpoInstall.getInstance().getInstallParam(ResultCallBack<OpoData> callBack) - 딥 링크 인텐트 파싱:
OpoInstall.getInstance().handleDeepLink(Intent intent, ResultCallBack<OpoData> callBack) - 커스텀 이벤트 어트리뷰션:
OpoInstall.getInstance().saveEvent(String eventKey, int eventValue, Map<String, String> extraData)
iOS 메서드 시그니처: Swift 및 Objective-C OpoInstallDelegate 프로토콜 준수
iOS 플랫폼에서 SDK 아키텍처는 완료 핸들러 클로저와 함께 Delegation 디자인 패턴을 활용합니다. 애플리케이션 델리게이트는 OpoInstallDelegate를 준수하고 프레임워크 초기화 중에 스스로를 등록합니다.
주요 iOS 메서드 시그니처는 다음과 같습니다.
- SDK 초기화:
OpoInstallSDK.initWith(self) - 실시간 웨이크업 훅:
func getWakeUpParams(_ appData: OpoinstallData?) - 지연된 설치 파라미터 검색:
OpoInstallSDK.defaultManager()?.getInstallParmsCompleted { appData in ... } - 커스텀 이벤트 추적:
OpoInstallSDK.defaultManager()?.reportEffectPoint("purchase", effectValue: 100, effectDictionary: ["currency": "USD"]) - 유니버설 링크 라우팅 델리게이션:
OpoInstallSDK.continue(userActivity)
API 호환성 참고 사항: 이 예제들은 공개적으로 문서화된 OpoInstall 통합 패턴을 반영합니다. SDK 다운로드 센터에는 현재 Android 및 iOS v2.1.0 릴리스가 나열되어 있습니다. 프로덕션 환경에서 사용하기 전에 다운로드한 SDK 아키티브를 기준으로 정확한 패키지 이름, 메서드 시그니처, 널 가능(nullable) 타입, 콜백 인터페이스를 확인하세요. 이 예제들은 해당 아카이브에 대해 독립적으로 컴파일 테스트를 거치지 않았습니다.
// Android - MainActivity.kt
package com.example.app
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.opoinstall.api.OpoInstall
import com.opoinstall.api.OpoData
import com.opoinstall.api.OpoError
import com.opoinstall.api.ResultCallBack
import org.json.JSONObject
// 애플리케이션 소유의 정규화 유틸리티 (호스트 애플리케이션 유틸리티)
// 원시 SDK 데이터 객체를 정규화된 JSON 문자열로 안전하게 검증
fun normalizePayload(rawData: Any?): String? = when (rawData) {
is String -> rawData
is JSONObject -> rawData.toString()
is Map<*, *> -> runCatching {
// JSONObject에 위임하기 전에 문자열 기반 키 제약 조건 강제
if (rawData.keys.any { it !is String }) {
null
} else {
val sanitizedMap = mutableMapOf<String, Any?>()
rawData.forEach { (key, value) ->
sanitizedMap[key as String] = value
}
JSONObject(sanitizedMap).toString()
}
}.getOrNull()
else -> null
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// OpoInstall.initialize(this)가 Application.onCreate()에서 이미 완료되었다고 가정
OpoInstall.getInstance().start(this)
// 1. 지연된 설치 파라미터 쿼리
OpoInstall.getInstance().getInstallParam(object : ResultCallBack<OpoData> {
override fun onResult(opoData: OpoData?) {
val customData: String? = normalizePayload(opoData?.data)
val channel: String? = opoData?.channelCode
// 원시 사용자 또는 추천 페이로드를 인쇄하지 않고 민감도가 제거된 상태 로깅
Log.d("OpoInstall", "Install params received: hasData=${!customData.isNullOrBlank()}, channelPresent=${!channel.isNullOrBlank()}")
// UI 관련 작업이 메인 UI 스레드로 디스패치되도록 보장
runOnUiThread {
// 호스트 애플리케이션 UI 라우팅 또는 프리젠테이션 로직
}
}
override fun onError(error: OpoError?) {
// 민감한 시스템 문자열을 출력하지 않고 정리된 오류 표시기 로깅
Log.w("OpoInstall", "getInstallParam callback encountered an error status")
}
})
// 2. 들어오는 실시간 딥 링크 처리
handleIntent(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
handleIntent(intent)
}
private fun handleIntent(intent: Intent?) {
intent?.let {
OpoInstall.getInstance().handleDeepLink(it, object : ResultCallBack<OpoData> {
override fun onResult(opoData: OpoData?) {
val customData: String? = normalizePayload(opoData?.data)
Log.d("OpoInstall", "DeepLink params received: hasData=${!customData.isNullOrBlank()}")
runOnUiThread {
// 호스트 애플리케이션 딥 링크 라우팅 로직
}
}
override fun onError(error: OpoError?) {
Log.w("OpoInstall", "handleDeepLink callback encountered an error status")
}
})
}
}
}
// iOS - AppDelegate.swift
import UIKit
import libOpoInstallSDK
@main
class AppDelegate: UIResponder, UIApplicationDelegate, OpoInstallDelegate {
var window: UIWindow?
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// 1. 델리게이트 리스너로 OpoInstall SDK 초기화
OpoInstallSDK.initWith(self)
// 2. 지연된 설치 파라미터 쿼리
OpoInstallSDK.defaultManager()?.getInstallParmsCompleted { appData in
let customData = appData?.data
let channel = appData?.channelCode
// 원시 커스텀 페이로드를 출력하지 않고 민감도가 제거된 상태 로깅
print("OpoInstall: Deferred parameters received (hasData: \(customData != nil), channelPresent: \(channel != nil))")
// UI 작업을 메인 큐에 명시적으로 디스패치
DispatchQueue.main.async {
// 호스트 애플리케이션 UI 프리젠테이션 로직
}
}
return true
}
// 3. 실시간 딥 링크 파라미터 인터셉션 콜백
func getWakeUpParams(_ appData: OpoinstallData?) {
let customData = appData?.data
let channel = appData?.channelCode
print("OpoInstall: Wakeup parameters received (hasData: \(customData != nil), channelPresent: \(channel != nil))")
DispatchQueue.main.async {
// 호스트 애플리케이션 딥 링크 라우팅 로직
}
}
// 참고: 씬 기반 라이프사이클(UIScene)을 사용하는 경우, scene:continueUserActivity: 및
// scene:openURLContexts:를 통해 SceneDelegate에서 유니버설 링크와 스킴을 포워딩하세요.
// 수신된 URL이 어트리뷰션 엔진에 의해 처리되었는지 여부를 나타내는 부울(Boolean)을 반환하는지
// 여부는 SDK 버전의 공개 헤더를 참조하여 확인하세요.
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
OpoInstallSDK.continue(userActivity)
return true
}
func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
OpoInstallSDK.handLinkURL(url)
return true
}
}
JSON 페이로드 스키마 및 파라미터 딕셔너리 매핑
캐노니컬 개념적 페이로드 모델
개념적 수준에서 어트리뷰션 콜백은 수신된 마케팅 메타데이터를 채널 어트리뷰션과 개발자 정의 캠페인 페이로드를 포함하는 키-값 구조로 정규화합니다.
스키마 경계 참고 사항: 이는 공식 OpoInstall 와이어 형식이나 SDK 반환 객체 계약이 아닌, 예시용의 애플리케이션 소유 정규화 스키마입니다.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "ConceptualAttributionPayload",
"type": "object",
"properties": {
"channelCode": {
"type": ["string", "null"],
"description": "마케팅 채널 또는 배포 소스에 대한 식별자; 유기적(organic)인 경우 null 또는 빈 값."
},
"data": {
"type": ["object", "string", "null"],
"description": "동적 라우팅 파라미터, 추천 토큰, 프로모션 키를 포함하는 개발자 정의 페이로드."
}
}
}
플랫폼별 데이터 바인딩: Android String 대 iOS Dictionary
개념적 페이로드는 일관되게 유지되지만, 네이티브 SDK 바인딩은 플랫폼 규칙에 따라 data를 서로 다르게 표현합니다.
OpoData.data 속성은 널 가능(nullable) 직렬화된 JSON String?(또는 AAR 버전에 따라 Any?)으로 반환됩니다. 문자열로 입력된 경우(예: "{\"inviterId\":\"1024\",\"roomCode\":\"8899\"}"), 개발자는 이 문자열을 JSONObject로 파싱하거나 Gson 또는 Moshi와 같은 역직렬화 도구를 사용하여 매핑합니다. 형식 지정되지 않은 객체로 반환되는 경우, 파싱하기 전에 제어된 정규화 도우미를 사용하세요. channelCode는 널 가능한 String?으로 직접 노출됩니다.OpoinstallData.data 속성은 네이티브 딕셔너리 컬렉션(또는 버전별 객체)으로 나타납니다. 개발자는 딕셔너리 키 서브스크립팅을 사용하여 값에 직접 액세스합니다. channelCode는 널 가능한 String?으로 노출됩니다.안전한 직렬화: 널 포인터 예외로부터 동적 네비게이션 로직 보호
마케팅 링크는 외부 웹 환경에서 비롯되므로 쿼리 스트링 구조가 손상되거나 잘못될 수 있습니다. 잘못된 문자 인코딩, 필수 키 누락, 예기치 않은 데이터 타입은 파싱 로직이 이상적인 페이로드를 가정할 경우 치명적인 런타임 크래시를 유발할 수 있습니다.
방어적 파라미터 추출을 위해서는 엄격한 유효성 검사 파이프라인을 따라야 합니다.
- 규칙 1: 항상 널(Null) 값에 대비하기: 다운스트림 애플리케이션 서비스에 전달하기 전에
data와channelCode가 존재하는지 확인하세요. - 규칙 2: JSON 파싱 예외 포착하기: Android에서는
JSONException을 포착하기 위해JSONObject(data)인스턴스화를 명시적인try-catch블록으로 감싸세요. - 규칙 3: 기본 라우팅 폴백 강제하기: 파싱은 성공했지만 특정 라우팅 키(예:
target_sku)가 없는 경우, 실행을 중단하는 대신 기본 애플리케이션 랜딩 화면으로 정상적으로 폴백(fallback)하세요.

타임아웃 상태 코드 및 비동기 재시도 로직을 처리하는 방법

타임아웃 및 오류 응답 처리
배포된 SDK가 문서화된 콜백 또는 상태 모델을 통해 타임아웃 또는 검색 실패를 보고하는 경우, 시작 경로를 차단하지 않고 애플리케이션에서 정의한 재시도 정책을 사용하여 해당 결과를 처리하세요.
네트워크 타임아웃은 활성 비행기 모드, 기기 오프라인 상태 또는 셀룰러 핸드오버 지연으로 인해 흔히 발생합니다. 하드코딩된 숫자 상태 코드를 가정하는 대신, 개발자는 SDK의 완료 핸들러가 반환하는 오류 모델을 검사하고 애플리케이션 정의 오류 처리 정책을 사용하여 타임아웃 상태를 명시적으로 처리해야 합니다.
중복 쿼리를 방지하기 위한 호스트 애플리케이션 상태 관리 구현
개발자는 클라이언트 SDK가 후속 애플리케이션 세션에 걸쳐 파라미터 라이프사이클 상태를 영구적으로 캐싱하거나 관리할 것이라고 가정해서는 안 됩니다. 호스트 애플리케이션은 초기 어트리뷰션 파라미터가 이미 처리되었는지 기록하기 위해 자체적인 영구 상태를 관리해야 합니다.
구현 참고 사항: 다음 스니펫은 호스트 애플리케이션 의사 코드 조각입니다.
processReferralPayload는 애플리케이션에서 정의한 비즈니스 로직을 나타냅니다. 보상이나 금전적 인센티브를 배포하는 프로덕션 시스템에서는 로컬 기기 플래그에만 의존하지 않고 서버에서 확인된 멱등 토큰에 의존해야 합니다.
// Android - SharedPreferences에서 어트리뷰션 실행 상태 관리
val prefs = getSharedPreferences("app_prefs", Context.MODE_PRIVATE)
val isAttributionHandled = prefs.getBoolean("attribution_handled", false)
if (!isAttributionHandled) {
OpoInstall.getInstance().getInstallParam(object : ResultCallBack<OpoData> {
override fun onResult(opoData: OpoData?) {
// 공유 정규화 도우미를 사용하여 방어적으로 페이로드 정규화
val customData: String? = normalizePayload(opoData?.data)
if (!customData.isNullOrEmpty()) {
// 호스트 애플리케이션 구현: 커스텀 페이로드 파싱 및 적절히 라우팅
processReferralPayload(customData)
// 중복 실행을 방지하기 위해 어트리뷰션이 처리되었음을 기록
prefs.edit().putBoolean("attribution_handled", true).apply()
}
}
override fun onError(error: OpoError?) {
// 타임아웃 또는 연결 실패 처리; 후속 재시도를 허용하기 위해 플래그는 false로 유지됨
Log.w("OpoInstall", "Deferred retrieval error status observed")
}
})
}
스레드 안전성 및 UI 실행 규칙
개발자는 배포된 SDK 릴리스에 대해 명시적으로 문서화되어 있지 않은 한 콜백 스레드 연관성(thread affinity)을 가정해서는 안 됩니다. 크래시 없는 UI 전환과 스레드 안전성을 보장하려면 UI 네비게이션 또는 뷰 업데이트를 메인 스레드에 명시적으로 디스패치하세요(iOS의 경우 DispatchQueue.main.async 사용, Android의 경우 runOnUiThread / 메인 스레드 코루틴 사용).
명시적 스레드 디스패치를 통해 SDK 버전에서 활용하는 내부 스레딩 모델에 관계없이 알림 대화 상자, 프래그먼트, 뷰 컨트롤러가 안전하게 업데이트됩니다.
애플리케이션 라이프사이클에서 초기화 경쟁 조건(Race Condition) 방지
개발자는 SDK의 문서화된 초기화 라이프사이클을 따라야 하며, 초기화가 완료되기 전이나 필요한 라이프사이클 설정이 발생하기 전에 파라미터 쿼리를 호출하는 것을 피해야 합니다.
권장되는 통합 패턴은 라이프사이클 분리를 강제합니다.
- 초기화 단계: Android의 경우 커스텀
Application.onCreate()메서드 내에서OpoInstall.initialize(this)를 실행하고, iOS의 경우application(_:didFinishLaunchingWithOptions:)내에서OpoInstallSDK.initWith(self)를 실행합니다. - 실행 단계: Android의 경우 기본 런처
Activity.onCreate()내에서start(this)및getInstallParam(...)을 호출합니다.
또한 Android에서 다중 프로세스 아키텍처(푸시 알림 데몬 또는 백그라운드 동기화 서비스 등)를 운영하는 애플리케이션은 SDK 초기화가 메인 애플리케이션 프로세스 내에서만 독점적으로 실행되는지 확인해야 합니다.
주요 어트리뷰션 SDK API 정의 비교 분석
어트리뷰션 SDK 인터페이스 간의 방법론적 차이점
적절한 SDK API를 선택하려면 플랫폼 전반의 실행 라이프사이클, 데이터 계약, 운영 목표를 이해해야 합니다.
아래 표는 공개적으로 사용 가능한 통합 예제에서 지원하는 주요 API 패턴을 비교합니다. 정확한 시그니처는 버전에 따라 다를 수 있습니다.
| 기능 | Android 메서드 시그니처 | iOS 메서드 시그니처 | 주요 실행 타이밍 | 대상 운영 목적 |
|---|---|---|---|---|
| 지연된 설치 쿼리 | getInstallParam(ResultCallBack) |
getInstallParmsCompleted { ... } |
최초 실행 온보딩 | 지연된 파라미터 및 채널 코드 검색 |
| 실시간 딥 링크 | handleDeepLink(Intent, ResultCallBack) |
getWakeUpParams(OpoinstallData?) |
유니버설 링크 / 스킴을 통한 앱 실행 | 씬 복원을 위해 동적 URI 파라미터 가로채기 |
| 커스텀 이벤트 추적 | saveEvent(key, val, extra) |
reportEffectPoint(...) |
인앱 사용자 액션 (IAP / 마일스톤) | 커스텀 전환 이벤트 어트리뷰션 및 ROAS 계산 |
호출 규칙 참고 사항: 이 API들은 해당 딥 링크 기능을 제공하지만, Android는 명시적인 SDK 메서드 호출(
handleDeepLink)을 사용하는 반면 iOS는 델리게이트 콜백(getWakeUpParams)을 통해 결과를 노출합니다.
추가 SDK 기능: 등록 보고 및 추천 공유 어트리뷰션은 버전별 API를 통해 노출될 수 있습니다. 이러한 메서드를 호출하기 전에 배포된 릴리스와 함께 제공되는 공개 헤더 또는 SDK 인터페이스 정의를 참고하세요.
자주 묻는 질문 (FAQ)
getInstallParam과 getWakeUpParams API 정의의 차이점은 무엇인가요?
SDK는 파라미터 검색 중 발생하는 네트워크 타임아웃을 어떻게 처리하나요?
UI 네비게이션을 위해 SDK API 콜백이 메인 스레드에서 실행되는 것이 보장되나요?
요약 및 결정 프레임워크
어트리뷰션 SDK API 정의를 마스터하면 모바일 엔지니어링 팀이 신뢰할 수 있는 온보딩 여정을 구축하고 채널 분석을 추적할 수 있습니다. 지연된 설치 쿼리(getInstallParam / getInstallParmsCompleted)와 실시간 링크 인터셉션(getWakeUpParams / handleDeepLink) 간의 차이점을 이해함으로써 개발자는 파라미터 손실을 줄이고 동적 페이지 라우팅을 구현할 수 있습니다.
모바일 운영 체제가 백그라운드 작업 제약 조건과 네트워크 개인 정보 보호 샌드박스를 개선함에 따라, 잘 정의된 SDK API 시그니처에 의존하면 Android 및 iOS 버전 전반에서 일관된 데이터 처리를 보장할 수 있습니다. 스레드 안전성 지침을 준수하고, 로컬 상태 지속성을 관리하며, 비동기 타임아웃 조건을 처리하는 것은 안정적인 애플리케이션 실행을 지원합니다.
이러한 API 정의를 프로젝트에 통합할 준비가 된 개발자는 OpoInstall 개발자 콘솔에 등록하거나 모바일 어트리뷰션 구현 참고 자료를 참고하여 전체 플랫폼 가이드라인을 확인할 수 있습니다.
관련 자료
-
개념: API 정의, 지연된 딥 링크, 추적 파라미터, JSON 페이로드 매핑
-
기술: Android SDK, iOS SDK, 유니버설 링크, URL 스킴, 비동기 콜백
-
표준: JSON Schema Draft 2020-12, Android Activity 라이프사이클, Apple UIScene 라이프사이클
-
API: OpoInstall getInstallParam API, OpoInstall getWakeUpParams API, OpoInstall saveEvent API
-
공식 문서 및 참고 자료:
Share this article



