Skip to content
스토브
마지막 업데이트

실제 적용 흐름이 궁금하신가요?

이용 시나리오 / 게임 소식 확인하기

팝업

이해하기


공지·이벤트·쿠폰 화면 등을 게임 안에서 이용자에게 보여주는 SDK 팝업 서비스예요. 각 화면은 파트너스에서 다양하게 설정할 수 있어요.
Mobile(Android/iOS)과 PC를 모두 지원하며, 플랫폼에 따라 제공 방식이 달라요.

팝업 종류

종류 설명 Mobile PC
자동 팝업 로비 진입 시 조작 없이 전면 팝업을 순차 노출. 광고·이벤트용.
수동 팝업 지정한 location 호출 시 등록된 화면 노출. 특정 조작·조건에서 띄울 때 사용.
뉴스 팝업 공지 게시글을 모아 노출. 내용이 없으면 "준비중" 표시.
쿠폰 팝업 발급받은 쿠폰 번호로 쿠폰 기능을 사용. (PC는 멀티플랫폼 게임만)
커뮤니티 스토브 커뮤니티를 팝업으로 노출. 로그인 유지 상태로 호출.
커스텀 URL 직접 제작한 웹페이지를 내장 WebView로 노출.
본인인증 팝업 인게임 본인인증 절차를 팝업으로 진행. (한국 전용)

쿠폰 팝업 연동은 별도 페이지에서 안내해요
쿠폰 팝업 연동 방법은 기능별 가이드의 쿠폰 페이지를 참고해 주세요.

Mobile / PC 비교

항목 Mobile PC
SDK Mobile SDK PCSDK View SDK (v3.1.0 이상)
팝업 노출 방식 SDK 내장 WebView로 팝업 노출 View SDK 내장 WebView로 팝업 노출 (Windows만 지원)
초기화 순서 이용자 로그인 완료 후 팝업 호출 가능 Base SDK 초기화 → View SDK 초기화 순서 필수
지원 플랫폼 Android (Kotlin/Java), iOS, Unity, Unreal Native C/C++, Unity, Unreal
팝업 관리 파트너스를 통해 각 이벤트 화면별 설정 파트너스를 통해 각 이벤트 화면별 설정 (모든 게임 유형 지원)
Overlay 기능 View 2.8.2 이상에서 Overlay UI 사용 설정 별도 필요 해당 없음

PC — View SDK 초기화 순서에 주의해요
ㆍ View SDK 초기화 전에 Base SDK 연동·초기화를 먼저 완료해야 해요(미완료 시 View SDK 기능 사용 불가).
ㆍ View SDK 초기화는 다른 View SDK 기능을 사용하기 전에 진행해 주세요.

팝업 공통 설정

뉴스 팝업, 자동 팝업, 수동 팝업에서 아래 항목을 공통으로 설정할 수 있어요.

설정 항목 설명
닫기 버튼 커스텀 이미지 또는 정해진 템플릿(뉴스/자동: 6종, 수동: 3종) 중 선택 가능.
하단 Navigation ON/OFF 설정 가능. (Back, Forward, Refresh, Home ON/OFF)
오늘은 그만 버튼 ON/OFF 및 1일/7일 중 선택 설정 가능. (뉴스·자동 팝업만 지원, 수동 팝업 미지원)

연동 가이드


연동 준비

Mobile

항목 내용
이용자 로그인 이용자 로그인 완료 필수.
파트너스 팝업 등록 파트너스에 팝업 정보 등록 (직접 호출 방식 제외).
Overlay UI 설정 (선택) Overlay 사용 시 별도 설정 (View 2.8.2 이상).

PC (PCSDK)

항목 내용
Base SDK 연동 및 초기화 View SDK 초기화 전 Base SDK 연동·초기화 완료.
파트너스 팝업 등록 파트너스에 기본 정보(world id) 등록 후 노출 설정.
게임프로필 설정 ㆍ 필드·캐릭터 정보 사용 시, 팝업 기능 전 게임프로필 설정 필수
ㆍ BaseSDK의 Base_SetGameProfile API 사용
팝업 지원 게임 확인 ㆍ PC SDK 팝업 API 전 파트너스에 팝업 메타데이터 등록 선행
ㆍ 멀티플랫폼 게임 및 PC only 게임 모두 사용 가능

개발하기


모바일

STOVE SDK View 모듈의 각 팝업 API를 호출하는 방법이에요. 플랫폼별 코드는 탭으로 구분되어 있으니 사용하는 플랫폼만 골라 확인하세요.

뉴스 팝업

공지성 게시글을 한 번에 모아서 보여주는 팝업이에요. 파트너스에서 각 이벤트 화면별로 세부 설정할 수 있어요.

  • 닫기 버튼: 커스텀 이미지 또는 정해진 템플릿 6종
  • 하단 Navigation (Back/Forward/Refresh/Home) ON/OFF
  • "오늘은 그만" 버튼 ON/OFF (1일/7일 선택)

csharp
public void News()
{
    ViewUI.News((Result result, Dictionary<string, string> dictionary) =>
    {
        if (result.IsSuccessful)
        {
        }
        else
        {
            OperationUI.HandleResult(result, (Result operationResult) =>
            {
                /** ex) 현재 화면 유지 **/
            });
        }
    });
}

kotlin
private fun newsPopup(activity: Activity) {
    ViewUI.news(activity) { result, map ->
        //closed view
    }
}

ErrorCodes

DomainErrorCodeDescription
com.stove.success0Success
com.stove.server404path variable을 입력하지 않거나 API 주소를 잘못 쓴 경우
com.stove.base.network10001NoConnectionError
com.stove.base.network10002TimeoutError

자동 팝업

게임 로비 화면에서 가장 많이 노출되는 광고·이벤트 팝업이에요. 인게임 진입 시 이용자 터치 없이도 전면 팝업이 순차적으로 노출돼요.

  • 닫기 버튼: 커스텀 이미지 또는 정해진 템플릿 6종
  • 하단 Navigation (Back/Forward/Refresh/Home) ON/OFF
  • "오늘은 그만" 버튼 ON/OFF (1일/7일 선택)
  • 자동 팝업 중에는 파트너스 설정에 따라 상점 팝업이 노출될 수 있고, 웹 내에서 아이템 결제가 가능해요.

결과 처리 가이드
자동 팝업은 이용자 터치 없이 노출되는 광고성 영역이라 콜백 시점에 게임 흐름을 막지 마세요. 성공 콜백에서는 화면을 그대로 유지하고, 상점 팝업으로 결제가 발생한 경우에는 게임 서버에 결제 결과 동기화를 별도로 요청하세요. 실패는 OperationUI.HandleResult(result, ...)에 위임해 SDK가 적절한 안내 화면을 띄우게 하세요.


csharp
public void AutoPopup()
{
    ViewUI.Popup((Result result, Dictionary<string, string> dictionary) =>
    {
        if (result.IsSuccessful)
        {
        }
        else
        {
            OperationUI.HandleResult(result, (Result operationResult) =>
            {
                /** ex) 현재 화면 유지 **/
            });
        }
    });
}

kotlin
private fun autoPopup(activity: Activity) {
    ViewUI.popup(activity) { result, map ->
        //closed view
    }
}

ErrorCodes

DomainErrorCodeDescription
com.stove.success0Success
com.stove.server1000WRONG_API_USAGE
com.stove.server2000SERVICE_ERROR
com.stove.server90000Error: request accessToken is not exists.
com.stove.server90001Error: accessToken invalid.
com.stove.base.network10001NoConnectionError
com.stove.base.network10002TimeoutError

수동 팝업

게임에서 원하는 위치에 정해진 location으로 수동 팝업을 호출하면 등록된 이벤트 화면이 노출돼요. 인게임에서 특정 UI 터치 또는 화면 진입 시 조건부로 팝업을 보여줄 때 사용해요.

  • 닫기 버튼: 커스텀 이미지 또는 정해진 템플릿 6종
  • 하단 Navigation (Back/Forward/Refresh/Home) ON/OFF

Parameters

ParameterTypeDescription
locationint팝업 위치 (1~5)

csharp
public void ManualPopup()
{
    /**
     * location : 팝업 위치 (int)
     **/
    ViewUI.Popup("location", (Result result, Dictionary<string, string> dictionary) =>
    {
        if (result.IsSuccessful)
        {
        }
        else
        {
            OperationUI.HandleResult(result, (Result operationResult) =>
            {
                /** ex) 현재 화면 유지 **/
            });
        }
    });
}

kotlin
private fun manualPopup(activity: Activity) {
    ViewUI.popup(activity, 1) { result, map ->
        //closed view
    }
}

ErrorCodes

DomainErrorCodeDescription
com.stove.success0Success
com.stove.server404path variable을 입력하지 않거나 API 주소를 잘못 쓴 경우
com.stove.server70004ui_location 값이 0인 경우
com.stove.base.network10001NoConnectionError
com.stove.base.network10002TimeoutError

쿠폰 사용

파트너스에서 발급받은 쿠폰 번호를 전달해 쿠폰 기능을 사용해요. Android는 인게임 화면에서 ViewUI.coupon을 사용하면 스토브 쿠폰 입력 창이 표시돼요.

  • 쿠폰 등록 방법: 파트너스-쿠폰관리 메뉴얼 참고
  • 서버 개발 가이드: 이용자가 쿠폰을 입력하고 지급 조건이 충족되면 아이템박스(STOVE ItemBox)에 지급 정보가 보관돼요. 게임서버는 실시간 전달(Notification) 또는 요청(API Call) 방식 중 하나를 구현할 수 있어요. 아이템박스 연동하기 참고.

에러 코드 그룹별 분기 처리
쿠폰 에러는 이용자 안내 메시지와 재시도 가능 여부가 달라요. 아래 그룹대로 콜백에서 분기를 작성하세요.

  • 재입력 유도 (5105 잘못된 쿠폰 / 5031 일일 인증 횟수 초과 / 6026 사용 횟수 초과): 메시지 노출 후 입력 창을 유지해 다시 입력받으세요.
  • 입력 창 닫기 + 안내 (5125 이미 사용 / 5130 사용 중지 / 5135 유효기간 만료 / 5161 등록 기간 만료 / 5169 사용 기간 아님 / 5202 이미 등록): 메시지 노출 후 입력 창을 닫으세요. 같은 쿠폰 재시도 의미 없음.
  • 자격 안내 (5162 국가 / 5164 월드 / 5200 사용 대상 / 5165 쿠폰함 전용 / 100 PC방 전용 / 2605 멤버쉽 사용 불가): 자격 미달임을 안내하고 입력 창을 닫으세요.
  • 인증 재처리 (997 Not Verify / 998 Expired): Auth.accessToken을 재조회하거나 재로그인 흐름으로 유도하세요. 그 외 시스템 에러(999, 6002)는 OperationUI.HandleResult에 위임하세요.

csharp
public void UseCoupon()
{
    /**
     * code : 쿠폰 입력 (string)
     **/
    View.UseCoupon("code", (Result result) =>
    {
        if (result.IsSuccessful)
        {
        }
        else
        {
            OperationUI.HandleResult(result, (Result operationResult) =>
            {
                /** ex) 현재 화면 유지 **/
            });
        }
    });
}

kotlin
fun useCoupon(context: Context, code: String) {
    View.useCoupon(context, code) { result, map ->

    }
}

ErrorCodes

DomainErrorCodeDescription
com.stove.server100PC방에서만 사용 가능한 쿠폰입니다.
com.stove.server997Not Verify AccessToken
com.stove.server998Expired AccessToken
com.stove.server999System Error
com.stove.server2605해당 멤버쉽 계정은 사용할 수 없습니다.
com.stove.server5031일일 인증 횟수를 초과하였습니다.
com.stove.server5105잘못된 쿠폰 번호입니다.
com.stove.server5125이미 사용한 쿠폰입니다.
com.stove.server5130사용 중지된 쿠폰입니다.
com.stove.server5135유효기간이 만료된 쿠폰입니다.
com.stove.server5155해당 쿠폰의 사용 가능 횟수를 초과하였습니다.
com.stove.server5161등록 기간이 만료된 쿠폰입니다.
com.stove.server5162해당 국가에서 사용할 수 없는 쿠폰입니다.
com.stove.server5164해당 월드에서는 사용할 수 없는 쿠폰입니다.
com.stove.server5165쿠폰함에서만 사용 가능한 쿠폰입니다.
com.stove.server5169해당 쿠폰의 사용 기간이 아닙니다.
com.stove.server5200해당 쿠폰에 대한 사용 대상이 아닙니다.
com.stove.server5202이미 쿠폰함에 등록된 쿠폰입니다.
com.stove.server6002해당 쿠폰번호를 더 이상 사용하실 수 없습니다.
com.stove.server6026사용 횟수가 초과되었습니다.

커뮤니티

인게임에서 스토브 커뮤니티를 팝업으로 노출해요. 커뮤니티가 정상 노출되려면 파트너스에 커뮤니티가 사전 세팅되어 있고, SDK Config의 VIEW > community_id에 파트너스 키값이 등록된 상태여야 해요.


csharp
public void Community()
{
    ViewUI.Community((Result result, Dictionary<string, string> dictionary) =>
    {
        if (result.IsSuccessful)
        {
            if (dictionary != null && dictionary.ContainsKey("received_data"))
            {
                string receivedData = dictionary["received_data"];
                Dictionary<string, object> data = Json.Deserialize(receivedData) as Dictionary<string, object>;

                if (data != null)
                {
                    if (data.TryGetValue("code", out object codeObj) && codeObj is long errorCode)
                    {
                        if (errorCode == 40104) {
                            /** SDK 인증 토큰 만료 — 로그아웃 후 초기화면으로 이동 **/
                        }
                    }
                }
            }
        }
        else
        {
            OperationUI.HandleResult(result, (Result operationResult) => { });
        }
    });
}

kotlin
private fun community(activity: Activity) {
    ViewUI.community(activity) { result, map ->
        //closed view
    }
}

ErrorCodes

DomainErrorCodeDescription
com.stove.success0Success
com.stove.server11236Error : Access token is wrong.
com.stove.base.network10001NoConnectionError
com.stove.base.network10002TimeoutError

커뮤니티 URL 직접 호출

커뮤니티 내 특정 URL을 일반적인 방법으로 호출하면 로그인이 풀린 상태로 호출돼요. 아래 인터페이스를 사용하면 로그인 유지 상태로 호출할 수 있어요.

received_data 응답 처리
성공 콜백의 userInfo["received_data"]는 JSON 문자열이에요. 파싱 후 code == 40104이면 SDK 인증 토큰이 만료된 상태이므로 재로그인 흐름으로 유도하세요. 그 외 코드는 게임이 정의한 형식에 맞춰 처리하거나 무시할 수 있어요. 실패 콜백은 OperationUI.HandleResult(result, ...)에 위임하세요.


csharp
public void CommunityWithURL()
{
    /**
     * url : url 입력 (string)
     **/
    ViewUI.Community("url", (Result result, Dictionary<string, string> dictionary) =>
    {
        if (result.IsSuccessful)
        {
            if (dictionary != null && dictionary.ContainsKey("received_data"))
            {
                string receivedData = dictionary["received_data"];
                Dictionary<string, object> data = Json.Deserialize(receivedData) as Dictionary<string, object>;

                if (data != null)
                {
                    if (data.TryGetValue("code", out object codeObj) && codeObj is long errorCode)
                    {
                        if (errorCode == 40104) {
                            /** SDK 인증 토큰 만료 **/
                        }
                    }
                }
            }
        }
        else
        {
            OperationUI.HandleResult(result, (Result operationResult) => { });
        }
    });
}

kotlin
private fun community(activity: Activity, url: String) {
    ViewUI.community(activity, url) { result, map ->
        //closed view
    }
}

ErrorCodes

DomainErrorCodeDescription
com.stove.success0Success
com.stove.server11236Error : Access token is wrong.
com.stove.base.network10001NoConnectionError
com.stove.base.network10002TimeoutError

커스텀 URL

게임에서 원하는 URL을 WebView로 노출해요. ViewConfiguration으로 부분 화면 또는 전체 화면 표시 방식을 선택할 수 있어요.

Parameters

ParameterTypeDescription
viewRequestViewRequestView를 보여주기 위한 config 항목

플랫폼별 구현 — 부분 화면

csharp
public void Load()
{
    ViewConfiguration viewConfiguration = ViewConfiguration.Partial();
    ViewRequest viewRequest = new ViewRequest("url", viewConfiguration);
    ViewUI.Load(viewRequest, (Result result, Dictionary<string, string> dictionary) =>
    {
        if (result.IsSuccessful)
        {
            if (result.UserInfo != null && result.UserInfo.TryGetValue("userAction", out string userAction))
            {
                if (!string.IsNullOrEmpty(userAction) && userAction.Equals("withdraw_complete"))
                {
                    /** ex) 게임 탈퇴 완료 **/
                }
            }
        }
        else
        {
            OperationUI.HandleResult(result, (Result operationResult) => { });
        }
    });
}

kotlin
private fun load(activity: Activity) {
    val url = "https://www.onstove.com/"
    val viewConfiguration = ViewConfiguration.partial()
    val viewRequest = ViewRequest(url, viewConfiguration = viewConfiguration)
    ViewUI.load(activity, viewRequest) { result, map ->
        if (result.isSuccessful()) {
            result.userInfo?.let { userInfo ->
                when (userInfo["userAction"]) {
                    "withdraw_complete" -> {
                        // 탈퇴 상태
                    }
                }
            }
        }
    }
}

플랫폼별 구현 — 전체 화면

csharp
public void Load()
{
    ViewConfiguration viewConfiguration = ViewConfiguration.Full();
    ViewRequest viewRequest = new ViewRequest("url", viewConfiguration);
    ViewUI.Load(viewRequest, (Result result, Dictionary<string, string> dictionary) =>
    {
        if (result.IsSuccessful)
        {
            if (result.UserInfo != null && result.UserInfo.TryGetValue("userAction", out string userAction))
            {
                if (!string.IsNullOrEmpty(userAction) && userAction.Equals("withdraw_complete"))
                {
                    /** ex) 게임 탈퇴 완료 **/
                }
            }
        }
        else
        {
            OperationUI.HandleResult(result, (Result operationResult) => { });
        }
    });
}

WebView 공통 가이드

게임이 직접 제작한 웹페이지를 SDK WebView로 노출할 때(뉴스·자동·수동 팝업, 커뮤니티, 커스텀 URL 등) 공통으로 사용하는 헤더 정보, URI scheme, JavascriptInterface, 데이터 송수신 패턴을 안내해요.


WebView 호출 시 SDK가 header에 넘기는 정보

게임 운영을 위해 웹페이지를 직접 제작하는 경우, 다음 데이터를 활용할 수 있어요. 아래 데이터는 header에 포함돼요.

KeyDescription
authorization스토브 인증 서버로부터 발급받은 token
characterno이용자의 캐릭터 번호 (게임에서 사용하는 경우에만 포함)
ServerID이용자의 월드 (게임에서 사용하는 경우에만 포함)
SDK-VersionView 모듈의 버전 (ex: 2.0.0)
Accept-Language디바이스 또는 게임에서 설정한 언어 (ex: ko)



Web과 통신하기

Stove SDK는 미리 정의된 JavascriptInterface와 URI scheme을 지원해요.

URI : 공통

정의내용예시사용 가능 버전
stovewebs://외부 링크(사파리, 크롬)로 이동stovewebs://naver.comhttps://naver.com 브라우저로 이동2.0.0
stovecommunitys://스토브 커뮤니티 오픈stovecommunityshttps로 변환 후 커뮤니티 뷰 이동2.0.0

URI : Android 에서만 제공

정의내용예시사용 가능 버전
intent://외부 링크로 이동stovewebs://naver.comhttps://naver.com로 이동2.0.0
http/https가 아닌 schemeACTION_VIEW Intent를 받을 수 있는 Activity 시작market://details?id=com.stove.mstove.google → PlayStore, twitch://open?link_click_id=... → Twitch2.0.0

JavascriptInterface

정의내용
closeWebview현재 뷰 닫기 (SDK에 데이터 전달 가능)
getDeviceInfo디바이스 정보 조회 (StoveJSBridge.callback으로 전달받음)
getValue게임의 property 조회. 파라미터로 key 전달 (StoveJSBridge.callback으로 전달받음)

코드 예제

javascript
function closeWebview(){
    if (window._StoveJSBridge) {
        window._StoveJSBridge.invoke("closeWebview", "게임 클라이언트에 전달할 데이터", null);
    } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.StoveJS) {
        var message = { method: 'closeWebview', parameter: '게임 클라이언트에 전달할 데이터' };
        window.webkit.messageHandlers.StoveJS.postMessage(message);
    }
}
function getDeviceInfo(){
    if (window._StoveJSBridge) {
        window._StoveJSBridge.invoke("getDeviceInfo", null, "getDeviceInfoCallbackId");
    } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.StoveJS) {
        var message = { method: 'getDeviceInfo', callbackId: 'getDeviceInfoCallbackId' };
        window.webkit.messageHandlers.StoveJS.postMessage(message);
    }
}
function getValue(){
    if (window._StoveJSBridge) {
        window._StoveJSBridge.invoke("getValue", '{"key":"fetchKey"}', "getValueCallbackId");
        //기본값 지정이 필요하면 '{"key":"fetchKey", "default":"testValue"}' 형태로 사용
    } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.StoveJS) {
        var message = { method: 'getValue', callbackId: 'getValueCallbackId' };
        window.webkit.messageHandlers.StoveJS.postMessage(message);
    }
}

var StoveJSBridge = {
    callback: function(callbackId, error, result) {
        if(callbackId === "getDeviceInfoCallbackId") {
            const resultJSON = JSON.parse(result);
            const marketGameId = resultJSON.market_game_id;
            const deviceId = resultJSON.device_info.device_id;
            const osName = resultJSON.device_info.os_name;
            const adid = resultJSON.device_info.adid;
        } else if(callbackId === "getValueCallbackId") {
            const resultJSON = JSON.parse(result);
            const returnCode = resultJSON.return_code;
            if(returnCode === 0){
                const key = resultJSON.key;
                const value = resultJSON.value;
            } else if(returnCode === 39403) {
                //Not Exist Key
            } else if(returnCode === 39002) {
                //Invalid Params
            }
        }
    }
};



SDK에서 JavascriptInterface로부터 데이터 수신하기

웹페이지에서 closeWebview로 전달한 데이터를 SDK 콜백의 received_data 키로 받아올 수 있어요.


csharp
private void News()
{
    ViewUI.News((Result result, Dictionary<string, string> dictionary) =>
    {
        if (dictionary != null && dictionary.ContainsKey("received_data"))
        {
            string value = dictionary["received_data"];
        }
    });
}

SDK에서 웹페이지에서 조회할 properties 설정하기

Game Client ↔ SDK ↔ Web 간 데이터 저장 및 조회 목적으로 사용돼요. @since 2.1.0


csharp
public void SetProperties()
{
    AccessToken accessToken = Auth.AccessToken;
    if (accessToken == null) { return; }
    Dictionary<string, object> properties = new Dictionary<string, object>();
    properties.Add("testKey", "testValue");
    GameProfile gameProfile = accessToken.User.GameProfile;
    if (gameProfile == null)
    {
        accessToken.User.GameProfile = new GameProfile();
    }
    accessToken.User.GameProfile.Properties = properties;
}

외부 브라우저 열기 (+SSO 연동)

인증 세션을 유지한 상태로 외부 브라우저에서 ON스토브 페이지(쿠폰/커뮤니티/고객센터 등)를 오픈해요.

⚠️ 주의
게스트 계정은 본 기능을 사용할 수 없어요.
스토브와 다른 인증서(서명키)로 로그인된 계정도 SSO 외부 브라우저 호출 금지. 반드시 '스토브 계정 전환' 완료 후 호출하세요.


csharp
/**
 * url : "외부브라우저를 연동할 url : 쿠폰 or 커뮤니티 등";
 **/
public void OpenExternalUrl()
{
    AccessToken accessToken = Auth.AccessToken;
    if (accessToken == null) { return; }

    string url = "외부브라우저를 연동할 url : 쿠폰 or 커뮤니티 등";

    ViewUI.OpenExternalUrl(url, (Result result) =>
    {
        if (result.IsSuccessful)
        {
            // 외부브라우저 연동 성공
        }
        else
        {
            OperationUI.HandleResult(result, (Result operationResult) => { });
        }
    });
}

PC (PCSDK)

사전 준비

  • ViewSDK는 Base SDK 초기화 완료 후 View_Initialize로 초기화해요. 내부 모드 팝업의 부모 HWND를 지정하려면 View_InitializeWithWndInfo(hwnd)를 사용해요. 외부 브라우저 모드만 사용한다면 부모 HWND 없이 View_Initialize를 호출해도 돼요.
  • 게임 루프에서 Base_RunCallback()이 주기적으로 호출돼야 비동기 콜백이 동작해요.
  • 파트너스 설정에서 캐릭터/필드 정보를 사용한다면 Base_SetGameProfile로 게임 프로파일을 먼저 설정해요.
  • 본인인증 팝업은 한국 외 국가에서 NOT_SUPPORTED_COUNTRY(31)을 반환해요.
  • 쿠폰 팝업은 별도 페이지에서 다뤄요. (쿠폰(Itembox) 참고)
  • 외부 브라우저로 ON스토브 페이지(커뮤니티/고객센터 등)를 여는 기능은 ViewSDK(팝업) 모듈이 아닌 BaseSDK 모듈 의 API(Base_OpenExternalUrl)예요. 따라서 Base_Initialize 완료만 되면 호출할 수 있어요. 스토브 관련 도메인만 허용되며 SSO 로그인이 유지돼요.

개발 흐름

  1. 초기화: Base SDK 초기화(Base_Initialize 또는 Base_InitializeEx)를 완료한 뒤 View_Initialize로 ViewSDK를 초기화해요. 내부 모드 팝업을 사용하려면 게임 메인 HWND를 넘기는 View_InitializeWithWndInfo를 사용해요.
  2. 팝업 노출: 시점/요건에 맞는 API를 호출해요. 모든 팝업 API는 첫 번째 인자로 WebViewMode(EXTERNAL: 외부 브라우저 / INTERNAL: SDK 내장 웹뷰)를 받아요. 자동·수동·뉴스 팝업은 Ex 버전 API를 사용하면 표시 완료 콜백과 별개로 팝업 종료 콜백(OnViewPopupDestroyFinished)을 함께 받을 수 있어요.
    • 자동 팝업: View_AutoPopup(mode, onFinished) (종료 이벤트가 필요하면 View_AutoPopupEx)
    • 수동 팝업: View_ManualPopup(resourceKey, mode, onFinished) (resourceKey로 노출할 팝업 지정, 종료 이벤트가 필요하면 View_ManualPopupEx)
    • 뉴스 팝업: View_NewsPopup(mode, onFinished) (종료 이벤트가 필요하면 View_NewsPopupEx)
    • 본인인증 팝업: View_VerifyIdentificationPopup(compareIdentifier, mode, onFinished, onDestroy) (compareIdentifier 지정, 한국 전용)
    • 쿠폰 팝업: 쿠폰(Itembox) 페이지 참고
  3. 이벤트 처리: 표시 완료 콜백과 팝업 종료 콜백을 받아 게임 진행을 분기해요. 팝업 닫힘 후 게임 흐름을 재개해야 한다면 Ex 버전 API의 종료 콜백에서 처리해요.
  4. 부가 제어: 필요 시 View_SetPopupDisallowed로 다시 보지 않기 설정, View_CloseAllPopups로 일괄 닫기 처리해요.
  5. 외부 브라우저 연동(BaseSDK): 인증 세션을 유지한 채 ON스토브 페이지(커뮤니티/고객센터 등)를 외부 브라우저로 열려면 ViewSDK가 아닌 BaseSDK 모듈의 Base_OpenExternalUrl을 호출해요. 스토브 관련 도메인만 허용되며 SSO 로그인이 유지돼요. 비동기 API라 결과는 Base_RunCallback() 시점의 콜백으로 받아요.
  6. 정리: 게임 종료 직전 View_UnInitialize()로 ViewSDK를 정리한 뒤 Base_UnInitialize()를 호출해요.

트러블슈팅

상황원인해결 방법
게임 시작 후 자동 팝업을 띄웠는데 아무 창도 뜨지 않아요View_Initialize 완료 전에 팝업 API를 호출했어요. ViewSDK 기능은 Base SDK 초기화 후 View_Initialize(내부 모드 팝업은 View_InitializeWithWndInfo)로 ViewSDK를 초기화해야 사용할 수 있어요.Base SDK 초기화를 완료한 뒤 View_Initialize(내부 모드 팝업은 게임 메인 HWND를 넘기는 View_InitializeWithWndInfo)로 ViewSDK 초기화를 끝내고 팝업 API를 호출하면 문제없어요.
팝업 결과 콜백이 한참 호출되지 않아요메인 루프에서 Base_RunCallback()을 호출하지 않으면 SDK가 결과를 게임에 전달할 시점을 잡지 못해요. 콜백은 Base_RunCallback()을 호출한 스레드에서 실행되도록 설계돼 있어요.게임 메인 루프(렌더 루프)에서 매 프레임 또는 일정 주기로 Base_RunCallback()을 호출해야 해요. 보통 입력 처리와 렌더링 사이에 한 번 호출하면 문제없어요.
한국 외 국가 빌드에서 본인인증 팝업이 NOT_SUPPORTED_COUNTRY(31)로 실패해요본인인증 팝업은 한국 서비스 한정 기능이라 한국 외 국가에서는 항상 31번 오류를 반환해요. 글로벌 빌드에 그대로 호출하면 이용자에게 의미 없는 실패 메시지가 노출돼요.Base_GetGds로 받은 StovePCGdsnation(ISO 3166-1 ALPHA-2, 한국이면 "KR") 값을 먼저 확인하고, 한국이 아닐 때는 본인인증 팝업 호출을 스킵해야 해요. 한국 빌드에서만 호출 흐름에 진입하도록 분기를 두면 문제없어요.
새 팝업을 띄웠더니 이전에 떠 있던 팝업이 갑자기 닫혀요ViewSDK는 새 팝업 호출 시 동일 채널에 떠 있던 기존 창을 모두 종료해요. 동시에 두 팝업이 노출되는 것을 막기 위한 의도된 동작이에요.동시 노출은 지원되지 않으므로, 이전에 떠 있던 팝업이 닫히는 것은 정상 동작이에요. 별도 처리 없이 새 팝업 호출만 진행하면 문제없어요.
팝업이 게임 창 뒤에 가려져 클릭되지 않아요ViewSDK 초기화 시 부모 창 핸들을 설정하지 않으면 팝업이 별도 윈도우로 떠서 게임 창보다 뒤로 갈 수 있어요. Exclusive fullscreen 모드에서는 internal 모드 팝업이 Windows API 한계로 게임 창 위로 올라오지 못해요.View_InitializeWithWndInfo에 게임의 메인 HWND를 넘겨 ViewSDK를 초기화해야 해요. Exclusive fullscreen 모드 게임이라면 팝업의 WebViewMode를 반드시 external 모드로 설정하면 문제없어요.
외부 브라우저 API(Base_OpenExternalUrl)가 컴파일/링크되지 않거나 호출되지 않아요외부 브라우저 연동은 ViewSDK가 아닌 BaseSDK 모듈 API라, ViewSDK 헤더만 포함하면 심볼을 찾지 못해요.BaseSDK 헤더(BaseSDK.h)를 포함하고 BaseSDK 초기화가 완료된 상태에서 호출하세요. ViewSDK 초기화 여부와는 무관해요.
외부 브라우저로 연 페이지에서 로그인(SSO)이 풀려요외부 브라우저 연동은 스토브 관련 도메인에서만 SSO 로그인이 유지돼요. 열린 페이지에서 다른 SSO 로그인을 요구하는 페이지로 이동하면 세션이 풀릴 수 있어요.스토브 관련 웹페이지(커뮤니티/고객센터 등) URL만 전달하고, 외부 도메인으로 이동하는 흐름은 피하세요.

팝업 닫힘 후 게임 흐름을 재개하려면 Ex 버전 API의 종료 콜백을 사용해요
View_AutoPopupEx, View_ManualPopupEx, View_NewsPopupEx는 표시 완료 콜백과 별개로, 팝업 창이 닫힌 시점에 호출되는 OnViewPopupDestroyFinished 콜백을 함께 받아요. 닫힘 시점에 다음 화면으로 진입하는 등 게임 흐름을 재개해야 한다면 이 종료 콜백에서 처리하세요.

샘플 코드

cpp
#include "ViewSDK.h"

using namespace Stove::PCSDK;
using namespace Stove::PCSDK::Base;
using namespace Stove::PCSDK::View;

// 1) ViewSDK 초기화 (Base_Initialize 완료 이후)
auto initResult = View_Initialize();
if (!initResult.IsSuccessful())
{
    // 초기화 실패 시 로직을 구현해 주세요.
    return;
}

// 2) 자동 팝업 (종료 이벤트 필요 시 Ex)
//    첫 번째 인자는 WebViewMode (EXTERNAL: 외부 브라우저 / INTERNAL: SDK 내장 웹뷰)
View_AutoPopupEx(
    WebViewMode::EXTERNAL,
    [](CallbackResult openResult) {
        if (openResult.GetResult().IsSuccessful())
        {
            // 팝업 열림 처리
        }
    },
    [](CallbackResult destroyResult) {
        // 팝업 종료 시 게임 흐름 재개
    }
);

// 3) 수동 팝업 (resourceKey 로 노출할 팝업 지정)
View_ManualPopup(L"your_resource_key", WebViewMode::EXTERNAL, /* onFinished */ nullptr);

// 4) 본인인증 팝업 (한국 전용)
//    compareIdentifier=true: SDI 검증 / false: simKey 전달
View_VerifyIdentificationPopup(
    true, WebViewMode::INTERNAL,
    [](CallbackResult result) {
        if (!result.GetResult().IsSuccessful())
        {
            // NOT_SUPPORTED_COUNTRY(31) 등 실패 시 로직
        }
    },
    [](CallbackResult result, const wchar_t* simKey) {
        // 팝업 종료 시 처리 (compareIdentifier=false 일 때 simKey 전달)
    });

// 5) 외부 브라우저 열기 (BaseSDK 모듈 API — ViewSDK 아님, BaseSDK.h)
//    스토브 관련 도메인만 허용, SSO 유지.
{
    std::wstring url = L"https://www.onstove.com";
    Base_OpenExternalUrl(url.c_str(), [](CallbackResult callbackResult) {
        if (callbackResult.GetResult().IsSuccessful())
        {
            // 외부 브라우저 연동 성공 처리
        }
    });
}

// 6) 종료 시 정리
View_UnInitialize();
// 이후 Base_UnInitialize 호출

자주 묻는 질문



Q1. 자동 팝업과 수동 팝업의 차이는 무엇인가요?
A. 자동 팝업은 인게임 진입 시 이용자 터치 없이 게임 내 전면 팝업을 순차적으로 노출해요.
수동 팝업은 특정 UI 터치 또는 화면 진입 조건에서 원하는 위치(location 1~5)에 팝업을 노출할 때 사용해요.
Q2. 뉴스 팝업에 노출할 내용이 없어도 팝업이 표시되나요?
A. 네, 노출할 내용이 없더라도 팝업이 표시되면 "준비중" 메시지가 노출돼요.
공지성 게시글을 한 번에 모아서 보여주고자 하는 경우에 사용해요.
Q3. 커뮤니티 팝업을 호출했는데 로그인이 풀린 상태로 열려요.
A. 커뮤니티 URL을 일반적인 방법으로 호출하면 로그인이 풀린 상태로 호출돼요.
SDK에서 제공하는 커뮤니티 인터페이스를 사용하면 로그인이 유지된 상태로 호출돼요.
또한 파트너스에 커뮤니티가 사전 세팅되어 있어야 하고, SDK Config에 VIEW > community_id에 파트너스에 세팅된 키값이 등록되어 있어야 해요.
Q4. 외부 브라우저 열기(SSO 연동) 기능을 게스트 계정도 사용할 수 있나요?
A. 아니요, 게스트 계정은 이 기능을 사용할 수 없어요. 또한 스토브와 다른 인증서(사명키)로 로그인된 계정은 SSO 외부 브라우저 호출이 금지되므로,
반드시 '스토브 계정 전환' 완료 후 해당 기능을 호출해야 해요.
Q5. PC SDK View SDK 초기화 전에 팝업 API를 호출하면 어떻게 되나요?
A. View SDK 초기화 단계를 먼저 구현해야 View SDK의 기능을 사용할 수 있어요.
View SDK 초기화 전에 Base SDK 연동 및 초기화가 이루어져야 하며, Base SDK 초기화가 완료되지 않은 경우 View SDK의 기능을 사용할 수 없어요.
Q6. PC SDK에서 팝업 API를 호출하면 이전에 열린 팝업이 닫히나요?
A. 네, 팝업 API를 호출하면 이전에 열려 있던 팝업 창이 모두 닫힌 후 새 창이 열려요.
열림/닫힘 콜백은 창 개수와 상관없이 각 1회씩 호출돼요.
Q7. PC SDK에서 팝업 창이 닫힐 때 이벤트를 받고 싶어요.
A. Ex 버전 API를 사용하면 팝업 창이 닫힐 때 OnViewPopupDestroyFinished 이벤트를 전달받을 수 있어요.
View_AutoPopupEx, View_ManualPopupEx, View_NewsPopupEx가 해당돼요.
Ex 버전은 기존 API와 기능이 동일하며, 팝업 종료 이벤트만 추가로 제공해요.
Q8. 본인인증 팝업은 어느 국가에서 사용할 수 있나요?
A. 본인인증 팝업은 한국에서만 동작하는 PC 전용 기능이에요.
한국 이외의 국가에서 호출 시 NOT_SUPPORTED_COUNTRY (31) 에러가 반환돼요.



직접 문의하고 싶으신가요? stove.developers@smilegate.com